diff options
Diffstat (limited to 'lib/diameter/doc/src/diameter_app.xml')
-rw-r--r-- | lib/diameter/doc/src/diameter_app.xml | 582 |
1 files changed, 582 insertions, 0 deletions
diff --git a/lib/diameter/doc/src/diameter_app.xml b/lib/diameter/doc/src/diameter_app.xml new file mode 100644 index 0000000000..c2fecce768 --- /dev/null +++ b/lib/diameter/doc/src/diameter_app.xml @@ -0,0 +1,582 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> +<header> + +<copyright> +<year>2011</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 +its application. +The messages and AVPs of the Diameter application are defined in a +specification 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> + +<note> +<p> +The arities of the callback functions below 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, except for peer_up, peer_down and handle_request, any extra +arguments passed to <seealso +marker="diameter#call">diameter:call/4</seealso>.</p> +</note> + +<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 communicativity 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> + +<!-- ===================================================================== --> +<!-- ===================================================================== --> + +<section> +<title>DATA TYPES</title> + +<taglist> + +<tag><c>capabilities() = #diameter_caps{}</c></tag> +<item> +<p> +A record containing the identities of +the local and remote Diameter peers 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> + +<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 in the 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: messages are sent exactly as specified.</p> + +</item> + +<tag><c>packet() = #diameter_packet{}</c></tag> +<item> +<p> +A container for incoming and outgoing Diameters message that's passed +through encode/decode and transport. +Defined in diameter.hrl. +Fields should not be altered except as documented.</p> +</item> + +<tag><c>peer_ref() = term()</c></tag> +<item> +<p> +A term identifying a transport connection with a Diameter peer. +Should be treated opaquely.</p> +</item> + +<tag><c>peer() = {peer_ref(), capabilities()}</c></tag> +<item> +<p> +A tuple representing a Diameter peer connection.</p> +</item> + +<tag><c>service_name() = term()</c></tag> +<item> +<p> +The service supporting the Diameter application. +Specified to <seealso +marker="diameter#start_service">diameter:start_service/2</seealso> +when starting the service.</p> +</item> + +<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 = service_name()</v> +<v>Peer = peer()</v> +<v>State = NewState = state()</v> +</type> +<desc> +<p> +Invoked when a transport connection has been established +and a successful capabilities exchange has indicated that the peer +supports the Diameter application of the application on which +the callback module in question has been configured.</p> + +<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 = service_name()</v> +<v>Peer = peer()</v> +<v>State = NewState = state()</v> +</type> +<desc> +<p> +Invoked when a transport connection has been lost following a previous +call to <seealso marker="peer_up">peer_up/3</seealso>.</p> + +<marker id="pick_peer"/> +</desc> +</func> + +<func> +<name>Mod:pick_peer(Cands, Reserved, SvcName, State) + -> {ok, Peer} | {Peer, NewState} | false</name> +<fsummary>Select a target peer for an outgoing request.</fsummary> +<type> +<v>Cands = [Peer]</v> +<v>Peer = peer() | false</v> +<v>SvcName = service_name()</v> +<v>State = NewState = state()</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 indicating the selected peer. +A new application state can also be returned but only if the Diameter +application in question was +configured with the option <c>call_mutates_state</c> set to +<c>true</c>, as documented for <seealso +marker="diameter#start_service">diameter:start_service/2</seealso>.</p> + +<p> +The candidate peers list will only include those +which are selected by any <c>filter</c> option specified in the call to +<seealso marker="diameter#call">diameter:call/4</seealso>.</p> +<!-- +The local candidates are those whose transport process is executing on +the local Erlang node, the remote list those that are available on +other nodes.</p> --> + +<p> +The return values <c>false</c> and <c>{false, State}</c> are +equivalent when callback state is mutable, as are +<c>{ok, Peer}</c> and <c>{Peer, State}</c>. +Returning a peer as <c>false</c> causes <c>{error, no_connection}</c> +to be returned from <seealso marker="diameter#call">diameter:call/4</seealso>. +Returning a peer() from an initial pick_peer/4 callback will result in a +<seealso marker="#prepare_request">prepare_request/3</seealso> callback +followed 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 transport with the peer is lost before this then a new <seealso +marker="#pick_peer">pick_peer/4</seealso> callback takes place to +select an alternate peer.</p> + +<p> +Note that 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, only +that the initial <seealso +marker="#pick_peer">pick_peer/4</seealso> will be, since a +retransmission to an alternate peer is abandoned if an answer is +received from a previously selected peer.</p> + +<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 = packet()</v> +<v>SvcName = service_name()</v> +<v>Peer = peer()</v> +<v>Action = {send, packet() | message()} | {discard, Reason} | discard</v> +</type> +<desc> +<p> +Invoked to return a request for encoding and transport. +Allows the sender to access the selected peer's capabilities +in order to set (for example) <c>Destination-Host</c> and/or +<c>Destination-Realm</c> in the outgoing request, although the +callback need not be limited to this usage. +Many implementations may simply want to return <c>{send, Packet}</c></p> + +<p> +A returned packet() 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 module. +Extra arguments passed to <seealso +marker="diameter#call">diameter:call/4</seealso> can be used to +communicate transport data to the callback.</p> + +<p> +Any returned packet() can set the <c>header</c> field to a +<c>diameter_header</c> record in order to specify values that should +be preserved in the outgoing request. +A specified <c>message_length</c> 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) -> Result</name> +<fsummary>Return a request for encoding and retransmission.</fsummary> +<type> +<v>Packet = packet()</v> +<v>SvcName = service_name()</v> +<v>Peer = peer()</v> +<v>Result = {send, packet() | message()} | {discard, Reason} | discard</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 +Packet passed to <c>prepare_retransmit/3</c> is as returned by +<c>prepare_request/3</c>.</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 = packet()</v> +<v>Request = message()</v> +<v>SvcName = service_name()</v> +<v>Peer = peer()</v> +<v>Result = term()</v> +</type> +<desc> +<p> +Invoked when an answer message is received from a peer. +The return value is returned from the call to <seealso +marker="diameter#call">diameter:call/4</seealso> for which the +callback takes place.</p> + +<p> +The decoded answer record is in the <c>msg</c> field of <c>Packet</c>, +the undecoded binary in the <c>packet</c> field. +<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> +before the request was passed to the transport.</p> + +<p> +For any given call to <seealso +marker="diameter#call">diameter:call/4</seealso> there is at most one +call to the handle_answer callback of the application in question: any +duplicate answer (due to retransmission or otherwise) is discarded. +Similarly, only one of <c>handle_answer/4</c> or <c>handle_error/4</c> is +called for any given request.</p> + +<p> +By default, an incoming answer message that cannot be successfully +decoded causes the request process in question to fail, causing the +relevant call to <seealso +marker="diameter#call">diameter:call/4</seealso> +to return <c>{error, failure}</c>. +There is no <c>handle_error/4</c> callback in this case. +Application configuration may change this behaviour as described for +<seealso +marker="diameter#start_service">diameter:start_service/2</seealso>.</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 = message()</v> +<v>SvcName = service_name()</v> +<v>Peer = peer()</v> +<v>Result = term()</v> +</type> +<desc> +<p> +Invoked when an error occurs before an answer message is received from +a peer in response to an outgoing request. +The return value is returned from the call to <seealso +marker="diameter#call">diameter:call/4</seealso> for which the +callback takes place.</p> + +<p> +Reason <c>timeout</c> indicates that an answer message has not been +received within the required time. +Reason <c>failover</c> indicates +that the transport connection to the peer to which the request has +been sent has been lost but that not alternate node was available, +possibly because a <seealso marker="#pick_peer">pick_peer/4</seealso> +callback returned false. +</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 = packet()</v> +<v>SvcName = term()</v> +<v>Peer = peer()</v> +<v>Action = Reply | NoReply | Relay | {eval, Action, ContF}</v> +<v>Reply = {reply, message()} + | {protocol_error, ResultCode}</v> +<v>NoReply = discard</v> +<v>Relay = {relay, Opts}</v> +<v>Opts = list()</v> +<v>ContF = diameter:evaluable()</v> +<v>ResultCode = 3000..3999</v> +</type> +<desc> +<p> +Invoked when a request message is received from a peer.</p> + +<p> +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 Diameter request message, the selected module being the one +whose corresponding <seealso +marker="diameter_dict#MESSAGE_RECORDS">dictionary</seealso> declares +itself as defining the application in question, or the RFC 3588 relay +application if the specific application is unsupported but the relay +application has been advertised.</p> + +<p> +The packet() in which the incoming request is communicated has the +following signature.</p> + +<code> +#diameter_packet{header = #diameter_header{}, + avps = [#diameter_avp{}], + msg = record() | undefined, + errors = [integer() | {integer(), #diameter_avp{}}], + bin = binary(), + transport_data = term()} +</code> + +<p> +The <c>msg</c> field will be <c>undefined</c> only 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 non-protocol errors that were +encountered in decoding the request and can be returned in a +<c>reply</c> tuple to have diameter set the Result-Code and Failed-AVP +AVP's appropriately. +The 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 in the packet() containing any answer message +sent back to the transport process unless another value is explicitly +specified.</p> + +<p> +The semantics of each of the possible return values are as follows. +(TODO: more.)</p> + +<taglist> + +<tag><c>{reply, Answer}</c></tag> +<item> +<p> +Send the specified answer message to the peer.</p> +</item> + +<tag><c>{relay, Opts}</c></tag> +<item> +<p> +Relay a request to another peer.</p> +</item> + +<tag><c>{protocol_error, ResultCode}</c></tag> +<item> +<p> +Send an answer message to the peer containing the specified 3xxx +protocol error.</p> + +<p> +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, ResultCode}</c> +tuple will cause the request process in question to fail.</p> +</item> + +<tag><c>discard</c></tag> +<item> +<p> +Discard the request.</p> +</item> + +<tag><c>{eval, Action, ContF}</c></tag> +<item> +<p> +Handle the request as if <c>Action</c> has been returned and then +evaluate the evaluable() <c>ContF</c> in the request process.</p> +</item> + +</taglist> + +<p> +Note that diameter will respond to protocol errors in an incoming +request without invoking the a <c>handle_request/3</c> callback.</p> + +</desc> +</func> + +</funcs> + +</erlref> |