Provided by: erlang-manpages_22.0.7+dfsg-1_all bug

NAME

       diameter_app - Callback module of a Diameter application.

DESCRIPTION

       A  diameter service as started by diameter:start_service/2 configures one of more Diameter
       applications, each of whose configuration  specifies  a  callback  that  handles  messages
       specific  to  the  application.  The messages and AVPs of the application are defined in a
       dictionary file whose format is documented in diameter_dict(5) while the  callback  module
       is  documented  here.  The  callback  module  implements the Diameter application-specific
       functionality of a service.

       A callback module must export  all  of  the  functions  documented  below.  The  functions
       themselves are of three distinct flavours:

         * peer_up/3  and  peer_down/3  signal  the  attainment  or  loss  of connectivity with a
           Diameter peer.

         * pick_peer/4,    prepare_request/3,    prepare_retransmit/3,    handle_answer/4     and
           handle_error/4 are (or may be) called as a consequence of a call to diameter:call/4 to
           send an outgoing Diameter request message.

         * handle_request/3 is called in response to an incoming Diameter request message.

       The arities for the the callback functions here assume no extra arguments.  All  functions
       will  also  be  passed any extra arguments configured with the callback module itself when
       calling diameter:start_service/2 and, for the call-specific callbacks, any extra arguments
       passed to diameter:call/4.

DATA TYPES

         capabilities() = #diameter_caps{}:
           A  record containing the identities of the local Diameter node and the remote Diameter
           peer having an established transport  connection,  as  well  as  the  capabilities  as
           determined  by capabilities exchange. Each field of the record is a 2-tuple consisting
           of values for the (local) host and (remote) peer. Optional or possibly multiple values
           are encoded as lists of values, mandatory values as the bare value.

         message() = diameter_codec:message():
           The representation of a Diameter message as passed to diameter:call/4 or returned from
           a handle_request/3 callback.

         packet() = diameter_codec:packet():
           A container  for  incoming  and  outgoing  Diameter  messages  that's  passed  through
           encode/decode  and  transport.  Fields  should  not  be set in return values except as
           documented.

         peer_ref() = term():
           A term identifying a transport connection with a Diameter peer.

         peer() = {peer_ref(), capabilities()}:
           A tuple representing a Diameter peer connection.

         state() = term():
           The state maintained by the application callback functions peer_up/3, peer_down/3  and
           (optionally)   pick_peer/4.   The   initial   state  is  configured  in  the  call  to
           diameter:start_service/2 that  configures  the  application  on  a  service.  Callback
           functions  returning  a state are evaluated in a common service-specific process while
           those not returning state are evaluated in a request-specific process.

EXPORTS

       Mod:peer_up(SvcName, Peer, State) -> NewState

              Types:

                 SvcName = diameter:service_name()
                 Peer = peer()
                 State = NewState = state()

              Invoked to signal the availability of a peer connection on the local  Erlang  node.
              In  particular,  capabilities  exchange with the peer has indicated support for the
              application in question, the RFC 3539 watchdog state machine for the connection has
              reached state OKAY and Diameter messages can be both sent and received.

          Note:
              A  watchdog  state  machine  can  reach state OKAY from state SUSPECT without a new
              capabilities exchange taking place. A new transport  connection  (and  capabilities
              exchange) results in a new peer_ref().

          Note:
              There  is  no  requirement  that  a  callback  return  before incoming requests are
              received: handle_request/3 callbacks must be handled independently of peer_up/3 and
              peer_down/3.

       Mod:peer_down(SvcName, Peer, State) -> NewState

              Types:

                 SvcName = diameter:service_name()
                 Peer = peer()
                 State = NewState = state()

              Invoked  to  signal  that  a  peer connection on the local Erlang node is no longer
              available following a previous call to peer_up/3. In particular, that the RFC  3539
              watchdog  state machine for the connection has left state OKAY and the peer will no
              longer be a candidate in pick_peer/4 callbacks.

       Mod:pick_peer(LocalCandidates, RemoteCandidates, SvcName, State) -> Selection | false

              Types:

                 LocalCandidates = RemoteCandidates = [peer()]
                 SvcName = diameter:service_name()
                 State = NewState = state()
                 Selection = {ok, Peer} | {Peer, NewState}
                 Peer = peer() | false

              Invoked as a consequence of a call to diameter:call/4 to select a destination  peer
              for an outgoing request. The return value indicates the selected peer.

              The  candidate  lists contain only those peers that have advertised support for the
              Diameter application in question during capabilities exchange,  that  have  not  be
              excluded by a filter option in the call to diameter:call/4 and whose watchdog state
              machine is in the OKAY state. The order of the elements is unspecified except  that
              any  peers  whose Origin-Host and Origin-Realm matches that of the outgoing request
              (in the sense of a {filter, {all, [host, realm]}} option to  diameter:call/4)  will
              be  placed  at the head of the list. LocalCandidates contains peers whose transport
              process resides on the local Erlang node while RemoteCandidates contains peers that
              have been communicated from other nodes by services of the same name.

              A  callback  that returns a peer() will be followed by a prepare_request/3 callback
              and,  if  the  latter  indicates  that  the  request  should  be  sent,  by  either
              handle_answer/4  or handle_error/4 depending on whether or not an answer message is
              received  from   the   peer.   If   the   transport   becomes   unavailable   after
              prepare_request/3  then a new pick_peer/4 callback may take place to failover to an
              alternate   peer,   after   which   prepare_retransmit/3   takes   the   place   of
              prepare_request/3   in  resending  the  request.  There  is  no  guarantee  that  a
              pick_peer/4 callback to select an alternate peer will be followed by any additional
              callbacks  since a retransmission to an alternate peer is abandoned if an answer is
              received from a previously selected peer.

              The return values false  and  {false,  State}  (that  is,  NewState  =  State)  are
              equivalent, as are {ok, Peer} and {Peer, State}.

          Note:
              The  diameter:service_opt()  use_shared_peers  determines  whether or not a service
              uses peers shared from other nodes. If not then RemoteCandidates is the empty list.

          Warning:
              The return value {Peer, NewState} is only allowed if the  Diameter  application  in
              question  was  configured  with the diameter:application_opt() {call_mutates_state,
              true}. Otherwise, the State argument is always the initial value as  configured  on
              the  application,  not  any subsequent value returned by a peer_up/3 or peer_down/3
              callback.

       Mod:prepare_request(Packet, SvcName, Peer) -> Action

              Types:

                 Packet = packet()
                 SvcName = diameter:service_name()
                 Peer = peer()
                 Action = Send | Discard | {eval_packet, Action, PostF}
                 Send = {send, packet() | message()}
                 Discard = {discard, Reason} | discard
                 PostF = diameter:eval()}

              Invoked to return a request for encoding and transport. Allows the  sender  to  use
              the   selected   peer's   capabilities   to   modify  the  outgoing  request.  Many
              implementations may simply want to return {send, Packet}

              A returned packet() should set the request to be encoded in its msg field  and  can
              set the transport_data field in order to pass information to the transport process.
              Extra arguments passed to diameter:call/4 can be used to communicate transport  (or
              any other) data to the callback.

              A  returned  packet()  can  set the header field to a #diameter_header{} to specify
              values that should be preserved in the outgoing  request,  values  otherwise  being
              those  in  the  header  record  contained in Packet. A returned length, cmd_code or
              application_id is ignored.

              A returned PostF will be evaluated  on  any  encoded  #diameter_packet{}  prior  to
              transmission,  the  bin  field  containing  the encoded binary. The return value is
              ignored.

              Returning  {discard,  Reason}  causes  the  request   to   be   aborted   and   the
              diameter:call/4  for  which the callback has taken place to return {error, Reason}.
              Returning discard is equivalent to returning {discard, discarded}.

       Mod:prepare_retransmit(Packet, SvcName, Peer) -> Action

              Types:

                 Packet = packet()
                 SvcName = diameter:service_name()
                 Peer = peer()
                 Action = Send | Discard | {eval_packet, Action, PostF}
                 Send = {send, packet() | message()}
                 Discard = {discard, Reason} | discard
                 PostF = diameter:eval()}

              Invoked to return a request for encoding and retransmission. Has the same  role  as
              prepare_request/3  in  the case that a peer connection is lost an an alternate peer
              selected but the argument packet() is as returned by the initial prepare_request/3.

              Returning {discard, Reason} causes the request to be aborted and  a  handle_error/4
              callback  to  take  place  with  Reason  as  initial argument. Returning discard is
              equivalent to returning {discard, discarded}.

       Mod:handle_answer(Packet, Request, SvcName, Peer) -> Result

              Types:

                 Packet = packet()
                 Request = message()
                 SvcName = diameter:service_name()
                 Peer = peer()
                 Result = term()

              Invoked when an answer message is  received  from  a  peer.  The  return  value  is
              returned from diameter:call/4 unless the detach option was specified.

              The decoded answer record and undecoded binary are in the msg and bin fields of the
              argument packet() respectively. Request is the  outgoing  request  message  as  was
              returned from prepare_request/3 or prepare_retransmit/3.

              For  any  given  call  to  diameter:call/4  there  is  at  most one handle_answer/4
              callback: any duplicate answer (due to retransmission or otherwise)  is  discarded.
              Similarly, only one of handle_answer/4 or handle_error/4 is called.

              By  default,  an incoming answer message that cannot be successfully decoded causes
              the request process to fail, causing diameter:call/4  to  return  {error,  failure}
              unless  the  detach option was specified. In particular, there is no handle_error/4
              callback in this case. The diameter:application_opt() answer_errors can be  set  to
              change this behaviour.

       Mod:handle_error(Reason, Request, SvcName, Peer) -> Result

              Types:

                 Reason = timeout | failover | term()
                 Request = message()
                 SvcName = diameter:service_name()
                 Peer = peer()
                 Result = term()

              Invoked when an error occurs before an answer message is received in response to an
              outgoing request. The return value is  returned  from  diameter:call/4  unless  the
              detach option was specified.

              Reason  timeout  indicates  that an answer message has not been received within the
              time  specified  with  the  corresponding  diameter:call_opt().   Reason   failover
              indicates  that  the transport connection to the peer to which the request has been
              sent has become unavailable and that not alternate peer was not selected.

       Mod:handle_request(Packet, SvcName, Peer) -> Action

              Types:

                 Packet = packet()
                 SvcName = term()
                 Peer = peer()
                 Action = Reply | {relay, [Opt]} | discard | {eval|eval_packet, Action, PostF}
                 Reply = {reply, packet() | message()} | {answer_message,  3000..3999|5000..5999}
                 | {protocol_error, 3000..3999}
                 Opt = diameter:call_opt()
                 PostF = diameter:eval()

              Invoked  when  a  request message is received from a peer. The application in which
              the callback  takes  place  (that  is,  the  callback  module  as  configured  with
              diameter:start_service/2) is determined by the Application Identifier in the header
              of  the  incoming  request  message,  the  selected  module  being  the  one  whose
              corresponding  dictionary  declares  itself  as  defining either the application in
              question or the Relay application.

              The argument packet() has the following signature.

              #diameter_packet{header = #diameter_header{},
                               avps   = [#diameter_avp{}],
                               msg    = record() | undefined,
                               errors = [Unsigned32() | {Unsigned32(), #diameter_avp{}}],
                               bin    = binary(),
                               transport_data = term()}

              The msg field will be undefined in case the request has been received in the  relay
              application.  Otherwise it contains the record representing the request as outlined
              in diameter_dict(5).

              The errors field  specifies  any  results  codes  identifying  errors  found  while
              decoding  the  request.  This  is  used  to  set Result-Code and/or Failed-AVP in a
              returned answer unless the callback returns a #diameter_packet{} whose errors field
              is  set  to  either  a  non-empty  list of its own, in which case this list is used
              instead, or the atom false to disable any setting of  Result-Code  and  Failed-AVP.
              Note that the errors detected by diameter are of the 3xxx and 5xxx series, Protocol
              Errors and Permanent Failures respectively. The errors list is empty if the request
              has been received in the relay application.

              The  transport_data  field contains an arbitrary term passed into diameter from the
              transport module in question, or the atom undefined if the transport  specified  no
              data.  The  term is preserved if a message() is returned but must be set explicitly
              in a returned packet().

              The semantics of each of the possible return values are as follows.

                {reply, packet() | message()}:
                  Send the specified answer message to the peer. In the case of a  packet(),  the
                  message to be sent must be set in the msg field and the header field can be set
                  to a #diameter_header{} to specify values  that  should  be  preserved  in  the
                  outgoing answer, appropriate values otherwise being set by diameter.

                {answer_message, 3000..3999|5000..5999}:
                  Send  an  answer  message  to  the  peer  containing the specified Result-Code.
                  Equivalent to

                {reply, ['answer-message' | Avps]

                  where Avps sets the Origin-Host, Origin-Realm, the  specified  Result-Code  and
                  (if  the  request  contained  one)  Session-Id AVPs, and possibly Failed-AVP as
                  described below.

                  Returning a value other than 3xxx or 5xxx will cause  the  request  process  in
                  question  to  fail,  as  will  returning a 5xxx value if the peer connection in
                  question  has  been  configured   with   the   RFC   3588   common   dictionary
                  diameter_gen_base_rfc3588.  (Since  RFC  3588  only  allows  3xxx  values in an
                  answer-message.)

                  When returning 5xxx, Failed-AVP will be populated with the  AVP  of  the  first
                  matching  Result-Code/AVP pair in the errors field of the argument packet(), if
                  found. If this is not appropriate then an answer-message should be  constructed
                  explicitly and returned in a reply tuple instead.

                {relay, Opts}:
                  Relay  a  request  to  another peer in the role of a Diameter relay agent. If a
                  routing  loop  is  detected  then   the   request   is   answered   with   3005
                  (DIAMETER_LOOP_DETECTED).  Otherwise a Route-Record AVP (containing the sending
                  peer's Origin-Host) is added to the  request  and  pick_peer/4  and  subsequent
                  callbacks take place just as if diameter:call/4 had been called explicitly. The
                  End-to-End Identifier of the incoming request is preserved in the header of the
                  relayed request.

                  The  returned  Opts  should  not  specify  detach. A subsequent handle_answer/4
                  callback for the relayed request must return its first argument,  the  packet()
                  containing  the  answer message. Note that the extra option can be specified to
                  supply arguments that can distinguish the relay case from others if so desired.
                  Any other return value (for example, from a handle_error/4 callback) causes the
                  request to be answered with 3002 (DIAMETER_UNABLE_TO_DELIVER).

                discard:
                  Discard the request. No answer message is sent to the peer.

                {eval, Action, PostF}:
                  Handle the request as if Action has been returned and then  evaluate  PostF  in
                  the request process. The return value is ignored.

                {eval_packet, Action, PostF}:
                  Like  eval  but  evaluate  PostF  on  any  encoded  #diameter_packet{} prior to
                  transmission, the bin field containing the encoded binary. The return value  is
                  ignored.

                {protocol_error, 3000..3999}:
                  Equivalent to {answer_message, 3000..3999}.

          Note:
              Requests  containing  errors may be answered by diameter, without a callback taking
              place, depending on the value of the diameter:application_opt() request_errors.