From 3c15ff32e89e401b4dde2b8acc9699be2614b996 Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Wed, 18 May 2011 18:29:12 +0200 Subject: Initial commit of the diameter application. The application provides an implementation of the Diameter protocol as defined in RFC 3588. --- lib/diameter/doc/src/diameter.xml | 1123 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1123 insertions(+) create mode 100644 lib/diameter/doc/src/diameter.xml (limited to 'lib/diameter/doc/src/diameter.xml') diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml new file mode 100644 index 0000000000..9774183a2a --- /dev/null +++ b/lib/diameter/doc/src/diameter.xml @@ -0,0 +1,1123 @@ + + + + +
+ + +2011 +Ericsson AB. All Rights Reserved. + + +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. + + + +diameter(3) + +Anders Svensson + + + + + +%VSN% +diameter.xml + +
+ + + + +diameter +Main API of the diameter application. + + +

+This module provides the interface with which a user +creates a service that sends and receives messages using the +Diameter protocol as defined in RFC 3588.

+ +

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

+ +

+Beware the difference between diameter application and +Diameter application. +The former refers to the Erlang application named diameter whose main +api is defined here, the latter to an application of the Diameter +protocol in the sense of RFC 3588. +More generally, capitalized Diameter refers to the RFC +and diameter to this implementation.

+ +

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

+ +
+ + + +
+DATA TYPES + + + +Address() +DiameterIdentity() +Time() +Unsigned32() +UTF8String() + +

+Types corresponding to RFC 3588 AVP Data Formats. +Defined in diameter_dict(4).

+ + +
+ +application_alias() = term() + +

+A name identifying a Diameter application in +service configuration passed to start_service/2 and passed to +call/4 when sending requests +belonging to the application.

+ + +
+ +application_module() = Mod | [Mod | ExtraArgs] + + +Mod = atom() +ExtraArgs = list() + + +

+A module implementing the callback interface defined in diameter_app(3), along with any +extra arguments to be appended to those documented for the interface. +Any extra arguments are appended to the documented list of arguments for +each function. +Note that additional arguments specific to an outgoing request be +specified to call/4, in which case +the call-specific arguments are appended to any specified with the +callback module.

+ + +
+ +application_opt() + + +

+Options defining a Diameter application as configured in an +application option passed to +start_service/2.

+ + + +{alias, application_alias()} + +

+An unique identifier for the application in the scope of the +service. +Optional, defaults to the value of the dictionary option.

+
+ +{dictionary, atom()} + +

+The name of an encode/decode module for the Diameter +messages defined by the application. +These modules are generated from a specification file whose format is +documented in diameter_dict(4).

+
+ +{module, application_module()} + +

+A callback module with which messages of the Diameter application are +handled. +See diameter_app(3) for +information on the required interface and semantics.

+
+ +{state, term()} + +

+The initial callback state. +Defaults to the value of the alias option if unspecified. +The prevailing state is passed to certain +diameter_app(3) +callbacks, which can then return a new state.

+
+ +{call_mutates_state, true|false} + +

+Specifies whether or not the pick_peer/4 +application callback (following from a call to +call/4) +can modifiy state, +Defaults to false if unspecified.

+ +

+Note that pick_peer callbacks are +serialized when these are allowed to modify state, which is a +potential performance bottleneck. +A simple Diameter client may suffer no ill effects from using mutable +state but a server or agent that responds to incoming request but +sending its own requests should probably avoid it.

+
+ +{answer_errors, callback|report|discard} + +

+Determines the manner in which incoming answer messages containing +decode errors are handled. +If callback then errors result in a handle_answer/4 +callback in the same fashion as for handle_request/3, in the +errors field of the diameter_packet record passed into +the callback. +If report then an answer containing errors is discarded +without a callback and a warning report is written to the log. +If discard then an answer containing errors is silently +discarded without a callback. +In both the report and discard cases the return value +for the call/4 invocation in +question is as if a callback had taken place and returned +{error, failure}.

+ +

+Defaults to report if unspecified.

+
+ +
+ + +
+ +call_opt() + + +

+Options available to call/4 when +sending an outgoing Diameter request.

+ + + +{extra, list()} + +

+Extra arguments to append to callbacks to the callback +module in question. +These are appended to any extra arguments configured with the callback +itself. +Multiple options append to the argument list.

+
+ +{filter, peer_filter()} + +

+A filter to apply to the list of available peers before passing them to +the pick_peer/4 +callback for the application in question. +Multiple options are equivalent a single all filter on the +corresponding list of filters. +Defaults to none.

+
+ +{timeout, Unsigned32()} + +

+The number of milliseconds after which the request should +timeout. +Defaults to 5000.

+
+ +detach + +

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

+
+ +
+ + +
+ +capability() + + +

+AVP values used in outgoing CER/CEA messages during capabilities exchange. +Can be configured both on a service and a transport, the latter taking +precedence over the former.

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

+Value of the Origin-Host AVP in outgoing messages.

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

+Value of the Origin-Realm AVP in outgoing messages.

+
+ +{'Host-IP-Address', [Address()]} + +

+Values of Host-IP-Address AVPs. +Optional.

+ +

+The list of addresses is available to the start function of a +transport module, which either uses them as is or returns a new list +(typically as configured as transport_config() on the +transport module in question) in order for the correct list of +addresses to be sent in capabilities exchange messages.

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

+Value of the Vendor-Id AVP sent in an outgoing capabilities +exchange message.

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

+Value of the Product-Name AVP sent in an outgoing capabilities +exchange message.

+
+ +{'Origin-State-Id', Unsigned32()} + +

+Value of Origin-State-Id to be included in outgoing messages sent by +diameter itself. +In particular, the AVP will be included in CER/CEA and DWR/DWA messages. +Optional.

+ +

+Setting a value of 0 (zero) is equivalent to not setting a +value as documented in RFC 3588. +The function origin_state_id/0 +can be used as to retrieve a value that is set when the diameter +application is started.

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

+Values of Supported-Vendor-Id AVPs sent in an outgoing +capabilities exchange message. +Optional, defaults to the empty list.

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

+Values of Auth-Application-Id AVPs sent in an outgoing +capabilities exchange message. +Optional, defaults to the empty list.

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

+Values of Acct-Application-Id AVPs sent in an outgoing +capabilities exchange message. +Optional, defaults to the empty list.

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

+Values of Vendor-Specific-Application-Id AVPs sent in +an outgoing capabilities exchange message. +Optional, defaults to the empty list.

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

+Value of the Firmware-Revision AVP sent in an outgoing capabilities +exchange message. +Optional.

+
+ +
+ +

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

+ + +
+ +evaluable() = {M,F,A} | fun() | [evaluable() | A] + +

+An expression that can be evaluated as a function in the following +sense.

+ + +eval([{M,F,A} | T]) -> + apply(M, F, T ++ A); +eval([F|A]) -> + apply(F, A); +eval(F) -> + eval([F]). + + +

+Evaluating an evaluable() E on an argument list A +is meant in the sense of eval([E|A]).

+ + +
+ +peer_filter() = term() + +

+A filter passed to call/4 +in order to select candidate peers for a +pick_peer/4 +callback. +Has one of the following types.

+ + + +none + +

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

+
+ +host + +

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

+
+ +realm + +

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

+
+ +{host, any|UTF8String()} + +

+Matches only those peers whose Origin-Host has the +specified value, or all peers if the atom any.

+
+ +{realm, any|UTF8String() + +

+Matches only those peers whose Origin-Realm has the +value, or all peers if the atom any.

+
+ +{eval, evaluable()} + +

+Matches only those peers for which the specified evaluable() evaluates +to true on the peer's diameter_caps record.

+
+ +{neg, peer_filter()} + +

+Matches only those peers not matched by the specified filter.

+
+ +{all, [peer_filter()]} + +

+Matches only those peers matched by each filter of the specified list.

+
+ +{any, [peer_filter()]} + +

+Matches only those peers matched by at least one filter of the +specified list.

+
+ +
+ + +
+ +service_event() = #diameter_event{} + +

+Event message sent to processes that have subscribed using subscribe/1.

+ +

+The info field of the event record can be one of the +following.

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

+Reports that the RFC 3539 watchdog state machine has +transitioned into (up) or out of (down) the open +state. +If a diameter_packet record is present in an up tuple +then there has been an exchange of capabilities exchange messages and +the record contains the received CER or CEA, otherwise the +connection has reestablished without the loss or transport +connectivity.

+ +

+Note that a single up/down event for a given peer corresponds to +as many peer_up/down callbacks as there are Diameter +applications shared by the peer, as determined during capablilities +exchange. +That is, the event communicates connectivity with the +peer as a whole while the callbacks communicate connectivity with +respect to individual Diameter applications.

+
+ +{reconnect, Ref, Opts} + + +Ref = transport_ref() +Opts = [transport_opt()] + + +

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

+
+ +
+ +

+For forward compatibility, a subscriber should be prepared to receive +diameter_event.info of forms other than those documented +above.

+ + +
+ +service_name() = term() + +

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

+ + +
+ +service_opt() + +

+Options accepted by start_service/2. +Can be any capability() tuple as +well as the following.

+ + + +{application, [application_opt()]} + +

+Defines a Diameter application supported by the service.

+ +

+A service must define one application for each Diameter application it +intends to support. +For an outgoing Diameter request, the application is specified by +passing the desired application's application_alias() to +call/4, while for an +incoming request the application identifier in the message +header determines the application (and callback module), the +application identifier being specified in the dictionary file defining the +application.

+
+ +
+ + +
+ +transport_opt() + +

+Options accepted by add_transport/2.

+ + +{transport_module, atom()} + +

+A module implementing a transport process as defined in diameter_transport(3). +Defaults to diameter_tcp if unspecified.

+ +

+The interface required of a transport module is documented in diameter_transport(3).

+
+ +{transport_config, term()} + +

+A term passed as the third argument to the start/3 function of +the relevant transport_module in order to start a transport process. +Defaults to the empty list if unspecified.

+
+ +{applications, [application_alias()]} + +

+The list of Diameter applications to which usage of the transport +should be restricted. +Defaults to all applications configured on the service +in question.

+
+ +{capabilities, [capability()]} + +

+AVP's used to construct outgoing CER/CEA messages. +Any AVP specified takes precedence over a corresponding value specified +for the service in question.

+
+ +{watchdog_timer, TwInit} + + +TwInit = Unsigned32() + | {M,F,A} + + +

+The RFC 3539 watchdog timer. +An integer value is interpreted as the RFC's TwInit in milliseconds, +a jitter of ± 2 seconds being added at each rearming of the +timer to compute the RFC's Tw. +An MFA is expected to return the RFC's Tw directly, with jitter +applied, allowing the jitter calculation to be performed by +the callback.

+ +

+An integer value must be at least 6000 as required by RFC 3539. +Defaults to 30000 if unspecified.

+
+ +{reconnect_timer, Tc} + + +Tc = Unsigned32() + + +

+For a connecting transport, the RFC 3588 Tc timer, in milliseconds. +Note that this timer determines the frequency with which the transport +will attempt to establish a connection with its peer only before +an initial connection is established: once there is an initial +connection it's watchdog_timer that determines the frequency of +reconnection attempts, as required by RFC 3539.

+ +

+For a listening transport, the timer specifies the time after which a +previously connected peer will be forgotten: a connection after this time is +regarded as an initial connection rather than a reestablishment, +causing the RFC 3539 state machine to pass to state OPEN rather than +REOPEN. +Note that these semantics are not goverened by the RFC and +that a listening transport's reconnect_timer should be greater than its +peers's Tc plus jitter.

+ +

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

+
+ +
+ +

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

+ +
+ +
+ +
+ + + + + + + +add_transport(SvcName, {connect|listen, Options}) + -> {ok, Ref} | {error, Reason} +Add transport capability to a service. + +SvcName = service_name() +Options = [transport_opt()] +Ref = ref() +Reason = term() + + +

+Add transport capability to a service. +The service will start a transport process(es) in order to establish a +connection with the peer, either by connecting to the peer +(connect) or by accepting incoming connection requests +(listen). +A connecting transport establishes transport connections with at most +one peer, an listening transport potentially with many.

+ +

+The diameter application takes responsibility for exchanging +CER/CEA with the peer. +Upon successful completion of capabilities exchange the service +calls each relevant application module's peer_up/3 callback +after which the caller can exchange Diameter messages with the peer over +the transport. +In addition to CER/CEA, the service takes responsibility for the +handling of DWR/DWA and required by RFC 3539 as well as for DPR/DPA.

+ +

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

+ +

+It is not an error to add a transport to a service that has not yet +been configured: a service can be started after configuring +transports.

+ + +
+
+ + + + +call(SvcName, App, Request, Options) -> Answer | {error, Reason} +Send a Diameter request message. + +SvcName = service_name() +App = application_alias() +Request = diameter_app:message() +Answer = term() +Options = [call_opt()] + + +

+Send a Diameter request message and possibly return the answer or error.

+ +

+App identifies the Diameter application in which the request is +defined and callbacks to the corresponding callback module +will follow as described below and in diameter_app(3). +The call returns either when an answer message is received from the +peer or an error occurs, unless the detach option has been +specified. +If detach is not specified then the form of an Answer is +as returned from a handle_answer/4 or +handle_error/4 +callback.

+ +

+If there are no suitable peers, or if +pick_peer/4 +rejects them by returning 'false', then {error, no_connection} +is returned. +If pick_peer/4 +selects a candidate peer then a request process is spawned for the +outgoing request, in which there is a +prepare_request/3 +callback, the message is encoded and sent.

+ +

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

+ + + + +

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

+
+ + +

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

+
+ + +

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

+
+ + +

+If the transport connection with the peer goes down after the request +has been sent but before an answer has been received then an attempt +is made to resend the request to an alternate peer. +If no such peer is available, or if the subsequent +pick_peer/4 +callback rejects the candidates, then a +handle_error/4 +callback takes place with Reason = failover. +If a peer is selected then a +prepare_retransmit/3 +callback takes place, after which the semantics are the same as +following an initial + +prepare_request/3 +callback.

+
+ + +

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

+
+ + +

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

+
+ +
+ +

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

+ + +
+
+ + + + +origin_state_id() -> Unsigned32() +Returns a reasonable Origin-State-Id. + +

+Return a reasonable value for use as Origin-State-Id in +outgoing messages. +The value returned is the number of seconds since 19680120T031408Z +(the first value that can be encoded as a Time()) +at the time the diameter application was started.

+ + +
+
+ + + + +remove_transport(SvcName, Pred) -> ok +Remove previously added transports. + +SvcName = service_name() +Pred = Fun | MFA | ref() | list() | true | false + +Fun = fun((reference(), connect|listen, list()) -> boolean()) +    | fun((reference(), list()) -> boolean()) +    | fun((list()) -> boolean()) +MFA = {atom(), atom(), list()} + + +

+Remove previously added transports.

+ +

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

+ + +Pred = fun(reference(), list()): fun(Ref, _, Opts) -> Pred(Ref, Opts) end +Pred = fun(list()): fun(_, _, Opts) -> Pred(Opts) end +Pred = reference(): fun(Ref, _, _) -> Pred == Ref end +Pred = list(): fun(_, _, Opts) -> [] == Pred -- Opts end +Pred = true: fun(_, _, _) -> true end +Pred = false: fun(_, _, _) -> false end +Pred = {M,F,A}: fun(Ref, Type, Opts) -> apply(M, F, [Ref, Type, Opts | A]) end + + +

+Removing a transport causes all associated transport connections to +be broken. +A base application DPR message with +Disconnect-Cause DO_NOT_WANT_TO_TALK_TO_YOU will be sent +to each connected peer before disassociating the transport configuration +from the service and terminating the transport upon reception of +DPA or timeout.

+ + + + +
+
+ + + + +service_info(SvcName) -> Info +Return information about a started service. + +SvcName = service_name() +Info = [{Item, Value}] + + +

+Return information about a started service. +Equivalent to service_info(SvcName, all).

+ + +
+
+ + + + +service_info(SvcName, Item) -> Value +Return specific information about a started service. + +SvcName = service_name() +Value = term() + + +

+Return specific information about a started service.

+ + +
+
+ + + + +services() -> [SvcName] +Return the list of started services. + +SvcName = service_name() + + +

+Return the list of started services.

+ + +
+
+ + + + +session_id(Ident) -> OctetString() +Return a value for a Session-Id AVP + +Ident = DiameterIdentity() + + +

+Return a value for a Session-Id AVP. +The value has the form required by section 8.8 of RFC 3588. +Ident should be the Origin-Host of the peer from which +the message containing the returned value will be sent.

+ + +
+
+ + + +start_service(SvcName, Options) -> ok | {error, Reason} +Start a Diameter service + +SvcName = service_name() +Options = [service_opt()] +Reason = term() + + +

+Start a diameter service. +A service defines a locally-implemented Diameter peer, specifying the +capabilities of the peer to be used during capabilities exchange and +the Diameter applications that it supports. +Transports are added to a service using add_transport/2.

+ + +
+
+ + + +stop_service(SvcName) -> ok | {error, Reason} +Stops a Diameter service. + +SvcName = service_name() +Reason = term() + + +

+Stop a diameter service.

+ + +
+
+ + + + +subscribe(SvcName) -> true +Subscribe to event messages from a service. + +SvcName = service_name() + + +

+Subscribe to service_event() messages from a service.

+ +

+It is not an error to subscribe to events from a service +that does not yet exist.

+ + +
+
+ + + + +unsubscribe(SvcName) -> true + + +SvcName = service_name() + + +

+Unsubscribe to event messages from a service.

+ +
+
+ +
+ + + +
+SEE ALSO + +

+diameter_app(3), +diameter_transport(3), +diameter_dict(4)

+ +
+ +
-- cgit v1.2.3