aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter
diff options
context:
space:
mode:
Diffstat (limited to 'lib/diameter')
-rw-r--r--lib/diameter/Makefile8
-rw-r--r--lib/diameter/doc/src/Makefile4
-rw-r--r--lib/diameter/doc/src/diameter.xml32
-rw-r--r--lib/diameter/doc/src/diameter_compile.xml6
-rw-r--r--lib/diameter/doc/src/diameter_dict.xml4
-rw-r--r--lib/diameter/doc/src/diameter_intro.xml6
-rw-r--r--lib/diameter/doc/src/diameter_sctp.xml22
-rw-r--r--lib/diameter/doc/src/diameter_tcp.xml15
-rw-r--r--lib/diameter/doc/src/diameter_using.xml6
-rw-r--r--lib/diameter/src/Makefile10
-rw-r--r--lib/diameter/src/base/diameter.erl4
-rw-r--r--lib/diameter/src/base/diameter_codec.erl2
-rw-r--r--lib/diameter/src/base/diameter_config.erl9
-rw-r--r--lib/diameter/src/base/diameter_peer.erl94
-rw-r--r--lib/diameter/src/base/diameter_service.erl24
-rw-r--r--lib/diameter/src/base/diameter_traffic.erl27
-rw-r--r--lib/diameter/src/diameter.app.src (renamed from lib/diameter/src/base/diameter.app.src)0
-rw-r--r--lib/diameter/src/diameter.appup.src (renamed from lib/diameter/src/base/diameter.appup.src)31
-rw-r--r--lib/diameter/src/dict/base_rfc3588.dia6
-rw-r--r--lib/diameter/src/transport/diameter_sctp.erl74
-rw-r--r--lib/diameter/src/transport/diameter_tcp.erl64
-rw-r--r--lib/diameter/test/Makefile6
-rw-r--r--lib/diameter/test/diameter_codec_SUITE.erl2
-rw-r--r--lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl2
-rw-r--r--lib/diameter/test/diameter_examples_SUITE.erl2
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl4
-rw-r--r--lib/diameter/test/diameter_util.erl2
-rw-r--r--lib/diameter/vsn.mk2
28 files changed, 355 insertions, 113 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/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_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_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)