diff options
Diffstat (limited to 'lib/diameter')
31 files changed, 655 insertions, 127 deletions
diff --git a/lib/diameter/Makefile b/lib/diameter/Makefile index 9961d627cf..aa1c9f7f20 100644 --- a/lib/diameter/Makefile +++ b/lib/diameter/Makefile @@ -1,7 +1,7 @@ -# +# # %CopyrightBegin% # -# Copyright Ericsson AB 2010-2012. All Rights Reserved. +# Copyright Ericsson AB 2010-2013. 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 @@ -22,11 +22,11 @@ include vsn.mk include subdirs.mk SUB_DIRECTORIES = $(SUB_DIRS) doc/src -SPECIAL_TARGETS = +SPECIAL_TARGETS = include $(ERL_TOP)/make/otp_subdir.mk -info: +info: @echo "APP_VSN = $(APP_VSN)" .PHONY: info diff --git a/lib/diameter/doc/src/Makefile b/lib/diameter/doc/src/Makefile index 99a6680f12..bd2b6b103a 100644 --- a/lib/diameter/doc/src/Makefile +++ b/lib/diameter/doc/src/Makefile @@ -1,4 +1,4 @@ -# +# # %CopyrightBegin% # # Copyright Ericsson AB 2010-2013. All Rights Reserved. @@ -117,7 +117,7 @@ info: # ---------------------------------------------------- # Release Target -# ---------------------------------------------------- +# ---------------------------------------------------- include $(ERL_TOP)/make/otp_release_targets.mk diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml index 318c98f786..db19fbb271 100644 --- a/lib/diameter/doc/src/diameter.xml +++ b/lib/diameter/doc/src/diameter.xml @@ -1,5 +1,7 @@ <?xml version="1.0" encoding="latin1" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd" [ + <!ENTITY spawn_opt + '<seealso marker="erts:erlang#spawn_opt-2">erlang:spawn_opt/2</seealso>'> <!ENTITY nodes '<seealso marker="erts:erlang#nodes-0">erlang:nodes/0</seealso>'> <!ENTITY make_ref @@ -27,12 +29,12 @@ 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(3)</title> @@ -871,6 +873,18 @@ of a single Diameter node across multiple Erlang nodes.</p> </note> </item> +<tag><c>{spawn_opt, [term()]}</c></tag> +<item> +<p> +An options list passed to &spawn_opt; when spawning a process for an +incoming Diameter request, unless the transport in question +specifies another value. +Options <c>monitor</c> and <c>link</c> are ignored.</p> + +<p> +Defaults to the empty list.</p> +</item> + <tag><c>{use_shared_peers, boolean() | [node()] | evaluable()}</c></tag> <item> <p> @@ -1161,6 +1175,18 @@ Defaults to 30000 for a connecting transport and 60000 for a listening transport.</p> </item> +<marker id="spawn_opt"/> +<tag><c>{spawn_opt, [term()]}</c></tag> +<item> +<p> +An options list passed to &spawn_opt; when spawning a process for an +incoming Diameter request. +Options <c>monitor</c> and <c>link</c> are ignored.</p> + +<p> +Defaults to the list configured on the service if not specified.</p> +</item> + <marker id="transport_config"/> <tag><c>{transport_config, term()}</c></tag> <tag><c>{transport_config, term(), &dict_Unsigned32; | infinity}</c></tag> @@ -1626,7 +1652,7 @@ The <c>caps</c> entry identifies the capabilities sent by the local node and received from the peer during capabilities exchange. The <c>port</c> entry displays socket-level information about the transport connection. -The <c>statistics</c> entry presents Diameter-level counters, +The <c>statistics</c> entry presents Diameter-level counters, an entry like <c>{{{0,280,1},recv},2}</c> saying that the client has received 2 DWR messages: <c>{0,280,1} = {Application_Id, Command_Code, R_Flag}</c>.</p> diff --git a/lib/diameter/doc/src/diameter_compile.xml b/lib/diameter/doc/src/diameter_compile.xml index fc81e4efed..6630019e5c 100644 --- a/lib/diameter/doc/src/diameter_compile.xml +++ b/lib/diameter/doc/src/diameter_compile.xml @@ -16,9 +16,9 @@ </copyright> <legalnotice> -The program may be used and/or copied only with the written permission -from Ericsson AB, or in accordance with the terms and conditions -stipulated in the agreement/contract under which the program has been +The program may be used and/or copied only with the written permission +from Ericsson AB, or in accordance with the terms and conditions +stipulated in the agreement/contract under which the program has been supplied. </legalnotice> diff --git a/lib/diameter/doc/src/diameter_dict.xml b/lib/diameter/doc/src/diameter_dict.xml index 419dc143af..4fcde495b3 100644 --- a/lib/diameter/doc/src/diameter_dict.xml +++ b/lib/diameter/doc/src/diameter_dict.xml @@ -25,12 +25,12 @@ 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_dict(4)</title> diff --git a/lib/diameter/doc/src/diameter_intro.xml b/lib/diameter/doc/src/diameter_intro.xml index fd578ccf45..288ebc0c7c 100644 --- a/lib/diameter/doc/src/diameter_intro.xml +++ b/lib/diameter/doc/src/diameter_intro.xml @@ -7,7 +7,7 @@ <chapter> <header> <copyright> -<year>2011</year><year>2012</year> +<year>2011</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> @@ -17,12 +17,12 @@ 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>Introduction</title> diff --git a/lib/diameter/doc/src/diameter_sctp.xml b/lib/diameter/doc/src/diameter_sctp.xml index df140b16b9..5fe14b1ef6 100644 --- a/lib/diameter/doc/src/diameter_sctp.xml +++ b/lib/diameter/doc/src/diameter_sctp.xml @@ -70,10 +70,15 @@ and implements the behaviour documented in <v>Type = connect | accept</v> <v>Ref = &mod_transport_ref;</v> <v>Svc = #diameter_service{}</v> -<v>Opt = {raddr, &ip_address;} | {rport, integer()} | term()</v> +<v>Opt = OwnOpt | SctpOpt</v> <v>Pid = pid()</v> <v>LAddr = &ip_address;</v> <v>Reason = term()</v> +<v>OwnOpt = {raddr, &ip_address;} + | {rport, integer()} + | {accept, Match}</v> +<v>SctpOpt = term()</v> +<v>Match = &ip_address; | string() | [Match]</v> </type> <desc> @@ -85,9 +90,20 @@ Options <c>raddr</c> and <c>rport</c> specify the remote address and port for a connecting transport and not valid for a listening transport: the former is required while latter defaults to 3868 if unspecified. -More than one <c>raddr</c> option can be specified, in which case the +Mupltiple <c>raddr</c> options can be specified, in which case the connecting transport in question attempts each in sequence until -an association is established. +an association is established.</p> + +<p> +Option <c>accept</c> specifies remote addresses for a listening +transport and is not valid for a connecting transport. +If specified, a remote address that does not match one of the +specified addresses causes the association to be aborted. +Multiple <c>accept</c> options can be specified. +A string-valued <c>Match</c> that does not parse as an address is +interpreted as a regular expression.</p> + +<p> Remaining options are any accepted by &gen_sctp_open1;, with the exception of options <c>mode</c>, <c>binary</c>, <c>list</c>, <c>active</c> and <c>sctp_events</c>. diff --git a/lib/diameter/doc/src/diameter_tcp.xml b/lib/diameter/doc/src/diameter_tcp.xml index 8e509aa829..ce4d6cfd0f 100644 --- a/lib/diameter/doc/src/diameter_tcp.xml +++ b/lib/diameter/doc/src/diameter_tcp.xml @@ -96,10 +96,12 @@ before configuring TLS capability on diameter transports.</p> <v>Reason = term()</v> <v>OwnOpt = {raddr, &ip_address;} | {rport, integer()} + | {accept, Match} | {port, integer()} | {fragment_timer, infinity | 0..16#FFFFFFFF}</v> <v>SslOpt = {ssl_options, true | list()}</v> <v>TcpOpt = term()</v> +<v>Match = &ip_address; | string() | [Match]</v> </type> <desc> @@ -109,7 +111,18 @@ The start function required by &man_transport;.</p> <p> Options <c>raddr</c> and <c>rport</c> specify the remote address and port for a connecting transport and are not valid for a listening -transport. +transport.</p> + +<p> +Option <c>accept</c> specifies remote addresses for a listening +transport and is not valid for a connecting transport. +If specified, a remote address that does not match one of the +specified addresses causes the connection to be aborted. +Multiple <c>accept</c> options can be specified. +A string-valued <c>Match</c> that does not parse as an address is +interpreted as a regular expression.</p> + +<p> Option <c>ssl_options</c> must be specified for a transport that should support TLS: a value of <c>true</c> results in a TLS handshake immediately upon connection establishment while diff --git a/lib/diameter/doc/src/diameter_using.xml b/lib/diameter/doc/src/diameter_using.xml index 7d9c0cd492..c487d94a16 100644 --- a/lib/diameter/doc/src/diameter_using.xml +++ b/lib/diameter/doc/src/diameter_using.xml @@ -5,7 +5,7 @@ <header> <copyright> -<year>2011</year><year>2012</year> +<year>2011</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> @@ -15,12 +15,12 @@ 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>Usage</title> diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml index ad61f12b5b..e750b56f1e 100644 --- a/lib/diameter/doc/src/notes.xml +++ b/lib/diameter/doc/src/notes.xml @@ -42,6 +42,229 @@ first.</p> <!-- ===================================================================== --> +<section><title>diameter 1.4.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix handling of 5014 (INVALID_AVP_LENGTH) errors.</p> + <p> + This was in some cases reported as 3009 + (INVALID_AVP_BITS).</p> + <p> + Note that the correction is partially implemented in + modules generated by diameterc(1): a dictionary file must + be recompiled for the correction to apply to any messages + it defines.</p> + <p> + Own Id: OTP-11007</p> + </item> + <item> + <p> + Fix faulty capitalization in release notes.</p> + <p> + Diameter = the protocol.<br/> diameter = the Erlang + application.</p> + <p> + Own Id: OTP-11014</p> + </item> + <item> + <p> + Fix watchdog memory leak.</p> + <p> + Entries were not removed from a service-specific ets + table, causing them to be orphaned at connection + reestablishment for listening transports, and + diameter:remove_transport/2 for both listening and + connecting transports.</p> + <p> + The fault was introduced by OTP-10692 in diameter-1.4.1 + (R16B).</p> + <p> + Own Id: OTP-11019 Aux Id: OTP-10692 </p> + </item> + <item> + <p> + Fix decode failure on AVP Length < 8.</p> + <p> + The failure caused the message in question to be + discarded.</p> + <p> + Own Id: OTP-11026</p> + </item> + <item> + <p> + Respect Host-IP-Address configuration.</p> + <p> + Addresses returned from a transport module were always + used to populate Host-IP-Address AVP's in an outgoing + CER/CEA, which precluded the sending of a VIP address. + Transport addresses are now only used if Host-IP-Address + is unspecified.</p> + <p> + Own Id: OTP-11045</p> + </item> + <item> + <p> + Fix mkdir race.</p> + <p> + Install could fail if examples/code and examples/dict + were created in parallel. Noticed on FreeBSD.</p> + <p> + Own Id: OTP-11051</p> + </item> + <item> + <p> + Fix recognition of 5001 on mandatory AVP's.</p> + <p> + An AVP setting the M-bit was not regarded as erroneous if + it was defined in the dictionary in question and its + container (message or Grouped AVP) had an 'AVP' field. + It's now regarded as a 5001 error (AVP_UNSUPPORTED), as + in the case that the AVP is not defined.</p> + <p> + Note that the correction is partially implemented in + modules generated by diameterc(1): a dictionary file must + be recompiled for the correction to apply to any messages + it defines.</p> + <p> + Own Id: OTP-11087</p> + </item> + <item> + <p> + Fix setting of Failed-AVP on handle_request + {answer_message, 5xxx} return.</p> + <p> + Failed-AVP was never in the outgoing answer-message. It + is now set with the AVP from the first entry with the + specified Result-Code in the errors field of the incoming + diameter_packet, if found.</p> + <p> + Own Id: OTP-11092</p> + </item> + <item> + <p> + Fix watchdog function_clause</p> + <p> + A listening transport on a service that allowed multiple + connections to the same peer could result in a + function_clause error in module diameter_watchdog. The + resulting crash was harmless but unseemly.</p> + <p> + Thanks to Aleksander Nycz.</p> + <p> + Own Id: OTP-11115</p> + </item> + <item> + <p> + Fix population of Failed-AVP.</p> + <p> + In cases in which diameter populated this AVP, many + values were sent instead of one as suggested by RFC 6733. + This was partially corrected by OTP-11007.</p> + <p> + Own Id: OTP-11127 Aux Id: OTP-11007 </p> + </item> + <item> + <p> + Fix list-valued Vendor-Specific-Application-Id config</p> + <p> + R16B (specifically, OTP-10760) broke the handling of such + configuration, resulting in a function clause error if + the list was not of length 3, and faulty interpretation + of the list's contents otherwise. Only record-valued + configuration was properly interpreted.</p> + <p> + Own Id: OTP-11165</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Allow peer connections to be shared between Erlang nodes + for the purpose of sending outgoing requests.</p> + <p> + A diameter_app(3) pick_peer/4 callback gets a list of + remote candidates as argument, allowing a callback on one + node to select a transport connection established on + another node. The service_opt() share_peers controls the + extent to which local connections are shared with remote + nodes. The service_opt() use_shared_peers controls the + extent to which connections shared from remote nodes are + utilized on the local node.</p> + <p> + Own Id: OTP-9610</p> + </item> + <item> + <p> + Allow listening diameter_{tcp,sctp} transports to be + configured with remote addresses.</p> + <p> + Option 'accept' allows remote addresses to be configured + as tuples or regular expressions. Remote addresses are + matched against the configured values at connection + establishment, any non-matching address causing the + connection to be aborted.</p> + <p> + Own Id: OTP-10893</p> + </item> + <item> + <p> + Detect more transport_opt() configuration errors at + diameter:add_transport/2.</p> + <p> + Many errors would previously not be detected until + transport start, diameter:add_transport/2 returning 'ok' + but transport connections failing to be established. An + error tuple is now returned.</p> + <p> + Own Id: OTP-10972</p> + </item> + <item> + <p> + Make explicit local address configuration optional in + diameter_tcp:start/3.</p> + <p> + The default address (as determined by gen_tcp) is now + used when a local address is not explicitly configured.</p> + <p> + Own Id: OTP-10986</p> + </item> + <item> + <p> + Improve handling of unrecognized service options.</p> + <p> + Such options were silently ignored by + diameter:start_service/2. An error tuple is now returned.</p> + <p> + Own Id: OTP-11017</p> + </item> + <item> + <p> + Don't send default Inband-Security-Id in CER/CEA.</p> + <p> + RFC 6733 recommends against the use of + Inband-Security-Id. Only send a value that differs from + the default, NO_INBAND_SECURITY = 0.</p> + <p> + Own Id: OTP-11050</p> + </item> + <item> + <p> + Make spawn options for request processes configurable.</p> + <p> + Own Id: OTP-11060</p> + </item> + </list> + </section> + +</section> + <section><title>diameter 1.4.1.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/diameter/src/Makefile b/lib/diameter/src/Makefile index c0cf418f06..578bbaee2e 100644 --- a/lib/diameter/src/Makefile +++ b/lib/diameter/src/Makefile @@ -1,19 +1,19 @@ -# +# # %CopyrightBegin% -# +# # Copyright Ericsson AB 2010-2013. 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% include $(ERL_TOP)/make/target.mk diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl index 57730cad61..77200cc7d0 100644 --- a/lib/diameter/src/base/diameter.erl +++ b/lib/diameter/src/base/diameter.erl @@ -306,7 +306,8 @@ call(SvcName, App, Message) -> | {restrict_connections, restriction()} | {sequence, sequence() | evaluable()} | {share_peers, remotes()} - | {use_shared_peers, remotes()}. + | {use_shared_peers, remotes()} + | {spawn_opt, list()}. -type application_opt() :: {alias, app_alias()} @@ -345,6 +346,7 @@ call(SvcName, App, Message) -> | {reconnect_timer, 'Unsigned32'()} | {watchdog_timer, 'Unsigned32'() | {module(), atom(), list()}} | {watchdog_config, [{okay|suspect, non_neg_integer()}]} + | {spawn_opt, list()} | {private, any()}. %% Predicate passed to remove_transport/2 diff --git a/lib/diameter/src/base/diameter_capx.erl b/lib/diameter/src/base/diameter_capx.erl index 4b821f5139..1a931a9854 100644 --- a/lib/diameter/src/base/diameter_capx.erl +++ b/lib/diameter/src/base/diameter_capx.erl @@ -419,12 +419,13 @@ app_union(#diameter_caps{auth_application_id = U, vendor_specific_application_id = V}) -> set_list(U ++ C ++ lists:flatmap(fun vsa_apps/1, V)). -vsa_apps([_ | [_,_] = Ids]) -> - lists:append(Ids); +vsa_apps(Vals) + when is_list(Vals) -> + lists:flatmap(fun({'Vendor-Id', _}) -> []; ({_, Ids}) -> Ids end, Vals); vsa_apps(Rec) when is_tuple(Rec) -> - [_|T] = tuple_to_list(Rec), - vsa_apps(T). + [_Name, _VendorId | Idss] = tuple_to_list(Rec), + lists:append(Idss). %% It's a configuration error for a locally advertised application not %% to be represented in Apps. Don't just match on lists:keyfind/3 in diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl index 6c0e73de36..1d647b8c87 100644 --- a/lib/diameter/src/base/diameter_codec.erl +++ b/lib/diameter/src/base/diameter_codec.erl @@ -204,7 +204,7 @@ msg_header(Mod, 'answer-message' = MsgName, Header) -> #diameter_header{application_id = Aid, cmd_code = Code} = Header, - {-1, Flags, ?DIAMETER_APP_ID_COMMON} = Mod:msg_header(MsgName), + {-1, Flags, ?APP_ID_COMMON} = Mod:msg_header(MsgName), {Code, Flags, Aid}; msg_header(Mod, MsgName, _) -> diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl index 2a145c874b..fc5c284bf2 100644 --- a/lib/diameter/src/base/diameter_config.erl +++ b/lib/diameter/src/base/diameter_config.erl @@ -549,6 +549,9 @@ opt({watchdog_timer, Tmo}) -> opt({watchdog_config, L}) -> is_list(L) andalso lists:all(fun wdopt/1, L); +opt({spawn_opt, Opts}) -> + is_list(Opts); + %% Options that we can't validate. opt({K, _}) when K == transport_config; @@ -632,7 +635,8 @@ make_config(SvcName, Opts) -> {false, use_shared_peers}, {false, monitor}, {?NOMASK, sequence}, - {nodes, restrict_connections}]), + {nodes, restrict_connections}, + {[], spawn_opt}]), #service{name = SvcName, rec = #diameter_service{applications = Apps, @@ -647,6 +651,9 @@ make_opts(Opts, Defs) -> [{K, opt(K,V)} || {K,V} <- Known]. +opt(spawn_opt, L) -> + is_list(L); + opt(K, false = B) when K /= sequence -> B; diff --git a/lib/diameter/src/base/diameter_peer.erl b/lib/diameter/src/base/diameter_peer.erl index 0d2efd4d1f..e5d4b28766 100644 --- a/lib/diameter/src/base/diameter_peer.erl +++ b/lib/diameter/src/base/diameter_peer.erl @@ -25,7 +25,8 @@ -export([recv/2, up/1, up/2, - up/3]). + up/3, + match/2]). %% ... and the stack. -export([start/1, @@ -63,16 +64,16 @@ -define(DEFAULT_TCFG, []). -define(DEFAULT_TTMO, infinity). -%%% --------------------------------------------------------------------------- -%%% # notify/3 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # notify/3 +%% --------------------------------------------------------------------------- notify(Nodes, SvcName, T) -> rpc:abcast(Nodes, ?SERVER, {notify, SvcName, T}). -%%% --------------------------------------------------------------------------- -%%% # start/1 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # start/1 +%% --------------------------------------------------------------------------- -spec start({T, [Opt], #diameter_service{}}) -> {TPid, [Addr], Tmo, Data} @@ -180,9 +181,34 @@ start(T, [M|Ms], Cfg, Svc, Tmo, Rest, Errs) -> start(Mod, Args) -> apply(Mod, start, Args). -%%% --------------------------------------------------------------------------- -%%% # up/1-3 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # match/2 +%% --------------------------------------------------------------------------- + +match(Addrs, Matches) + when is_list(Addrs) -> + lists:all(fun(A) -> match1(A, Matches) end, Addrs). + +match1(Addr, Matches) + when not is_integer(hd(Matches)) -> + lists:any(fun(M) -> match1(Addr, M) end, Matches); + +match1(Addr, Match) -> + match(Addr, addr(Match), Match). + +match(Addr, {ok, A}, _) -> + Addr == A; +match(Addr, {error, _}, RE) -> + match == re:run(inet_parse:ntoa(Addr), RE, [{capture, none}]). + +addr([_|_] = A) -> + inet_parse:address(A); +addr(A) -> + {ok, A}. + +%% --------------------------------------------------------------------------- +%% # up/1-3 +%% --------------------------------------------------------------------------- up(Pid) -> %% accepting transport ifc_send(Pid, {self(), connected}). @@ -193,16 +219,16 @@ up(Pid, Remote) -> %% connecting transport up(Pid, Remote, LAddrs) -> %% connecting transport ifc_send(Pid, {self(), connected, Remote, LAddrs}). -%%% --------------------------------------------------------------------------- -%%% # recv/2 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # recv/2 +%% --------------------------------------------------------------------------- recv(Pid, Pkt) -> ifc_send(Pid, {recv, Pkt}). -%%% --------------------------------------------------------------------------- -%%% # send/2 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # send/2 +%% --------------------------------------------------------------------------- send(Pid, #diameter_packet{transport_data = undefined, bin = Bin}) -> @@ -211,16 +237,16 @@ send(Pid, #diameter_packet{transport_data = undefined, send(Pid, Pkt) -> ifc_send(Pid, {send, Pkt}). -%%% --------------------------------------------------------------------------- -%%% # close/1 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # close/1 +%% --------------------------------------------------------------------------- close(Pid) -> ifc_send(Pid, {close, self()}). -%%% --------------------------------------------------------------------------- -%%% # abort/1 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # abort/1 +%% --------------------------------------------------------------------------- abort(Pid) -> exit(Pid, shutdown). @@ -241,16 +267,16 @@ state() -> uptime() -> call(uptime). -%%% ---------------------------------------------------------- -%%% # init(Role) -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # init(Role) +%% ---------------------------------------------------------- init([]) -> {ok, #state{}}. -%%% ---------------------------------------------------------- -%%% # handle_call(Request, From, State) -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # handle_call(Request, From, State) +%% ---------------------------------------------------------- handle_call(state, _, State) -> {reply, State, State}; @@ -262,17 +288,17 @@ handle_call(Req, From, State) -> ?UNEXPECTED([Req, From]), {reply, nok, State}. -%%% ---------------------------------------------------------- -%%% # handle_cast(Request, State) -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # handle_cast(Request, State) +%% ---------------------------------------------------------- handle_cast(Msg, State) -> ?UNEXPECTED([Msg]), {noreply, State}. -%%% ---------------------------------------------------------- -%%% # handle_info(Request, State) -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # handle_info(Request, State) +%% ---------------------------------------------------------- %% Remote service is distributing a message. handle_info({notify, SvcName, T}, S) -> diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl index 112e83476d..9dd8aafc61 100644 --- a/lib/diameter/src/base/diameter_service.erl +++ b/lib/diameter/src/base/diameter_service.erl @@ -770,10 +770,8 @@ start(Ref, Type, Opts, #state{watchdogT = WatchdogT, = Svc = merge_service(Opts, Svc0), {_,_} = Mask = proplists:get_value(sequence, SvcOpts), - Pid = s(Type, Ref, {diameter_traffic:make_recvdata([SvcName, - PeerT, - Apps, - Mask]), + RecvData = diameter_traffic:make_recvdata([SvcName, PeerT, Apps, Mask]), + Pid = s(Type, Ref, {{spawn_opts([Opts, SvcOpts]), RecvData}, Opts, SvcOpts, Svc}), @@ -787,6 +785,12 @@ start(Ref, Type, Opts, #state{watchdogT = WatchdogT, %% record so that each watchdog may get a different record. This %% record is what is passed back into application callbacks. +spawn_opts(Optss) -> + SpawnOpts = get_value(spawn_opt, Optss, []), + [T || T <- SpawnOpts, + T /= link, + T /= monitor]. + s(Type, Ref, T) -> {_MRef, Pid} = diameter_watchdog:start({Type, Ref}, T), Pid. @@ -986,6 +990,18 @@ keyfind([Key | Rest], Pos, L) -> T end. +%% get_value/3 + +get_value(_, [], Def) -> + Def; +get_value(Key, [L | Rest], Def) -> + case lists:keyfind(Key, 1, L) of + {_,V} -> + V; + _ -> + get_value(Key, Rest, Def) + end. + %% find_outgoing_app/2 find_outgoing_app(Alias, Apps) -> diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl index 0b15e68ec7..8b6f026b34 100644 --- a/lib/diameter/src/base/diameter_traffic.erl +++ b/lib/diameter/src/base/diameter_traffic.erl @@ -48,6 +48,7 @@ -define(BASE, ?DIAMETER_DICT_COMMON). %% Note: the RFC 3588 dictionary -define(DEFAULT_TIMEOUT, 5000). %% for outgoing requests +-define(DEFAULT_SPAWN_OPTS, []). %% Table containing outgoing requests for which a reply has yet to be %% received. @@ -153,13 +154,8 @@ receive_message(TPid, Pkt, Dict0, RecvData) RecvData). %% Incoming request ... -recv(true, false, TPid, Pkt, Dict0, RecvData) -> - try - spawn(fun() -> recv_request(TPid, Pkt, Dict0, RecvData) end) - catch - error: system_limit = E -> %% discard - ?LOG({error, E}, now()) - end; +recv(true, false, TPid, Pkt, Dict0, T) -> + spawn_request(TPid, Pkt, Dict0, T); %% ... answer to known request ... recv(false, #request{ref = Ref, handler = Pid} = Req, _, Pkt, Dict0, _) -> @@ -177,6 +173,21 @@ recv(false, #request{ref = Ref, handler = Pid} = Req, _, Pkt, Dict0, _) -> recv(false, false, _, _, _, _) -> ok. +%% spawn_request/4 + +spawn_request(TPid, Pkt, Dict0, {Opts, RecvData}) -> + spawn_request(TPid, Pkt, Dict0, Opts, RecvData); +spawn_request(TPid, Pkt, Dict0, RecvData) -> + spawn_request(TPid, Pkt, Dict0, ?DEFAULT_SPAWN_OPTS, RecvData). + +spawn_request(TPid, Pkt, Dict0, Opts, RecvData) -> + try + spawn_opt(fun() -> recv_request(TPid, Pkt, Dict0, RecvData) end, Opts) + catch + error: system_limit = E -> %% discard + ?LOG({error, E}, now()) + end. + %% --------------------------------------------------------------------------- %% recv_request/4 %% --------------------------------------------------------------------------- @@ -780,7 +791,7 @@ failed([MsgName | Values], FailedAvp, Dict) -> %% ... or record. failed(Rec, FailedAvp, Dict) -> try - RecName = element(1, Rec), + RecName = element(1, Rec), Dict:'#info-'(RecName, {index, 'Failed-AVP'}), {'Failed-AVP', [FailedAvp]} catch diff --git a/lib/diameter/src/base/diameter.app.src b/lib/diameter/src/diameter.app.src index ceefb9b398..ceefb9b398 100644 --- a/lib/diameter/src/base/diameter.app.src +++ b/lib/diameter/src/diameter.app.src diff --git a/lib/diameter/src/base/diameter.appup.src b/lib/diameter/src/diameter.appup.src index 359f434941..62ace16faa 100644 --- a/lib/diameter/src/base/diameter.appup.src +++ b/lib/diameter/src/diameter.appup.src @@ -31,10 +31,36 @@ {"1.4", [{restart_application, diameter}]}, %% R16A {"1.4.1", [{load_module, diameter_reg}, %% R16B {load_module, diameter_stats}, + {load_module, diameter_traffic}, {load_module, diameter_service}, + {load_module, diameter_config}, + {load_module, diameter_peer}, + {load_module, diameter_peer_fsm}, {load_module, diameter_watchdog}, {load_module, diameter_capx}, - {load_module, diameter}]} + {load_module, diameter_codec}, + {load_module, diameter_gen_base_rfc3588}, + {load_module, diameter_gen_base_accounting}, + {load_module, diameter_gen_base_rfc6733}, + {load_module, diameter_gen_base_acct6733}, + {load_module, diameter_tcp}, + {load_module, diameter_lib}, + {load_module, diameter}]}, + {"1.4.1.1", [{load_module, diameter_traffic}, + {load_module, diameter_service}, + {load_module, diameter_config}, + {load_module, diameter_peer}, + {load_module, diameter_peer_fsm}, + {load_module, diameter_watchdog}, + {load_module, diameter_capx}, + {load_module, diameter_codec}, + {load_module, diameter_gen_base_rfc3588}, + {load_module, diameter_gen_base_accounting}, + {load_module, diameter_gen_base_rfc6733}, + {load_module, diameter_gen_base_acct6733}, + {load_module, diameter_tcp}, + {load_module, diameter_lib}, + {load_module, diameter}]} ], [ {"0.9", [{restart_application, diameter}]}, @@ -46,6 +72,7 @@ {"1.3", [{restart_application, diameter}]}, {"1.3.1", [{restart_application, diameter}]}, {"1.4", [{restart_application, diameter}]}, - {"1.4.1", [{restart_application, diameter}]} + {"1.4.1", [{restart_application, diameter}]}, + {"1.4.1.1", [{restart_application, diameter}]} ] }. diff --git a/lib/diameter/src/dict/base_rfc3588.dia b/lib/diameter/src/dict/base_rfc3588.dia index acd7fffd00..43a417b8dc 100644 --- a/lib/diameter/src/dict/base_rfc3588.dia +++ b/lib/diameter/src/dict/base_rfc3588.dia @@ -1,7 +1,7 @@ ;; ;; %CopyrightBegin% ;; -;; Copyright Ericsson AB 2010-2011. All Rights Reserved. +;; Copyright Ericsson AB 2010-2013. 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 @@ -421,7 +421,7 @@ DIAMETER_INVALID_AVP_BIT_COMBO 5016 DIAMETER_NO_COMMON_SECURITY 5017 -@grouped +@grouped Proxy-Info ::= < AVP Header: 284 > { Proxy-Host } @@ -440,7 +440,7 @@ [ Auth-Application-Id ] [ Acct-Application-Id ] -;; The E2E-Sequence AVP is defined in RFC 3588 as Grouped, but +;; The E2E-Sequence AVP is defined in RFC 3588 as Grouped, but ;; there is no definition of the group - only an informal text stating ;; that there should be a nonce (an OctetString) and a counter ;; (integer) diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl index 8b8c2a6694..49a530b4eb 100644 --- a/lib/diameter/src/transport/diameter_sctp.erl +++ b/lib/diameter/src/transport/diameter_sctp.erl @@ -42,6 +42,9 @@ -export([ports/0, ports/1]). +-export_type([listen_option/0, + connect_option/0]). + -include_lib("kernel/include/inet_sctp.hrl"). -include_lib("diameter/include/diameter.hrl"). @@ -54,6 +57,9 @@ %% The default port for a listener. -define(DEFAULT_PORT, 3868). %% RFC 3588, ch 2.1 +%% Remote addresses to accept connections from. +-define(DEFAULT_ACCEPT, []). %% any + %% How long a listener with no associations lives before offing %% itself. -define(LISTENER_TIMEOUT, 30000). @@ -62,6 +68,17 @@ %% association establishment. -define(ACCEPT_TIMEOUT, 5000). +-type connect_option() :: {raddr, inet:ip_address()} + | {rport, inet:port_number()} + | gen_sctp:open_option(). + +-type match() :: inet:ip_address() + | string() + | [match()]. + +-type listen_option() :: {accept, match()} + | gen_sctp:open_option(). + -type uint() :: non_neg_integer(). %% Accepting/connecting transport process state. @@ -69,7 +86,7 @@ {parent :: pid(), mode :: {accept, pid()} | accept - | {connect, {list(inet:ip_address()), uint(), list()}} + | {connect, {[inet:ip_address()], uint(), list()}} %% {RAs, RP, Errors} | connect, socket :: gen_sctp:sctp_socket(), @@ -86,7 +103,8 @@ tmap = ets:new(?MODULE, []) :: ets:tid(), %% {MRef, Pid|AssocId}, {AssocId, Pid} pending = {0, ets:new(?MODULE, [ordered_set])}, - tref :: reference()}). + tref :: reference(), + accept :: [match()]}). %% Field tmap is used to map an incoming message or event to the %% relevent transport process. Field pending implements a queue of %% transport processes to which an association has been assigned (at @@ -102,6 +120,13 @@ %% # start/3 %% --------------------------------------------------------------------------- +-spec start({accept, Ref}, #diameter_service{}, [listen_option()]) + -> {ok, pid(), [inet:ip_address()]} + when Ref :: diameter:transport_ref(); + ({connect, Ref}, #diameter_service{}, [connect_option()]) + -> {ok, pid(), [inet:ip_address()]} + when Ref :: diameter:transport_ref(). + start(T, #diameter_service{capabilities = Caps}, Opts) when is_list(Opts) -> diameter_sctp_sup:start(), %% start supervisors on demand @@ -169,12 +194,14 @@ init(T) -> %% A process owning a listening socket. i({listen, Ref, {Opts, Addrs}}) -> - {LAs, Sock} = AS = open(Addrs, Opts, ?DEFAULT_PORT), + {[Matches], Rest} = proplists:split(Opts, [accept]), + {LAs, Sock} = AS = open(Addrs, Rest, ?DEFAULT_PORT), proc_lib:init_ack({ok, self(), LAs}), ok = gen_sctp:listen(Sock, true), true = diameter_reg:add_new({?MODULE, listener, {Ref, AS}}), start_timer(#listener{ref = Ref, - socket = Sock}); + socket = Sock, + accept = accept(Matches)}); %% A connecting transport. i({connect, Pid, Opts, Addrs, Ref}) -> @@ -311,6 +338,9 @@ handle_call({{accept, Ref}, Pid}, _, #listener{ref = Ref, {TPid, NewS} = accept(Ref, Pid, S), {reply, {ok, TPid}, NewS#listener{count = N+1}}; +handle_call(T, From, {listener,_,_,_,_,_,_} = S) -> % started in old code + handle_call(T, From, upgrade(S)); + handle_call(_, _, State) -> {reply, nok, State}. @@ -329,7 +359,10 @@ handle_info(T, #transport{} = S) -> {noreply, #transport{} = t(T,S)}; handle_info(T, #listener{} = S) -> - {noreply, #listener{} = l(T,S)}. + {noreply, #listener{} = l(T,S)}; + +handle_info(T, {listener,_,_,_,_,_,_} = S) -> % started in old code + handle_info(T, upgrade(S)). %% --------------------------------------------------------------------------- %% # code_change/3 @@ -363,6 +396,9 @@ terminate(_, #listener{socket = Sock}) -> %% --------------------------------------------------------------------------- +upgrade(S) -> + #listener{} = erlang:append_element(S, ?DEFAULT_ACCEPT). + putr(Key, Val) -> put({?MODULE, Key}, Val). @@ -386,7 +422,7 @@ l({sctp, Sock, _RA, _RP, Data} = Msg, #listener{socket = Sock} = S) -> try find(Id, Data, S) of {TPid, NewS} -> - TPid ! {peeloff, peeloff(Sock, Id, TPid), Msg}, + TPid ! {peeloff, peeloff(Sock, Id, TPid), Msg, S#listener.accept}, NewS; false -> S @@ -460,11 +496,14 @@ t(T,S) -> %% transition/2 %% Listening process is transfering ownership of an association. -transition({peeloff, Sock, {sctp, LSock, _RA, _RP, _Data} = Msg}, +transition({peeloff, Sock, {sctp, LSock, _RA, _RP, _Data} = Msg, Matches}, #transport{mode = {accept, _}, socket = LSock} = S) -> + ok = accept_peer(Sock, Matches), transition(Msg, S#transport{socket = Sock}); +transition({peeloff = T, _Sock, _Msg} = T, #transport{} = S) ->% from old code + transition(erlang:append_element(T, ?DEFAULT_ACCEPT), S); %% Incoming message. transition({sctp, _Sock, _RA, _RP, Data}, #transport{socket = Sock} = S) -> @@ -510,6 +549,27 @@ transition({resolve_port, Pid}, #transport{socket = Sock}) %% Crash on anything unexpected. +ok({ok, T}) -> + T; +ok(T) -> + x(T). + +%% accept_peer/2 + +accept_peer(_, []) -> + ok; + +accept_peer(Sock, Matches) -> + {RAddrs, _} = ok(inet:peername(Sock)), + diameter_peer:match(RAddrs, Matches) + orelse x({accept, RAddrs, Matches}), + ok. + +%% accept/1 + +accept(Opts) -> + [[M] || {accept, M} <- Opts]. + %% accept/3 %% %% Start a new transport process or use one that's already been diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl index cbbba714ac..4d1b8bec51 100644 --- a/lib/diameter/src/transport/diameter_tcp.erl +++ b/lib/diameter/src/transport/diameter_tcp.erl @@ -42,6 +42,9 @@ -export([ports/0, ports/1]). +-export_type([connect_option/0, + listen_option/0]). + -include_lib("diameter/include/diameter.hrl"). %% Keys into process dictionary. @@ -80,6 +83,25 @@ -type frag() :: {length(), size(), binary(), list(binary())} | binary(). +-type connect_option() :: {raddr, inet:ip_address()} + | {rport, pos_integer()} + | {ssl_options, true | [ssl:connect_option()]} + | option() + | ssl:connect_option() + | gen_tcp:connect_option(). + +-type match() :: inet:ip_address() + | string() + | [match()]. + +-type listen_option() :: {accept, match()} + | {ssl_options, true | [ssl:listen_option()]} + | ssl:listen_option() + | gen_tcp:listen_option(). + +-type option() :: {port, non_neg_integer()} + | {fragment_timer, 0..16#FFFFFFFF}. + %% Accepting/connecting transport process state. -record(transport, {socket :: inet:socket() | ssl:sslsocket(), %% accept/connect socket @@ -100,18 +122,14 @@ %% # start/3 %% --------------------------------------------------------------------------- --spec start({accept, Ref}, Svc, [Opt]) +-spec start({accept, Ref}, #diameter_service{}, [listen_option()]) -> {ok, pid(), [inet:ip_address()]} - when Ref :: diameter:transport_ref(), - Svc :: #diameter_service{}, - Opt :: diameter:transport_opt(); - ({connect, Ref}, Svc, [Opt]) + when Ref :: diameter:transport_ref(); + ({connect, Ref}, #diameter_service{}, [connect_option()]) -> {ok, pid(), [inet:ip_address()]} | {ok, pid()} - when Ref :: diameter:transport_ref(), - Svc :: #diameter_service{}, - Opt :: diameter:transport_opt(). - + when Ref :: diameter:transport_ref(). + start({T, Ref}, #diameter_service{capabilities = Caps}, Opts) -> diameter_tcp_sup:start(), %% start tcp supervisors on demand {Mod, Rest} = split(Opts), @@ -225,10 +243,10 @@ laddr([], Mod, Sock) -> Addr; laddr([{ip, Addr}], _, _) -> Addr. - + own(Opts) -> - {Own, Rest} = proplists:split(Opts, [fragment_timer]), - {lists:append(Own), Rest}. + {[Own], Rest} = proplists:split(Opts, [fragment_timer]), + {Own, Rest}. ssl(Opts) -> {[SslOpts], Rest} = proplists:split(Opts, [ssl_options]), @@ -257,9 +275,11 @@ init(Type, Ref, Mod, Pid, _, Opts, Addrs) -> %% init/6 init(accept = T, Ref, Mod, Pid, Opts, Addrs) -> - {LAddr, LSock} = listener(Ref, {Mod, Opts, Addrs}), + {[Matches], Rest} = proplists:split(Opts, [accept]), + {LAddr, LSock} = listener(Ref, {Mod, Rest, Addrs}), proc_lib:init_ack({ok, self(), [LAddr]}), Sock = ok(accept(Mod, LSock)), + ok = accept_peer(Mod, Sock, accept(Matches)), publish(Mod, T, Ref, Sock), diameter_peer:up(Pid), Sock; @@ -282,7 +302,7 @@ init_rc([]) -> up(Pid, Remote, [{ip, _Addr}], _, _) -> diameter_peer:up(Pid, Remote); -up(Pid, Remote, [], Mod, Sock) -> +up(Pid, Remote, [], Mod, Sock) -> {Addr, _Port} = ok(sockname(Mod, Sock)), diameter_peer:up(Pid, Remote, [Addr]). @@ -298,6 +318,22 @@ ok(No) -> x(Reason) -> exit({shutdown, Reason}). +%% accept_peer/3 + +accept_peer(_Mod, _Sock, []) -> + ok; + +accept_peer(Mod, Sock, Matches) -> + {RAddr, _} = ok(peername(Mod, Sock)), + diameter_peer:match([RAddr], Matches) + orelse x({accept, RAddr, Matches}), + ok. + +%% accept/1 + +accept(Opts) -> + [[M] || {accept, M} <- Opts]. + %% listener/2 listener(LRef, T) -> diff --git a/lib/diameter/test/Makefile b/lib/diameter/test/Makefile index 9719c67b32..aff1b18cf8 100644 --- a/lib/diameter/test/Makefile +++ b/lib/diameter/test/Makefile @@ -1,4 +1,4 @@ -# +# # %CopyrightBegin% # # Copyright Ericsson AB 2010-2013. All Rights Reserved. @@ -76,7 +76,7 @@ any: opt $(MAKE) -i $(SUITES) clean: - rm -f $(TARGET_FILES) + rm -f $(TARGET_FILES) rm -f depend.mk coverspec realclean: clean @@ -159,7 +159,7 @@ log: # ---------------------------------------------------- # Release Targets -# ---------------------------------------------------- +# ---------------------------------------------------- /%: % force sed -f release.sed $< > "$(RELSYSDIR)$@" diff --git a/lib/diameter/test/diameter_capx_SUITE.erl b/lib/diameter/test/diameter_capx_SUITE.erl index 8c9bb67e61..deabdd720b 100644 --- a/lib/diameter/test/diameter_capx_SUITE.erl +++ b/lib/diameter/test/diameter_capx_SUITE.erl @@ -27,6 +27,8 @@ -export([suite/0, all/0, groups/0, + init_per_suite/1, + end_per_suite/1, init_per_group/2, end_per_group/2, init_per_testcase/2, @@ -56,6 +58,11 @@ peer_down/4]). -include("diameter.hrl"). +-include("diameter_gen_base_rfc3588.hrl"). +%% Use only the Vendor-Specific-Application-Id record from the base +%% include, to test the independence of capabilities configuration +%% from the different definitions of Vendor-Id in RFC's 3588 and RFC +%% 6733. %% =========================================================================== @@ -69,6 +76,11 @@ -define(REALM, "erlang.org"). -define(HOST(Name), Name ++ "." ++ ?REALM). +%% Application id's that are never agreed upon at capabilities +%% exchange. Testcase no_common_application references them in order +%% to exercise Vendor-Specific-Application-Id handling. +-define(NOAPPS, [1111, 2222, 3333, 4444]). + %% Config for diameter:start_service/2. -define(SERVICE, [{'Origin-Realm', ?REALM}, @@ -83,7 +95,10 @@ || {A,D} <- [{base3588, diameter_gen_base_rfc3588}, {acct3588, diameter_gen_base_accounting}, {base6733, diameter_gen_base_rfc6733}, - {acct6733, diameter_gen_acct_rfc6733}]]]). + {acct6733, diameter_gen_acct_rfc6733}]]] + ++ [{application, [{dictionary, dict(N)}, + {module, not_really}]} + || N <- ?NOAPPS]). -define(A, list_to_atom). -define(L, atom_to_list). @@ -116,6 +131,16 @@ groups() -> Tc = lists:flatmap(fun tc/1, tc()), [{D, [], Tc} || D <- ?DICTS]. +init_per_suite(Config) -> + lists:foreach(fun load_dict/1, ?NOAPPS), + Config. + +end_per_suite(_Config) -> + [] = [Mod || N <- ?NOAPPS, + Mod <- [dict(N)], + false <- [code:delete(Mod)]], + ok. + %% Generate a unique hostname for each testcase so that watchdogs %% don't prevent a connection from being brought up immediately. init_per_testcase(Name, Config) -> @@ -160,7 +185,7 @@ start(_Config) -> ok = diameter:start(). %% Ensure that both integer and list-valued vendor id's can be -%% configured in a 'Vendor-Specific-Application-Id, the arity having +%% configured in a Vendor-Specific-Application-Id, the arity having %% changed between RFC 3588 and RFC 6733. vendor_id(_Config) -> [] = ?util:run([[fun vid/1, V] || V <- [1, [1], [1,2], x]]). @@ -188,13 +213,13 @@ add_listeners(Config) -> Acct = [listen(?SERVER, [{capabilities, [{'Origin-Host', ?HOST(H)}, {'Auth-Application-Id', []}]}, - {applications, [A]}, + {applications, [A | noapps()]}, {capabilities_cb, [fun server_capx/3, acct]}]) || {A,H} <- [{acct3588, "acct3588-srv"}, {acct6733, "acct6733-srv"}]], Base = [listen(?SERVER, [{capabilities, [{'Origin-Host', ?HOST(H)}]}, - {applications, A}, + {applications, A ++ noapps()}, {capabilities_cb, [fun server_capx/3, base]}]) || {A,H} <- [{[base3588, acct3588], "base3588-srv"}, {[base6733, acct6733], "base6733-srv"}]], @@ -224,15 +249,33 @@ stop(_Config) -> %% DIAMETER_NO_COMMON_APPLICATION = 5010. s_no_common_application(Config) -> - server_closed(Config, fun no_common_application/1, 5010). + Vs = [[{'Vendor-Id', 111}, + {'Auth-Application-Id', [1111]}], + #'diameter_base_Vendor-Specific-Application-Id' + {'Vendor-Id' = [222], + 'Acct-Application-Id' = [2222]}], + server_closed(Config, + fun(C) -> no_common_application(C,Vs) end, + 5010). c_no_common_application(Config) -> - client_closed(Config, "acct-srv", fun no_common_application/1, 5010). - -no_common_application(Config) -> + Vs = [#'diameter_base_Vendor-Specific-Application-Id' + {'Vendor-Id' = 333, + 'Auth-Application-Id' = [3333]}, + [{'Vendor-Id', [444]}, + {'Acct-Application-Id', [4444]}]], + client_closed(Config, + "acct-srv", + fun(C) -> no_common_application(C,Vs) end, + 5010). + +no_common_application(Config, Vs) -> [Common, _Acct] = apps(Config), - connect(Config, acct, [{capabilities, [{'Acct-Application-Id', []}]}, - {applications, [Common]}]). + connect(Config, + acct, + [{capabilities, [{'Acct-Application-Id', []}, + {'Vendor-Specific-Application-Id', Vs}]}, + {applications, [Common | noapps()]}]). %% ==================== %% Ask the base server to speak accounting with an unknown security @@ -324,6 +367,25 @@ client_reject(Config) -> %% =========================================================================== +noapps() -> + lists:map(fun dict/1, ?NOAPPS). + +dict(N) -> + ?A(?L(?MODULE) ++ "_" ++ integer_to_list(N)). + +%% Compile and load minimal dictionary modules. These actually have to +%% exists since diameter will call their id/0 to extract application +%% id's, failing with app_not_configured if it can't. +load_dict(N) -> + Mod = dict(N), + Forms = [{attribute, 1, module, Mod}, + {attribute, 2, compile, [export_all]}, + {function, 3, id, 0, + [{clause, 4, [], [], [{integer, 4, N}]}]}], + {ok, Mod, Bin, []} = compile:forms(Forms, [return]), + {module, Mod} = code:load_binary(Mod, Mod, Bin), + N = Mod:id(). + %% server_closed/3 server_closed(Config, F, RC) -> diff --git a/lib/diameter/test/diameter_codec_SUITE.erl b/lib/diameter/test/diameter_codec_SUITE.erl index 2e219bbb10..cd8ca41f66 100644 --- a/lib/diameter/test/diameter_codec_SUITE.erl +++ b/lib/diameter/test/diameter_codec_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-2013. 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 diff --git a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl index 49f2158b1a..cdf0cf55e1 100644 --- a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl +++ b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-2013. 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 diff --git a/lib/diameter/test/diameter_examples_SUITE.erl b/lib/diameter/test/diameter_examples_SUITE.erl index 1954bc319b..75b542b679 100644 --- a/lib/diameter/test/diameter_examples_SUITE.erl +++ b/lib/diameter/test/diameter_examples_SUITE.erl @@ -149,7 +149,7 @@ to_erl(File, Opts) -> No -> throw({make, No}) end. - + to_beam(Name) -> case compile:file(Name ++ ".erl", [return]) of {ok, _, _} -> diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl index 38bdf55af8..a97c54fc04 100644 --- a/lib/diameter/test/diameter_traffic_SUITE.erl +++ b/lib/diameter/test/diameter_traffic_SUITE.erl @@ -171,7 +171,8 @@ {'Product-Name', "OTP/diameter"}, {'Auth-Application-Id', [?DIAMETER_APP_ID_COMMON]}, {'Acct-Application-Id', [?DIAMETER_APP_ID_ACCOUNTING]}, - {restrict_connections, false} + {restrict_connections, false}, + {spawn_opt, [{min_heap_size, 5000}]} | [{application, [{dictionary, D}, {module, ?MODULE}, {answer_errors, callback}]} @@ -321,6 +322,7 @@ add_transports(Config) -> LRef = ?util:listen(?SERVER, tcp, [{capabilities_cb, fun capx/2}, + {spawn_opt, [{min_heap_size, 8096}]}, {applications, apps(rfc3588)}]), Cs = [?util:connect(?CLIENT, tcp, diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl index aa489fef5f..92c72c84e7 100644 --- a/lib/diameter/test/diameter_util.erl +++ b/lib/diameter/test/diameter_util.erl @@ -336,7 +336,7 @@ opts(Prot, T) -> {transport_config, [{ip, ?ADDR}, {port, 0} | opts(T)]}]. opts(listen) -> - []; + [{accept, M} || M <- [{256,0,0,1}, ["256.0.0.1", ["^.+$"]]]]; opts(PortNr) -> [{raddr, ?ADDR}, {rport, PortNr}]. diff --git a/lib/diameter/vsn.mk b/lib/diameter/vsn.mk index 757f29a32e..f7462c3916 100644 --- a/lib/diameter/vsn.mk +++ b/lib/diameter/vsn.mk @@ -18,5 +18,5 @@ # %CopyrightEnd% APPLICATION = diameter -DIAMETER_VSN = 1.4.1.1 +DIAMETER_VSN = 1.4.2 APP_VSN = $(APPLICATION)-$(DIAMETER_VSN)$(PRE_VSN) |