aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter
diff options
context:
space:
mode:
Diffstat (limited to 'lib/diameter')
-rw-r--r--lib/diameter/doc/src/notes.xml2
-rw-r--r--lib/diameter/src/base/diameter_callback.erl4
-rw-r--r--lib/diameter/src/base/diameter_config.erl9
-rw-r--r--lib/diameter/src/base/diameter_peer_fsm.erl2
-rw-r--r--lib/diameter/src/base/diameter_service.erl2
-rw-r--r--lib/diameter/src/base/diameter_traffic.erl42
-rw-r--r--lib/diameter/src/compiler/diameter_codegen.erl2
-rw-r--r--lib/diameter/src/info/diameter_info.erl4
-rw-r--r--lib/diameter/src/transport/diameter_sctp.erl4
-rw-r--r--lib/diameter/test/diameter_capx_SUITE.erl2
-rw-r--r--lib/diameter/test/diameter_examples_SUITE.erl6
-rw-r--r--lib/diameter/test/diameter_pool_SUITE.erl4
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl15
-rw-r--r--lib/diameter/test/diameter_transport_SUITE.erl44
-rw-r--r--lib/diameter/test/diameter_util.erl57
15 files changed, 105 insertions, 94 deletions
diff --git a/lib/diameter/doc/src/notes.xml b/lib/diameter/doc/src/notes.xml
index 70e1880be5..50f568abaa 100644
--- a/lib/diameter/doc/src/notes.xml
+++ b/lib/diameter/doc/src/notes.xml
@@ -11,7 +11,7 @@
<header>
<copyright>
<year>2011</year>
-<year>2016</year>
+<year>2017</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
diff --git a/lib/diameter/src/base/diameter_callback.erl b/lib/diameter/src/base/diameter_callback.erl
index f479cb6612..f9cdc66c70 100644
--- a/lib/diameter/src/base/diameter_callback.erl
+++ b/lib/diameter/src/base/diameter_callback.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@
%% in a callback applied to the atom-valued callback name and argument
%% list. For all callbacks not to this module, the 'extra' field is a
%% list of additional arguments, following arguments supplied by
-%% diameter but preceeding those of the diameter:evaluable() being
+%% diameter but preceding those of the diameter:evaluable() being
%% applied.
%%
%% For example, the following config to diameter:start_service/2, in
diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
index 1db9b52dfa..34018ae6d3 100644
--- a/lib/diameter/src/base/diameter_config.erl
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -610,6 +610,9 @@ opt({watchdog_timer, Tmo}) ->
opt({watchdog_config, L}) ->
is_list(L) andalso lists:all(fun wdopt/1, L);
+opt({spawn_opt, {M,F,A}})
+ when is_atom(M), is_atom(F), is_list(A) ->
+ true;
opt({spawn_opt = K, Opts}) ->
if is_list(Opts) ->
{value, {K, spawn_opts(Opts)}};
@@ -739,6 +742,10 @@ opt(incoming_maxlen, N)
when 0 =< N, N < 1 bsl 24 ->
N;
+opt(spawn_opt, {M,F,A} = T)
+ when is_atom(M), is_atom(F), is_list(A) ->
+ T;
+
opt(spawn_opt, L)
when is_list(L) ->
spawn_opts(L);
@@ -881,7 +888,7 @@ init_cb(List) ->
V <- [proplists:get_value(F, List, D)]],
#diameter_callback{} = list_to_tuple([diameter_callback | Values]).
-%% Retreive and validate.
+%% Retrieve and validate.
get_opt(Key, List, Def, Other) ->
init_opt(Key, get_opt(Key, List, Def), [Def|Other]).
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index a5dab45684..1b0dc417e5 100644
--- a/lib/diameter/src/base/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -367,7 +367,7 @@ handle_info(T, #state{} = State) ->
%% Note that there's no guarantee that the service and transport
%% capabilities are good enough to build a CER/CEA that can be
-%% succesfully encoded. It's not checked at diameter:add_transport/2
+%% successfully encoded. It's not checked at diameter:add_transport/2
%% since this can be called before creating the service.
%% terminate/2
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index 4fc49309b5..a976a8b998 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -114,7 +114,7 @@
incoming_maxlen := diameter:message_length(),
strict_mbit := boolean(),
string_decode := boolean(),
- spawn_opt := list()}}).
+ spawn_opt := list() | {module(), atom(), list()}}}).
%% Record representing an RFC 3539 watchdog process implemented by
%% diameter_watchdog.
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 7a5a3d662a..85378babea 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -213,8 +213,9 @@ incr_rc(Dir, Pkt, TPid, Dict0) ->
%% ---------------------------------------------------------------------------
-spec receive_message(pid(), Route, #diameter_packet{}, module(), RecvData)
- -> pid()
- | boolean()
+ -> pid() %% request handler
+ | boolean() %% answer, known request or not
+ | discard %% request discarded by MFA
when Route :: {Handler, RequestRef, Seqs}
| Ack,
RecvData :: {[SpawnOpt], #recvdata{}},
@@ -231,9 +232,10 @@ receive_message(TPid, Route, Pkt, Dict0, RecvData) ->
%% recv/6
%% Incoming request ...
-recv(true, Ack, TPid, Pkt, Dict0, RecvData)
+recv(true, Ack, TPid, Pkt, Dict0, T)
when is_boolean(Ack) ->
- spawn_request(Ack, TPid, Pkt, Dict0, RecvData);
+ {Opts, RecvData} = T,
+ spawn_request(Ack, TPid, Pkt, Dict0, RecvData, Opts);
%% ... answer to known request ...
recv(false, {Pid, Ref, TPid}, _, Pkt, Dict0, _) ->
@@ -255,18 +257,46 @@ recv(false, false, TPid, Pkt, _, _) ->
incr(TPid, {{unknown, 0}, recv, discarded}),
false.
-%% spawn_request/5
+%% spawn_request/6
-spawn_request(Ack, TPid, Pkt, Dict0, {Opts, RecvData}) ->
+%% An MFA should return a pid() or the atom 'discard'. The latter
+%% results in an acknowledgment back to the transport process when
+%% appropriate, to ensure that send/recv callbacks can count
+%% outstanding requests. Acknowledgement is implicit if the
+%% handler process dies (in a handle_request callback for example).
+spawn_request(Ack, TPid, Pkt, Dict0, RecvData, {M,F,A}) ->
+ ReqF = fun() ->
+ ack(Ack, TPid, recv_request(Ack, TPid, Pkt, Dict0, RecvData))
+ end,
+ ack(Ack, TPid, apply(M, F, [ReqF | A]));
+
+%% A spawned process acks implicitly when it dies, so there's no need
+%% to handle 'discard'.
+spawn_request(Ack, TPid, Pkt, Dict0, RecvData, Opts) ->
spawn_opt(fun() ->
recv_request(Ack, TPid, Pkt, Dict0, RecvData)
end,
Opts).
+%% ack/3
+
+ack(Ack, TPid, RC) ->
+ RC == discard andalso Ack andalso (TPid ! {send, false}),
+ RC.
+
%% ---------------------------------------------------------------------------
%% recv_request/5
%% ---------------------------------------------------------------------------
+-spec recv_request(Ack :: boolean(),
+ TPid :: pid(),
+ #diameter_packet{},
+ Dict0 :: module(),
+ #recvdata{})
+ -> ok %% answer was sent
+ | discard %% or not
+ | false. %% no transport
+
recv_request(Ack,
TPid,
#diameter_packet{header = #diameter_header{application_id = Id}}
diff --git a/lib/diameter/src/compiler/diameter_codegen.erl b/lib/diameter/src/compiler/diameter_codegen.erl
index 2a1c0db381..f56e4a5249 100644
--- a/lib/diameter/src/compiler/diameter_codegen.erl
+++ b/lib/diameter/src/compiler/diameter_codegen.erl
@@ -186,7 +186,7 @@ erl_forms(Mod, ParseD) ->
f_enumerated_avp(ParseD),
f_empty_value(ParseD),
f_dict(ParseD),
- {eof, erl_anno:new(?LINE)}]],
+ {eof, ?LINE}]],
lists:append(Forms).
diff --git a/lib/diameter/src/info/diameter_info.erl b/lib/diameter/src/info/diameter_info.erl
index 59a3b94ee4..23a42e48fd 100644
--- a/lib/diameter/src/info/diameter_info.erl
+++ b/lib/diameter/src/info/diameter_info.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2015. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -195,7 +195,7 @@ format(Tables, SFun, CFun)
%%%
%%% Description: Pretty-print records in a named tables as collected
%%% from local and remote nodes. Each table listing is
-%%% preceeded by a banner.
+%%% preceded by a banner.
%%% ----------------------------------------------------------
format(Local, Remote, SFun) ->
diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl
index e47febaf99..6a9f1f940b 100644
--- a/lib/diameter/src/transport/diameter_sctp.erl
+++ b/lib/diameter/src/transport/diameter_sctp.erl
@@ -104,7 +104,7 @@
os = 0 :: uint(), %% next output stream
packet = true :: boolean() %% legacy transport_data?
| raw,
- message_cb :: false | diameter:evaluable(),
+ message_cb = false :: false | diameter:evaluable(),
send = false :: pid() | boolean()}). %% sending process
%% Monitor process state.
@@ -447,7 +447,7 @@ handle_info(T, #monitor{} = S) ->
m(T,S),
{noreply, S}.
-%% Prior to the possiblity of setting pool_size on in transport
+%% Prior to the possibility of setting pool_size on in transport
%% configuration, a new accepting transport was only started following
%% the death of a predecessor, so that there was only at most one
%% previously started transport process waiting for an association.
diff --git a/lib/diameter/test/diameter_capx_SUITE.erl b/lib/diameter/test/diameter_capx_SUITE.erl
index 0d535b6642..51b6c1d7f2 100644
--- a/lib/diameter/test/diameter_capx_SUITE.erl
+++ b/lib/diameter/test/diameter_capx_SUITE.erl
@@ -384,7 +384,7 @@ load_dict(N) ->
A3 = erl_anno:new(3),
A4 = erl_anno:new(4),
Forms = [{attribute, A1, module, Mod},
- {attribute, A2, compile, [export_all]},
+ {attribute, A2, export, [{id,0}]},
{function, A3, id, 0,
[{clause, A4, [], [], [{integer, A4, N}]}]}],
{ok, Mod, Bin, []} = compile:forms(Forms, [return]),
diff --git a/lib/diameter/test/diameter_examples_SUITE.erl b/lib/diameter/test/diameter_examples_SUITE.erl
index 680ce4f366..fad54d62b2 100644
--- a/lib/diameter/test/diameter_examples_SUITE.erl
+++ b/lib/diameter/test/diameter_examples_SUITE.erl
@@ -70,8 +70,6 @@
%% Transport protocols over which the example Diameter nodes are run.
-define(PROTS, [tcp, sctp]).
--define(ADDR, diameter_util:ip4()).
-
%% ===========================================================================
suite() ->
@@ -348,7 +346,7 @@ top(Dir, LibDir) ->
start({server, Prot}) ->
ok = diameter:start(),
ok = server:start(),
- {ok, Ref} = server:listen({Prot, ?ADDR, 3868}),
+ {ok, Ref} = server:listen(Prot),
[_] = ?util:lport(Prot, Ref),
ok;
@@ -356,7 +354,7 @@ start({client = Svc, Prot}) ->
ok = diameter:start(),
true = diameter:subscribe(Svc),
ok = client:start(),
- {ok, Ref} = client:connect({Prot, ?ADDR, ?ADDR, 3868}),
+ {ok, Ref} = client:connect(Prot),
receive #diameter_event{info = {up, Ref, _, _, _}} -> ok end;
start(Config) ->
diff --git a/lib/diameter/test/diameter_pool_SUITE.erl b/lib/diameter/test/diameter_pool_SUITE.erl
index eadb354a1d..97c16940ff 100644
--- a/lib/diameter/test/diameter_pool_SUITE.erl
+++ b/lib/diameter/test/diameter_pool_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2015. All Rights Reserved.
+%% Copyright Ericsson AB 2015-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -115,7 +115,7 @@ connect(ClientProt, ServerProt) ->
%% 'up' events. (Although it's likely.)
sleep(),
{9,5} = count("server", LRef, accept), %% 5 connections + 4 accepting
- %% Ensure ther are still the expected number of accepting transports
+ %% Ensure there are still the expected number of accepting transports
%% after stopping the client service.
ok = diameter:stop_service("client"),
sleep(),
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 6b2f1a6ba8..84b41f14b7 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -92,7 +92,6 @@
send_multiple_filters_2/1,
send_multiple_filters_3/1,
send_anything/1,
- outstanding/1,
remove_transports/1,
empty/1,
stop_services/1,
@@ -203,8 +202,7 @@
{'Acct-Application-Id', [?DIAMETER_APP_ID_ACCOUNTING]},
{restrict_connections, false},
{string_decode, Decode},
- {incoming_maxlen, 1 bsl 21},
- {spawn_opt, [{min_heap_size, 5000}]}
+ {incoming_maxlen, 1 bsl 21}
| [{application, [{dictionary, D},
{module, ?MODULE},
{answer_errors, callback}]}
@@ -256,7 +254,7 @@ suite() ->
[{timetrap, {seconds, 10}}].
all() ->
- [start, result_codes, {group, traffic}, outstanding, empty, stop].
+ [start, result_codes, {group, traffic}, empty, stop].
groups() ->
[{P, [P], Ts} || Ts <- [tc(tc())], P <- [shuffle, parallel]]
@@ -466,8 +464,8 @@ add_transports(Config) ->
|| T == sctp andalso CS]],
[{capabilities_cb, fun capx/2},
{pool_size, 8},
- {spawn_opt, [{min_heap_size, 8096}]},
- {applications, apps(rfc3588)}]),
+ {applications, apps(rfc3588)}]
+ ++ [{spawn_opt, {erlang, spawn, []}} || CS]),
Cs = [?util:connect(CN,
[T, {sender, CS}],
LRef,
@@ -486,11 +484,6 @@ apps(D0) ->
D = dict0(D0),
[acct(D), D].
-%% Ensure there are no outstanding requests in request table.
-outstanding(_Config) ->
- [] = [T || T <- ets:tab2list(diameter_request),
- is_atom(element(1,T))].
-
remove_transports(Config) ->
#group{client_service = CN,
server_service = SN}
diff --git a/lib/diameter/test/diameter_transport_SUITE.erl b/lib/diameter/test/diameter_transport_SUITE.erl
index 14c748ad20..9d981d0a2b 100644
--- a/lib/diameter/test/diameter_transport_SUITE.erl
+++ b/lib/diameter/test/diameter_transport_SUITE.erl
@@ -56,10 +56,8 @@
-define(RECV(Pat, Ret), receive Pat -> Ret end).
-define(RECV(Pat), ?RECV(Pat, diameter_lib:now())).
-%% Address to open sockets on.
--define(ADDR(Prot), if sctp == Prot -> diameter_util:ip4();
- true -> {127,0,0,1}
- end).
+%% Sockets are opened on the loopback address.
+-define(ADDR, {127,0,0,1}).
%% diameter_tcp doesn't use anything but host_ip_address, and that
%% only is a local address isn't configured as at transport start.
@@ -351,14 +349,13 @@ rand_bytes(N) ->
%% start_connect/3
start_connect(Prot, PortNr, Ref) ->
- Addr = ?ADDR(Prot),
- {ok, TPid, [_]} = start_connect(Prot,
- {connect, Ref},
- ?SVC([]),
- [{raddr, Addr},
- {rport, PortNr},
- {ip, Addr},
- {port, 0}]),
+ {ok, TPid, [?ADDR]} = start_connect(Prot,
+ {connect, Ref},
+ ?SVC([]),
+ [{raddr, ?ADDR},
+ {rport, PortNr},
+ {ip, ?ADDR},
+ {port, 0}]),
?RECV(?TMSG({TPid, connected, _})),
TPid.
@@ -371,9 +368,9 @@ start_connect(tcp, T, Svc, Opts) ->
start_accept(Prot, Ref) ->
{Mod, Opts} = tmod(Prot),
- {ok, TPid, [_]} = Mod:start({accept, Ref},
- ?SVC([?ADDR(Prot)]),
- [{port, 0} | Opts]),
+ {ok, TPid, [?ADDR]} = Mod:start({accept, Ref},
+ ?SVC([?ADDR]),
+ [{port, 0} | Opts]),
?RECV(?TMSG({TPid, connected})),
TPid.
@@ -387,20 +384,19 @@ tmod(tcp) ->
%% gen_connect/2
gen_connect(sctp = P, PortNr) ->
- Addr = ?ADDR(P),
- {ok, Sock} = Ok = gen_sctp:open([{ip, Addr}, {port, 0} | ?SCTP_OPTS]),
- ok = gen_sctp:connect_init(Sock, Addr, PortNr, []),
+ {ok, Sock} = Ok = gen_sctp:open([{ip, ?ADDR}, {port, 0} | ?SCTP_OPTS]),
+ ok = gen_sctp:connect_init(Sock, ?ADDR, PortNr, []),
Ok = gen_accept(P, Sock);
-gen_connect(tcp = P, PortNr) ->
- gen_tcp:connect(?ADDR(P), PortNr, ?TCP_OPTS).
+gen_connect(tcp, PortNr) ->
+ gen_tcp:connect(?ADDR, PortNr, ?TCP_OPTS).
%% gen_listen/1
-gen_listen(sctp = P) ->
- {ok, Sock} = gen_sctp:open([{ip, ?ADDR(P)}, {port, 0} | ?SCTP_OPTS]),
+gen_listen(sctp) ->
+ {ok, Sock} = gen_sctp:open([{ip, ?ADDR}, {port, 0} | ?SCTP_OPTS]),
{gen_sctp:listen(Sock, true), Sock};
-gen_listen(tcp = P) ->
- gen_tcp:listen(0, [{ip, ?ADDR(P)} | ?TCP_OPTS]).
+gen_listen(tcp) ->
+ gen_tcp:listen(0, [{ip, ?ADDR} | ?TCP_OPTS]).
%% gen_accept/2
diff --git a/lib/diameter/test/diameter_util.erl b/lib/diameter/test/diameter_util.erl
index 7266d3678c..03f79096ac 100644
--- a/lib/diameter/test/diameter_util.erl
+++ b/lib/diameter/test/diameter_util.erl
@@ -32,8 +32,7 @@
foldl/3,
scramble/1,
unique_string/0,
- have_sctp/0,
- ip4/0]).
+ have_sctp/0]).
%% diameter-specific
-export([lport/2,
@@ -185,13 +184,19 @@ unique_string() ->
%% have_sctp/0
have_sctp() ->
+ have_sctp(erlang:system_info(system_architecture)).
+
+%% Don't run SCTP on platforms where it's either known to be flakey or
+%% isn't available.
+
+have_sctp("sparc-sun-solaris2.10") ->
+ false;
+
+have_sctp(_) ->
case gen_sctp:open() of
{ok, Sock} ->
- RC = gen_sctp:connect(Sock, ip4(), 3868, []),
gen_sctp:close(Sock),
- %% Connect has been seen to return eafnosupport on at least
- %% one SunOS 10 Sparc host, for reasons unknown.
- RC /= {error, eafnosupport};
+ true;
{error, E} when E == eprotonosupport;
E == esocktnosupport -> %% fail on any other reason
false
@@ -360,8 +365,7 @@ tmod(any) ->
opts([Prot | Opts], T) ->
tmo(T, lists:append([[{transport_module, M}, {transport_config, C ++ Opts}]
|| M <- tmod(Prot),
- C <- [buf(M,T) ++ [{ip, addr(M)}, {port, 0}]
- ++ remote(M,T)]]));
+ C <- [cfg(M,T) ++ cfg(M) ++ cfg(T)]]));
opts(Prot, T) ->
opts([Prot], T).
@@ -380,38 +384,21 @@ tmo([M, C | Opts]) ->
%% Listening SCTP socket need larger-than-default buffers to avoid
%% resends on some platforms (eg. SLES 11).
-buf(diameter_sctp, listen) ->
+cfg(diameter_sctp, listen) ->
[{recbuf, 1 bsl 16}, {sndbuf, 1 bsl 16}];
-buf(_, _) ->
+
+cfg(_, _) ->
[].
-addr(diameter_tcp) ->
- {127,0,0,1};
-addr(diameter_sctp) ->
- ip4().
+cfg(M)
+ when M == diameter_tcp;
+ M == diameter_sctp ->
+ [{ip, ?ADDR}, {port, 0}];
-remote(_, listen) ->
+cfg(listen) ->
[{accept, M} || M <- [{256,0,0,1}, ["256.0.0.1", ["^.+$"]]]];
-remote(Mod, PortNr) ->
- [{raddr, addr(Mod)}, {rport, PortNr}].
-
-%% Try to use something other than the loopback address where this
-%% address is known to be problematic for gen_sctp.
-ip4() ->
- try
- "sparc-sun-solaris2.10" = erlang:system_info(system_architecture),
- {ok, List} = inet:getifaddrs(),
- hd(lists:flatmap(fun ip4/1, List))
- catch
- error:_ ->
- ?ADDR
- end.
-
-ip4({_, Opts}) ->
- {flags, Flags} = lists:keyfind(flags, 1, Opts),
- [A || lists:member(up, Flags),
- not lists:member(loopback, Flags),
- {addr, {_,_,_,_} = A} <- Opts].
+cfg(PortNr) ->
+ [{raddr, ?ADDR}, {rport, PortNr}].
%% ---------------------------------------------------------------------------
%% info/0