diff options
Diffstat (limited to 'lib/diameter')
-rw-r--r-- | lib/diameter/doc/src/notes.xml | 2 | ||||
-rw-r--r-- | lib/diameter/src/base/diameter_callback.erl | 4 | ||||
-rw-r--r-- | lib/diameter/src/base/diameter_config.erl | 9 | ||||
-rw-r--r-- | lib/diameter/src/base/diameter_peer_fsm.erl | 2 | ||||
-rw-r--r-- | lib/diameter/src/base/diameter_service.erl | 2 | ||||
-rw-r--r-- | lib/diameter/src/base/diameter_traffic.erl | 42 | ||||
-rw-r--r-- | lib/diameter/src/compiler/diameter_codegen.erl | 2 | ||||
-rw-r--r-- | lib/diameter/src/info/diameter_info.erl | 4 | ||||
-rw-r--r-- | lib/diameter/src/transport/diameter_sctp.erl | 4 | ||||
-rw-r--r-- | lib/diameter/test/diameter_capx_SUITE.erl | 2 | ||||
-rw-r--r-- | lib/diameter/test/diameter_examples_SUITE.erl | 6 | ||||
-rw-r--r-- | lib/diameter/test/diameter_pool_SUITE.erl | 4 | ||||
-rw-r--r-- | lib/diameter/test/diameter_traffic_SUITE.erl | 15 | ||||
-rw-r--r-- | lib/diameter/test/diameter_transport_SUITE.erl | 44 | ||||
-rw-r--r-- | lib/diameter/test/diameter_util.erl | 57 |
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 |