# `diameter_codec` [🔗](https://github.com/garazdawi/otp/blob/lukas/shell_docs/fix-bugs/lib/diameter/src/base/diameter_codec.erl#L23) Decode and encode of Diameter messages. Incoming Diameter messages are decoded from binary() before being communicated to `m:diameter_app` callbacks. Similarly, outgoing Diameter messages are encoded into binary() before being passed to the appropriate `m:diameter_transport` module for transmission. The functions documented here implement the default encode/decode. > #### Warning {: .warning } > > The diameter user does not need to call functions here explicitly when sending > and receiving messages using `diameter:call/4` and the callback interface > documented in `m:diameter_app`: diameter itself provides encode/decode as a > consequence of configuration passed to `diameter:start_service/2`, and the > results may differ from those returned by the functions documented here, > depending on configuration. The [header()](`m:diameter_codec#header`) and [packet()](`m:diameter_codec#packet`) records below are defined in diameter.hrl, which can be included as follows. ```erlang -include_lib("diameter/include/diameter.hrl"). ``` Application-specific records are defined in the hrl files resulting from dictionary file compilation. ## DATA TYPES - **`uint8()  = 0..255`{: #integers }** - **`uint24() = 0..16777215`** - **`uint32() = 0..4294967295`** - 8-bit, 24-bit and 32-bit integers occurring in Diameter and AVP headers. - **`avp() = #diameter_avp{}`{: #avp }** - The application-neutral representation of an AVP. Primarily intended for use by relay applications that need to handle arbitrary Diameter applications. A service implementing a specific Diameter application (for which it configures a dictionary) can manipulate values of type [message()](`m:diameter_codec#message`) instead. Fields have the following types. - **`code = uint32()`** - **`is_mandatory = boolean()`** - **`need_encryption = boolean()`** - **`vendor_id = uint32() | undefined`** - Values in the AVP header, corresponding to AVP Code, the M flag, P flags and Vendor-ID respectively. A Vendor-ID other than `undefined` implies a set V flag. - **`data = iolist()`** - The data bytes of the AVP. - **`name = atom()`** - The name of the AVP as defined in the dictionary file in question, or `undefined` if the AVP is unknown to the dictionary file in question. - **`value = term()`** - The decoded value of an AVP. Will be `undefined` on decode if the data bytes could not be decoded, the AVP is unknown, or if the [decode format](`m:diameter#decode_format`) is `none`. The type of a decoded value is as document in [diameter_dict(4)](diameter_dict.md#DATA_TYPES). - **`type = atom()`** - The type of the AVP as specified in the dictionary file in question (or one it inherits). Possible types are `undefined` and the Diameter types: `OctetString`, `Integer32`, `Integer64`, `Unsigned32`, `Unsigned64`, `Float32`, `Float64`, `Grouped`, `Enumerated`, `Address`, `Time`, `UTF8String`, `DiameterIdentity`, `DiameterURI`, `IPFilterRule` and `QoSFilterRule`. - **`dictionary() = module()`{: #dictionary }** - The name of a generated dictionary module as generated by [diameterc(1)](diameterc_cmd.md) or `diameter_make:codec/2`. The interface provided by a dictionary module is an implementation detail that may change. - **`header() = #diameter_header{}`{: #header }** - The record representation of the Diameter header. Values in a [packet()](`m:diameter_codec#packet`) returned by `decode/2` are as extracted from the incoming message. Values set in an [packet()](`m:diameter_codec#packet`) passed to `encode/2` are preserved in the encoded binary(), with the exception of `length`, `cmd_code` and `application_id`, all of which are determined by the [dictionary()](`m:diameter_codec#dictionary`) in question. > #### Note {: .info } > > It is not necessary to set header fields explicitly in outgoing messages as > diameter itself will set appropriate values. Setting inappropriate values > can be useful for test purposes. Fields have the following types. - **`version = uint8()`** - **`length = uint24()`** - **`cmd_code = uint24()`** - **`application_id = uint32()`** - **`hop_by_hop_id = uint32()`** - **`end_to_end_id = uint32()`** - Values of the Version, Message Length, Command-Code, Application-ID, Hop-by-Hop Identifier and End-to-End Identifier fields of the Diameter header. - **`is_request = boolean()`** - **`is_proxiable = boolean()`** - **`is_error = boolean()`** - **`is_retransmitted = boolean()`** - Values corresponding to the R(equest), P(roxiable), E(rror) and T(Potentially re-transmitted message) flags of the Diameter header. - **`message() = record() | maybe_improper_list()`{: #message }** - The representation of a Diameter message as passed to `diameter:call/4` or returned from a [handle_request/3](`c:diameter_app:handle_request/3`) callback. The record representation is as outlined in [diameter_dict(4)](diameter_dict.md#MESSAGE_RECORDS): a message as defined in a dictionary file is encoded as a record with one field for each component AVP. Equivalently, a message can also be encoded as a list whose head is the atom-valued message name (as specified in the relevant dictionary file) and whose tail is either a list of AVP name/values pairs or a map with values keyed on AVP names. The format at decode is determined by [diameter:service_opt()](`m:diameter#service_opt`) [decode_format](`m:diameter#decode_format`). Any of the formats is accepted at encode. Another list-valued representation allows a message to be specified as a list whose head is a [header()](`m:diameter_codec#header`) and whose tail is an [avp()](`m:diameter_codec#avp`) list. This representation is used by diameter itself when relaying requests as directed by the return value of a [handle_request/3](`c:diameter_app:handle_request/3`) callback. It differs from the other two in that it bypasses the checks for messages that do not agree with their definitions in the dictionary in question: messages are sent exactly as specified. - **`packet() = #diameter_packet{}`{: #packet }** - A container for incoming and outgoing Diameter messages. Fields have the following types. - **`header = `[`header()`](`m:diameter_codec#header`)` | undefined`** - The Diameter header of the message. Can be (and typically should be) `undefined` for an outgoing message in a non-relay application, in which case diameter provides appropriate values. - **`avps = [`[`avp()`](`m:diameter_codec#avp`)`] | undefined`** - The AVPs of the message. Ignored for an outgoing message if the `msg` field is set to a value other than `undefined`. - **`msg = `[`message()`](`m:diameter_codec#message`)` | undefined`** - The incoming/outgoing message. For an incoming message, a term corresponding to the configured [decode format](`m:diameter#decode_format`) if the message can be decoded in a non-relay application, `undefined` otherwise. For an outgoing message, setting a `[`[`header()`](`m:diameter_codec#header`)`|`[`avp()`](`m:diameter_codec#avp`)`]` list is equivalent to setting the `header` and `avps` fields to the corresponding values. > #### Warning {: .warning } > > A value in the `msg` field does _not_ imply an absence of decode errors. > The `errors` field should also be examined. - **`bin = binary()`** - The incoming message prior to encode or the outgoing message after encode. - **`errors = [5000..5999 | {5000..5999, avp()}]`** - Errors detected at decode of an incoming message, as identified by a corresponding 5xxx series Result-Code (Permanent Failures). For an incoming request, these should be used to formulate an appropriate answer as documented for the [handle_request/3](`c:diameter_app:handle_request/3`) callback in `m:diameter_app`. For an incoming answer, the [diameter:application_opt()](`m:diameter#application_opt`) `answer_errors` determines the behaviour. - **`transport_data = term()`** - An arbitrary term of meaning only to the transport process in question, as documented in `m:diameter_transport`. ## SEE ALSO [diameterc(1)](diameterc_cmd.md), `m:diameter_app`, [diameter_dict(4)](diameter_dict.md), `m:diameter_make` # `dictionary` *not exported* *since OTP R15B03* ```erlang -type dictionary() :: module(). ``` The name of a generated [dictionary module](`m:diameter_codec#dictionary`) as generated by [diameterc(1)](diameterc_cmd.md) or `diameter_make:codec/2`. The interface provided by a dictionary module is an implementation detail that may change. # `message` *since OTP R15B03* ```erlang -type message() :: record() | maybe_improper_list(). ``` The representation of a Diameter [message](`m:diameter_codec#message`) as passed to `diameter:call/4` or returned from a [handle_request/3](`c:diameter_app:handle_request/3`) callback. # `packet` *since OTP R15B03* ```erlang -type packet() :: #diameter_packet{header :: term(), avps :: term(), msg :: term(), bin :: term(), errors :: term(), transport_data :: term()}. ``` A [container](`m:diameter_codec#packet`) for incoming and outgoing Diameter messages. # `decode` *since OTP R15B03* ```erlang -spec decode(Mod, Bin) -> Pkt when Mod :: dictionary(), Bin :: binary(), Pkt :: packet(). ``` Decode a Diameter message. # `encode` *since OTP R15B03* ```erlang -spec encode(Mod, Msg) -> Pkt when Mod :: dictionary(), Msg :: message() | packet(), Pkt :: packet(). ``` Encode a Diameter message. --- *Consult [api-reference.md](api-reference.md) for complete listing*