Skip to content

Message

API reference for diameter.message.

Diameter base message implementation.

This module contains the base functions for encoding and decoding diameter message headers and messages.

Message

Message(header: MessageHeader = None, avps: list[Avp] = None)

Base message class.

All implemented diameter commands extend this class.

The base message class is not intended to be used directly; its main purpose is to provide the Message.from_bytes class method, for parsing network-received bytes into Python diameter command message instances.

code class-attribute instance-attribute

code: int = 0

Diameter command code value.

header instance-attribute

header: MessageHeader = header or MessageHeader()

A message header. Always exists, defaults to an empty header for new messages.

Note

The length property of the message header is zero for newly created messages and will not be set until the message is rendered using the as_bytes method.

name class-attribute instance-attribute

name: str = 'Unknown'

A human-readable diameter command code name, e.g. "Accounting-Request".

append_avp

append_avp(avp: Avp)

Add an AVP to the internal list of AVPs.

as_bytes

as_bytes() -> bytes

Retrieve entire message as bytes.

Retrieving the message also builds each AVP it contains. Until this point, the list of AVPs has not been built yet and the message header length is still zero. The header length is updated every time as_bytes() is called.

find_avps

find_avps(
    *code_and_vendor: tuple[int, int], alt_list: list[Avp] = None
) -> list[Avp]

Find specific AVPs in the message internal AVP tree.

If more than one code_and_vendor pair is given, the list is assumed to be a chain of AVPs to follow. The returned list of AVPs will be the AVPs found at the end of each chain.

Examples:

In an AVP structure such as:

Multiple-Services-Credit-Control <Code: 0x1c8, Flags: 0x40 (-M-), Length: 168>
  Requested-Service-Unit <Code: 0x1b5, Flags: 0x40 (-M-), Length: 0>
  Used-Service-Unit <Code: 0x1be, Flags: 0x40 (-M-), Length: 84>
    CC-Time <Code: 0x1a4, Flags: 0x40 (-M-), Length: 12, Val: 9>
    CC-Total-Octets <Code: 0x1a5, Flags: 0x40 (-M-), Length: 16, Val: 0>

The "CC-Total-Octets" AVP can be found with:

>>> msg = Message()
>>> avp = msg.find_avps(
>>>     (AVP_MULTIPLE_SERVICES_CREDIT_CONTROL, 0),
>>>     (AVP_USED_SERVICE_UNIT, 0),
>>>     (AVP_CC_TOTAL_OCTETS, 0))
>>> print(avp[0])
CC-Total-Octets <Code: 0x1a5, Flags: 0x40 (-M-), Length: 16, Val: 0>

The search is cached internally, repeating the same find operation will return a cached result.

Note

Searching for AVPs can be somewhat resource intensive, especially for larger command structures. For messages constructed from received network bytes, it is much cheaper to simply access the values of the message attributes directly. E.g. the example above is the same as:

>>> avp = msg.multiple_services_credit_control[0].used_service_unit[0].cc_total_octets
>>> print(avp[0])
0

The method can also be used to search any arbitrary AVP list, by passing an optional keyword argument alt_avps.

from_bytes classmethod

from_bytes(
    msg_data: bytes, plain_msg: bool = False
) -> _AnyMessageType

Generate a new Message from network received bytes.

Accepts a byte string containing received network data and constructs a new Message instance, returning one of its subclasses, if the command code is a known one.

If possible, the returned insance is one of the specific subclasses, e.g. CreditControlRequest or CapabilitiesExchangeRequest, which attempt to be as smart as possible and offer direct access to AVPs as class attributes, i.e. CreditControlRequest.session_id. If this is not wanted, the additional keyword argument plain_msg can be set to True, which returns just an instance of Message that holds the list of parsed AVPs and does nothing else.

>>> # construct a specific Message with parsed attributes
>>> ccr = Message.from_bytes(b"...")
>>> ccr.session_id
labocs1.gy;379;3434872354
>>> # construct a plain message with no attribute access
>>> msg = Message.from_bytes(b"...", plain_msg=True)
>>> # does not work
>>> msg.session_id
AttributeError: 'CreditControl' object has no attribute 'session_id'
>>> # this will work
>>> session_id = msg.find_avps((AVP_SESSION_ID, 0))[0]
>>> session_id.value
labocs1.gy;379;3434872354

to_answer

to_answer() -> _AnyMessageType

Produce answer from a request.

Copies the request message header to a new answer message, clearing all the flags except the proxyable bit. Attempts to by determine if a suitable python Answer class exists, if not, uses the base class and returns a new instance with the copied header.

type_factory classmethod

type_factory(header: MessageHeader) -> Type[_AnyMessageType] | None

Generate a type that should be used to create new instances.

This method is called internally by Message.from_bytes and it can be overridden by inheriting classes to indicate the specific type of message class to generate, e.g. in order to produce different types for "Request" and "Answer" messages, based on the given header.

If no type is returned, the base class type will be used.

MessageHeader

MessageHeader(
    version: int = 1,
    length: int = 0,
    command_flags: int = 0,
    command_code: int = 0,
    application_id: int = 0,
    hop_by_hop_identifier: int = 0,
    end_to_end_identifier: int = 0,
)

DefinedMessage

DefinedMessage(header: MessageHeader = None, avps: list[Avp] = None)

Bases: Message

A base class for every diameter message that is defined in Python.

Every subclass of this class has AVPs defined as python instance attributes, defined based on the corresponding diameter specification.

The attribute values can be changed. When a DefinedMessage instance is converted back to bytes, appropriate AVPs are generated based on the set instance attributes.

avps property writable

avps: list[Avp]

Full list of all AVPs within the message.

If the message was generated from network-received bytes, the list of AVPs may not be in the same order as originally received. The returned list of AVPs contains first the AVPs defined by the base rfc6733 spec, if set, followed by any unknown AVPs.

append_avp

append_avp(avp: Avp)

Add an individual custom AVP.

UndefinedMessage

UndefinedMessage(
    header: MessageHeader = None, avps: list[Avp] = None
)

Bases: Message

A base class for every unknown command message.

Every diameter command message that does not map to an instance of DefinedMessage will be represented as an instance of UndefinedMessage.

This class will automatically attempt to convert received AVPs into read-only instance attributes, using a naive conversion based on the AVP's name. The AVP name is converted into lower case and all "-" are replaced with underscores. I.e. a "Visited-PLMN-Id" AVP would be converted to a "visited_plmn_id" instance attribute.

If an AVP appears multiple times in the original message, it is converted into a list of AVPs.

If an AVP is of the type Grouped, it is converted into an instance of UndefinedGroupedAvp and its sub-AVPs are set as instance attributes as well.

Note

Unlike DefinedMessage, instances of this class cannot be converted back to bytes; there is no conversion of set instance attributes into actual AVPs. Instances of this class are effectively read-only.

dump

dump(msg: Message) -> str

Produce a human-readable representation of the given message.

Produces a recursive text dump of the given message, its header and all AVPs that it contains. Will work also on unknown AVPs and message command codes; data that is not known to the diameter package is marked with "Unknown".

Is essentially the same as calling str on the message itself, and then recursively looping through each AVP and calling str(avp).

Parameters:

Name Type Description Default
msg Message

Any message type

required

Sample output:

Credit-Control <Version: 0x01, Length: 312, Flags: 0x40 (proxyable), Hop-by-Hop Identifier: 0x2711, End-to-End Identifier: 0x4e21>
  Session-Id <Code: 0x107, Flags: 0x40 (-M-), Length: 73, Val: sctp-saegwc-poz01.lte.orange.pl;221424325;287370797;65574b0c-2d02>
  Result-Code <Code: 0x10c, Flags: 0x40 (-M-), Length: 12, Val: 2001>
  Origin-Host <Code: 0x108, Flags: 0x00 (---), Length: 21, Val: b'ocs6.mvno.net'>
  Origin-Realm <Code: 0x128, Flags: 0x00 (---), Length: 16, Val: b'mvno.net'>
  Auth-Application-Id <Code: 0x102, Flags: 0x40 (-M-), Length: 12, Val: 4>
  CC-Request-Type <Code: 0x1a0, Flags: 0x40 (-M-), Length: 12, Val: 2>
  CC-Request-Number <Code: 0x19f, Flags: 0x40 (-M-), Length: 12, Val: 952>
  Multiple-Services-Credit-Control <Code: 0x1c8, Flags: 0x40 (-M-), Length: 128>
    Granted-Service-Unit <Code: 0x1af, Flags: 0x40 (-M-), Length: 24>
      CC-Total-Octets <Code: 0x1a5, Flags: 0x40 (-M-), Length: 16, Val: 174076000>
    Rating-Group <Code: 0x1b0, Flags: 0x40 (-M-), Length: 12, Val: 8000>
    Validity-Time <Code: 0x1c0, Flags: 0x40 (-M-), Length: 12, Val: 3600>
    Result-Code <Code: 0x10c, Flags: 0x40 (-M-), Length: 12, Val: 2001>
    Final-Unit-Indication <Code: 0x1ae, Flags: 0x40 (-M-), Length: 44>
      Final-Unit-Action <Code: 0x1c1, Flags: 0x40 (-M-), Length: 12, Val: 0>
      Unknown <Code: 0x266e, Flags: 0x80 (V--), Length: 21, Vnd: None, Val: b'TERMINATE'>
    Quota-Holding-Time <Code: 0x367, Flags: 0xc0 (VM-), Length: 16, Vnd: TGPP, Val: 0>

Note that:

  • Message header version, flags and identifiers are as hexadecimal strings
  • AVP flags are shown as three letters, "VMP", where "V" indicates vendor specific, "M" indicates mandatory and "P" indicates private. If a flag is not set, it is replaced by a "-"
  • AVP codes are in hexadecimal
  • Unknown AVPs are rendered, but shown as "Unknown"