Skip to content

Node

API reference for diameter.node.

Node

Node(
    origin_host: str,
    realm_name: str,
    ip_addresses: list[str] = None,
    tcp_port: int = None,
    sctp_port: int = None,
    vendor_ids: list[int] = None,
)

A diameter node.

A single diameter node represents the local peer. It handles connections to other peers, exchanging capabilities-exchange, device-watchdog and disconnect-peer requests and answers on its own.

The node can act either as a server or as a client. In both cases it will handle both incoming and outgoing requests, however when acting as a client, other diameter nodes cannot connect to it, all connections must be initiated and managed by the client. When acting as a server, connections can be established by any party.

The node supports both TCP and SCTP transport modes. When acting as a server, it can always listen on multiple addresses, however this is only useful when utilising SCTP, as other peers will only connect to a single TCP address at a time.

The node can connect to multiple peers simultaneously; peers can be added using Node.add_peer. Both TCP and SCTP transport modes are accepted and can be mixed at will. Peers can be flagged as persistent, in which case the Node will periodically attempt to reconnect, if a connection is lost.

>>> node = Node()
>>> node.add_peer("aaa://dra1.gy:3868;transport=tcp", "realm.net", ["10.16.17.5"])
>>> node.add_peer("aaa://dra2.gy;transport=sctp", "realm.net", ["10.16.17.6", "172.16.0.6"])
>>> node.start()

Any other message than CER/CEA, DWR/DWA and DPR/DPA will be routed to a diameter application that is expected to do the actual work. Applications can be created by subclassing either diameter.node.application.Application or diameter.node.application.ThreadingApplication and adding them to this node using add_application. If a message is received that is intended for an application that does not exist, a diameter error is returned to the peer.

Outgoing requests are routed based on realm and peer routing tables; if a request does not contain the Destination-Host AVP, the request is forwarded to a peer that has a matching realm and application ID set. If multiple peers are available, a rudimentary load balancing based on least used connections is used. Answers are routed back to the peer that they originated from, or dropped if the peer has gone away.

Parameters:

Name Type Description Default
origin_host str

Our local node FQDN, must include the realm

required
realm_name str

Realm FQDN

required
ip_addresses list[str]

An optional list of IP address that the node will listen on for incoming requests. Must be set if the node is to act as a server. When not set, the node will not listen for any incoming connection attempts.

None
tcp_port int

An optional TCP listen port, should be set if ip_addresses is set, defaults to 3868 if nothing is given

None
sctp_port int

An optional SCTP listen port, should be set if ip_addresses is set, defaults to 3868 if nothing is given

None
vendor_ids list[int]

List of supported vendor IDs. If not set, will default to all known vendor IDs. The list of vendor IDs is only used in advertising the node's capabilities in CER/CEA

None

applications instance-attribute

applications: list[Application] = []

List of configured applications.

cea_timeout instance-attribute

cea_timeout: int = 4

Default timeout waiting for a CEA after sending a CER, in seconds. Will be used if no specific timeout value has been configured for a peer.

cer_timeout instance-attribute

cer_timeout: int = 4

Default timeout waiting for a CER after receiving a connection attempt, in seconds. Will be used if no specific timeout value has been configured for a peer

connections instance-attribute

connections: dict[str, PeerConnection] = {}

Currently handled peer connections.

dwa_timeout instance-attribute

dwa_timeout: int = 4

Default timeout waiting for a DWA after sending a DWR, in seconds. Will be used if no specific timeout value has been configured for a peer.

end_to_end_seq instance-attribute

end_to_end_seq = SequenceGenerator(state_id)

An end-to-end identifier generator. The next identifier can be retrieved with Node.end_to_end_seq.next_sequence().

idle_timeout instance-attribute

idle_timeout: int = 30

Default time spent idle before a DWR is triggered, in seconds. Will be used if no specific timeout value has been configured for a peer.

peer_sockets instance-attribute

peer_sockets: dict[str, socket | sctpsocket] = {}

Currently held sockets, one for each peer connection.

peers instance-attribute

peers: dict[str, Peer] = {}

All currently known peers as a dictionary of host identities as keys and instances of Peer as values..

peers_logging instance-attribute

peers_logging: bool = False

If enabled, will dump a JSON representation of each peer configuration and their current connection status, at every wakeup_interval seconds. The logging will be done through "diameter.stats" log facility an can also be silenced by changing the log level to anything above DEBUG.

product_name instance-attribute

product_name: str = 'python-diameter'

Our product name.

retransmit_queue_size instance-attribute

retransmit_queue_size: int = 10240

The amount of request end-to-end identifiers to "remember" after sending an answer. The list of remembered identifiers is checked every time a request with the "T" flag is received. The request will be rejected if a matching end-to-end identifier is still present in the queue. The size of this should match roughly with the amount of requests that are expected to arrive within a time period that retransmits may arrive. There is no noticeable performance loss when setting this higher than the default value of 10240.

session_generator instance-attribute

session_generator = SessionGenerator(origin_host)

A unique diameter session ID generator. The next unique session ID can be retrieved Node.session_generator.next_id().

socket_peers instance-attribute

socket_peers: dict[int, PeerConnection] = {}

Peer connection lookup based on socket fileno.

statistics property

statistics: NodeStats

Calculated, cumulated and averaged statistics for the entire node.

statistics_history instance-attribute

statistics_history: deque[dict] = deque(maxlen=1440)

A list of node statistics snapshots, taken at one minute intervals and kept for 24 hours. Each snapshot is a dictionary representation of a NodeStats instance.

stats_logging instance-attribute

stats_logging: bool = False

If enabled, will dump a JSON representation of the statistics for each peer in the logs, at every wakeup_interval seconds. The logging will be done through "diameter.stats" log facility an can also be silenced by changing the log level to anything above DEBUG. Enabling this may have a slight performance impact, as the main thread will block while the statistics are being gathered.

vendor_id instance-attribute

vendor_id: int = 99999

Our vendor ID. Defaults to "unknown".

wakeup_interval instance-attribute

wakeup_interval: int = 6

Time in seconds between forced wakeups while waiting for connection sockets to become active. This timer value controls how often peer timers are checked, how often reconnects are attempted and how often statistics are dumped in the logfiles.

As this also defines the interval at which peer timers are checked, it is also the smallest possible value for a peer timer value. Setting this value very low will consume more CPU, setting it too high will make observing short timeouts impossible.

This value also defines how long a node will continue to run, after stop with force argument set to True is called.

add_application

add_application(
    app: Application, peers: list[Peer], realms: list[str] = None
)

Register an application with diameter node.

The added application will receive diameter requests that the node receives, which an application-id message header value matching the application's ID.

When added, the node calls the application's start method immediately. The application is stopped when the node stops.

Parameters:

Name Type Description Default
app Application

An instance of a class that implements Application

required
peers list[Peer]

A list of Peer instances that have been returned by Node.add_peer. The given list of peers will be used to determine how messages are to be routed

required
realms list[str]

An optional list of realms served for the peers through the application, in addition to the realm name given as part of Node.add_peer call. The realm names given here are only used for routing messages with Destination-Realm AVP values deviating from the peer's default realm name. Any auto-generated Message, e.g. DWR/DWA, will use the realm name configured while creating the peer instance.

None

add_peer

add_peer(
    peer_uri: str,
    realm_name: str = None,
    ip_addresses: list[str] = None,
    is_persistent: bool = False,
    is_default: bool = False,
) -> Peer

Add a known peer.

The node will only connect to known connections and (optionally) accept requests from known connections only.

Parameters:

Name Type Description Default
peer_uri str

A diameter node's DiameterIdentity as a DiameterURI string, i.e. "aaa://:;transport=". The URI must contain at least the scheme and FQDN; the port and transport will default to 3868 and "TCP" if not included

required
realm_name str

Peer realm name. If not given, will be set to the same realm as the node has been configured with

None
ip_addresses list[str]

A list of IP addresses for the peer. If not given, no outgoing connection attempt to the peer will be made. For TCP, only the first IP of the list is used. For SCTP, a connection will be established to every address

None
is_persistent bool

Enable persistent connection to the peer. If enabled, the node will automatically re-establish a connection to the peer on startup and at connection loss

False
is_default bool

Set this peer as the default peer for the realm. Note that multiple defaults is permitted. Setting multiple pers as default will result in load balancing between the peers.

False

Returns:

Type Description
Peer

An instance of the peer. The returned instance is the actual peer instance, permitting configuration to be adjusted after node has been started, by altering its attributes.

close_connection_socket

close_connection_socket(
    conn: PeerConnection,
    disconnect_reason: int = DISCONNECT_REASON_UNKNOWN,
)

Shuts down connection socket and stops observing it forever.

If the corresponding peer has persistency enabled, the node will automatically re-establish the connection after Node.reconnect_timeout seconds.

Closing the peer socket will automatically call Node.remove_peer_connection.

Parameters:

Name Type Description Default
conn PeerConnection

An instance of a peer connection to disconnect

required
disconnect_reason int

Reason for the connection being disconnected, one of the PEER_DISCONNECT_REASON_* constant values

DISCONNECT_REASON_UNKNOWN

remove_peer_connection

remove_peer_connection(
    conn: PeerConnection,
    disconnect_reason: int = DISCONNECT_REASON_UNKNOWN,
)

Removes a peer connection that is no longer connected.

Warning

This method should not be called directly, unless it is absolutely certain that the peer socket is no longer connected. The safer way is to use Node.close_connection_socket instead, which will first close the socket and then remove the peer.

Parameters:

Name Type Description Default
conn PeerConnection

An instance of peer connection to remove from the list of active connections

required
disconnect_reason int

A reason for the connection being disconnected, one of the PEER_DISCONNECT_REASON_* constant values.

DISCONNECT_REASON_UNKNOWN

route_answer

route_answer(message: Message) -> tuple[PeerConnection, Message]

Determine which peer should be used for sending an answer message.

Should always be used by an application before sending an answer.

Determines the proper peer to be used, by keeping track of which requests have been sent, and always forwarding answers in reverse direction to correct peer connections.

Parameters:

Name Type Description Default
message Message

The exact answer message to send

required

Returns:

Type Description
tuple[PeerConnection, Message]

A tuple with an instance of a peer to route to, and the same message as was passed to the method.

Raises:

Type Description
NotRoutable

when there is either no peer waiting for the answer, or when the peer exists, but does not accept messages at the time

route_request

route_request(
    app: Application, message: Message
) -> tuple[PeerConnection, Message]

Determine which peer should be used for sending a request message.

Should always be used by an application before sending a request.

Determines the proper peer to be used for the particular message, by comparing the configured peer list with what is currently connected and ready to receive requests. If multiple connections are available, a rudimentary load balancing is used, with least-used peer selected.

Sets the hop-by-hop identifier automatically based on the selected peer.

Parameters:

Name Type Description Default
app Application

The application instance that wants to send a request

required
message Message

The exact message to send

required

Returns:

Type Description
tuple[PeerConnection, Message]

A tuple with an instance of a peer to route to, and the same message as was passed to the method.

Raises:

Type Description
NotRoutable

when there is either no connections configured for the application, or if none of the configured connections is connected or accepting requests at the time

send_message

send_message(conn: PeerConnection, message: Message)

Manually send a message towards a peer.

Normally messages are sent through applications, but this method permits manually sending messages towards known connections.

Parameters:

Name Type Description Default
conn PeerConnection

An instance of a peer connection to send the message to. The connection must be in PEER_READY or PEER_READY_WAITING_DWA state

required
message Message

A valid diameter message instance to send, can be either a request or an answer.

required

start

start()

Start the node.

This method must be called once after the peer has been created. At startup, the node will create the local listening sockets, start its work threads and connect to any connections that have persistent connections enabled.

stop

stop(wait_timeout: int = 180, force: bool = False)

Stop node.

Stopping the node will emit a Disconnect-PeerConnection-Request towards each currently connected peer, with disonnect cause "REBOOTING". The node will then wait until each peer has produced a Disconnect-PeerConnection-Answer, and regardless of the answer's result code or error status, the peer sockets are closed. Some diameter vendors may also already close the socket from their end immediately, if no messages are pending.

After all connections have disconnected, the node's own listening sockets will close, and afterwards the active applications are shut down.

Parameters:

Name Type Description Default
wait_timeout int

Set a timeout for the DPR/DPA procedure to cpmplete. This should be usually fairly high, as time must be given for not only for the DPR/DPA messages to travel, but also for the peer connections to empty their in- and out buffers and for the applications to finish processing responses.

180
force bool

Optionally skip DPR/DPA procedure and just force each peer connection to close immediately, with a very short (5-10 seconds) wait period for their threads to join.

False

NodeStats dataclass

NodeStats(
    avg_response_time: dict[str, float],
    avg_response_time_overall: float,
    processed_req_per_second: dict[str, float],
    processed_req_per_second_overall: float,
    received_req_counters: list[int],
    sent_result_code_range_counters: dict[str, list[int]],
)

Cumulated and averaged node statistics.

Represents a snapshot with cumulated and averaged statistical values for all configured peers at the time of retrieval. The meaning of each statistical value is identical to those of PeerStats.

avg_response_time instance-attribute

avg_response_time: dict[str, float]

Average response time, split by message type.

avg_response_time_overall instance-attribute

avg_response_time_overall: float

Overall average response time.

processed_req_per_second instance-attribute

processed_req_per_second: dict[str, float]

Rate of requests processed per second, split by message type.

processed_req_per_second_overall instance-attribute

processed_req_per_second_overall: float

Rate of requests processed per second.

received_req_counters instance-attribute

received_req_counters: list[int]

Exact amount of requests received in the last minute, last five minutes and the last 15 minutes.

sent_result_code_range_counters instance-attribute

sent_result_code_range_counters: dict[str, list[int]]

Exact amount of answers sent in the last minute, last five minutes and the last 15 minutes, once for each diameter result code range. The result code range is expressed as a string in form of "1xxx", "2xxx" etc.

NodeError

Bases: Exception

Base error for all exceptions raised by Node.

NotRoutable

Bases: NodeError

Error raised when a message can not be routed to any peer.