diff options
Diffstat (limited to 'lib/diameter/src/base')
-rw-r--r-- | lib/diameter/src/base/diameter.erl | 42 | ||||
-rw-r--r-- | lib/diameter/src/base/diameter_codec.erl | 4 | ||||
-rw-r--r-- | lib/diameter/src/base/diameter_config.erl | 20 | ||||
-rw-r--r-- | lib/diameter/src/base/diameter_service.erl | 83 | ||||
-rw-r--r-- | lib/diameter/src/base/diameter_traffic.erl | 14 |
5 files changed, 91 insertions, 72 deletions
diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl index ee5ff38a42..2982486a10 100644 --- a/lib/diameter/src/base/diameter.erl +++ b/lib/diameter/src/base/diameter.erl @@ -352,45 +352,45 @@ call(SvcName, App, Message) -> %% Options common to both start_service/2 and add_transport/2. -type common_opt() - :: {pool_size, pos_integer()} + :: {avp_dictionaries, [module()]} | {capabilities_cb, eval()} | {capx_timeout, 'Unsigned32'()} - | {strict_capx, boolean()} - | {strict_mbit, boolean()} - | {avp_dictionaries, [module()]} + | {connect_timer, 'Unsigned32'()} | {disconnect_cb, eval()} - | {dpr_timeout, 'Unsigned32'()} | {dpa_timeout, 'Unsigned32'()} + | {dpr_timeout, 'Unsigned32'()} | {incoming_maxlen, message_length()} | {length_errors, exit | handle | discard} - | {connect_timer, 'Unsigned32'()} - | {watchdog_timer, 'Unsigned32'() | {module(), atom(), list()}} + | {pool_size, pos_integer()} + | {spawn_opt, list() | mfa()} + | {strict_capx, boolean()} + | {strict_mbit, boolean()} | {watchdog_config, [{okay|suspect, non_neg_integer()}]} - | {spawn_opt, list() | mfa()}. + | {watchdog_timer, 'Unsigned32'() | {module(), atom(), list()}}. %% Options passed to start_service/2 -type service_opt() :: capability() | {application, [application_opt()]} + | {decode_format, decode_format()} | {restrict_connections, restriction()} | {sequence, sequence() | eval()} | {share_peers, remotes()} - | {decode_format, decode_format()} - | {traffic_counters, boolean()} - | {string_decode, boolean()} | {strict_arities, true | strict_arities()} + | {string_decode, boolean()} + | {traffic_counters, boolean()} | {use_shared_peers, remotes()} | common_opt(). -type application_opt() :: {alias, app_alias()} + | {answer_errors, callback|report|discard} + | {call_mutates_state, boolean()} | {dictionary, module()} | {module, app_module()} - | {state, any()} - | {call_mutates_state, boolean()} - | {answer_errors, callback|report|discard} - | {request_errors, answer_3xxx|answer|callback}. + | {request_errors, answer_3xxx|answer|callback} + | {state, any()}. -type app_alias() :: any(). @@ -408,11 +408,11 @@ call(SvcName, App, Message) -> %% Options passed to add_transport/2 -type transport_opt() - :: {transport_module, atom()} + :: {applications, [app_alias()]} + | {capabilities, [capability()]} | {transport_config, any()} | {transport_config, any(), 'Unsigned32'() | infinity} - | {applications, [app_alias()]} - | {capabilities, [capability()]} + | {transport_module, atom()} | common_opt() | {private, any()}. @@ -431,8 +431,8 @@ call(SvcName, App, Message) -> %% Options passed to call/4 -type call_opt() - :: {extra, list()} + :: detach + | {extra, list()} | {filter, peer_filter()} - | {timeout, 'Unsigned32'()} | {peer, peer_ref()} - | detach. + | {timeout, 'Unsigned32'()}. diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl index 493a6ab1e3..7f6baf666a 100644 --- a/lib/diameter/src/base/diameter_codec.erl +++ b/lib/diameter/src/base/diameter_codec.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2018. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. 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. @@ -208,7 +208,7 @@ values(Avps) -> encode_avps(_, _, [#diameter_avp{} | _] = Avps, Opts) -> encode_avps(Avps, Opts); -%% ... or as a tuple list or record. +%% ... or as a tuple list, map, or record. encode_avps(Mod, MsgName, Values, Opts) -> Mod:encode_avps(MsgName, Values, Opts). diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl index 36ae4c2276..495e57e456 100644 --- a/lib/diameter/src/base/diameter_config.erl +++ b/lib/diameter/src/base/diameter_config.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2018. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. 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. @@ -661,6 +661,9 @@ opt(transport, {transport_module, M}) -> opt(transport, {transport_config, _, Tmo}) -> ?IS_UINT32(Tmo) orelse Tmo == infinity; +opt(transport, {transport_config, _}) -> + true; + opt(transport, {applications, As}) -> is_list(As); @@ -720,15 +723,16 @@ opt(_, {K, _}) when K == disconnect_cb; K == capabilities_cb -> true; -opt(transport, {K, _}) - when K == transport_config; - K == private -> +opt(transport, {private, _}) -> true; -%% Anything else, which is ignored in transport config. This makes -%% options sensitive to spelling mistakes, but arbitrary options are -%% passed by some users as a way to identify transports so can't just -%% do away with it. +%% Anything else is ignored in transport config. This makes options +%% sensitive to spelling mistakes and unintentionally passing service +%% options, but arbitrary options are passed by some users as a way to +%% identify transports (they can be returned by diameter:service_info/2 +%% for example) so can't just do away with it, although silently +%% swallowing service options is at least debatable. The documentation +%% says anything, so accept anything. opt(K, _) -> K == transport. diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl index 77d184cfc7..520a7233cc 100644 --- a/lib/diameter/src/base/diameter_service.erl +++ b/lib/diameter/src/base/diameter_service.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2018. All Rights Reserved. +%% Copyright Ericsson AB 2010-2020. 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. @@ -735,29 +735,31 @@ init_peers() -> %% Alias, %% TPid} +%% Valid service options are all 2-tuples. service_opts(Opts) -> - remove([{strict_arities, true}, - {avp_dictionaries, []}], - maps:merge(maps:from_list([{monitor, false} | def_opts()]), - maps:from_list(Opts))). + remove([{strict_arities, true}, {avp_dictionaries, []}], + merge(lists:append([[{monitor, false}] | def_opts()]), Opts)). + +merge(List1, List2) -> + maps:merge(maps:from_list(List1), maps:from_list(List2)). remove(List, Map) -> maps:filter(fun(K,V) -> not lists:member({K,V}, List) end, Map). -def_opts() -> %% defaults on the service map - [{share_peers, false}, - {use_shared_peers, false}, - {sequence, {0,32}}, - {restrict_connections, nodes}, - {incoming_maxlen, 16#FFFFFF}, - {strict_arities, true}, - {strict_mbit, true}, - {decode_format, record}, - {avp_dictionaries, []}, - {traffic_counters, true}, - {string_decode, true}, - {spawn_opt, []}]. +def_opts() -> %% defaults on the options map + [[{decode_format, record}, %% service options + {restrict_connections, nodes}, + {sequence, {0,32}}, + {share_peers, false}, + {strict_arities, true}, + {string_decode, true}, + {traffic_counters, true}, + {use_shared_peers, false}], + [{avp_dictionaries, []}, %% common options + {incoming_maxlen, 16#FFFFFF}, + {spawn_opt, []}, + {strict_mbit, true}]]. mref(false = No) -> No; @@ -875,27 +877,46 @@ start(Ref, Type, Opts, N, #state{watchdogT = WatchdogT, = Svc1 = merge_service(Opts, Svc0), Svc = binary_caps(Svc1, SD), - {SOpts, TOpts} = merge_opts(SvcOpts, Opts), - RecvData = diameter_traffic:make_recvdata([SvcName, PeerT, Apps, SOpts]), - T = {TOpts, SOpts, RecvData, Svc}, + {Map, Rest} = merge_opts(SvcOpts, Opts), + RecvData = diameter_traffic:make_recvdata([SvcName, PeerT, Apps, Map]), + T = {Rest, Map, RecvData, Svc}, Rec = #watchdog{type = Type, ref = Ref, - options = TOpts}, - + options = Opts}, %% original options, returned + %% by service_info/2 diameter_lib:fold_n(fun(_,A) -> [wd(Type, Ref, T, WatchdogT, Rec) | A] end, [], N). -merge_opts(SvcOpts, Opts) -> - Keys = [K || {K,_} <- def_opts()], - SO = [T || {K,_} = T <- Opts, lists:member(K, Keys)], - TO = Opts -- SO, - {maps:merge(maps:with(Keys, SvcOpts), maps:from_list(SO)), - TO ++ [T || {K,_} = T <- maps:to_list(SvcOpts), - not lists:member(K, Keys), - not lists:keymember(K, 1, Opts)]}. +%% This is awkward. We have service options that have been passed to +%% diameter:start_service/2 (minus application and capabilities +%% options, removed in diameter_config) and transport options passed +%% to diameter:add_transport/2. The former can include defaults for +%% the latter, but the latter can also contain arbitrary options that +%% are just returned by diameter:service_info/2. There's nothing +%% stopping these arbitrary options from being valid service options, +%% but these aren't interpreted as such. +%% +%% The options are merged (transport defaults have already been merged +%% into the service options in service_opts/1) and split into a map +%% for the service options and a few transport options, and a list for +%% the rest. This is historical convolution. Some options are are +%% pulled out of the list on the way to starting the transport process +%% in diameter_peer_fsm, but more work could probably be done here to +%% simplify things. +%% +%% Transport options are not necessarily 2-tuples: the transport_config +%% 3-tuple means they can't just be turned into a map. +merge_opts(SOpts, TOpts) -> + [SD,TD] = Def = def_opts(), + Keys = [K || L <- Def, {K,_} <- L], + Opts = [T || {K,_} = T <- TOpts, lists:keymember(K, 1, TD)], + {maps:merge(maps:with(Keys, SOpts), maps:from_list(Opts)),%% merge TOpts + TOpts ++ [T || {K,_} = T <- maps:to_list(SOpts), %% append SOpts + not lists:keymember(K, 1, SD), + [] == [A || {A,_} <- TOpts, A == K]]}. binary_caps(Svc, true) -> Svc; diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl index 76f2420c7b..4667bbc3f2 100644 --- a/lib/diameter/src/base/diameter_traffic.erl +++ b/lib/diameter/src/base/diameter_traffic.erl @@ -86,6 +86,7 @@ string_decode := boolean(), strict_arities => diameter:strict_arities(), strict_mbit := boolean(), + ordered_encode => boolean(), incoming_maxlen := diameter:message_length()}}). %% Note that incoming_maxlen is currently handled in diameter_peer_fsm, %% so that any message exceeding the maximum is discarded. Retain the @@ -526,7 +527,7 @@ request_cb(noreply, _App, EvalPktFs, EvalFs) -> %% Relay a request to another peer. This is equivalent to doing an %% explicit call/4 with the message in question except that (1) a loop -%% will be detected by examining Route-Record AVP's, (3) a +%% will be detected by examining Route-Record AVP's, (2) a %% Route-Record AVP will be added to the outgoing request and (3) the %% End-to-End Identifier will default to that in the %% #diameter_header{} without the need for an end_to_end_identifier @@ -562,14 +563,7 @@ request_cb(T, App, _, _) -> send_A({reply, Ans}, TPid, App, Dict0, RecvData, Pkt, _Caps, Fs) -> AppDict = App#diameter_app.dictionary, MsgDict = msg_dict(AppDict, Dict0, Ans), - send_answer(Ans, - TPid, - MsgDict, - AppDict, - Dict0, - RecvData, - Pkt, - Fs); + send_answer(Ans, TPid, MsgDict, AppDict, Dict0, RecvData, Pkt, Fs); send_A({call, Opts}, TPid, App, Dict0, RecvData, Pkt, Caps, Fs) -> AppDict = App#diameter_app.dictionary, @@ -673,7 +667,7 @@ is_answer_message(#diameter_packet{msg = Msg}, Dict0) -> is_answer_message([#diameter_header{is_request = R, is_error = E} | _], _) -> E andalso not R; -%% Message sent as a map or tagged avp/value list. +%% Message sent as a map or avp list. is_answer_message([Name | _], _) -> Name == 'answer-message'; |