Provided by: erlang-manpages_20.2.2+dfsg-1ubuntu2_all bug


       diameter - Main API of the diameter application.


       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 6733.

       Basic usage consists of creating a representation of a locally implemented  Diameter  node
       and   its   capabilities   with   start_service/2,   adding   transport  capability  using
       add_transport/2 and sending Diameter requests and receiving Diameter answers with  call/4.
       Incoming  Diameter requests are communicated as callbacks to a diameter_app(3erl) callback
       modules as specified in the service configuration.

       Beware the difference between diameter (not capitalized) and Diameter  (capitalized).  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 6733.

       The diameter application must be started before calling most functions in this module.








           Types corresponding to RFC 6733 AVP Data Formats. Defined in diameter_dict(5).

         application_alias() = term():
           Name identifying a Diameter application in service  configuration.  Passed  to  call/4
           when sending requests defined by the application.

         application_module() = Mod | [Mod | ExtraArgs] | #diameter_callback{}:

         Mod = atom()
         ExtraArgs = list()

           Module  implementing  the callback interface defined in diameter_app(3erl), along with
           any extra arguments to be appended to those  documented.  Note  that  extra  arguments
           specific  to  an  outgoing request can be specified to call/4, in which case those are
           are appended to any module-specific extra arguments.

           Specifying a #diameter_callback{} record allows individual functions to be  configured
           in  place  of  the  usual  diameter_app(3erl) callbacks. See diameter_callback.erl for

           Options defining a Diameter application. Has one the following types.

           {alias, application_alias()}:
             Unique identifier for the application in the scope of the service. Defaults  to  the
             value of the dictionary option.

           {dictionary, atom()}:
             Name   of  an  encode/decode  module  for  the  Diameter  messages  defined  by  the
             application. These modules are generated from files whose format  is  documented  in

           {module, application_module()}:
             Callback  module  in  which  messages  of  the Diameter application are handled. See
             diameter_app(3erl) for the required interface and semantics.

           {state, term()}:
             Initial callback state. The prevailing state is passed  to  some  diameter_app(3erl)
             callbacks,  which  can  then  return a new state. Defaults to the value of the alias

           {call_mutates_state, true|false}:
             Whether or not the pick_peer/4  application  callback  can  modify  the  application
             state. Defaults to false.

           pick_peer/4  callbacks  are  serialized when this option is true, which is a potential
           performance bottleneck. A simple Diameter client may suffer no ill effects from  using
           mutable  state but a server or agent that responds to incoming request should probably
           avoid it.

           {answer_errors, callback|report|discard}:
             Manner in which incoming answer messages containing decode errors are handled.

             If callback then errors result in a handle_answer/4 callback in the same fashion  as
             for   handle_request/3,  with  errors  communicated  in  the  errors  field  of  the
             #diameter_packet{} passed to the callback.  If  report  then  an  answer  containing
             errors  is  discarded without a callback and a warning report is written to the log.
             If discard then  an  answer  containing  errors  is  silently  discarded  without  a
             callback.  In  both  the  report  and  discard cases the return value for the call/4
             invocation in question is as if a callback had  taken  place  and  returned  {error,

             Defaults to discard.

           {request_errors, answer_3xxx|answer|callback}:
             Manner  in  which  incoming  requests  are  handled  when  an  error other than 3007
             (DIAMETER_APPLICATION_UNSUPPORTED, which cannot be associated  with  an  application
             callback module), is detected.

             If answer_3xxx then requests are answered without a handle_request/3 callback taking
             place. If answer then even 5xxx errors are answered without a  callback  unless  the
             connection in question has configured the RFC 3588 common dictionary as noted below.
             If callback then a handle_request/3 callback always takes place and its return value
             determines the answer sent to the peer, if any.

             Defaults to answer_3xxx.

           Answers  sent  by diameter set the E-bit in the Diameter Header. Since RFC 3588 allows
           only 3xxx result codes  in  an  answer-message,  answer  has  the  same  semantics  as
           answer_3xxx    when   the   transport   in   question   has   been   configured   with
           diameter_gen_base_rfc3588 as its common dictionary. Since RFC 6733  allows  both  3xxx
           and 5xxx result codes in an answer-message, a transport with diameter_gen_base_rfc6733
           as its common dictionary does distinguish between answer_3xxx and answer.

           Options available to call/4 when sending an outgoing Diameter request. Has one of  the
           following types.

           {extra, list()}:
             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.

           {filter, peer_filter()}:
             Filter  to apply to the list of available peers before passing it to the pick_peer/4
             callback for the application in question. Multiple options are equivalent  a  single
             all filter on the corresponding list of filters. Defaults to none.

           {peer, diameter_app:peer_ref()}:
             Peer to which the request in question can be sent, preempting the selection of peers
             having advertised support for the Diameter application in question. Multiple options
             can  be  specified,  and their order is respected in the candidate lists passed to a
             subsequent pick_peer/4 callback.

           {timeout, Unsigned32()}:
             Number of milliseconds after which the request should timeout. Defaults to 5000.

             Cause call/4 to return ok as soon as the  request  in  question  has  been  encoded,
             instead of waiting for and returning the result from a subsequent handle_answer/4 or
             handle_error/4 callback.

           An invalid option will cause call/4 to fail.

           AVP values sent in outgoing CER or CEA messages during capabilities exchange.  Can  be
           configured  both on a service and a transport, values on the latter taking precedence.
           Has one of the following types.

           {'Origin-Host', DiameterIdentity()}:

           {'Origin-Realm', DiameterIdentity()}:

           {'Host-IP-Address', [Address()]}:
             An address list is available to the start function of a transport module, which  can
             return  a new list for use in the subsequent CER or CEA. Host-IP-Address need not be
             specified if the transport module  in  question  communicates  an  address  list  as
             described in diameter_transport(3erl)

           {'Vendor-Id', Unsigned32()}:

           {'Product-Name', UTF8String()}:

           {'Origin-State-Id', Unsigned32()}:
             Origin-State-Id is optional but, if configured, will be included in outgoing CER/CEA
             and DWR/DWA messages. Setting a value of 0 (zero) is equivalent  to  not  setting  a
             value,  as  documented in RFC 6733. The function origin_state_id/0 can be used as to
             retrieve a value that is computed when the diameter application is started.

           {'Supported-Vendor-Id', [Unsigned32()]}:

           {'Auth-Application-Id', [Unsigned32()]}:

           {'Inband-Security-Id', [Unsigned32()]}:
             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.

           {'Acct-Application-Id', [Unsigned32()]}:

           {'Vendor-Specific-Application-Id', [Grouped()]}:

           {'Firmware-Revision', Unsigned32()}:

           Note that each tuple communicates one or more AVP values. It is an  error  to  specify
           duplicate tuples.

         eval() = {M,F,A} | fun() | [eval() | A]:
           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) ->

           Applying an eval() E to an argument list A is meant in the sense of eval([E|A]).

         Beware  of  using  fun expressions of the form fun Name/Arity in situations in which the
         fun is not short-lived and code is  to  be  upgraded  at  runtime  since  any  processes
         retaining  such  a fun will have a reference to old code. In particular, such a value is
         typically inappropriate in configuration passed to start_service/2 or add_transport/2.

         peer_filter() = term():
           Filter passed to call/4 in order to select candidate peers for a pick_peer/4 callback.
           Has one of the following types.

             Matches  any  peer.  This  is  a convenience that provides a filter equivalent to no

             Matches only those peers whose Origin-Host has the same value as Destination-Host in
             the  outgoing  request  in  question,  or any peer if the request does not contain a
             Destination-Host AVP.

             Matches only those peers whose Origin-Realm has the same value as  Destination-Realm
             in  the  outgoing request in question, or any peer if the request does not contain a
             Destination-Realm AVP.

           {host, any|DiameterIdentity()}:
             Matches only those peers whose Origin-Host has the specified value, or all peers  if
             the atom any.

           {realm, any|DiameterIdentity()}:
             Matches only those peers whose Origin-Realm has the specified value, or all peers if
             the atom any.

           {eval, eval()}:
             Matches only those peers for which the specified eval() returns true when applied to
             the  connection's  diameter_caps  record.  Any  other  return  value or exception is
             equivalent to false.

           {neg, peer_filter()}:
             Matches only those peers not matched by the specified filter.

           {all, [peer_filter()]}:
             Matches only those peers matched by each filter in the specified list.

           {any, [peer_filter()]}:
             Matches only those peers matched by at least one filter in the specified  list.  The
             resulting  list  will be in match order, peers matching the first filter of the list
             sorting before those matched by the second, and so on.

           {first, [peer_filter()]}:
             Like any, but stops at the first filter for which there are matches,  which  can  be
             much  more  efficient  when  there are many peers. For example, the following filter
             causes only peers best matching both the host and realm filters to be presented.

           {first, [{all, [host, realm]}, realm]}

           An invalid filter is equivalent to {any,[]}, a filter that matches no peer.

         The host and realm filters cause the Destination-Host and Destination-Realm AVPs  to  be
         extracted  from  the  outgoing  request,  assuming  it  to  be  a record- or list-valued
         diameter_codec:message(), and assuming at most one of each AVP. If this is not the  case
         then  the  {host|realm,  DiameterIdentity()} filters must be used to achieve the desired
         result.  An  empty  DiameterIdentity()  (which  should  not  be  typical)  matches   all
         hosts/realms for the purposes of filtering.

         A  host  filter  is  not typically desirable when setting Destination-Host since it will
         remove peer agents from the candidates list.

         service_event()    =    #diameter_event{service     =     service_name(),     info     =
           An event message sent to processes that have subscribed to these using subscribe/1.

         service_event_info() = term():
           The info field of a service_event() record. Can have one of the following types.


             The  service  is being started or stopped. No event precedes a start event. No event
             follows a stop event, and this  event  implies  the  termination  of  all  transport

           {up, Ref, Peer, Config, Pkt}:

           {up, Ref, Peer, Config}:

           {down, Ref, Peer, Config}:

           Ref    = transport_ref()
           Peer   = diameter_app:peer()
           Config = {connect|listen, [transport_opt()]}
           Pkt    = #diameter_packet{}

             The  RFC 3539 watchdog state machine has transitioned into (up) or out of (down) the
             OKAY state. If a #diameter_packet{} is present in an up event then there has been  a
             capabilities  exchange  on  a  newly established transport connection and the record
             contains the received CER or CEA.

             Note that a single up or down  event  for  a  given  peer  corresponds  to  multiple
             peer_up/3  or  peer_down/3  callbacks,  one  for  each  of the Diameter applications
             negotiated  during  capabilities  exchange.  That   is,   the   event   communicates
             connectivity  with  the peer as a whole while the callbacks communicate connectivity
             with respect to individual Diameter applications.

           {reconnect, Ref, Opts}:

           Ref  = transport_ref()
           Opts = [transport_opt()]

             A connecting transport is attempting to establish/reestablish a transport connection
             with a peer following connect_timer or watchdog_timer expiry.

           {closed, Ref, Reason, Config}:

           Ref = transport_ref()
           Config = {connect|listen, [transport_opt()]}

             Capabilities exchange has failed. Reason can have one of the following types.

             {'CER', Result, Caps, Pkt}:

             Result = ResultCode | {capabilities_cb, CB, ResultCode|discard}
             Caps = #diameter_caps{}
             Pkt  = #diameter_packet{}
             ResultCode = integer()
             CB = eval()

               An  incoming  CER  has been answered with the indicated result code, or discarded.
               Caps contains pairs of values, for the local node and  remote  peer  respectively.
               Pkt  contains  the  CER  in  question.  In the case of rejection by a capabilities
               callback, the tuple contains the rejecting callback.

             {'CER', Caps, {ResultCode, Pkt}}:

             ResultCode = integer()
             Caps = #diameter_caps{}
             Pkt  = #diameter_packet{}

               An incoming CER contained errors and has been answered with the  indicated  result
               code.  Caps  contains  values  for  the  local  node only. Pkt contains the CER in

             {'CER', timeout}:
               An expected CER was not received within capx_timeout of connection establishment.

             {'CEA', Result, Caps, Pkt}:

             Result = ResultCode | 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
               Result  indicates  the result code sent by the peer. Caps contains pairs of values
               for the local node and remote peer. Pkt contains the CEA in question. In the  case
               of  rejection  by  a  capabilities  callback,  the  tuple  contains  the rejecting

             {'CEA', Caps, Pkt}:

             Caps = #diameter_caps{}
             Pkt  = #diameter_packet{}

               An incoming CEA contained errors and has been rejected. Caps contains only  values
               for the local node. Pkt contains the CEA in question.

             {'CEA', timeout}:
               An expected CEA was not received within capx_timeout of connection establishment.

           {watchdog, Ref, PeerRef, {From, To}, Config}:

           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.

         service_name() = term():
           Name of a service  as  passed  to  start_service/2  and  with  which  the  service  is
           identified.  There  can be at most one service with a given name on a given node. Note
           that erlang:make_ref/0 can be used to generate a service name that is somewhat unique.

           Option passed to start_service/2. Can be any capability() as well as the following.

           {application, [application_opt()]}:
             A Diameter application supported by the service.

             A service must configure one tuple for  each  Diameter  application  it  intends  to
             support.  For  an  outgoing  request,  the relevant application_alias() is passed to
             call/4, while for an incoming request the  application  identifier  in  the  message
             header   determines   the   application,  the  identifier  being  specified  in  the
             application's dictionary file.

           The capabilities advertised by a node  must  match  its  configured  applications.  In
           particular,  application  configuration  must be matched by corresponding capability()
           configuration, of *-Application-Id AVPs in particular.

           {decode_format, record | list | map | none}:
             The format of decoded messages and grouped AVPs in the msg field of  diameter_packet
             records  and  value  field  of  diameter_avp  records respectively. If record then a
             record whose definition is generated from the dictionary file in question.  If  list
             or  map then a [Name | Avps] pair where Avps is a list of AVP name/values pairs or a
             map keyed on AVP names respectively. If none then the atom-value  message  name,  or
             undefined for a Grouped AVP. See also diameter_codec:message().

             Defaults to record.

           AVPs  are decoded into a list of diameter_avp records in avps field of diameter_packet
           records independently of decode_format.

           {restrict_connections, false | node | nodes | [node()] | eval()}:
             The degree to which the service allows multiple transport connections  to  the  same
             peer, as identified by its Origin-Host at capabilities exchange.

             If  [node()]  then  a connection is rejected if another already exists on any of the
             specified nodes. Types false, node, nodes and eval() are equivalent to [], [node()],
             [node()|nodes()] and the evaluated value respectively, evaluation of each expression
             taking place whenever a new connection is to be established. Note that false  allows
             an unlimited number of connections to be established with the same peer.

             Multiple  connections  are  independent  and governed by their own peer and watchdog
             state machines.

             Defaults to nodes.

           {sequence, {H,N} | eval()}:
             A constant value H for the topmost 32-N bits of of 32-bit End-to-End and  Hop-by-Hop
             Identifiers  generated  by  the service, either explicitly or as a return value of a
             function to be evaluated at start_service/2. In  particular,  an  identifier  Id  is
             mapped to a new identifier as follows.

           (H bsl N) bor (Id band ((1 bsl N) - 1))

             Note  that  RFC 6733 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
             appropriate  values  of  N:  at  a  rate  of R requests per second, an N-bit counter
             traverses all of its values in (1 bsl N) div (R*60) minutes, so the bound is  4*R*60
             =< 1 bsl N.

             N  must  lie in the range 0..32 and H must be a non-negative integer less than 1 bsl

             Defaults to {0,32}.

           Multiple Erlang nodes implementing the same Diameter node should  be  configured  with
           different  sequence  masks  to ensure that each node uses a unique range of End-to-End
           and Hop-by-Hop Identifiers for outgoing requests.

           {share_peers, boolean() | [node()] | eval()}:
             Nodes  to  which  peer  connections  established  on  the  local  Erlang  node   are
             communicated.  Shared peers become available in the remote candidates list passed to
             pick_peer/4 callbacks on remote nodes whose services are configured to use them: see
             use_shared_peers below.

             If  false  then  peers  are  not  shared. If [node()] then peers are shared with the
             specified list of nodes. If eval() then peers are shared with the nodes returned  by
             the  specified function, evaluated whenever a peer connection becomes available or a
             remote service requests information about  local  connections.  The  value  true  is
             equivalent  to  fun  erlang:nodes/0.  The  value  node()  in a list is ignored, so a
             collection of services can all be configured to share with the same list of nodes.

             Defaults to false.

           Peers are only shared with services of the  same  name  for  the  purpose  of  sending
           outgoing  requests.  Since the value of the application_opt() alias, passed to call/4,
           is the handle for identifying a peer as a  suitable  candidate,  services  that  share
           peers  must use the same aliases to identify their supported applications. They should
           typically also configure identical capabilities(), since by sharing  peer  connections
           they  are  distributing  the  implementation of a single Diameter node across multiple
           Erlang nodes.

           {strict_arities, boolean() | encode | decode}:
             Whether or not to require that the number of AVPs in a message or grouped AVP  agree
             with  those  specified  in  the  dictionary  in  question  when  passing messages to
             diameter_app(3erl) callbacks. If true then mismatches in an outgoing messages  cause
             message  encoding  to  fail, while mismatches in an incoming message are reported as
             5005/5009 errors in the  errors  field  of  the  diameter_packet  record  passed  to
             handle_request/3  or  handle_answer/4  callbacks.  If  false  then  neither error is
             enforced/detected. If encode or decode then errors  are  only  enforced/detected  on
             outgoing or incoming messages respectively.

             Defaults to true.

           Disabling  arity  checks affects the form of messages at encode/decode. In particular,
           decoded AVPs are represented as lists of values, regardless of the  AVP's  arity  (ie.
           expected number in the message/AVP grammar in question), and values are expected to be
           supplied as lists at encode. This  differs  from  the  historic  decode  behaviour  of
           representing AVPs of arity 1 as bare values, not wrapped in a list.

           {string_decode, boolean()}:
             Whether  or  not  to  decode  AVPs  of  type  OctetString()  and  its  derived types
             DiameterIdentity(),    DiameterURI(),    IPFilterRule(),    QoSFilterRule(),     and
             UTF8String().  If  true  then  AVPs of these types are decoded to string(). If false
             then values are retained as binary().

             Defaults to true.

           This option should be set to false since a sufficiently malicious peer  can  otherwise
           cause large amounts of memory to be consumed when decoded Diameter messages are passed
           between processes. The default value is for backwards compatibility.

           {traffic_counters, boolean()}:
             Whether  or  not  to  count   application-specific   messages;   those   for   which
             diameter_app(3erl)  callbacks  take  place.  If  false then only messages handled by
             diameter itself are counted: CER/CEA, DWR/DWA, DPR/DPA.

             Defaults to true.

           Disabling counters is a performance improvement, but means that the  omitted  counters
           are not returned by service_info/2.

           {use_shared_peers, boolean() | [node()] | eval()}:
             Nodes from which communicated peers are made available in the remote candidates list
             of pick_peer/4 callbacks.

             If false then remote peers are not used.  If  [node()]  then  only  peers  from  the
             specified  list  of  nodes  are  used.  If  eval()  then  only peers returned by the
             specified function are  used,  evaluated  whenever  a  remote  service  communicates
             information  about an available peer connection. The value true is equivalent to fun
             erlang:nodes/0. The value node() in a list is ignored.

             Defaults to false.

           A service that does not use shared peers will always pass the empty list as the second
           argument of pick_peer/4 callbacks.

           Sending  a  request  over  a  peer  connection on a remote node is less efficient than
           sending it over a  local  connection.  It  may  be  preferable  to  make  use  of  the
           service_opt()  restrict_connections  and  maintain a dedicated connection on each node
           from which requests are sent.

             Any transport option except applications  or  capabilities.  Used  as  defaults  for
             transport   configuration,   values  passed  to  add_transport/2  overriding  values
             configured on the service.

           Option passed to add_transport/2. Has one of the following types.

           {applications, [application_alias()]}:
             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.

           The capabilities advertised by a node  must  match  its  configured  applications.  In
           particular,  setting  applications  on  a  transport  typically  implies having to set
           matching *-Application-Id AVPs in a capabilities() tuple.

           {avp_dictionaries, [module()]}:
             A list of alternate dictionary modules with which to encode/decode AVPs that are not
             defined  by  the dictionary of the application in question. At decode, such AVPs are
             represented as diameter_avp records in the 'AVP'  field  of  a  decoded  message  or
             Grouped  AVP,  the  first  alternate  that  succeeds in decoding the AVP setting the
             record's value field. At encode, values in an  'AVP'  list  can  be  passed  as  AVP
             name/value 2-tuples, and it is an encode error for no alternate to define the AVP of
             such a tuple.

             Defaults to the empty list.

           The motivation for alternate dictionaries is RFC 7683,  Diameter  Overload  Indication
           Conveyance  (DOIC),  which  defines  AVPs  to be piggybacked onto existing application
           messages rather than defining an application  of  its  own.  The  DOIC  dictionary  is
           provided  by  the  diameter  application,  as  module  diameter_gen_doic_rfc7683,  but
           alternate dictionaries can be used to encode/decode any set of AVPs not  known  to  an
           application dictionary.

           {capabilities, [capability()]}:
             AVPs  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

           {capabilities_cb, eval()}:
             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 transport_ref()
             and #diameter_caps{} record of the connection.

             The return value can have one of the following types.

               Accept the connection.

               Causes an incoming CER to be answered with the specified Result-Code.

               Causes an incoming CER to be discarded without CEA being sent.

               Equivalent to returning 3010, DIAMETER_UNKNOWN_PEER.

             Returning anything but ok  or  a  2xxx  series  result  code  causes  the  transport
             connection to be broken. Multiple capabilities_cb options can be specified, in which
             case the corresponding callbacks are applied until either all return ok or one  does

           {capx_timeout, Unsigned32()}:
             Number  of  milliseconds  after  which  a  transport  process  having an established
             transport connection will  be  terminated  if  the  expected  capabilities  exchange
             message  (CER or CEA) is not received from the peer. For a connecting transport, the
             timing of connection attempts is governed by connect_timer or watchdog_timer expiry.
             For a listening transport, the peer determines the timing.

             Defaults to 10000.

           {connect_timer, Tc}:

           Tc = Unsigned32()

             For  a  connecting  transport,  the  RFC  6733 Tc timer, in milliseconds. This timer
             determines the frequency with which a transport attempts  to  establish  an  initial
             connection  with  its  peer  following  transport  configuration.  Once  an  initial
             connection  has  been  established,  watchdog_timer  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 reestablishment, causing the RFC 3539 state machine
             to pass to state OKAY rather than REOPEN. Note that these semantics are not governed
             by the RFC and that a listening transport's connect_timer should be greater than its
             peer's Tw plus jitter.

             Defaults to 30000 for a connecting transport and 60000 for a listening transport.

           {disconnect_cb, eval()}:
             Callback  invoked  prior  to  terminating  the  transport  process  of  a  transport
             connection  having watchdog state OKAY. Applied to application|service|transport and
             the transport_ref() and diameter_app:peer() in question: application indicates  that
             the  diameter  application is being stopped, service that the service in question is
             being stopped by stop_service/1, and transport that the  transport  in  question  is
             being removed by remove_transport/2.

             The return value can have one of the following types.

             {dpr, [option()]}:
               Send  Disconnect-Peer-Request  to the peer, the transport process being terminated
               following reception of Disconnect-Peer-Answer or timeout. An option() can  be  one
               of the following.

               {cause, 0|rebooting|1|busy|2|goaway}:
                 Disconnect-Cause   to   send,  REBOOTING,  BUSY  and  DO_NOT_WANT_TO_TALK_TO_YOU
                 respectively. Defaults to rebooting for  Reason=service|application  and  goaway
                 for Reason=transport.

               {timeout, Unsigned32()}:
                 Number  of  milliseconds  after which the transport process is terminated if DPA
                 has not been received. Defaults to the value of dpa_timeout.

               Equivalent to {dpr, []}.

               Terminate the transport process without Disconnect-Peer-Request being sent to  the

               Equivalent to not having configured the callback.

             Multiple  disconnect_cb  options  can  be specified, in which case the corresponding
             callbacks are applied until one of them returns  a  value  other  than  ignore.  All
             callbacks returning ignore is equivalent to not having configured them.

             Defaults to a single callback returning dpr.

           {dpa_timeout, Unsigned32()}:
             Number of milliseconds after which a transport connection is terminated following an
             outgoing DPR if DPA is not received.

             Defaults to 1000.

           {dpr_timeout, Unsigned32()}:
             Number of milliseconds after which a transport connection is terminated following an
             incoming DPR if the peer does not close the connection.

             Defaults to 5000.

           {incoming_maxlen, 0..16777215}:
             Bound  on  the expected size of incoming Diameter messages. Messages larger than the
             specified number of bytes are discarded.

             Defaults to 16777215, the maximum value of the 24-bit  Message  Length  field  in  a
             Diameter Header.

           {length_errors, exit|handle|discard}:
             How  to  deal  with  errors in the Message Length field of the Diameter Header in an
             incoming message. An error in this context is that the length is  not  at  least  20
             bytes  (the  length  of a Header), is not a multiple of 4 (a valid length) or is not
             the length of the message in question, as  received  over  the  transport  interface
             documented in diameter_transport(3erl).

             If  exit then the transport process in question exits. If handle then the message is
             processed as usual, a resulting handle_request/3 or handle_answer/4 callback (if one
             takes place) indicating the 5015 error (DIAMETER_INVALID_MESSAGE_LENGTH). If discard
             then the message in question is silently discarded.

             Defaults to exit.

           The default value reflects the fact that a  transport  module  for  a  stream-oriented
           transport like TCP may not be able to recover from a message length error since such a
           transport must use the Message Length header to divide the incoming byte  stream  into
           individual  Diameter  messages.  An  invalid  length leaves it with no reliable way to
           rediscover message boundaries, which may result in the failure of subsequent messages.
           See diameter_tcp(3erl) for the behaviour of that module.

           {pool_size, pos_integer()}:
             Number  of  transport  processes to start. For a listening transport, determines the
             size of the pool of accepting transport processes, a larger number  being  desirable
             for  processing  multiple  concurrent  peer  connection  attempts.  For a connecting
             transport, determines the number of connections to the peer in question that will be
             attempted  to  be establshed: the service_opt(): restrict_connections should also be
             configured on the service in question to allow  multiple  connections  to  the  same

           {spawn_opt, [term()]}:
             Options  passed  to  erlang:spawn_opt/2  when  spawning  a  process  for an incoming
             Diameter request. Options monitor and link are ignored.

             Defaults to the empty list.

           {strict_capx, boolean()]}:
             Whether or not  to  enforce  the  RFC  6733  requirement  that  any  message  before
             capabilities  exchange  should  close  the peer connection. If false then unexpected
             messages are discarded.

             Defaults to true. Changing this results in non-standard behaviour, but can be useful
             in case peers are known to be behave badly.

           {strict_mbit, boolean()}:
             Whether  or  not  to  regard  an AVP setting the M-bit as erroneous when the command
             grammar in question does not explicitly allow the AVP. If true then  such  AVPs  are
             regarded  as  5001  errors,  DIAMETER_AVP_UNSUPPORTED.  If  false  then the M-bit is
             ignored and policing it becomes the receiver's responsibility.

             Defaults to true.

           RFC 6733 is unclear about the semantics of the  M-bit.  One  the  one  hand,  the  CCF
           specification  in  section  3.2  documents  AVP  in  a  command grammar as meaning any
           arbitrary AVP; on the other hand, 1.3.4 states that AVPs setting the M-bit  cannot  be
           added  to  an  existing  command: the modified command must instead be placed in a new
           Diameter application.

           The reason for the latter is  presumably  interoperability:  allowing  arbitrary  AVPs
           setting  the  M-bit  in  a  command makes its interpretation implementation-dependent,
           since there's no guarantee that all implementations will understand the  same  set  of
           arbitrary  AVPs  in  the  context  of  a given command. However, interpreting AVP in a
           command grammar as any AVP, regardless of M-bit, renders 1.3.4 meaningless, since  the
           receiver  can  simply  ignore  any  AVP  it  thinks  isn't relevant, regardless of the
           sender's intent.

           Beware of confusing mandatory in the sense of the M-bit with mandatory in the sense of
           the  command  grammar.  The  former  is  a  semantic  requirement:  that  the receiver
           understand the semantics of the AVP in the  context  in  question.  The  latter  is  a
           syntactic requirement: whether or not the AVP must occur in the message in question.

           {transport_config, term()}:

           {transport_config, term(), Unsigned32() | infinity}:
             Term  passed as the third argument to the start/3 function of the relevant transport
             module in order to start a transport process. Defaults to the empty list.

             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.

           {transport_module, atom()}:
             Module  implementing  a  transport  process  as defined in diameter_transport(3erl).
             Defaults to diameter_tcp.

             Multiple transport_module and transport_config options are  allowed.  The  order  of
             these  is significant in this case (and only in this case), a transport_module being
             paired with the first transport_config following it in  the  options  list,  or  the
             default  value for trailing modules. Transport starts will be attempted with each of
             the modules in order until one establishes a  connection  within  the  corresponding
             timeout (see below) or all fail.

           {watchdog_config, [{okay|suspect, non_neg_integer()}]}:
             Configuration  that alters the behaviour of the watchdog state machine. On key okay,
             the non-negative number of answered DWR messages before transitioning from REOPEN to
             OKAY. On key suspect, the number of watchdog timeouts before transitioning from OKAY
             to SUSPECT when DWR is unanswered, or 0 to not make the transition.

             Defaults to [{okay, 3}, {suspect,  1}].  Not  specifying  a  key  is  equivalent  to
             specifying the default value for that key.

           The  default  value  is  as  required by RFC 3539: changing it results in non-standard
           behaviour that should only be used to simulate misbehaving nodes during test.

           {watchdog_timer, TwInit}:

           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.

           Unrecognized   options   are   silently   ignored   but  are  returned  unmodified  by
           service_info/2  and  can  be  referred   to   in   predicate   functions   passed   to

         transport_ref() = reference():
           Reference returned by add_transport/2 that identifies the configuration.


       add_transport(SvcName, {connect|listen, [Opt]}) -> {ok, Ref} | {error, Reason}


                 SvcName = service_name()
                 Opt = transport_opt()
                 Ref = transport_ref()
                 Reason = term()

              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  (connect)  or  by
              accepting incoming connection requests (listen). A connecting transport establishes
              transport connections with at most one peer,  an  listening  transport  potentially
              with many.

              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  peer_up/3  callback  after  which  the  caller  can exchange
              Diameter messages with the peer over the transport. In  addition  to  CER/CEA,  the
              service  takes responsibility for the handling of DWR/DWA and required by RFC 3539,
              as well as for DPR/DPA.

              The returned reference uniquely identifies the transport within the  scope  of  the
              service.  Note  that  the  function  returns before a transport connection has been

              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.

       call(SvcName, App, Request, [Opt]) -> Answer | ok | {error, Reason}


                 SvcName = service_name()
                 App = application_alias()
                 Request = diameter_codec:message()
                 Answer = term()
                 Opt = call_opt()

              Send a Diameter request message.

              App  specifies  the  Diameter  application  in  which  the  request  is defined and
              callbacks to the corresponding callback module will follow as described  below  and
              in  diameter_app(3erl).  Unless  the  detach  option is specified, the call returns
              either when an answer message is received from the peer or an error occurs. In  the
              answer  case, the return value is as returned by a handle_answer/4 callback. In the
              error case, whether or not the error is returned directly by  diameter  or  from  a
              handle_error/4  callback  depends  on  whether  or  not  the  outgoing  request  is
              successfully encoded for transmission to  the  peer,  the  cases  being  documented

              If  there are no suitable peers, or if pick_peer/4 rejects them by returning false,
              then {error,no_connection} is returned. Otherwise  pick_peer/4  is  followed  by  a
              prepare_request/3 callback, the message is encoded and then sent.

              There  are  several error cases which may prevent an answer from being received and
              passed to a handle_answer/4 callback:

                * If the initial encode of the outgoing request fails, then the  request  process
                  fails and {error,encode} is returned.

                * If the request is successfully encoded and sent but the answer times out then a
                  handle_error/4 callback takes place with Reason = timeout.

                * If the request is successfully encoded and sent but the service in question  is
                  stopped before an answer is received then a handle_error/4 callback takes place
                  with Reason = cancel.

                * 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  pick_peer/4  callback rejects the candidates, then a handle_error/4
                  callback takes place with Reason = failover. If  a  peer  is  selected  then  a
                  prepare_retransmit/3  callback  takes  place, after which the semantics are the
                  same as following an initial prepare_request/3 callback.

                * If an encode error takes place during retransmission then the  request  process
                  fails and {error,failure} is returned.

                * If  an  application  callback  made in processing the request fails (pick_peer,
                  prepare_request, prepare_retransmit, handle_answer or handle_error) then either
                  {error,encode} or {error,failure} is returned depending on whether or not there
                  has been an attempt to send the request over the transport.

              Note that {error,encode} is the only return value which guarantees that the request
              has not been sent over the transport connection.

       origin_state_id() -> Unsigned32()

              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 Time(), at the time the diameter application  was

       remove_transport(SvcName, Pred) -> ok | {error, Reason}


                 SvcName = service_name()
                 Pred = Fun | MFA | transport_ref() | list() | true | false

                 Fun = fun((transport_ref(), connect|listen, list()) -> boolean())
                  | fun((transport_ref(), list()) -> boolean())
                  | fun((list()) -> boolean())
                 MFA = {atom(), atom(), list()}
                 Reason = term()

              Remove previously added transports.

              Pred  determines  which  transports  to  remove. An arity-3-valued Pred removes all
              transports for which Pred(Ref, Type, Opts) returns true, where Type and Opts are as
              passed  to  add_transport/2  and  Ref is as returned by it. The remaining forms are
              equivalent to an arity-3 fun as follows.

              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 the corresponding transport processes to be terminated.
              Whether  or  not  a  DPR  message  is  sent  to  a  peer  is controlled by value of
              disconnect_cb configured on the transport.

       service_info(SvcName, Info) -> term()


                 SvcName = service_name()
                 Info = Item | [Info]
                 Item = atom()

              Return information about a started service. Requesting info for an unknown  service
              causes undefined to be returned. Requesting a list of items causes a tagged list to
              be returned.

              Item can be one of the following.












                  Return a capability value as configured with start_service/2.

                  Return the list of applications as configured with start_service/2.

                  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 add_transport/2. Each entry is a tagged  list  containing  both
                  configuration  and  information  about established peer connections. An example
                  return value with for a client service  with  Origin-Host  ""
                  configured with a single transport connected to "" might look
                  as follows.


                  Here ref is a transport_ref() and  options  the  corresponding  transport_opt()
                  list  passed  to  add_transport/2.  The  watchdog  entry  shows  the state of a
                  connection's RFC 3539 watchdog state machine. The  peer  entry  identifies  the
                  diameter_app:peer_ref()  for which there will have been peer_up/3 callbacks for
                  the Diameter applications identified  by  the  apps  entry,  common  being  the
                  application_alias().  The  caps  entry  identifies the capabilities sent by the
                  local node and received from the peer during capabilities  exchange.  The  port
                  entry  displays  socket-level  information  about the transport connection. The
                  statistics   entry   presents   Diameter-level   counters,   an   entry    like
                  {{{0,280,1},recv},2}  saying  that  the  client  has  received  2 DWR messages:
                  {0,280,1} = {Application_Id, Command_Code, R_Flag}.

                  Note that watchdog, peer, apps, caps and port entries  depend  on  connectivity
                  with  the  peer  and  may  not  be present. Note also that the statistics entry
                  presents values accumulated during the lifetime of the transport configuration.

                  A listening transport presents its information slightly differently since there
                  may  be  multiple  accepted  connections  for  the  same  transport_ref().  The
                  transport info returned by a server with a single client connection might  look
                  as follows.


                  The information presented here is as in the connect case except that the client
                  connections are grouped under an accept tuple.

                  Whether or not the transport_opt() pool_size has been  configured  affects  the
                  format  of  the  listing  in  the case of a connecting transport, since a value
                  greater  than  1  implies   multiple   transport   processes   for   the   same
                  transport_ref(),  as  in the listening case. The format in this case is similar
                  to the listening case, with a pool tuple in place of an accept tuple.

                  Return a list containing one entry for every established  transport  connection
                  whose  watchdog  state machine is not in the down state. This is a flat view of
                  transport info which lists only active connections and for which Diameter-level
                  statistics are accumulated only for the lifetime of the transport connection. A
                  return value for the server above might look as follows.


                  Note that there may be multiple entries with  the  same  ref,  in  contrast  to
                  transport info.

                  Return a {{Counter, Ref}, non_neg_integer()} list of counter values. Ref can be
                  either a transport_ref() or a diameter_app:peer_ref(). Entries for  the  latter
                  are  folded  into  corresponding  entries for the former as peer connections go
                  down. Entries for both are removed at  remove_transport/2.  The  Diameter-level
                  statistics  returned  by  transport  and  connections info are based upon these

                  Return transport configuration associated with a  single  peer,  as  passed  to
                  add_transport/2.  The  returned list is empty if the peer is unknown. Otherwise
                  it contains the ref, type and options tuples as in  transport  and  connections
                  info above. For example:


       services() -> [SvcName]


                 SvcName = service_name()

              Return the list of started services.

       session_id(Ident) -> OctetString()


                 Ident = DiameterIdentity()

              Return a value for a Session-Id AVP.

              The  value  has  the  form required by section 8.8 of RFC 6733. Ident should be the
              Origin-Host of the peer from which the message containing the returned  value  will
              be sent.

       start() -> ok | {error, Reason}

              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/0

       start_service(SvcName, Options) -> ok | {error, Reason}


                 SvcName = service_name()
                 Options = [service_opt()]
                 Reason = term()

              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 add_transport/2.

              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() -> ok | {error, Reason}

              Stop the diameter application.

       stop_service(SvcName) -> ok | {error, Reason}


                 SvcName = service_name()
                 Reason = term()

              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 remove_transport/2.

              Stopping a service does not remove any  associated  transports:  remove_transport/2
              must be called to remove transport configuration.

       subscribe(SvcName) -> true


                 SvcName = service_name()

              Subscribe to service_event() messages from a service.

              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
              transport-related events.

       unsubscribe(SvcName) -> true


                 SvcName = service_name()

              Unsubscribe to event messages from a service.


       diameter_app(3erl), diameter_transport(3erl), diameter_dict(5)