aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter/doc/src/diameter_app.xml
diff options
context:
space:
mode:
Diffstat (limited to 'lib/diameter/doc/src/diameter_app.xml')
-rw-r--r--lib/diameter/doc/src/diameter_app.xml582
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>