diff options
-rw-r--r-- | lib/diameter/doc/src/.gitignore | 2 | ||||
-rw-r--r-- | lib/diameter/doc/src/Makefile | 31 | ||||
-rw-r--r-- | lib/diameter/doc/src/depend.sed | 34 | ||||
-rw-r--r-- | lib/diameter/doc/src/diameter.xml | 121 | ||||
-rw-r--r-- | lib/diameter/doc/src/diameter_app.xml | 184 | ||||
-rw-r--r-- | lib/diameter/doc/src/diameter_dict.xml | 69 | ||||
-rw-r--r-- | lib/diameter/doc/src/diameter_examples.xml | 5 | ||||
-rw-r--r-- | lib/diameter/doc/src/diameter_intro.xml | 58 | ||||
-rw-r--r-- | lib/diameter/doc/src/diameter_transport.xml | 2 | ||||
-rw-r--r-- | lib/diameter/doc/src/diameter_using.xml | 3 | ||||
-rw-r--r-- | lib/diameter/doc/src/notes.xml | 59 | ||||
-rw-r--r-- | lib/diameter/examples/server_cb.erl | 9 | ||||
-rw-r--r-- | lib/diameter/include/diameter.hrl | 2 | ||||
-rw-r--r-- | lib/diameter/src/app/.gitignore | 1 | ||||
-rw-r--r-- | lib/diameter/src/app/Makefile | 2 | ||||
-rw-r--r-- | lib/diameter/src/app/diameter.erl | 24 | ||||
-rw-r--r-- | lib/diameter/src/app/diameter_service.erl | 16 | ||||
-rw-r--r-- | lib/diameter/src/compiler/Makefile | 2 | ||||
-rw-r--r-- | lib/diameter/src/transport/Makefile | 2 |
19 files changed, 405 insertions, 221 deletions
diff --git a/lib/diameter/doc/src/.gitignore b/lib/diameter/doc/src/.gitignore new file mode 100644 index 0000000000..feeb378fd8 --- /dev/null +++ b/lib/diameter/doc/src/.gitignore @@ -0,0 +1,2 @@ + +/depend.mk diff --git a/lib/diameter/doc/src/Makefile b/lib/diameter/doc/src/Makefile index f2a91a88b7..1453138cb6 100644 --- a/lib/diameter/doc/src/Makefile +++ b/lib/diameter/doc/src/Makefile @@ -35,8 +35,10 @@ RELSYSDIR = $(RELEASE_PATH)/lib/$(APPLICATION)-$(VSN) # ---------------------------------------------------- include files.mk +XML_REF_FILES = $(XML_REF1_FILES) $(XML_REF3_FILES) $(XML_REF4_FILES) + XML_FILES = $(BOOK_FILES) $(XML_APPLICATION_FILES) \ - $(XML_REF1_FILES) $(XML_REF3_FILES) $(XML_REF4_FILES) \ + $(XML_REF_FILES) \ $(XML_PART_FILES) $(XML_CHAPTER_FILES) INTERNAL_HTML_FILES = $(TECHNICAL_DESCR_FILES:%.xml=$(HTMLDIR)/%.html) @@ -49,9 +51,7 @@ HTML_FILES = $(HTML_APP_FILES) $(HTML_EXTRA_FILES) $(HTML_PART_FILES) INFO_FILE = ../../info -HTML_REF_FILES = $(XML_REF1_FILES:%.xml=$(HTMLDIR)/%.html) \ - $(XML_REF3_FILES:%.xml=$(HTMLDIR)/%.html) \ - $(XML_REF4_FILES:%.xml=$(HTMLDIR)/%.html) +HTML_REF_FILES = $(XML_REF_FILES:%.xml=$(HTMLDIR)/%.html) HTML_CHAPTER_FILES = $(XML_CHAPTER_FILES:%.xml=$(HTMLDIR)/%.html) @@ -98,6 +98,7 @@ html: gifs $(HTML_REF_MAN_FILE) clean clean_docs: clean_pdf clean_html clean_man rm -f errs core *~ + rm -f depend.mk clean_pdf: rm -f $(PDFDIR)/* @@ -118,7 +119,9 @@ $(INDEX_TARGET): $(INDEX_SRC) $(APP_FILE) s/%UP_ONE_LEVEL%/..\/..\/..\/doc\/index.html/; \ s/%OFF_PRINT%/pdf\/diameter-$(VSN).pdf/' $< > $@ -depend debug opt: +depend: depend.mk + +debug opt: info: @echo "->Makefile<-" @@ -181,17 +184,13 @@ release_docs_spec: $(LOCAL)docs release_spec: -$(HTMLDIR)/diameter_app.html: diameter_app.xml -$(HTMLDIR)/diameter_compile.html: diameter_compile.xml -$(HTMLDIR)/diameter_debug.html: diameter_debug.xml -$(HTMLDIR)/diameter_dict.html: diameter_dict.xml -$(HTMLDIR)/diameter_intro.html: diameter_intro.xml -$(HTMLDIR)/diameter_run.html: diameter_run.xml -$(HTMLDIR)/diameter.html: diameter.xml -$(HTMLDIR)/diameter_tcp.html: diameter_tcp.xml -$(HTMLDIR)/diameter_transport.html: diameter_transport.xml -$(HTMLDIR)/diameter_soc.html: diameter_soc.xml -$(HTMLDIR)/diameter_sctp.html: diameter_sctp.xml +depend.mk: depend.sed $(XML_REF_FILES) $(XML_CHAPTER_FILES) Makefile + (for f in $(XML_REF_FILES) $(XML_CHAPTER_FILES); do \ + sed -f $< $$f | sed "s@%FILE%@`basename $$f .xml`@g"; \ + done) \ + > $@ + +-include depend.mk .PHONY: clean clean_html clean_man clean_pdf \ depend debug opt info \ diff --git a/lib/diameter/doc/src/depend.sed b/lib/diameter/doc/src/depend.sed new file mode 100644 index 0000000000..5973c4586e --- /dev/null +++ b/lib/diameter/doc/src/depend.sed @@ -0,0 +1,34 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 2011. 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. +# +# %CopyrightEnd% + +# +# Generate dependencies for html output. The output is further +# massaged in Makefile. +# + +/^<com>\([^<]*\)<\/com>/b rf +/^<module>\([^<]*\)<\/module>/b rf + +/^<chapter>/!d + +s@@$(HTMLDIR)/%FILE%.html: %FILE%.xml@ +q + +:rf +s@@$(HTMLDIR)/\1.html: %FILE%.xml@ +q diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml index 9774183a2a..36b6cbf0cf 100644 --- a/lib/diameter/doc/src/diameter.xml +++ b/lib/diameter/doc/src/diameter.xml @@ -415,6 +415,12 @@ eval(F) -> Evaluating an evaluable() <c>E</c> on an argument list <c>A</c> is meant in the sense of <c>eval([E|A])</c>.</p> +<p> +Beware of using local funs (that is, fun expressions not of the +form <c>fun Module:Name/Arity</c>) in situations in which the fun is +not short-lived and code is to be upgraded at runtime since any +processes retaining such a fun will have a reference to old code.</p> + <marker id="peer_filter"/> </item> @@ -712,7 +718,7 @@ transport.</p> <p> Unrecognized options are silently ignored but are returned unmodified by <seealso -marker="#service_info_1">service_info/1,2</seealso> and can be referred to +marker="#service_info">service_info/2</seealso> and can be referred to in predicate functions passed to <seealso marker="#remove_transport">remove_transport/2</seealso>.</p> @@ -739,7 +745,9 @@ marker="#remove_transport">remove_transport/2</seealso>.</p> </type> <desc> <p> -Add transport capability to a service. +Add transport capability to a service.</p> + +<p> The service will start a transport process(es) in order to establish a connection with the peer, either by connecting to the peer (<c>connect</c>) or by accepting incoming connection requests @@ -761,10 +769,8 @@ handling of DWR/DWA and required by RFC 3539 as well as for DPR/DPA.</p> <p> 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.</p> - -<p> +Note 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.</p> @@ -776,7 +782,7 @@ transports.</p> <!-- ===================================================================== --> <func> -<name>call(SvcName, App, Request, Options) -> Answer | {error, Reason}</name> +<name>call(SvcName, App, Request, Options) -> ok | Answer | {error, Reason}</name> <fsummary>Send a Diameter request message.</fsummary> <type> <v>SvcName = service_name()</v> @@ -794,15 +800,19 @@ Send a Diameter request message and possibly return the answer or error.</p> defined and callbacks to the corresponding callback module will follow as described below and in <seealso marker="diameter_app">diameter_app(3)</seealso>. -The call returns either when an answer message is received from the -peer or an error occurs, unless the <c>detach</c> option has been -specified. -If <c>detach</c> is not specified then the form of an <c>Answer</c> is -as returned from a <seealso -marker="diameter_app#handle_answer">handle_answer/4</seealso> or +Unless the <c>detach</c> option has been specified to cause an earlier +return, the call returns either when an answer message is received +from the peer or an error occurs. +In the case of an answer, the return value is as returned by a <seealso +marker="diameter_app#handle_answer">handle_answer/4</seealso> +callback. +In the case of an error, whether or not the error is returned directly +by diameter or from a <seealso marker="diameter_app#handle_error">handle_error/4</seealso> -callback.</p> +callback depends on whether or not the outgoing request is +successfully encoded for transmission from the peer, the cases being +documented below.</p> <p> If there are no suitable peers, or if @@ -888,7 +898,8 @@ attempt to send the request over the transport.</p> <p> Note that <c>{error, encode}</c> is the only return value which -guarantees that the request has not been sent over the transport.</p> +guarantees that the request has <em>not</em> been sent over the +transport.</p> <marker id="origin_state_id"/> </desc> @@ -902,9 +913,11 @@ guarantees that the request has not been sent over the transport.</p> <desc> <p> 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()) +outgoing messages.</p> + +<p> +The value returned is the number of seconds since 19680120T031408Z, +the first value that can be encoded as a Diameter Time(), at the time the diameter application was started.</p> <marker id="remove_transport"/> @@ -959,25 +972,7 @@ DPA or timeout.</p> <!-- TODO: document the timeout value, possibly make configurable. --> -<marker id="service_info_1"/> -</desc> -</func> - -<!-- ===================================================================== --> - -<func> -<name>service_info(SvcName) -> Info</name> -<fsummary>Return information about a started service.</fsummary> -<type> -<v>SvcName = service_name()</v> -<v>Info = [{Item, Value}]</v> -</type> -<desc> -<p> -Return information about a started service. -Equivalent to <c>service_info(SvcName, all)</c>.</p> - -<marker id="service_info_2"/> +<marker id="service_info"/> </desc> </func> @@ -992,7 +987,7 @@ Equivalent to <c>service_info(SvcName, all)</c>.</p> </type> <desc> <p> -Return specific information about a started service.</p> +Return information about a started service.</p> <marker id="services"/> </desc> @@ -1018,17 +1013,36 @@ Return the list of started services.</p> <func> <name>session_id(Ident) -> OctetString()</name> -<fsummary>Return a value for a Session-Id AVP</fsummary> +<fsummary>Return a value for a Session-Id AVP.</fsummary> <type> <v>Ident = DiameterIdentity()</v> </type> <desc> <p> -Return a value for a Session-Id AVP. +Return a value for a Session-Id AVP.</p> + +<p> 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.</p> +<marker id="start"/> +</desc> +</func> + +<!-- ===================================================================== --> +<func> +<name>start() -> ok | {error, Reason}</name> +<fsummary>Start the diameter application.</fsummary> +<desc> +<p> +Start the diameter application.</p> + +<p> +The diameter application must be started before starting a service. +In a production system this will typically be accomplished by a boot +file, not by calling <c>start/0</c> explicitly.</p> + <marker id="start_service"/> </desc> </func> @@ -1036,7 +1050,7 @@ the message containing the returned value will be sent.</p> <!-- ===================================================================== --> <func> <name>start_service(SvcName, Options) -> ok | {error, Reason}</name> -<fsummary>Start a Diameter service</fsummary> +<fsummary>Start a Diameter service.</fsummary> <type> <v>SvcName = service_name()</v> <v>Options = [service_opt()]</v> @@ -1044,7 +1058,9 @@ the message containing the returned value will be sent.</p> </type> <desc> <p> -Start a diameter service. +Start a diameter service.</p> + +<p> 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. @@ -1057,8 +1073,23 @@ marker="#add_transport">add_transport/2</seealso>.</p> <!-- ===================================================================== --> <func> +<name>stop() -> ok | {error, Reason}</name> +<fsummary>Stop the diameter application.</fsummary> +<desc> +<p> +Stop the diameter application.</p> + +<p> +</p> + +<marker id="stop_service"/> +</desc> +</func> + +<!-- ===================================================================== --> +<func> <name>stop_service(SvcName) -> ok | {error, Reason}</name> -<fsummary>Stops a Diameter service.</fsummary> +<fsummary>Stop a Diameter service.</fsummary> <type> <v>SvcName = service_name()</v> <v>Reason = term()</v> @@ -1075,7 +1106,7 @@ Stop a diameter service.</p> <func> <name>subscribe(SvcName) -> true</name> -<fsummary>Subscribe to event messages from a service.</fsummary> +<fsummary>Subscribe to event messages.</fsummary> <type> <v>SvcName = service_name()</v> </type> @@ -1095,7 +1126,7 @@ that does not yet exist.</p> <func> <name>unsubscribe(SvcName) -> true</name> -<fsummary></fsummary> +<fsummary>Unsubscribe to event messages.</fsummary> <type> <v>SvcName = service_name()</v> </type> diff --git a/lib/diameter/doc/src/diameter_app.xml b/lib/diameter/doc/src/diameter_app.xml index c2fecce768..fc359b9d1d 100644 --- a/lib/diameter/doc/src/diameter_app.xml +++ b/lib/diameter/doc/src/diameter_app.xml @@ -47,23 +47,12 @@ 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 +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> -<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> @@ -72,8 +61,8 @@ The functions themselves are of three distinct flavours:</p> <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> +<seealso marker="#peer_down">peer_down/3</seealso> signal the +attainment or loss of connectivity with a Diameter peer.</p> </item> <item> @@ -98,6 +87,17 @@ is called in response to an incoming Diameter request message.</p> </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> + <!-- ===================================================================== --> <!-- ===================================================================== --> @@ -131,8 +131,8 @@ 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> +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 @@ -144,7 +144,8 @@ as directed by the return value of a 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> +question (since relays agents must handle arbitrary request): messages +are sent exactly as specified.</p> </item> @@ -153,8 +154,8 @@ question: messages are sent exactly as specified.</p> <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> +Fields of a packet() record should not be set in return values except +as documented.</p> </item> <tag><c>peer_ref() = term()</c></tag> @@ -236,18 +237,18 @@ the callback module in question has been configured.</p> <desc> <p> Invoked when a transport connection has been lost following a previous -call to <seealso marker="peer_up">peer_up/3</seealso>.</p> +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) +<name>Mod:pick_peer(Candidates, 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>Candidates = [peer()]</v> <v>Peer = peer() | false</v> <v>SvcName = service_name()</v> <v>State = NewState = state()</v> @@ -266,11 +267,9 @@ 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> --> +<seealso marker="diameter#call">diameter:call/4</seealso>, and only +those which have indicated support for the Diameter application in +question.</p> <p> The return values <c>false</c> and <c>{false, State}</c> are @@ -326,13 +325,14 @@ A returned packet() should set the request to be encoded in its 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 +communicate transport data to the callback. +A returned packet() can also 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> +be preserved in the outgoing request, although this should typically +not be necessary and allows the callback to set header values +inappropriately. +A returned <c>length</c>, <c>cmd_code</c> or <c>application_id</c> is +ignored.</p> <p> Returning <c>{discard, Reason}</c> causes the request to be aborted @@ -361,7 +361,7 @@ 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 +argument packet() is as returned by the initial <c>prepare_request/3</c>.</p> <p> @@ -391,10 +391,12 @@ discarded}</c>.</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> +callback takes place unless the <c>detach</c> option was +specified.</p> <p> -The decoded answer record is in the <c>msg</c> field of <c>Packet</c>, +The decoded answer record is in the <c>msg</c> field of the argument +packet(), 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 @@ -414,8 +416,10 @@ 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. +to return <c>{error, failure} (unless the <c>detach</c> option was +specified)</c>. +In particular, 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> @@ -440,7 +444,8 @@ 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> +callback takes place (unless the <c>detach</c> option was +specified).</p> <p> Reason <c>timeout</c> indicates that an answer message has not been @@ -449,8 +454,7 @@ 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> +callback returned false.</p> <marker id="handle_request"/> </desc> @@ -463,40 +467,33 @@ callback returned false. <v>Packet = packet()</v> <v>SvcName = term()</v> <v>Peer = peer()</v> -<v>Action = Reply | NoReply | Relay | {eval, Action, ContF}</v> +<v>Action = Reply | {relay, Opts} | discard | {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> + | {protocol_error, 3000..3999}</v> +<v>Opts = diameter:call_opts()</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> +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 Diameter request message, the selected module being the one +incoming 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> +itself as defining either the application in question or the Relay +application.</p> <p> -The packet() in which the incoming request is communicated has the -following signature.</p> +The argument packet() has the following signature.</p> <code> #diameter_packet{header = #diameter_header{}, avps = [#diameter_avp{}], msg = record() | undefined, - errors = [integer() | {integer(), #diameter_avp{}}], + errors = ['Unsigned32'() | {'Unsigned32'(), #diameter_avp{}}], bin = binary(), transport_data = term()} </code> @@ -509,12 +506,16 @@ 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> +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 message() before sending it to the peer: +the returned message() 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 @@ -525,34 +526,59 @@ 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> +The semantics of each of the possible return values are as follows.</p> <taglist> -<tag><c>{reply, Answer}</c></tag> +<tag><c>{reply, message()}</c></tag> <item> <p> Send the specified answer message to the peer.</p> </item> -<tag><c>{relay, Opts}</c></tag> +<tag><c>{protocol_error, 3000..3999}</c></tag> <item> <p> -Relay a request to another peer.</p> -</item> - -<tag><c>{protocol_error, ResultCode}</c></tag> -<item> +Send an answer message to the peer containing the specified +protocol error. +Equivalent to</p> +<code> +{reply, ['answer-message' | Avps] +</code> <p> -Send an answer message to the peer containing the specified 3xxx -protocol error.</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> -RFC 3588 mandates that only answers with a 3xxx series +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, ResultCode}</c> -tuple will cause the request process in question to fail.</p> +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. +The appropriate Route-Record AVP will be added to the relayed request +by diameter and <seealso marker="#pick_peer">pick_peer/4</seealso> +and <seealso marker="#prepare_request">prepare_request/3</seealso> +callback will take place just as if <seealso +marker="diameter#call">diameter:call/4</seealso> had been called +explicitly. +However, returning a <c>relay</c> tuple also causes the End-to-End +Identifier to be preserved in the header of the relayed request as +required by RFC 3588.</p> + +<p> +The returned <c>Opts</c> should not specify <c>detach</c> and +the <seealso marker="#handle_answer">handle_answer/4</seealso> +callback following from a 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, +although the form of the request message may be sufficient.</p> </item> <tag><c>discard</c></tag> @@ -565,14 +591,14 @@ Discard the request.</p> <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> +evaluate <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> +request without invoking <c>handle_request/3</c>.</p> </desc> </func> diff --git a/lib/diameter/doc/src/diameter_dict.xml b/lib/diameter/doc/src/diameter_dict.xml index 5bc3cab9e4..a87f59bad5 100644 --- a/lib/diameter/doc/src/diameter_dict.xml +++ b/lib/diameter/doc/src/diameter_dict.xml @@ -48,37 +48,41 @@ to encode and decode its messages and AVP's. The dictionary module is in turn generated from a file that defines these messages and AVP's. The format of such a file is defined in -<seealso marker="#FILE_FORMAT">FILE FORMAT</seealso> below.</p> +<seealso marker="#FILE_FORMAT">FILE FORMAT</seealso> below. +Users add support for their specific applications by creating +dictionary files, compiling them to Erlang modules using +<seealso marker="diameterc">diameterc</seealso> and configuring the +resulting dictionaries modules on a service.</p> <p> -The codec generation also results in an hrl that defines records +The codec generation also results in a hrl file that defines records for the messages and grouped AVP's defined for the application, these -records being what a user of the diameter application sends and -receives. +records being what a user of the diameter application sends and receives. +(Modulo other available formats as discussed in <seealso +marker="diameter_app">diameter_app(3)</seealso>.) These records and the underlying Erlang data types corresponding to Diameter data formats are discussed in <seealso marker="#MESSAGE_RECORDS">MESSAGE RECORDS</seealso> and <seealso -marker="#DATA_TYPES">DATA TYPES</seealso> respectively.</p> - -<!-- TODO: Need some reserved dictionary for agents that shouldn't --> -<!-- know about specific applications. --> - -<p> -The diameter application defines the base application of RFC 3588 in -the file diameter_gen_base_rfc3588.dia, and -this is the only application that diameter itself has any specific -knowledge of. -Other applications are callback modules configured for an application -as far as diameter is concerned.</p> - -<p> -A generated hrl also contains defines for the values of defined for +marker="#DATA_TYPES">DATA TYPES</seealso> respectively. +The generated hrl also contains defines for the possible values of AVPs of type Enumerated.</p> <p> -See <seealso marker="diameter_compile">diameterc</seealso> for a -utility that transforms dictionary files into codec modules needed -at runtime.</p> +The diameter application includes three dictionary modules +corresponding to applications defined in section 2.4 of RFC 3588: +<c>diameter_gen_base_rfc3588</c> for the Diameter Common Messages +application with application identifier 0, +<c>diameter_gen_accounting</c> for the Diameter Base Accounting +application with application identifier 3 and +<c>diameter_gen_relay</c>the Relay application with application +identifier 0xFFFFFFFF. +The Common Message and Relay applications are the only applications +that diameter itself has any specific knowledge of. +The Common Message application is used for messages that diameter +itself handles: CER/CEA, DWR/DWA and DPR/DPA. +The Relay application is given special treatment with regard to +encode/decode since the messages and AVP's it handles are not specifically +defined.</p> <marker id="FILE_FORMAT"/> </description> @@ -89,7 +93,7 @@ at runtime.</p> <title>FILE FORMAT</title> <p> -A specification file consists of distinct sections. +A dictionary file consists of distinct sections. Each section starts with a line consisting of a tag followed by zero or more arguments. Each section ends at the the start of the next section or end of file. @@ -223,7 +227,7 @@ The section content is empty.</p> <p> Can occur 0 or more times (with different values of Mod) but all dictionaries should typically inherit RFC3588 AVPs from -diameter_gen_base_rfc3588.</p> +<c>diameter_gen_base_rfc3588</c>.</p> <p> Example:</p> @@ -248,7 +252,7 @@ M and P characters indicating the flags to be set on an outgoing AVP or a single - (minus) character if none are to be set. Type identifies either an AVP Data Format as defined in <seealso -marker="DATA_TYPES">DATA TYPES</seealso> below or a +marker="#DATA_TYPES">DATA TYPES</seealso> below or a type as defined by a <c>@custom_types</c> tag.</p> <p> @@ -263,7 +267,8 @@ Requested-Information 353 Enumerated V <p> Note that the P flag has been deprecated by the Diameter Maintenance -and Extensions Working Group of the IETF.</p> +and Extensions Working Group of the IETF: diameter will set the P flag +to 0 as mandated by the current draft standard.</p> </item> @@ -446,7 +451,7 @@ as values of the types defined here. Values are passed to <seealso marker="diameter#call">diameter:call/4</seealso> in a request record when sending a request, returned in a resulting -answer record and passed to a diameter_app(3) <seealso +answer record and passed to a <seealso marker="diameter_app#handle_request">handle_request</seealso> callback upon reception of an incoming request.</p> @@ -476,8 +481,8 @@ Grouped() = record() <p> On encode, an OctetString() can be specified as an iolist(), excessively large floats (in absolute value) are equivalent to -infinity or '-infinity' and excessively large integers result in -encode failure. +<c>infinity</c> or <c>'-infinity'</c> and excessively large integers +result in encode failure. The records for grouped AVPs are as discussed in the previous section.</p> @@ -583,7 +588,7 @@ QoSFilterRule() = OctetString() </code> <p> -Values of these types are not parsed by diameter.</p> +Values of these types are not currently parsed by diameter.</p> </section> @@ -594,7 +599,9 @@ Values of these types are not parsed by diameter.</p> <title>SEE ALSO</title> <p> -<seealso marker="diameter_util">diameterc(1)</seealso></p> +<seealso marker="diameterc">diameterc(1)</seealso>, +<seealso marker="diameter">diameter(3)</seealso>, +<seealso marker="diameter_app">diameter_app(3)</seealso></p> </section> diff --git a/lib/diameter/doc/src/diameter_examples.xml b/lib/diameter/doc/src/diameter_examples.xml index 344b237866..966d1f1eee 100644 --- a/lib/diameter/doc/src/diameter_examples.xml +++ b/lib/diameter/doc/src/diameter_examples.xml @@ -36,5 +36,10 @@ under the License. <!-- ===================================================================== --> +<p> +To be written. +Example code can be found in the diameter application's +<c>examples</c> subdirectory.</p> + </chapter> diff --git a/lib/diameter/doc/src/diameter_intro.xml b/lib/diameter/doc/src/diameter_intro.xml index 0009b2b77d..ef08002a8b 100644 --- a/lib/diameter/doc/src/diameter_intro.xml +++ b/lib/diameter/doc/src/diameter_intro.xml @@ -36,10 +36,60 @@ under the License. <p> The diameter application is an implementation of the Diameter protocol as defined by RFC 3588. -It supports arbitrary Diameter applications by allowing a client to -specify the commands and AVP's to be supported and has support for -implementing all roles defined in the RFC: client, server and agent. -</p> +It supports arbitrary Diameter applications by way of a +<em>dictionary</em> interface that allows messages and AVP's to be +defined and input into diameter as configuration. +It has support for all roles defined in the RFC: client, server and +agent. +This chapter provides a short overview of the application.</p> + +<p> +A Diameter peer is implemented by configuring a <em>service</em> and +one or more <em>transports</em> using the interface module +<seealso marker="diameter">diameter</seealso>. +The service configuration defines the Diameter applications to be +supported by the peer and, typically, the capabilities that it should +send to remote peers at capabilities exchange upon the establishment +of transport connections. +A transport is configured on a service and provides protocol-specific +send/receive functionality by way of a transport interface defined by +diameter and implemented by a transport module. +The diameter application provides two transport modules: <seealso +marker="diameter_tcp">diameter_tcp</seealso> and <seealso +marker="diameter_sctp">diameter_sctp</seealso> for transport over TCP +(using <c>gen_tcp</c>) and SCTP (using <c>gen_sctp</c>) respectively. +Other transports can be provided by any module that implements +diameter's <seealso marker="diameter_transport">transport +interface</seealso>.</p> + +<p> +While a service typically implements a single Diameter peer (as +identified by an Origin-Host AVP), transports can themselves be +associated with capabilities AVP's so that a single service be used to +implement more than one Diameter peer.</p> + +<p> +Each Diameter application defined on a service is configured with a +callback module that implements the <seealso +marker="diameter_app">application interface</seealso> through which +diameter communicates the connectivity of remote peers, requests peer +selection for outgoing requests, and communicates the reception of +incoming Diameter request and answer messages. +An application using diameter implements these application callback +modules to provide the functionality of the Diameter peer(s) it +implements.</p> + +<p> +Each Diameter application is also configured with one or more +dictionary modules +that provide encode/decode functionality for outgoing/incoming +Diameter messages. +A module is generated from a <seealso +marker="diameter_dict">specification file</seealso> using the <seealso +marker="diameterc">diameterc</seealso> utility. +Dictionaries for the RFC 3588 Diameter Common Messages, Base +Accounting and Relay applications are provided by the diameter +application.</p> </chapter> diff --git a/lib/diameter/doc/src/diameter_transport.xml b/lib/diameter/doc/src/diameter_transport.xml index be1bb2c56e..37cc871e75 100644 --- a/lib/diameter/doc/src/diameter_transport.xml +++ b/lib/diameter/doc/src/diameter_transport.xml @@ -33,7 +33,7 @@ under the License. </header> <module>diameter_transport</module> -<modulesummary>Diameter transport behaviour.</modulesummary> +<modulesummary>Diameter transport interface.</modulesummary> <description> diff --git a/lib/diameter/doc/src/diameter_using.xml b/lib/diameter/doc/src/diameter_using.xml index 737a0a3941..809b76bdf3 100644 --- a/lib/diameter/doc/src/diameter_using.xml +++ b/lib/diameter/doc/src/diameter_using.xml @@ -35,6 +35,9 @@ under the License. </header> +<p> +To be written.</p> + <!-- ===================================================================== --> </chapter> diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml index 8fdb88749e..eafddd7d1e 100644 --- a/lib/diameter/doc/src/notes.xml +++ b/lib/diameter/doc/src/notes.xml @@ -40,8 +40,65 @@ first.</p> <title>diameter 0.9</title> <p> -First OTP release.</p> +Initial release of the diameter application.</p> +<p> +Known issues or limitations:</p> + +<list> + +<item> +<p> +Some agent-related functionality is not entirely complete. +In particular, support for proxy agents, that advertise specific +Diameter applications but otherwise relay messages in much the same +way as relay agents (for which a <seealso +marker="diameter_app#handle_request">handle_request/3</seealso> +callback can return a <c>relay</c> tuple), will be completed in an +upcoming release. +There may also be more explicit support for redirect agents, although +redirect behaviour can be implemented with the current +functionality.</p> + +</item> + +<item> +<p> +There is some asymmetry in the treatment of messages sent as +<c>diameter_header/avp</c> records and those sent in the "normal" +fashion, and not all of this is documented. +This is related to the previous point since this form of sending a +message was introduced specifically to handle relay agent behaviour +using the same callback interface as for client/server behaviour.</p> +</item> + +<item> +<p> +The User's Guide is currently quite thin. +The introductory chapter followed by the examples (in the application +<c>examples</c> subdirectory) may be sufficient +for those having some familiarity with the Diameter protocol but the +intention is to provide more introductory text. +The reference documentation is quite complete, although some points +could likely be expanded upon.</p> +</item> + +<item> +<p> +The function <seealso +marker="diameter#service_info">diameter:service_info/2</seealso> +can be used to retrieve information about a started service +(statistics, information about connected peers, etc) but +this is not yet documented and both the input and output may change +in the next release.</p> +</item> + + +</list> + +<p> +See <seealso marker="diameter_soc">Standards Compliance</seealso> for +standards-related issues.</p> </section> </chapter> diff --git a/lib/diameter/examples/server_cb.erl b/lib/diameter/examples/server_cb.erl index b8705aedfc..43b8e24b5c 100644 --- a/lib/diameter/examples/server_cb.erl +++ b/lib/diameter/examples/server_cb.erl @@ -74,11 +74,8 @@ handle_request(#diameter_packet{msg = Req, errors = []}, _SvcName, {_, Caps}) {reply, answer(RT, Id, OH, OR)}; %% ... or one that wasn't. 3xxx errors are answered by diameter itself -%% but these are non-3xxx errors for which we must contruct a reply. -%% Returning a packet with the non-[] errors field will cause -%% diameter to add the appropriate result code and Failed-AVPs avps. -%% We just have to return the relevant answer record with any required -%% avps. +%% but these are 5xxx errors for which we must contruct a reply. +%% diameter will set Result-Code and Failed-AVP's. handle_request(#diameter_packet{msg = Req} = Pkt, _SvcName, {_, Caps}) when is_record(Req, diameter_base_RAR) -> #diameter_caps{origin_host = {OH,_}, @@ -91,7 +88,7 @@ handle_request(#diameter_packet{msg = Req} = Pkt, _SvcName, {_, Caps}) 'Origin-Realm' = OR, 'Session-Id' = Id}, - {reply, Pkt#diameter_packet{msg = Ans}}; + {reply, Ans}; %% Should really reply to other base messages that we don't support %% but simply discard them instead. diff --git a/lib/diameter/include/diameter.hrl b/lib/diameter/include/diameter.hrl index 8bd1ad1e51..0fa7fd406f 100644 --- a/lib/diameter/include/diameter.hrl +++ b/lib/diameter/include/diameter.hrl @@ -110,7 +110,7 @@ %% The diameter service and diameter_apps records are only passed %% through the transport interface when starting a transport process, %% although typically a transport implementation will (and probably -%% should) only be interested diameter_service.host_ip_address. +%% should) only be interested host_ip_address. -record(diameter_service, {pid, diff --git a/lib/diameter/src/app/.gitignore b/lib/diameter/src/app/.gitignore index 1310a0da6b..d388e61877 100644 --- a/lib/diameter/src/app/.gitignore +++ b/lib/diameter/src/app/.gitignore @@ -2,4 +2,5 @@ /diameter_gen_*.erl /diameter_gen_*.hrl /depend.mk +/diameter.mk diff --git a/lib/diameter/src/app/Makefile b/lib/diameter/src/app/Makefile index 8985ca4911..6de220d282 100644 --- a/lib/diameter/src/app/Makefile +++ b/lib/diameter/src/app/Makefile @@ -187,7 +187,7 @@ depend: depend.mk # has already been made since it's currently not smart enough to not # force a rebuild of those beams dependent on generated hrls, and this # is a no-no at make release. -depend.mk: depend.sed $(MODULES:%=%.erl) modules.mk Makefile +depend.mk: depend.sed $(MODULES:%=%.erl) Makefile (for f in $(MODULES); do \ sed -f $< $$f.erl | sed "s@/@/$$f@"; \ done) \ diff --git a/lib/diameter/src/app/diameter.erl b/lib/diameter/src/app/diameter.erl index 5f2ab82475..2f721421d8 100644 --- a/lib/diameter/src/app/diameter.erl +++ b/lib/diameter/src/app/diameter.erl @@ -35,7 +35,6 @@ %% Information. -export([services/0, - service_info/1, service_info/2]). %% Start/stop the application. In a "real" application this should @@ -44,12 +43,6 @@ -export([start/0, stop/0]). -%% Backwards compatibility. --export([add_connector/2, - add_listener/2, - remove_connector/2, - remove_listener/2]). - -include("diameter_internal.hrl"). -include("diameter_types.hrl"). @@ -109,7 +102,7 @@ services() -> [Name || {Name, _} <- diameter_service:services()]. %%% -------------------------------------------------------------------------- -%%% service_info/[12] +%%% service_info/2 %%% -------------------------------------------------------------------------- -spec service_info(service_name(), atom() | [atom()]) @@ -118,9 +111,6 @@ services() -> service_info(SvcName, Option) -> diameter_service:info(SvcName, Option). -service_info(SvcName) -> - service_info(SvcName, all). - %%% -------------------------------------------------------------------------- %%% add_transport/3 %%% -------------------------------------------------------------------------- @@ -133,12 +123,6 @@ add_transport(SvcName, {T, Opts} = Cfg) when is_list(Opts), (T == connect orelse T == listen) -> diameter_config:add_transport(SvcName, Cfg). -add_listener(SvcName, Opts) -> - add_transport(SvcName, {listen, Opts}). - -add_connector(SvcName, Opts) -> - add_transport(SvcName, {connect, Opts}). - %%% -------------------------------------------------------------------------- %%% remove_transport/2 %%% -------------------------------------------------------------------------- @@ -149,12 +133,6 @@ add_connector(SvcName, Opts) -> remove_transport(SvcName, Pred) -> diameter_config:remove_transport(SvcName, Pred). -remove_listener(SvcName, Pred) -> - remove_transport(SvcName, {listen, Pred}). - -remove_connector(SvcName, Pred) -> - remove_transport(SvcName, {connect, Pred}). - %%% -------------------------------------------------------------------------- %%% # subscribe(SvcName) %%% diff --git a/lib/diameter/src/app/diameter_service.erl b/lib/diameter/src/app/diameter_service.erl index 82a8d7a994..63b0649dc4 100644 --- a/lib/diameter/src/app/diameter_service.erl +++ b/lib/diameter/src/app/diameter_service.erl @@ -1278,18 +1278,15 @@ send_request({TPid, Caps, App}, Msg, Opts, Caller, SvcName) -> %% make_packet/1 %% %% Turn an outgoing request as passed to call/4 into a diameter_packet -%% record in preparation for a prepare_request callback. There are two -%% cases: a diameter_packet as argument when we're calling call/4 -%% ourselves in order to relay a request or a bare message in case the -%% call came by way of diameter:call/4. +%% record in preparation for a prepare_request callback. make_packet(Bin) when is_binary(Bin) -> #diameter_packet{header = diameter_codec:decode_header(Bin), bin = Bin}; -make_packet(#diameter_packet{msg = [#diameter_header{} | _]} = Pkt) -> - Pkt; +make_packet(#diameter_packet{msg = [#diameter_header{} = Hdr | Avps]} = Pkt) -> + Pkt#diameter_packet{msg = [make_header(Hdr) | Avps]}; make_packet(#diameter_packet{header = Hdr} = Pkt) -> Pkt#diameter_packet{header = make_header(Hdr)}; @@ -1955,6 +1952,7 @@ is_loop(Code, Vid, OH, Avps) -> %% %% Send a locally originating reply. +%% No errors or a diameter_header/avp list. reply(Msg, Dict, TPid, #diameter_packet{errors = Es, transport_data = TD} = ReqPkt) @@ -1964,11 +1962,7 @@ reply(Msg, Dict, TPid, #diameter_packet{errors = Es, incr(send, Pkt, Dict, TPid), %% count result codes in sent answers send(TPid, Pkt#diameter_packet{transport_data = TD}); -%% Simplify the handling of error cases by accepting a list consisting -%% of an answer record followed by failed AVPs to be packed into a -%% Failed-AVP field, either directly or into an AVP field. Only if -%% the message is a tuple-list or record however, not a list -%% with a list of #diameter_header{} and #diameter_avp{}. +%% Or not: set Result-Code and Failed-AVP AVP's. reply(Msg, Dict, TPid, #diameter_packet{errors = [H|_] = Es} = Pkt) -> reply(rc(Msg, rc(H), [A || {_,A} <- Es], Dict), Dict, diff --git a/lib/diameter/src/compiler/Makefile b/lib/diameter/src/compiler/Makefile index 8512eb515a..3ab76064ac 100644 --- a/lib/diameter/src/compiler/Makefile +++ b/lib/diameter/src/compiler/Makefile @@ -130,7 +130,7 @@ force: depend: depend.mk # Generate dependencies makefile. -depend.mk: ../app/depend.sed $(ERL_FILES) modules.mk Makefile +depend.mk: ../app/depend.sed $(ERL_FILES) Makefile for f in $(MODULES); do \ sed -f $< $$f.erl | sed "s@/@/$$f@"; \ done \ diff --git a/lib/diameter/src/transport/Makefile b/lib/diameter/src/transport/Makefile index 5dc1772796..4b53100fd2 100644 --- a/lib/diameter/src/transport/Makefile +++ b/lib/diameter/src/transport/Makefile @@ -130,7 +130,7 @@ force: depend: depend.mk # Generate dependencies makefile. -depend.mk: ../app/depend.sed $(ERL_FILES) modules.mk Makefile +depend.mk: ../app/depend.sed $(ERL_FILES) Makefile for f in $(MODULES); do \ sed -f $< $$f.erl | sed "s@/@/$$f@"; \ done \ |