aboutsummaryrefslogblamecommitdiffstats
path: root/lib/diameter/doc/src/diameter_app.xml
blob: 290b8a3984a4d52d699f2f8eb4f24973c2837b51 (plain) (tree)
1
2
3
4
5
6
7
8






                                        
                                  






































                                                                      

                                                         
                                             




                                                                







                                                                    

                                                             























                                                                        










                                                                     







                                                                              

                           



                                                   

                                                              







                                                                    

                      











                                                                     

                                                                     


                                                                 

                                                                         





                                                                      

                                                                      


       

                     


                                               
                                                                     
                                    
                                                                   

       

                       


                                     
                                                                   

       

                   


                                                                              




                                                    

                    






























                                                                              
                                                                                          

                                                                      


       






















                                                                     








                                                                       
                                                                                          

                                                                      


       






                                                                      





                        

                                                          

                                                                  
                                                              
                                                                                          
                                                                    

                                                              




                                                                        

                                                 

   




                                                                     




                                                                         

   



                                                                      

                                                                     
                                                   
                                                                         



                                                                     
                                                                      

                                     
                                                            
                                                                      


                                                                









                                                                     

      

                                                                     

                                                                      





                                                                     








                                                                 
                                                            
                                                                                          
                                                      





                                                                            



                                                       

                                                         


                                                                        

                                                                      
                                                                     
                                             

                                                               




                                                               
                                                       

                                                                     

                                                                     

   

                                                                     
                              


                                











                                                                   
                                                                    

                                                                      
                                                             
                                                                                          






                                                                            






                                                                      


                                                                    
















                                                                        

                                                               
                                                                                          
                                                         




                                                       


                                                           

   


                                                                    

                                                                   

                                                                    



                                                                     
                                                                        
                                                                   



                                                            


                                                                  





                                                                     
     


                                                                      









                                                                       
                                                               
                                                                                          
                                                         



                       




                                                                 


                                                                   

                                                                  

                                                                  

                                                                








                                                                
                                                             
                       
                                                         


                           
                                                  

                                                                    
                                             
                                                                                  
                                                                                    


       
                                                       



                                                                   
                                                           

                                                                    

                                                                  

   
                                                                                          
 
     


                                               
                                                                                                                                                                                     

                                         
      

   
                                                                     





                                                                      



                                                                      

                                                                                                   



                                                                    




                                                                      


                                                                          

   
                                                                       


         

                                                                         

      






                                                                  

       
                                              

      


                                                           
     
                                 
      
   

                                                                   

   
                                                                
                                                






                                                           





                                                                           

                                                                

                                                                     

   


                                                                       
                                                                    

                                                                      



                                                                             




                         

                                          

       
                                       


                                                                 








                                                                     
                              
                                




          

                                                                 






         
<?xml version="1.0" encoding="latin1" ?>
<!DOCTYPE erlref SYSTEM "erlref.dtd">

<erlref>
<header>

<copyright>
<year>2011</year><year>2012</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
The contents of this file are subject to the Erlang Public License,
Version 1.1, (the "License"); you may not use this file except in
compliance with the License. You should have received a copy of the
Erlang Public License along with this software. If not, it can be
retrieved online at http://www.erlang.org/.

Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.

</legalnotice>

<title>diameter_app(3)</title>
<prepared>Anders Svensson</prepared>
<responsible></responsible>
<docno></docno>
<approved></approved>
<checked></checked>
<date></date>
<rev>%REV%</rev>
<file>diameter_app.xml</file>

</header>

<module>diameter_app</module>
<modulesummary>
Callback module of a Diameter application.</modulesummary>

<description>

<p>
A diameter service as started by <seealso
marker="diameter#start_service">diameter:start_service/2</seealso>
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
<seealso marker="diameter_dict">diameter_dict(4)</seealso>
while the callback module is documented here.
The callback module implements the Diameter application-specific
functionality of a service.</p>

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

<list>
<item>
<p>
<seealso marker="#peer_up">peer_up/3</seealso> and
<seealso marker="#peer_down">peer_down/3</seealso> signal the
attainment or loss of connectivity with a Diameter peer.</p>
</item>

<item>
<p>
<seealso marker="#pick_peer">pick_peer/4</seealso>,
<seealso marker="#prepare_request">prepare_request/3</seealso>,
<seealso marker="#prepare_retransmit">prepare_retransmit/3</seealso>,
<seealso marker="#handle_answer">handle_answer/4</seealso>
and <seealso marker="#handle_error">handle_error/4</seealso> are (or may
be) called as a consequence of a call to <seealso 
marker="diameter#call">diameter:call/4</seealso> to send an outgoing
Diameter request message.</p>
</item>

<item>
<p>
<seealso marker="#handle_request">handle_request/3</seealso>
is called in response to an incoming Diameter request message.</p>
</item>

</list>

</description>

<note>
<p>
The arities given 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 <seealso
marker="diameter#start_service">diameter:start_service/2</seealso>
and, for the call-specific callbacks, any extra arguments passed to
<seealso marker="diameter#call">diameter:call/4</seealso>.</p>
</note>

<!-- ===================================================================== -->
<!-- ===================================================================== -->

<section>
<title>DATA TYPES</title>

<taglist>

<marker id="capabilities"/>

<tag><c>capabilities() = #diameter_caps{}</c></tag>
<item>
<p>
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.</p>
</item>

<marker id="message"/>

<tag><c>message() = record() | list()</c></tag>
<item>
<p>
The representation of a Diameter message as passed to
<seealso marker="diameter#call">diameter:call/4</seealso>.
The record representation is as outlined in
<seealso
marker="diameter_dict#MESSAGE_RECORDS">diameter_dict(4)</seealso>:
a message as defined in a dictionary file is encoded as a record with
one field for each component AVP.
Equivalently, a message can also be encoded as a list whose head is
the atom-valued message name (the record name minus any
prefix specified in the relevant dictionary file) and whose tail is a
list of <c>{FieldName, FieldValue}</c> pairs.</p>

<p>
A third representation allows a message to be specified as a list
whose head is a <c>#diameter_header{}</c> record and whose tail is a list
of <c>#diameter_avp{}</c> records.
This representation is used by diameter itself when relaying requests
as directed by the return value of a
<seealso marker="#handle_request">handle_request/3</seealso>
callback.
It differs from the other other two in that it bypasses the checks for
messages that do not agree with their definitions in the dictionary in
question (since relays agents must handle arbitrary request): messages
are sent exactly as specified.</p>

</item>

<marker id="packet"/>

<tag><c>packet() = #diameter_packet{}</c></tag>
<item>
<p>
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.</p>
</item>

<marker id="peer_ref"/>

<tag><c>peer_ref() = term()</c></tag>
<item>
<p>
A term identifying a transport connection with a Diameter peer.</p>
</item>

<marker id="peer"/>

<tag><c>peer() =
          {<seealso marker="#peer_ref">peer_ref()</seealso>,
           <seealso marker="#capabilities">capabilities()</seealso>}</c></tag>
<item>
<p>
A tuple representing a Diameter peer connection.</p>
</item>

<marker id="state"/>

<tag><c>state() = term()</c></tag>
<item>
<p>
The state maintained by the application callback functions
<seealso marker="#peer_up">peer_up/3</seealso>,
<seealso marker="#peer_down">peer_down/3</seealso> and (optionally)
<seealso marker="#pick_peer">pick_peer/4</seealso>.
The initial state is configured in the call to
<seealso
marker="diameter#start_service">diameter:start_service/2</seealso>
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.</p>
</item>

</taglist>

<marker id="peer_up"/>
</section>

<!-- ===================================================================== -->
<!-- ===================================================================== -->

<funcs>

<func>
<name>Mod:peer_up(SvcName, Peer, State) -> NewState</name>
<fsummary>Invoked when a transport connection has been established</fsummary>
<type>
<v>SvcName = <seealso marker="diameter#service_name">diameter:service_name()</seealso></v>
<v>Peer    = <seealso marker="#peer">peer()</seealso></v>
<v>State   = NewState = <seealso marker="#state">state()</seealso></v>
</type>
<desc>
<p>
Invoked to signal the availability of a peer connection.
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 <c>OKAY</c> and Diameter
messages can be both sent and received.</p>

<note>
<p>
A watchdog state machine can reach state <c>OKAY</c> from state
<c>SUSPECT</c> without a new capabilities exchange taking place.
A new transport connection (and capabilities exchange) results in a
new peer_ref().</p>
</note>

<note>
<p>
There is no requirement that a callback return before incoming
requests are received: <seealso
marker="#handle_request">handle_request/3</seealso> callbacks must be
handled independently of <seealso
marker="#peer_up">peer_up/3</seealso> and <seealso
marker="#peer_down">peer_down/3</seealso>.</p>
</note>

<marker id="peer_down"/>
</desc>
</func>

<func>
<name>Mod:peer_down(SvcName, Peer, State) -> NewState</name>
<fsummary>Invoked when a transport connection has been lost.</fsummary>
<type>
<v>SvcName = <seealso marker="diameter#service_name">diameter:service_name()</seealso></v>
<v>Peer    = <seealso marker="#peer">peer()</seealso></v>
<v>State   = NewState = <seealso marker="#state">state()</seealso></v>
</type>
<desc>
<p>
Invoked to signal that a peer connection is no longer available
following a previous call to <seealso
marker="#peer_up">peer_up/3</seealso>.
In particular, that the RFC 3539 watchdog state machine for the
connection has left state <c>OKAY</c> and the peer will no longer be a
candidate in <seealso marker="#pick_peer">pick_peer()</seealso>
callbacks.</p>

<marker id="pick_peer"/>
</desc>
</func>

<func>
<name>Mod:pick_peer(Candidates, _Reserved, SvcName, State)
      -> Selection | false</name>
<fsummary>Select a target peer for an outgoing request.</fsummary>
<type>
<v>Candidates = [<seealso marker="#peer">peer()</seealso>]</v>
<v>SvcName = <seealso marker="diameter#service_name">diameter:service_name()</seealso></v>
<v>State = NewState = <seealso marker="#state">state()</seealso></v>
<v>Selection = {ok, Peer} | {Peer, NewState}</v>
<v>Peer = <seealso marker="#peer">peer()</seealso> | false</v>
</type>
<desc>
<p>
Invoked as a consequence of a call to <seealso
marker="diameter#call">diameter:call/4</seealso> to select a destination
peer for an outgoing request.
The return value indicates the selected peer.</p>

<p>
The candidate list contains only those peers that have advertised
support for the Diameter application in question during capabilities
exchange, that have not be excluded by a <c>filter</c> option in
the call to <seealso marker="diameter#call">diameter:call/4</seealso>
and whose watchdog state machine is in the <c>OKAY</c> 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 <c>{filter, {all, [host, realm]}}</c>
option to <seealso marker="diameter#call">diameter:call/4</seealso>)
will be placed at the head of the list.</p>

<p>
A callback that returns a peer() will be followed by a
<seealso marker="#prepare_request">prepare_request/3</seealso>
callback and, if the latter indicates that the request should be sent,
by either <seealso marker="#handle_answer">handle_answer/4</seealso>
or <seealso marker="#handle_error">handle_error/4</seealso> depending
on whether or not an answer message is received from the peer.
If the transport becomes unavailable after <seealso
marker="#prepare_request">prepare_request/3</seealso> then a new <seealso
marker="#pick_peer">pick_peer/4</seealso> callback may take place to
failover to an alternate peer, after which <seealso
marker="#prepare_retransmit">prepare_retransmit/3</seealso> takes the
place of <seealso
marker="#prepare_request">prepare_request/3</seealso> in resending the
request.
There is no guarantee that a <seealso
marker="#pick_peer">pick_peer/4</seealso> 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.</p>

<p>
Returning <c>false</c> or <c>{false, NewState}</c> causes <c>{error,
no_connection}</c> to be returned from <seealso
marker="diameter#call">diameter:call/4</seealso>.</p>

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

<note>
<p>
The return value <c>{Peer, NewState}</c> is only allowed if
the Diameter application in question was configured with the <seealso
marker="diameter#application_opt">diameter:application_opt()</seealso>
<c>{call_mutates_state, true}</c>.
Otherwise, the <c>State</c> argument is always
the intial value as configured on the application, not any subsequent
value returned by a <seealso marker="#peer_up">peer_up/3</seealso>
or <seealso marker="#peer_down">peer_down/3</seealso> callback.</p>
</note>

<marker id="prepare_request"/>
</desc>

</func>

<func>
<name>Mod:prepare_request(Packet, SvcName, Peer) -> Action</name>
<fsummary>Return a request for encoding and transport.</fsummary>
<type>
<v>Packet = <seealso marker="#packet">packet()</seealso></v>
<v>SvcName = <seealso marker="diameter#service_name">diameter:service_name()</seealso></v>
<v>Peer = <seealso marker="#peer">peer()</seealso></v>
<v>Action = Send | Discard | {eval_packet, Action, PostF}</v>
<v>Send = {send, <seealso marker="#packet">packet()</seealso>
                 | <seealso marker="#message">message()</seealso>}</v>
<v>Discard = {discard, Reason} | discard</v>
<v>PostF =
    <seealso marker="diameter#evaluable">diameter:evaluable()</seealso>}</v>
</type>
<desc>
<p>
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 <c>{send, Packet}</c></p>

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

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

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

<p>
Returning <c>{discard, Reason}</c> causes the request to be aborted
and the <seealso
marker="diameter#call">diameter:call/4</seealso> for which the
callback has taken place to return <c>{error, Reason}</c>.
Returning <c>discard</c> is equivalent to returning <c>{discard,
discarded}</c>.</p>

<marker id="prepare_retransmit"/>
</desc>
</func>

<func>
<name>Mod:prepare_retransmit(Packet, SvcName, Peer) -> Action</name>
<fsummary>Return a request for encoding and retransmission.</fsummary>
<type>
<v>Packet  = <seealso marker="#packet">packet()</seealso></v>
<v>SvcName = <seealso marker="diameter#service_name">diameter:service_name()</seealso></v>
<v>Peer = <seealso marker="#peer">peer()</seealso></v>
<v>Action = Send | Discard | {eval_packet, Action, PostF}</v>
<v>Send = {send, <seealso marker="#packet">packet()</seealso>
                | <seealso marker="#message">message()</seealso>}</v>
<v>Discard = {discard, Reason} | discard</v>
<v>PostF =
    <seealso marker="diameter#evaluable">diameter:evaluable()</seealso>}</v>
</type>
<desc>
<p>
Invoked to return a request for encoding and retransmission.
Has the same role as <seealso
marker="#prepare_request">prepare_request/3</seealso> in the case that
a peer connection is lost an an alternate peer selected but the
argument <seealso marker="#packet">packet()</seealso> is as returned
by the initial <seealso
marker="#prepare_request">prepare_request/3</seealso>.</p>

<p>
Returning <c>{discard, Reason}</c> causes the request to be aborted
and a <seealso
marker="#handle_error">handle_error/4</seealso> callback to
take place with <c>Reason</c> as initial argument.
Returning <c>discard</c> is equivalent to returning <c>{discard,
discarded}</c>.</p>

<marker id="handle_answer"/>
</desc>
</func>

<func>
<name>Mod:handle_answer(Packet, Request, SvcName, Peer) -> Result</name>
<fsummary>Receive an answer message from a peer.</fsummary>
<type>
<v>Packet  = <seealso marker="#packet">packet()</seealso></v>
<v>Request = <seealso marker="#message">message()</seealso></v>
<v>SvcName = <seealso marker="diameter#service_name">diameter:service_name()</seealso></v>
<v>Peer    = <seealso marker="#peer">peer()</seealso></v>
<v>Result  = term()</v>
</type>
<desc>
<p>
Invoked when an answer message is received from a peer.
The return value is returned from <seealso
marker="diameter#call">diameter:call/4</seealso> unless the
<c>detach</c> option was specified.</p>

<p>
The decoded answer record and undecoded binary are in the <c>msg</c>
and <c>bin</c> fields of the argument
<seealso marker="#packet">packet()</seealso> respectively.
<c>Request</c> is the outgoing request message as was returned from
<seealso marker="#prepare_request">prepare_request/3</seealso> or
<seealso
    marker="#prepare_retransmit">prepare_retransmit/3</seealso>.</p>

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

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

<marker id="handle_error"/>
</desc>
</func>

<func>
<name>Mod:handle_error(Reason, Request, SvcName, Peer) -> Result</name>
<fsummary>Return an error from a outgoing request.</fsummary>
<type>
<v>Reason  = timeout | failover | term()</v>
<v>Request = <seealso marker="#message">message()</seealso></v>
<v>SvcName = <seealso marker="diameter#service_name">diameter:service_name()</seealso></v>
<v>Peer    = <seealso marker="#peer">peer()</seealso></v>
<v>Result  = term()</v>
</type>
<desc>
<p>
Invoked when an error occurs before an answer message is received
in response to an outgoing request.
The return value is returned from <seealso
marker="diameter#call">diameter:call/4</seealso> unless the
<c>detach</c> option was specified.</p>

<p>
Reason <c>timeout</c> indicates that an answer message has not been
received within the time specified with the corresponding <seealso
marker="diameter#call_opt">diameter:call_opt()</seealso>.
Reason <c>failover</c> 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.</p>

<marker id="handle_request"/>
</desc>
</func>

<func>
<name>Mod:handle_request(Packet, SvcName, Peer) -> Action</name>
<fsummary>Receive an incoming request.</fsummary>
<type>
<v>Packet  = <seealso marker="#packet">packet()</seealso></v>
<v>SvcName = term()</v>
<v>Peer    = <seealso marker="#peer">peer()</seealso></v>
<v>Action  = Reply
           | {relay, [Opt]}
           | discard
           | {eval|eval_packet, Action, PostF}</v>
<v>Reply   = {reply, <seealso marker="#packet">packet()</seealso>
                   | <seealso marker="#message">message()</seealso>}
           | {protocol_error, 3000..3999}</v>
<v>Opt     = <seealso marker="diameter#call_opt">diameter:call_opt()</seealso></v>
<v>PostF   = <seealso marker="diameter#evaluable">diameter:evaluable()</seealso></v>
</type>
<desc>
<p>
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 <seealso
marker="diameter#start_service">diameter:start_service/2</seealso>)
is determined by the Application Identifier in the header of the
incoming request message, the selected module being the one
whose corresponding <seealso
marker="diameter_dict#MESSAGE_RECORDS">dictionary</seealso> declares
itself as defining either the application in question or the Relay
application.</p>

<p>
The argument <seealso marker="#packet">packet()</seealso> has the following signature.</p>

<pre>
#diameter_packet{header = #diameter_header{},
                 avps   = [#diameter_avp{}],
                 msg    = record() | undefined,
                 errors = [<seealso marker="diameter_dict#DATA_TYPES">Unsigned32()</seealso> | {<seealso marker="diameter_dict#DATA_TYPES">Unsigned32()</seealso>, #diameter_avp{}}],
                 bin    = binary(),
                 transport_data = term()}
</pre>

<p>
The <c>msg</c> field will be <c>undefined</c> in case the request has
been received in the relay application.
Otherwise it contains the record representing the request as outlined
in <seealso
marker="diameter_dict#MESSAGE_RECORDS">diameter_dict(4)</seealso>.</p>

<p>
The <c>errors</c> field specifies any Result-Code's identifying errors
that were encountered in decoding the request.
In this case diameter will set both Result-Code and
Failed-AVP AVP's in a returned
answer <seealso marker="#message">message()</seealso> before sending it to the peer:
the returned <seealso marker="#message">message()</seealso> need only set any other required AVP's.
Note that the errors detected by diameter are all of the 5xxx series
(Permanent Failures).
The <c>errors</c> list is empty if the request has been received in
the relay application.</p>

<p>
The <c>transport_data</c> field contains an arbitrary term passed into
diameter from the transport module in question, or the atom
<c>undefined</c> if the transport specified no data.
The term is preserved if a <seealso
marker="#packet">message()</seealso> is returned but must be set
explicitly in a returned <seealso marker="#packet">packet()</seealso>.</p>

<p>
The semantics of each of the possible return values are as follows.</p>

<taglist>

<tag><c>{reply, <seealso marker="#packet">packet()</seealso>
              | <seealso marker="#message">message()</seealso>}</c></tag>
<item>
<p>
Send the specified answer message to the peer.
In the case of a <seealso marker="#packet">packet()</seealso>, the
message to be sent must be set in the
<c>msg</c> field and the <c>header</c> field can be set to a
<c>#diameter_header{}</c> to specify values that should be
preserved in the outgoing answer, appropriate values otherwise
being set by diameter.</p>
</item>

<tag><c>{protocol_error, 3000..3999}</c></tag>
<item>
<p>
Send an answer message to the peer containing the specified
protocol error.
Equivalent to</p>
<pre>
{reply, ['answer-message' | Avps]
</pre>
<p>
where <c>Avps</c> sets the Origin-Host, Origin-Realm, the specified
Result-Code and (if the request sent one) Session-Id AVP's.</p>

<p>
Note that RFC 3588 mandates that only answers with a 3xxx series
Result-Code (protocol errors) may set the E bit.
Returning a non-3xxx value in a <c>protocol_error</c> tuple
will cause the request process in question to fail.</p>
</item>

<tag><c>{relay, Opts}</c></tag>
<item>
<p>
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 <seealso marker="#pick_peer">pick_peer/4</seealso>
and subsequent callbacks take place just as if <seealso
marker="diameter#call">diameter:call/4</seealso> had been called
explicitly.
The End-to-End Identifier of the incoming request is preserved in the
header of the relayed request.</p>

<p>
The returned <c>Opts</c> should not specify <c>detach</c>.
A subsequent <seealso marker="#handle_answer">handle_answer/4</seealso>
callback for the relayed request must return its first
argument, the <c>#diameter_packet{}</c> record containing the answer
message.
Note that the <c>extra</c> 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
<seealso marker="#handle_error">handle_error/4</seealso> callback)
causes the request to be answered with 3002 (DIAMETER_UNABLE_TO_DELIVER).</p>
</item>

<tag><c>discard</c></tag>
<item>
<p>
Discard the request.
No answer message is sent to the peer.</p>
</item>

<tag><c>{eval, Action, PostF}</c></tag>
<item>
<p>
Handle the request as if <c>Action</c> has been returned and then
evaluate <c>PostF</c> in the request process.
The return value is ignored.</p>
</item>

<tag><c>{eval_packet, Action, PostF}</c></tag>
<item>
<p>
Like <c>eval</c> but evaluate <c>PostF</c> on any encoded
<c>#diameter_packet{}</c> prior to transmission, the <c>bin</c> field
containing the encoded binary.
The return value is ignored.</p>
</item>

</taglist>

<p>
Note that protocol errors detected by diameter will result in an
answer message without <c>handle_request/3</c> being invoked.</p>

</desc>
</func>

</funcs>

</erlref>