This module provides the interface with which a user can implement a Diameter node that sends and receives messages using the Diameter protocol as defined in RFC 3588.
Basic usage consists of creating a representation of a
locally implemented Diameter node and its capabilities with
Beware the difference between diameter (not capitalised) and Diameter (capitalised). The former refers to the Erlang application named diameter whose main api is defined here, the latter to Diameter protocol in the sense of RFC 3588.
The diameter application must be started before calling most functions in this module.
Types corresponding to RFC 3588 AVP Data Formats.
Defined in
A name identifying a Diameter application in
service configuration.
Passed to
Mod = atom()
ExtraArgs = list()
A module implementing the callback interface defined in
Specifying a
Options defining a Diameter application. Has one the following types.
An unique identifier for the application in the scope of the
service.
Defaults to the value of the
The name of an encode/decode module for the Diameter
messages defined by the application.
These modules are generated from a specification file whose format is
documented in
The callback module with which messages of the Diameter application are
handled.
See
The initial callback state.
The prevailing state is passed to some
Specifies whether or not the
Determines the manner in which incoming answer messages containing
decode errors are handled.
If
Defaults to
Options available to
Extra arguments to append to callbacks to the callback module in question. These are appended to any extra arguments configured on the callback itself. Multiple options append to the argument list.
A filter to apply to the list of available peers before passing them to
the
The number of milliseconds after which the request should timeout. Defaults to 5000.
Causes
An invalid option will cause
AVP values sent in outgoing CER or CEA messages during capabilities exchange. Can be configured both on a service and a transport, values specified on the latter taking precedence over any specified on the former. Has one of the following types.
An address list is available to the start function of a
Origin-State-Id is optional but will be included in outgoing messages
sent by diameter itself: CER/CEA, DWR/DWA and DPR/DPA.
Setting a value of
Inband-Security-Id defaults to the empty list, which is equivalent to a list containing only 0 (= NO_INBAND_SECURITY). If 1 (= TLS) is specified then TLS is selected if the CER/CEA received from the peer offers it.
Note that each tuple communicates one or more AVP values. It is an error to specify duplicate tuples.
An expression that can be evaluated as a function in the following sense.
eval([{M,F,A} | T]) ->
apply(M, F, T ++ A);
eval([[F|A] | T]) ->
eval([F | T ++ A]);
eval([F|A]) ->
apply(F, A);
eval(F) ->
eval([F]).
Applying an
Beware of using fun expressions of the form
A filter passed to
Matches any peer. This is a convenience that provides a filter equivalent to no filter at all.
Matches only those peers whose
Matches only those peers whose
Matches only those peers whose
Matches only those peers whose
Matches only those peers for which the specified
Matches only those peers not matched by the specified filter.
Matches only those peers matched by each filter in the specified list.
Matches only those peers matched by at least one filter in the specified list.
An invalid filter is equivalent to
The
A
An event message sent to processes that have subscribed to these using
The
Ref = transport_ref()
Peer = diameter_app:peer()
Config = {connect|listen, [transport_opt() ]}
Pkt = #diameter_packet{}
The RFC 3539 watchdog state machine has
transitioned into (
Note that a single
Ref = transport_ref()
Opts = [transport_opt() ]
A connecting transport is attempting to establish/reestablish a
transport connection with a peer following
Ref = transport_ref()
Config = {connect|listen, [transport_opt() ]}
Capabilities exchange has failed.
Result = ResultCode | {capabilities_cb, CB, ResultCode|discard}
Caps = #diameter_caps{}
Pkt = #diameter_packet{}
ResultCode = integer()
CB = evaluable()
An incoming CER has been answered with the indicated result code or
discarded.
ResultCode = integer()
Caps = #diameter_caps{}
Pkt = #diameter_packet{}
An incoming CER contained errors and has been answered with the
indicated result code.
Result = integer() | atom() | {capabilities_cb, CB, ResultCode|discard}
Caps = #diameter_caps{}
Pkt = #diameter_packet{}
ResultCode = integer()
An incoming CEA has been rejected for the indicated reason.
An integer-valued
Caps = #diameter_caps{}
Pkt = #diameter_packet{}
An incoming CEA contained errors and has been rejected.
Ref = transport_ref()
PeerRef = diameter_app:peer_ref()
From, To = initial | okay | suspect | down | reopen
Config = {connect|listen, [transport_opt()]}
An RFC 3539 watchdog state machine has changed state.
For forward compatibility, a subscriber should be prepared to receive info fields of forms other than the above.
The name of a service as passed to
An option passed to
Defines a Diameter application supported by the service.
A service must configure one
Specifies a constant value
(H bsl N) bor (Id band ((1 bsl N) - 1))
Note that RFC 3588 requires that End-to-End identifiers remain unique
for a period of at least 4 minutes and that this and the call rate
places a lower bound on the appropriate values of
Defaults to
An option passed to
A module implementing a transport process as defined in
Multiple
A term passed as the third argument to the
The 3-tuple form additionally specifies an interval, in milliseconds, after which a started transport process should be terminated if it has not yet established a connection. For example, the following options on a connecting transport request a connection with one peer over SCTP or another (typically the same) over TCP.
{transport_module, diameter_sctp}
{transport_config, SctpOpts, 5000}
{transport_module, diameter_tcp}
{transport_config, TcpOpts}
To listen on both SCTP and TCP, define one transport for each.
The list of Diameter applications to which the transport should be restricted. Defaults to all applications configured on the service in question. Applications not configured on the service in question are ignored.
AVP's used to construct outgoing CER/CEA messages. Values take precedence over any specified on the service in question.
Specifying a capability as a transport option
may be particularly appropriate for Inband-Security-Id, in case
TLS is desired over TCP as implemented by
A callback invoked upon reception of CER/CEA during capabilities
exchange in order to ask whether or not the connection should
be accepted.
Applied to the relevant
Multiple
TwInit = Unsigned32()
| {M,F,A}
The RFC 3539 watchdog timer. An integer value is interpreted as the RFC's TwInit in milliseconds, a jitter of ± 2 seconds being added at each rearming of the timer to compute the RFC's Tw. An MFA is expected to return the RFC's Tw directly, with jitter applied, allowing the jitter calculation to be performed by the callback.
An integer value must be at least 6000 as required by RFC 3539. Defaults to 30000 if unspecified.
Tc = Unsigned32()
For a connecting transport, the RFC 3588 Tc timer, in milliseconds. Note that this timer determines the frequency with which a transport will attempt to establish a connection with its peer only before an initial connection is established: once there is an initial connection it's watchdog_timer that determines the frequency of reconnection attempts, as required by RFC 3539.
For a listening transport, the timer specifies the time after which a
previously connected peer will be forgotten: a connection after this time is
regarded as an initial connection rather than a reestablishment,
causing the RFC 3539 state machine to pass to state OPEN rather than
REOPEN.
Note that these semantics are not goverened by the RFC and
that a listening transport's
Defaults to 30000 for a connecting transport and 60000 for a listening transport.
Unrecognized options are silently ignored but are returned unmodified
by
An reference returned by
Add transport capability to a service.
The service will start transport processes as required in order to
establish a connection with the peer, either by connecting to the peer
(
The diameter application takes responsibility for exchanging
CER/CEA with the peer.
Upon successful completion of capabilities exchange the service
calls each relevant application module's
The returned reference uniquely identifies the transport within the scope of the service. Note that the function returns before a transport connection has been established.
It is not an error to add a transport to a service that has not yet been configured: a service can be started after configuring its transports.
Send a Diameter request message.
If there are no suitable peers, or if
There are several error cases which may prevent an
answer from being received and passed to a
If the initial encode of the outgoing request
fails, then the request process fails and
If the request is successfully encoded and sent but
the answer times out then a
If the request is successfully encoded and sent but the service in
question is stopped before an answer is received then a
If the transport connection with the peer goes down after the request
has been sent but before an answer has been received then an attempt
is made to resend the request to an alternate peer.
If no such peer is available, or if the subsequent
If an encode error takes place during
retransmission then the request process fails and
If an application callback made in processing the request fails
(pick_peer, prepare_request, prepare_retransmit,
handle_answer or handle_error) then either
Note that
Return a reasonable value for use as Origin-State-Id in outgoing messages.
The value returned is the number of seconds since 19680120T031408Z,
the first value that can be encoded as a Diameter
Remove previously added transports.
Pred = fun(transport_ref(), list()): fun(Ref, _, Opts) -> Pred(Ref, Opts) end
Pred = fun(list()): fun(_, _, Opts) -> Pred(Opts) end
Pred = transport_ref(): fun(Ref, _, _) -> Pred == Ref end
Pred = list(): fun(_, _, Opts) -> [] == Pred -- Opts end
Pred = true: fun(_, _, _) -> true end
Pred = false: fun(_, _, _) -> false end
Pred = {M,F,A}: fun(Ref, Type, Opts) -> apply(M, F, [Ref, Type, Opts | A]) end
Removing a transport causes all associated transport connections to
be broken.
A DPR message with
Disconnect-Cause
Return information about a started service.
Return a capability value as configured with
Return the list of applications as configured with
Return a tagged list of all capabilities values as configured with
Return a list containing one entry for each of the service's transport
as configured with
[[{ref,#Ref<0.0.0.93>},
{type,connect},
{options,[{transport_module,diameter_tcp},
{transport_config,[{ip,{127,0,0,1}},
{raddr,{127,0,0,1}},
{rport,3868},
{reuseaddr,true}]}]},
{watchdog,{<0.66.0>,{1346,171491,996448},okay}},
{peer,{<0.67.0>,{1346,171491,999906}}},
{apps,[{0,common}]},
{caps,[{origin_host,{"client.example.com","server.example.com"}},
{origin_realm,{"example.com","example.com"}},
{host_ip_address,{[{127,0,0,1}],[{127,0,0,1}]}},
{vendor_id,{0,193}},
{product_name,{"Client","Server"}},
{origin_state_id,{[],[]}},
{supported_vendor_id,{[],[]}},
{auth_application_id,{[0],[0]}},
{inband_security_id,{[],[0]}},
{acct_application_id,{[],[]}},
{vendor_specific_application_id,{[],[]}},
{firmware_revision,{[],[]}},
{avp,{[],[]}}]},
{port,[{owner,<0.69.0>},
{module,diameter_tcp},
{socket,{{127,0,0,1},48758}},
{peer,{{127,0,0,1},3868}},
{statistics,[{recv_oct,656},
{recv_cnt,6},
{recv_max,148},
{recv_avg,109},
{recv_dvi,19},
{send_oct,836},
{send_cnt,6},
{send_max,184},
{send_avg,139},
{send_pend,0}]}]},
{statistics,[{{{0,258,0},recv},3},
{{{0,258,1},send},3},
{{{0,257,0},recv},1},
{{{0,257,1},send},1},
{{{0,258,0},recv,{'Result-Code',2001}},3},
{{{0,280,1},recv},2},
{{{0,280,0},send},2}]}]]
Here
Note that
A listening transport presents its information slightly differently
since there may be multiple accepted connections for the same
[[{ref,#Ref<0.0.0.61>},
{type,listen},
{options,[{transport_module,diameter_tcp},
{transport_config,[{reuseaddr,true},
{ip,{127,0,0,1}},
{port,3868}]}]},
{accept,[[{watchdog,{<0.56.0>,{1346,171481,226895},okay}},
{peer,{<0.58.0>,{1346,171491,999511}}},
{apps,[{0,common}]},
{caps,[{origin_host,{"server.example.com","client.example.com"}},
{origin_realm,{"example.com","example.com"}},
{host_ip_address,{[{127,0,0,1}],[{127,0,0,1}]}},
{vendor_id,{193,0}},
{product_name,{"Server","Client"}},
{origin_state_id,{[],[]}},
{supported_vendor_id,{[],[]}},
{auth_application_id,{[0],[0]}},
{inband_security_id,{[],[]}},
{acct_application_id,{[],[]}},
{vendor_specific_application_id,{[],[]}},
{firmware_revision,{[],[]}},
{avp,{[],[]}}]},
{port,[{owner,<0.62.0>},
{module,diameter_tcp},
{socket,{{127,0,0,1},3868}},
{peer,{{127,0,0,1},48758}},
{statistics,[{recv_oct,1576},
{recv_cnt,16},
{recv_max,184},
{recv_avg,98},
{recv_dvi,26},
{send_oct,1396},
{send_cnt,16},
{send_max,148},
{send_avg,87},
{send_pend,0}]}]}],
[{watchdog,{<0.72.0>,{1346,171491,998404},initial}}]]},
{statistics,[{{{0,280,0},recv},7},
{{{0,280,1},send},7},
{{{0,258,0},send,{'Result-Code',2001}},3},
{{{0,258,1},recv},3},
{{{0,258,0},send},3},
{{{0,280,1},recv},5},
{{{0,280,0},send},5},
{{{0,257,1},recv},1},
{{{0,257,0},send},1}]}]]
The information presented here is as in the
Return a list containing one entry for every established transport
connection whose watchdog state machine is not in the
[[{ref,#Ref<0.0.0.61>},
{type,accept},
{options,[{transport_module,diameter_tcp},
{transport_config,[{reuseaddr,true},
{ip,{127,0,0,1}},
{port,3868}]}]},
{watchdog,{<0.56.0>,{1346,171481,226895},okay}},
{peer,{<0.58.0>,{1346,171491,999511}}},
{apps,[{0,common}]},
{caps,[{origin_host,{"server.example.com","client.example.com"}},
{origin_realm,{"example.com","example.com"}},
{host_ip_address,{[{127,0,0,1}],[{127,0,0,1}]}},
{vendor_id,{193,0}},
{product_name,{"Server","Client"}},
{origin_state_id,{[],[]}},
{supported_vendor_id,{[],[]}},
{auth_application_id,{[0],[0]}},
{inband_security_id,{[],[]}},
{acct_application_id,{[],[]}},
{vendor_specific_application_id,{[],[]}},
{firmware_revision,{[],[]}},
{avp,{[],[]}}]},
{port,[{owner,<0.62.0>},
{module,diameter_tcp},
{socket,{{127,0,0,1},3868}},
{peer,{{127,0,0,1},48758}},
{statistics,[{recv_oct,10124},
{recv_cnt,132},
{recv_max,184},
{recv_avg,76},
{recv_dvi,9},
{send_oct,10016},
{send_cnt,132},
{send_max,148},
{send_avg,75},
{send_pend,0}]}]},
{statistics,[{{{0,280,0},recv},62},
{{{0,280,1},send},62},
{{{0,258,0},send,{'Result-Code',2001}},3},
{{{0,258,1},recv},3},
{{{0,258,0},send},3},
{{{0,280,1},recv},66},
{{{0,280,0},send},66},
{{{0,257,1},recv},1},
{{{0,257,0},send},1}]}]]
Note that there may be multiple entries with the same
Return a
Requesting info for an unknown service causes
Return the list of started services.
Return a value for a Session-Id AVP.
The value has the form required by section 8.8 of RFC 3588. Ident should be the Origin-Host of the peer from which the message containing the returned value will be sent.
Start the diameter application.
The diameter application must be started before starting a service.
In a production system this is typically accomplished by a boot
file, not by calling
Start a diameter service.
A service defines a locally-implemented Diameter node, specifying the
capabilities to be advertised during capabilities exchange.
Transports are added to a service using
A transport can both override its service's capabilities and restrict its supported Diameter applications so "service = Diameter node as identified by Origin-Host" is not necessarily the case.
Stop the diameter application.
Stop a diameter service.
Stopping a service causes all associated transport connections to be
broken.
A DPR message with be sent as in the case of
Stopping a transport does not remove any associated transports:
Subscribe to
It is not an error to subscribe to events from a service that does not yet exist. Doing so before adding transports is required to guarantee the reception of all related events.
Unsubscribe to event messages from a service.