diff options
author | Anders Svensson <[email protected]> | 2013-01-21 17:34:36 +0100 |
---|---|---|
committer | Anders Svensson <[email protected]> | 2013-02-08 19:28:46 +0100 |
commit | f0a36c79af84c044ba04af3602506624a5ee8799 (patch) | |
tree | 010c75f2ef263fc666354276e3ce020fc0e87fbb /lib/diameter/src/base/diameter_service.erl | |
parent | d8ef1f220f1a85ff883fa288cd641430667525d7 (diff) | |
download | otp-f0a36c79af84c044ba04af3602506624a5ee8799.tar.gz otp-f0a36c79af84c044ba04af3602506624a5ee8799.tar.bz2 otp-f0a36c79af84c044ba04af3602506624a5ee8799.zip |
Don't hardcode common dictionary
Instead, use whatever dictionary a transport has configured as
supporting application id 0. This is to support the updated RFC 6733
dictionaries (which bring with them updated records) and also to be able
to transparently support any changed semantics (eg. 5xxx in
answer-message).
Diffstat (limited to 'lib/diameter/src/base/diameter_service.erl')
-rw-r--r-- | lib/diameter/src/base/diameter_service.erl | 732 |
1 files changed, 394 insertions, 338 deletions
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl index 3cab914fdb..6e7adb1be2 100644 --- a/lib/diameter/src/base/diameter_service.erl +++ b/lib/diameter/src/base/diameter_service.erl @@ -32,7 +32,7 @@ call/4]). %% towards diameter_watchdog --export([receive_message/3]). +-export([receive_message/4]). %% service supervisor -export([start_link/1]). @@ -50,7 +50,7 @@ state/1, uptime/1]). -%%% gen_server callbacks +%% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, @@ -82,6 +82,7 @@ -define(RESTART_TC, 1000). %% if restart was this recent -define(RELAY, ?DIAMETER_DICT_RELAY). +-define(BASE, ?DIAMETER_DICT_COMMON). %% Used to be able to swap this with anything else dict-like but now %% rely on the fact that a service's #state{} record does not change @@ -112,7 +113,7 @@ %% State of service gen_server. -record(state, {id = now(), - service_name, %% as passed to start_service/2, key in ?STATE_TABLE + service_name :: diameter:service_name(), %% key in ?STATE_TABLE service :: #diameter_service{}, watchdogT = ets_new(watchdogs) %% #watchdog{} at start :: ets:tid(), @@ -173,9 +174,16 @@ timeout = ?DEFAULT_TIMEOUT :: 0..16#FFFFFFFF, detach = false :: boolean()}). -%%% --------------------------------------------------------------------------- -%%% # start(SvcName) -%%% --------------------------------------------------------------------------- +%% Term passed back to receive_message/4 with every incoming message. +-record(recvdata, + {peerT :: ets:tid(), + service_name :: diameter:service_name(), + apps :: [#diameter_app{}], + sequence :: diameter:sequence()}). + +%% --------------------------------------------------------------------------- +%% # start/1 +%% --------------------------------------------------------------------------- start(SvcName) -> diameter_service_sup:start_child(SvcName). @@ -186,9 +194,9 @@ start_link(SvcName) -> %% Put the arbitrary term SvcName in a list in case we ever want to %% send more than this and need to distinguish old from new. -%%% --------------------------------------------------------------------------- -%%% # stop(SvcName) -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # stop/1 +%% --------------------------------------------------------------------------- stop(SvcName) -> case whois(SvcName) of @@ -204,25 +212,25 @@ stop(ok, Pid) -> stop(No, _) -> No. -%%% --------------------------------------------------------------------------- -%%% # start_transport(SvcName, {Ref, Type, Opts}) -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # start_transport/3 +%% --------------------------------------------------------------------------- -start_transport(SvcName, {_,_,_} = T) -> +start_transport(SvcName, {_Ref, _Type, _Opts} = T) -> call_service_by_name(SvcName, {start, T}). -%%% --------------------------------------------------------------------------- -%%% # stop_transport(SvcName, Refs) -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # stop_transport/2 +%% --------------------------------------------------------------------------- stop_transport(_, []) -> ok; stop_transport(SvcName, [_|_] = Refs) -> call_service_by_name(SvcName, {stop, Refs}). -%%% --------------------------------------------------------------------------- -%%% # info(SvcName, Item) -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # info/2 +%% --------------------------------------------------------------------------- info(SvcName, Item) -> case find_state(SvcName) of @@ -232,31 +240,37 @@ info(SvcName, Item) -> undefined end. -%%% --------------------------------------------------------------------------- -%%% # receive_message(TPid, Pkt, MessageData) -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # receive_message/4 +%% --------------------------------------------------------------------------- %% Handle an incoming Diameter message in the watchdog process. This %% used to come through the service process but this avoids that %% becoming a bottleneck. -receive_message(TPid, Pkt, T) +receive_message(TPid, Pkt, Dict0, RecvData) when is_pid(TPid) -> #diameter_packet{header = #diameter_header{is_request = R}} = Pkt, - recv(R, (not R) andalso lookup_request(Pkt, TPid), TPid, Pkt, T). + recv(R, + (not R) andalso lookup_request(Pkt, TPid), + TPid, + Pkt, + Dict0, + RecvData). %% Incoming request ... -recv(true, false, TPid, Pkt, T) -> +recv(true, false, TPid, Pkt, Dict0, RecvData) -> try - spawn(fun() -> recv_request(TPid, Pkt, T) end) + spawn(fun() -> recv_request(TPid, Pkt, Dict0, RecvData) end) catch error: system_limit = E -> %% discard ?LOG({error, E}, now()) end; %% ... answer to known request ... -recv(false, #request{from = {_, Ref}, handler = Pid} = Req, _, Pkt, _) -> - Pid ! {answer, Ref, Req, Pkt}; +recv(false, #request{from = From, handler = Pid} = Req, _, Pkt, Dict0, _) -> + {_, Ref} = From, + Pid ! {answer, Ref, Req, Dict0, Pkt}; %% Note that failover could have happened prior to this message being %% received and triggering failback. That is, both a failover message %% and answer may be on their way to the handler process. In the worst @@ -267,12 +281,12 @@ recv(false, #request{from = {_, Ref}, handler = Pid} = Req, _, Pkt, _) -> %% any others are discarded. %% ... or not. -recv(false, false, _, _, _) -> +recv(false, false, _, _, _, _) -> ok. -%%% --------------------------------------------------------------------------- -%%% # call(SvcName, App, Msg, Options) -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # call/4 +%% --------------------------------------------------------------------------- call(SvcName, App, Msg, Options) when is_list(Options) -> @@ -374,10 +388,10 @@ mo(detach, Rec) -> mo(T, _) -> ?ERROR({invalid_option, T}). -%%% --------------------------------------------------------------------------- -%%% # subscribe(SvcName) -%%% # unsubscribe(SvcName) -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # subscribe/1 +%% # unsubscribe/1 +%% --------------------------------------------------------------------------- subscribe(SvcName) -> diameter_reg:add({?MODULE, subscriber, SvcName}). @@ -394,9 +408,9 @@ subscriptions() -> pmap(Props) -> lists:map(fun({{?MODULE, _, Name}, Pid}) -> {Name, Pid} end, Props). -%%% --------------------------------------------------------------------------- -%%% # services(Pattern) -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # services/1 +%% --------------------------------------------------------------------------- services(Pat) -> pmap(diameter_reg:match({?MODULE, service, Pat})). @@ -426,9 +440,9 @@ uptime(Svc) -> call_module(Service, AppMod, Request) -> call_service(Service, {call_module, AppMod, Request}). -%%% --------------------------------------------------------------------------- -%%% # init([SvcName]) -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # init/1 +%% --------------------------------------------------------------------------- init([SvcName]) -> process_flag(trap_exit, true), %% ensure terminate(shutdown, _) @@ -439,9 +453,9 @@ i(SvcName, true) -> i(_, false) -> {stop, {shutdown, already_started}}. -%%% --------------------------------------------------------------------------- -%%% # handle_call(Req, From, State) -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # handle_call/3 +%% --------------------------------------------------------------------------- handle_call(state, _, S) -> {reply, S, S}; @@ -477,17 +491,17 @@ handle_call(Req, From, S) -> unexpected(handle_call, [Req, From], S), {reply, nok, S}. -%%% --------------------------------------------------------------------------- -%%% # handle_cast(Req, State) -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # handle_cast/2 +%% --------------------------------------------------------------------------- handle_cast(Req, S) -> unexpected(handle_cast, [Req], S), {noreply, S}. -%%% --------------------------------------------------------------------------- -%%% # handle_info(Req, State) -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # handle_info/2 +%% --------------------------------------------------------------------------- handle_info(T, #state{} = S) -> case transition(T,S) of @@ -581,9 +595,9 @@ transition(Req, S) -> unexpected(handle_info, [Req], S), ok. -%%% --------------------------------------------------------------------------- -%%% # terminate(Reason, State) -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # terminate/2 +%% --------------------------------------------------------------------------- terminate(Reason, #state{service_name = Name} = S) -> send_event(Name, stop), @@ -591,9 +605,9 @@ terminate(Reason, #state{service_name = Name} = S) -> shutdown == Reason %% application shutdown andalso shutdown(application, S). -%%% --------------------------------------------------------------------------- -%%% # code_change(FromVsn, State, Extra) -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # code_change/3 +%% --------------------------------------------------------------------------- code_change(FromVsn, #state{service_name = SvcName, @@ -668,9 +682,9 @@ mod_state(Alias) -> mod_state(Alias, ModS) -> put({?MODULE, mod_state, Alias}, ModS). -%%% --------------------------------------------------------------------------- -%%% # shutdown/2 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # shutdown/2 +%% --------------------------------------------------------------------------- %% remove_transport shutdown(Refs, #state{watchdogT = WatchdogT}) @@ -697,9 +711,9 @@ st(#watchdog{pid = Pid}, Reason, Acc) -> Pid ! {shutdown, self(), Reason}, [Pid | Acc]. -%%% --------------------------------------------------------------------------- -%%% # call_service/2 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # call_service/2 +%% --------------------------------------------------------------------------- call_service(Pid, Req) when is_pid(Pid) -> @@ -722,9 +736,9 @@ cs(Pid, Req) cs(undefined, _) -> {error, no_service}. -%%% --------------------------------------------------------------------------- -%%% # i/1 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # i/1 +%% --------------------------------------------------------------------------- %% Intialize the state of a service gen_server. @@ -794,9 +808,9 @@ get_value(Key, Vs) -> {_, V} = lists:keyfind(Key, 1, Vs), V. -%%% --------------------------------------------------------------------------- -%%% # start/3 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # start/3 +%% --------------------------------------------------------------------------- %% If the initial start/3 at service/transport start succeeds then %% subsequent calls to start/4 on the same service will also succeed @@ -830,14 +844,21 @@ start(Ref, Type, Opts, #state{watchdogT = WatchdogT, peerT = PeerT, options = SvcOpts, service_name = SvcName, - service = Svc}) + service = Svc0}) when Type == connect; Type == accept -> - Pid = s(Type, Ref, {PeerT, + #diameter_service{applications = Apps} + = Svc + = merge_service(Opts, Svc0), + Pid = s(Type, Ref, {#recvdata{service_name = SvcName, + peerT = PeerT, + apps = Apps, + sequence + = {_,_} + = proplists:get_value(sequence, SvcOpts)}, Opts, - SvcName, SvcOpts, - merge_service(Opts, Svc)}), + Svc}), insert(WatchdogT, #watchdog{pid = Pid, type = Type, ref = Ref, @@ -884,9 +905,9 @@ ms({capabilities, Opts}, #diameter_service{capabilities = Caps0} = Svc) ms(_, Svc) -> Svc. -%%% --------------------------------------------------------------------------- -%%% # accepted/3 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # accepted/3 +%% --------------------------------------------------------------------------- accepted(Pid, _TPid, #state{watchdogT = WatchdogT} = S) -> #watchdog{ref = Ref, type = accept = T, peer = false, options = Opts} @@ -899,11 +920,11 @@ fetch(Tid, Key) -> [T] = ets:lookup(Tid, Key), T. -%%% --------------------------------------------------------------------------- -%%% # watchdog/6 -%%% -%%% React to a watchdog state transition. -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # watchdog/6 +%% +%% React to a watchdog state transition. +%% --------------------------------------------------------------------------- %% Watchdog has a new open connection. watchdog(TPid, [T], _, ?WD_OKAY, Wd, State) -> @@ -933,43 +954,43 @@ watchdog(TPid, [], _, ?WD_DOWN = To, Wd, #state{peerT = PeerT} = S) -> watchdog(_, [], _, _, _, _) -> ok. -%%% --------------------------------------------------------------------------- -%%% # connection_up/3 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # connection_up/3 +%% --------------------------------------------------------------------------- %% Watchdog process has reached state OKAY. -connection_up({TPid, {Caps, SApps, Pkt}}, +connection_up({TPid, {Caps, SupportedApps, Pkt}}, #watchdog{pid = Pid} = Wd, #state{peerT = PeerT} = S) -> Pr = #peer{pid = TPid, - apps = SApps, + apps = SupportedApps, caps = Caps, watchdog = Pid}, insert(PeerT, Pr), connection_up([Pkt], Wd#watchdog{peer = TPid}, Pr, S). -%%% --------------------------------------------------------------------------- -%%% # reopen/3 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # reopen/3 +%% --------------------------------------------------------------------------- -reopen({TPid, {Caps, SApps, _Pkt}}, +reopen({TPid, {Caps, SupportedApps, _Pkt}}, #watchdog{pid = Pid} = Wd, #state{watchdogT = WatchdogT, peerT = PeerT}) -> insert(PeerT, #peer{pid = TPid, - apps = SApps, + apps = SupportedApps, caps = Caps, watchdog = Pid}), insert(WatchdogT, Wd#watchdog{state = ?WD_REOPEN, peer = TPid}). -%%% --------------------------------------------------------------------------- -%%% # connection_up/2 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # connection_up/2 +%% --------------------------------------------------------------------------- %% Watchdog has recovered as suspect connection. Note that there has %% been no new capabilties exchange in this case. @@ -987,8 +1008,7 @@ connection_up(Extra, #state{watchdogT = WatchdogT, local_peers = LDict, service_name = SvcName, - service - = #diameter_service{applications = Apps}} + service = #diameter_service{applications = Apps}} = S) -> insert(WatchdogT, Wd#watchdog{state = ?WD_OKAY}), request_peer_up(TPid), @@ -1028,9 +1048,9 @@ peer_cb(MFA, Alias) -> false end. -%%% --------------------------------------------------------------------------- -%%% # connection_down/3 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # connection_down/3 +%% --------------------------------------------------------------------------- connection_down(#watchdog{state = ?WD_OKAY, peer = TPid} @@ -1077,9 +1097,9 @@ down_conn(Id, Alias, TC, {SvcName, Apps}) -> peer_cb({ModX, peer_down, [SvcName, TC]}, Alias). -%%% --------------------------------------------------------------------------- -%%% # watchdog_down/2 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # watchdog_down/2 +%% --------------------------------------------------------------------------- %% Watchdog process has died. @@ -1172,9 +1192,9 @@ tc(true, {Ref, Type, Opts}, #state{service_name = SvcName} tc(false = No, _, _) -> %% removed No. -%%% --------------------------------------------------------------------------- -%%% # close/2 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # close/2 +%% --------------------------------------------------------------------------- %% The watchdog doesn't start a new fsm in the accept case, it %% simply stays alive until someone tells it to die in order for @@ -1207,9 +1227,9 @@ c(Pid, false, _Opts) -> %% which a new connection attempt is expected of a connecting peer. %% The value should be greater than the peer's Tc + jitter. -%%% --------------------------------------------------------------------------- -%%% # reconnect/2 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # reconnect/2 +%% --------------------------------------------------------------------------- reconnect(Pid, #state{service_name = SvcName, watchdogT = WatchdogT}) -> @@ -1219,9 +1239,9 @@ reconnect(Pid, #state{service_name = SvcName, = fetch(WatchdogT, Pid), send_event(SvcName, {reconnect, Ref, Opts}). -%%% --------------------------------------------------------------------------- -%%% # call_module/4 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # call_module/4 +%% --------------------------------------------------------------------------- %% Backwards compatibility and never documented/advertised. May be %% removed. @@ -1268,9 +1288,9 @@ cm([], _, _, _) -> cm([_,_|_], _, _, _) -> multiple. -%%% --------------------------------------------------------------------------- -%%% # send_request/6 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # send_request/6 +%% --------------------------------------------------------------------------- %% Send an outgoing request in its dedicated process. %% @@ -1402,20 +1422,20 @@ fold_record(Rec, R) -> %% send_req/6 -send_req(Pkt, {TPid, Caps, App}, Opts, Caller, SvcName, Fs) -> +send_req(Pkt0, {TPid, Caps, App}, Opts, Caller, SvcName, Fs) -> #diameter_app{alias = Alias, dictionary = Dict, module = ModX, options = [{answer_errors, AE} | _]} = App, - EPkt = encode(Dict, Pkt, Fs), + Pkt = encode(Dict, Pkt0, Fs), #options{filter = Filter, timeout = Timeout} = Opts, - Req = #request{packet = Pkt, + Req = #request{packet = Pkt0, from = Caller, handler = self(), transport = TPid, @@ -1426,11 +1446,11 @@ send_req(Pkt, {TPid, Caps, App}, Opts, Caller, SvcName, Fs) -> module = ModX}, try - TRef = send_request(TPid, EPkt, Req, Timeout), + TRef = send_request(TPid, Pkt, Req, Timeout), ack(Caller), handle_answer(SvcName, AE, recv_answer(Timeout, SvcName, {TRef, Req})) after - erase_request(EPkt) + erase_request(Pkt) end. %% Tell caller a send has been attempted. @@ -1450,13 +1470,13 @@ recv_answer(Timeout, %% is, from the last peer to which we've transmitted. receive - {answer = A, Ref, Rq, Pkt} -> %% Answer from peer - {A, Rq, Pkt}; - {timeout = Reason, TRef, _} -> %% No timely reply + {answer = A, Ref, Rq, Dict0, Pkt} -> %% Answer from peer + {A, Rq, Dict0, Pkt}; + {timeout = Reason, TRef, _} -> %% No timely reply {error, Req, Reason}; - {failover = Reason, TRef, false} -> %% No alternate peer + {failover = Reason, TRef, false} -> %% No alternate peer {error, Req, Reason}; - {failover, TRef, Transport} -> %% Resend to alternate peer + {failover, TRef, Transport} -> %% Resend to alternate peer try_retransmit(Timeout, SvcName, Req, Transport); {failover, TRef} -> %% May have missed failover notification Seqs = diameter_codec:sequence_numbers(RPkt), @@ -1499,49 +1519,19 @@ encode(Dict, Pkt, Fs) -> %% encode/2 -%% Note that prepare_request can return a diameter_packet containing +%% Note that prepare_request can return a diameter_packet containing a %% header or transport_data. Even allow the returned record to contain -%% an encoded binary. This isn't the usual case but could some in -%% handy, for test at least. (For example, to send garbage.) +%% an encoded binary. This isn't the usual case and doesn't properly +%% support retransmission but is useful for test. -%% The normal case: encode the returned message. -encode(Dict, #diameter_packet{msg = Msg, bin = undefined} = Pkt) -> - D = pick_dictionary([Dict, ?BASE], Msg), - diameter_codec:encode(D, Pkt); +%% A message to be encoded. +encode(Dict, #diameter_packet{bin = undefined} = Pkt) -> + diameter_codec:encode(Dict, Pkt); -%% Callback has returned an encoded binary: just send. +%% An encoded binary: just send. encode(_, #diameter_packet{} = Pkt) -> Pkt. -%% pick_dictionary/2 - -%% Pick the first dictionary that declares the application id in the -%% specified header. -pick_dictionary(Ds, [#diameter_header{application_id = Id} | _]) -> - pd(Ds, fun(D) -> Id = D:id() end); - -%% Pick the first dictionary that knows the specified message name. -pick_dictionary(Ds, [MsgName|_]) -> - pd(Ds, fun(D) -> D:msg2rec(MsgName) end); - -%% Pick the first dictionary that knows the name of the specified -%% message record. -pick_dictionary(Ds, Rec) -> - Name = element(1, Rec), - pd(Ds, fun(D) -> D:rec2msg(Name) end). - -pd([D|Ds], F) -> - try - F(D), - D - catch - error:_ -> - pd(Ds, F) - end; - -pd([], _) -> - ?ERROR(no_dictionary). - %% send_request/4 send_request(TPid, #diameter_packet{bin = Bin} = Pkt, Req, Timeout) @@ -1613,15 +1603,15 @@ resend_req(T, {_, _, App}, _, _, _) -> %% retransmit/6 -retransmit(Pkt, {TPid, Caps, _}, #request{dictionary = D} = Req0, Tmo, Fs) -> - EPkt = encode(D, Pkt, Fs), +retransmit(Pkt0, {TPid, Caps, _}, #request{dictionary = D} = Req0, Tmo, Fs) -> + Pkt = encode(D, Pkt0, Fs), Req = Req0#request{transport = TPid, - packet = Pkt, + packet = Pkt0, caps = Caps}, ?LOG(retransmission, Req), - TRef = send_request(TPid, EPkt, Req, Tmo), + TRef = send_request(TPid, Pkt, Req, Tmo), {TRef, Req}. %% store_request/4 @@ -1692,14 +1682,14 @@ request_peer_down(TPid, S) -> %% given handler as there are peers its sent to. All but one of these %% will be ignored. -%%% --------------------------------------------------------------------------- -%%% recv_request/3 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% recv_request/4 +%% --------------------------------------------------------------------------- -recv_request(TPid, Pkt, {PeerT, SvcName, Apps, Mask}) -> +recv_request(TPid, Pkt, Dict0, #recvdata{peerT = PeerT} = RecvData) -> try ets:lookup(PeerT, TPid) of - [C] -> - recv_request(C, TPid, Pkt, SvcName, Apps, Mask); + [Pr] -> + recv_request(Pr, TPid, Pkt, Dict0, RecvData); [] -> %% transport has gone down ok catch @@ -1712,23 +1702,17 @@ recv_request(TPid, Pkt, {PeerT, SvcName, Apps, Mask}) -> recv_request(#peer{apps = SApps, caps = Caps}, TPid, Pkt, - SvcName, - Apps, - Mask) -> - #diameter_caps{origin_host = {OH,_}, - origin_realm = {OR,_}} - = Caps, - + Dict0, + RecvData) -> #diameter_packet{header = #diameter_header{application_id = Id}} = Pkt, recv_request(find_recv_app(Id, SApps), - {SvcName, OH, OR}, TPid, - Apps, - Mask, Caps, - Pkt). + Pkt, + Dict0, + RecvData). %% find_recv_app/2 @@ -1736,7 +1720,7 @@ recv_request(#peer{apps = SApps, caps = Caps}, find_recv_app(?APP_ID_RELAY, _) -> false; -%% With any other id we either support it locally or as a relay. +%% With any other id, must either support it or be a relay. find_recv_app(Id, SApps) -> keyfind([Id, ?APP_ID_RELAY], 1, SApps). @@ -1752,26 +1736,27 @@ keyfind([Key | Rest], Pos, L) -> T end. -%% recv_request/7 +%% recv_request/6 -recv_request({Id, Alias}, T, TPid, Apps, Mask, Caps, Pkt) -> +recv_request({Id, Alias}, TPid, Caps, Pkt, Dict0, RecvData) -> #diameter_app{dictionary = Dict} - = A - = find_app(Alias, Apps), - recv_request(T, - {TPid, Caps}, - A, - Mask, - diameter_codec:decode(Id, Dict, Pkt)); + = App + = find_app(Alias, RecvData#recvdata.apps), + recv_req(App, + TPid, + Caps, + Dict0, + RecvData, + diameter_codec:decode(Id, Dict, Pkt)); %% Note that the decode is different depending on whether or not Id is %% ?APP_ID_RELAY. %% DIAMETER_APPLICATION_UNSUPPORTED 3007 %% A request was sent for an application that is not supported. -recv_request(false, T, TPid, _, _, _, Pkt) -> +recv_request(false, TPid, Caps, Pkt, Dict0, _) -> As = collect_avps(Pkt), - protocol_error(3007, T, TPid, Pkt#diameter_packet{avps = As}). + protocol_error(3007, TPid, Caps, Dict0, Pkt#diameter_packet{avps = As}). collect_avps(Pkt) -> case diameter_codec:collect_avps(Pkt) of @@ -1781,7 +1766,7 @@ collect_avps(Pkt) -> As end. -%% recv_request/5 +%% recv_req/6 %% Wrong number of bits somewhere in the message: reply. %% @@ -1790,9 +1775,14 @@ collect_avps(Pkt) -> %% set to an unrecognized value, or that is inconsistent with the %% AVP's definition. %% -recv_request(T, {TPid, _}, _, _, #diameter_packet{errors = [Bs | _]} = Pkt) +recv_req(_App, + TPid, + Caps, + Dict0, + _RecvData, + #diameter_packet{errors = [Bs | _]} = Pkt) when is_bitstring(Bs) -> - protocol_error(3009, T, TPid, Pkt); + protocol_error(3009, TPid, Caps, Dict0, Pkt); %% Either we support this application but don't recognize the command %% or we're a relay and the command isn't proxiable. @@ -1802,16 +1792,17 @@ recv_request(T, {TPid, _}, _, _, #diameter_packet{errors = [Bs | _]} = Pkt) %% recognize or support. This MUST be used when a Diameter node %% receives an experimental command that it does not understand. %% -recv_request(T, - {TPid, _}, - #diameter_app{id = Id}, - _, - #diameter_packet{header = #diameter_header{is_proxiable = P}, - msg = M} - = Pkt) +recv_req(#diameter_app{id = Id}, + TPid, + Caps, + Dict0, + _RecvData, + #diameter_packet{header = #diameter_header{is_proxiable = P}, + msg = M} + = Pkt) when ?APP_ID_RELAY /= Id, undefined == M; ?APP_ID_RELAY == Id, not P -> - protocol_error(3001, T, TPid, Pkt); + protocol_error(3001, TPid, Caps, Dict0, Pkt); %% Error bit was set on a request. %% @@ -1820,30 +1811,38 @@ recv_request(T, %% either set to an invalid combination, or to a value that is %% inconsistent with the command code's definition. %% -recv_request(T, - {TPid, _}, - _, - _, - #diameter_packet{header = #diameter_header{is_error = true}} - = Pkt) -> - protocol_error(3008, T, TPid, Pkt); +recv_req(_App, + TPid, + Caps, + Dict0, + _RecvData, + #diameter_packet{header = #diameter_header{is_error = true}} + = Pkt) -> + protocol_error(3008, TPid, Caps, Dict0, Pkt); %% A message in a locally supported application or a proxiable message %% in the relay application. Don't distinguish between the two since %% each application has its own callback config. That is, the user can %% easily distinguish between the two cases. -recv_request(T, TC, App, Mask, Pkt) -> - request_cb(T, TC, App, Mask, examine(Pkt)). +recv_req(App, TPid, Caps, Dict0, RecvData, Pkt) -> + request_cb(App, TPid, Caps, Dict0, RecvData, examine(Pkt)). %% Note that there may still be errors but these aren't protocol %% (3xxx) errors that lead to an answer-message. -request_cb({SvcName, _OH, _OR} = T, TC, App, Mask, Pkt) -> - request_cb(cb(App, handle_request, [Pkt, SvcName, TC]), +request_cb(App, + TPid, + Caps, + Dict0, + #recvdata{service_name = SvcName} + = RecvData, + Pkt) -> + request_cb(cb(App, handle_request, [Pkt, SvcName, {TPid, Caps}]), App, - Mask, - T, - TC, + TPid, + Caps, + Dict0, + RecvData, [], Pkt). @@ -1865,7 +1864,7 @@ examine(#diameter_packet{errors = Es} = Pkt) -> Pkt#diameter_packet{errors = [5011 | Es]}. %% It's odd/unfortunate that this isn't a protocol error. -%% request_cb/7 +%% request_cb/8 %% A reply may be an answer-message, constructed either here or by %% the handle_request callback. The header from the incoming request @@ -1874,24 +1873,39 @@ examine(#diameter_packet{errors = Es} = Pkt) -> %% the base encoder. request_cb({reply, Ans}, #diameter_app{dictionary = Dict}, - _, - _, - {TPid, _}, + TPid, + _Caps, + Dict0, + _RecvData, Fs, Pkt) -> - reply(Ans, Dict, TPid, Fs, Pkt); + reply(Ans, dict(Dict, Dict0, Ans), TPid, Fs, Pkt); %% An 3xxx result code, for which the E-bit is set in the header. -request_cb({protocol_error, RC}, _, _, T, {TPid, _}, Fs, Pkt) +request_cb({protocol_error, RC}, + _App, + TPid, + Caps, + Dict0, + _RecvData, + Fs, + Pkt) when 3000 =< RC, RC < 4000 -> - protocol_error(RC, T, TPid, Fs, Pkt); + protocol_error(RC, TPid, Caps, Dict0, Fs, Pkt); %% RFC 3588 says we must reply 3001 to anything unrecognized or %% unsupported. 'noreply' is undocumented (and inappropriately named) %% backwards compatibility for this, protocol_error the documented %% alternative. -request_cb(noreply, _, _, T, {TPid, _}, Fs, Pkt) -> - protocol_error(3001, T, TPid, Fs, Pkt); +request_cb(noreply, + _App, + TPid, + Caps, + Dict0, + _RecvData, + Fs, + Pkt) -> + protocol_error(3001, TPid, Caps, Dict0, Fs, Pkt); %% 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 @@ -1911,57 +1925,101 @@ request_cb(noreply, _, _, T, {TPid, _}, Fs, Pkt) -> request_cb({A, Opts}, #diameter_app{id = Id} = App, - Mask, - T, - TC, + TPid, + Caps, + Dict0, + RecvData, Fs, Pkt) when A == relay, Id == ?APP_ID_RELAY; A == proxy, Id /= ?APP_ID_RELAY; A == resend -> - resend(Opts, App, Mask, T, TC, Fs, Pkt); + resend(Opts, App, TPid, Caps, Dict0, RecvData, Fs, Pkt); -request_cb(discard, _, _, _, _, _, _) -> +request_cb(discard, _, _, _, _, _, _, _) -> ok; -request_cb({eval_packet, RC, F}, App, Mask, T, TC, Fs, Pkt) -> - request_cb(RC, App, Mask, T, TC, [F|Fs], Pkt); +request_cb({eval_packet, RC, F}, App, TPid, Caps, Dict0, RecvData, Fs, Pkt) -> + request_cb(RC, App, TPid, Caps, Dict0, RecvData, [F|Fs], Pkt); -request_cb({eval, RC, F}, App, Mask, T, TC, Fs, Pkt) -> - request_cb(RC, App, Mask, T, TC, Fs, Pkt), +request_cb({eval, RC, F}, App, TPid, Caps, Dict0, RecvData, Fs, Pkt) -> + request_cb(RC, App, TPid, Caps, Dict0, RecvData, Fs, Pkt), diameter_lib:eval(F). -%% protocol_error/5 +%% dict/3 + +%% An incoming answer, not yet decoded. +dict(Dict, Dict0, #diameter_packet{header + = #diameter_header{is_request = false, + is_error = E}, + msg = undefined}) -> + if E -> Dict0; true -> Dict end; + +dict(Dict, Dict0, [Msg]) -> + dict(Dict, Dict0, Msg); + +dict(Dict, Dict0, #diameter_packet{msg = Msg}) -> + dict(Dict, Dict0, Msg); + +dict(_Dict, Dict0, ['answer-message' | _]) -> + Dict0; + +dict(Dict, Dict0, Rec) -> + try + 'answer-message' = Dict0:rec2msg(element(1,Rec)), + Dict0 + catch + error:_ -> Dict + end. + +%% protocol_error/6 + +protocol_error(RC, TPid, Caps, Dict0, Fs, Pkt) -> + #diameter_caps{origin_host = {OH,_}, + origin_realm = {OR,_}} + = Caps, + #diameter_packet{avps = Avps, errors = Es} + = Pkt, -protocol_error(RC, {_, OH, OR}, TPid, Fs, Pkt) -> - #diameter_packet{avps = Avps, errors = Es} = Pkt, ?LOG({error, RC}, Pkt), - reply(answer_message({OH, OR, RC}, Avps), - ?BASE, + reply(answer_message({OH, OR, RC}, Dict0, Avps), + Dict0, TPid, Fs, Pkt#diameter_packet{errors = [RC | Es]}). %% Note that reply/5 may set the result code once more. It's set in -%% answer_message/2 in case reply/5 doesn't. +%% answer_message/3 in case reply/5 doesn't. -%% protocol_error/4 +%% protocol_error/5 -protocol_error(RC, T, TPid, Pkt) -> - protocol_error(RC, T, TPid, [], Pkt). +protocol_error(RC, TPid, Caps, Dict0, Pkt) -> + protocol_error(RC, TPid, Caps, Dict0, [], Pkt). %% resend/7 %% %% Resend a message as a relay or proxy agent. resend(Opts, - #diameter_app{} = App, - Mask, - {_SvcName, OH, _OR} = T, - {_TPid, _Caps} = TC, + #diameter_app{} + = App, + TPid, + #diameter_caps{origin_host = {OH,_}} + = Caps, + Dict0, + RecvData, Fs, - #diameter_packet{avps = Avps} = Pkt) -> - {Code, _Flags, Vid} = ?BASE:avp_header('Route-Record'), - resend(is_loop(Code, Vid, OH, Avps), Opts, App, Mask, T, TC, Fs, Pkt). + #diameter_packet{avps = Avps} + = Pkt) -> + {Code, _Flags, Vid} = Dict0:avp_header('Route-Record'), + resend(is_loop(Code, Vid, OH, Dict0, Avps), + Opts, + App, + TPid, + Caps, + Dict0, + RecvData, + Fs, + Pkt). %% DIAMETER_LOOP_DETECTED 3005 %% An agent detected a loop while trying to get the message to the @@ -1969,8 +2027,8 @@ resend(Opts, %% if one is available, but the peer reporting the error has %% identified a configuration problem. -resend(true, _, _, _, T, {TPid, _}, Fs, Pkt) -> %% Route-Record loop - protocol_error(3005, T, TPid, Fs, Pkt); +resend(true, _Opts, _App, TPid, Caps, Dict0, _RecvData, Fs, Pkt) -> + protocol_error(3005, TPid, Caps, Dict0, Fs, Pkt); %% 6.1.8. Relaying and Proxying Requests %% @@ -1981,18 +2039,21 @@ resend(true, _, _, _, T, {TPid, _}, Fs, Pkt) -> %% Route-Record loop resend(false, Opts, App, - Mask, - {SvcName, _, _} = T, - {TPid, #diameter_caps{origin_host = {_, OH}}}, + TPid, + #diameter_caps{origin_host = {_,OH}} + = Caps, + Dict0, + #recvdata{service_name = SvcName, + sequence = Mask}, Fs, #diameter_packet{header = Hdr0, avps = Avps} = Pkt) -> - Route = #diameter_avp{data = {?BASE, 'Route-Record', OH}}, + Route = #diameter_avp{data = {Dict0, 'Route-Record', OH}}, Seq = diameter_session:sequence(Mask), Hdr = Hdr0#diameter_header{hop_by_hop_id = Seq}, Msg = [Hdr, Route | Avps], - resend(call(SvcName, App, Msg, Opts), T, TPid, Fs, Pkt). + resend(call(SvcName, App, Msg, Opts), TPid, Caps, Dict0, Fs, Pkt). %% The incoming request is relayed with the addition of a %% Route-Record. Note the requirement on the return from call/4 below, %% which places a requirement on the value returned by the @@ -2009,47 +2070,49 @@ resend(false, %% RFC 6.3 says that a relay agent does not modify Origin-Host but %% says nothing about a proxy. Assume it should behave the same way. -%% resend/4 +%% resend/6 %% %% Relay a reply to a relayed request. %% Answer from the peer: reset the hop by hop identifier and send. resend(#diameter_packet{bin = B} = Pkt, - _, TPid, + _Caps, + _Dict0, Fs, #diameter_packet{header = #diameter_header{hop_by_hop_id = Id}, transport_data = TD}) -> P = Pkt#diameter_packet{bin = diameter_codec:hop_by_hop_id(Id, B), - transport_data = TD}, + transport_data = TD}, eval_packet(P, Fs), send(TPid, P); %% TODO: counters %% Or not: DIAMETER_UNABLE_TO_DELIVER. -resend(_, T, TPid, Fs, Pkt) -> - protocol_error(3002, T, TPid, Fs, Pkt). +resend(_, TPid, Caps, Dict0, Fs, Pkt) -> + protocol_error(3002, TPid, Caps, Dict0, Fs, Pkt). -%% is_loop/4 +%% is_loop/5 %% %% Is there a Route-Record AVP with our Origin-Host? is_loop(Code, Vid, Bin, + _Dict0, [#diameter_avp{code = Code, vendor_id = Vid, data = Bin} | _]) -> true; -is_loop(_, _, _, []) -> +is_loop(_, _, _, _, []) -> false; -is_loop(Code, Vid, OH, [_ | Avps]) +is_loop(Code, Vid, OH, Dict0, [_ | Avps]) when is_binary(OH) -> - is_loop(Code, Vid, OH, Avps); + is_loop(Code, Vid, OH, Dict0, Avps); -is_loop(Code, Vid, OH, Avps) -> - is_loop(Code, Vid, ?BASE:avp(encode, OH, 'Route-Record'), Avps). +is_loop(Code, Vid, OH, Dict0, Avps) -> + is_loop(Code, Vid, Dict0:avp(encode, OH, 'Route-Record'), Dict0, Avps). %% reply/5 %% @@ -2066,8 +2129,7 @@ reply([Msg], Dict, TPid, Fs, Pkt) reply(Msg, Dict, TPid, Fs, #diameter_packet{errors = Es} = ReqPkt) when [] == Es; is_record(hd(Msg), diameter_header) -> - Pkt = diameter_codec:encode(Dict, make_answer_packet(Msg, ReqPkt)), - eval_packet(Pkt, Fs), + Pkt = encode(Dict, make_answer_packet(Msg, ReqPkt), Fs), incr(send, Pkt, Dict, TPid), %% count result codes in sent answers send(TPid, Pkt); @@ -2124,15 +2186,15 @@ rc(RC) -> %% rc/4 -rc(#diameter_packet{msg = Rec} = Pkt, RC, Failed, Dict) -> - Pkt#diameter_packet{msg = rc(Rec, RC, Failed, Dict)}; +rc(#diameter_packet{msg = Rec} = Pkt, RC, Failed, DictT) -> + Pkt#diameter_packet{msg = rc(Rec, RC, Failed, DictT)}; -rc(Rec, RC, Failed, Dict) +rc(Rec, RC, Failed, DictT) when is_integer(RC) -> set(Rec, - lists:append([rc(Rec, {'Result-Code', RC}, Dict), - failed_avp(Rec, Failed, Dict)]), - Dict). + lists:append([rc(Rec, {'Result-Code', RC}, DictT), + failed_avp(Rec, Failed, DictT)]), + DictT). %% Reply as name and tuple list ... set([_|_] = Ans, Avps, _) -> @@ -2259,20 +2321,20 @@ fa(Rec, FailedAvp, Dict) -> %% Error-Message AVP is not intended to be useful in real-time, and %% SHOULD NOT be expected to be parsed by network entities. -%% answer_message/2 +%% answer_message/3 -answer_message({OH, OR, RC}, Avps) -> - {Code, _, Vid} = ?BASE:avp_header('Session-Id'), +answer_message({OH, OR, RC}, Dict0, Avps) -> + {Code, _, Vid} = Dict0:avp_header('Session-Id'), ['answer-message', {'Origin-Host', OH}, {'Origin-Realm', OR}, {'Result-Code', RC} - | session_id(Code, Vid, Avps)]. + | session_id(Code, Vid, Dict0, Avps)]. -session_id(Code, Vid, Avps) +session_id(Code, Vid, Dict0, Avps) when is_list(Avps) -> try {value, #diameter_avp{data = D}} = find_avp(Code, Vid, Avps), - [{'Session-Id', [?BASE:avp(decode, D, 'Session-Id')]}] + [{'Session-Id', [Dict0:avp(decode, D, 'Session-Id')]}] catch error: _ -> [] @@ -2353,9 +2415,9 @@ find(Pred, [H|T]) -> %% code, the missing vendor id, and a zero filled payload of the minimum %% required length for the omitted AVP will be added. -%%% --------------------------------------------------------------------------- -%%% # handle_answer/3 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # handle_answer/3 +%% --------------------------------------------------------------------------- %% Process an answer message in call-specific process. @@ -2364,9 +2426,11 @@ handle_answer(SvcName, _, {error, Req, Reason}) -> handle_answer(SvcName, AnswerErrors, - {answer, #request{dictionary = Dict} = Req, Pkt}) -> - answer(examine(diameter_codec:decode(Dict, Pkt)), + {answer, #request{dictionary = Dict} = Req, Dict0, Pkt}) -> + Mod = dict(Dict, Dict0, Pkt), + answer(examine(diameter_codec:decode(Mod, Pkt)), SvcName, + Mod, AnswerErrors, Req). @@ -2374,9 +2438,7 @@ handle_answer(SvcName, %% just resend with a new hop by hop identifier, but might a proxy %% want to examine the answer? -answer(Pkt, SvcName, AE, #request{transport = TPid, - dictionary = Dict} - = Req) -> +answer(Pkt, SvcName, Dict, AE, #request{transport = TPid} = Req) -> try incr(recv, Pkt, Dict, TPid) of @@ -2408,7 +2470,7 @@ a(Pkt, SvcName, discard, Req) -> %% %% Increment a stats counter for an incoming or outgoing message. -%% TODO: fix +%% Outgoing message as binary: don't yet count. (TODO) incr(_, #diameter_packet{msg = undefined}, _, _) -> ok; @@ -2495,9 +2557,9 @@ x(Reason, F, A) -> x(T) -> exit(T). -%%% --------------------------------------------------------------------------- -%%% # failover/[23] -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # failover/[23] +%% --------------------------------------------------------------------------- %% Failover as a consequence of request_peer_down/2. failover({_, #request{handler = Pid} = Req, TRef}, S) -> @@ -2515,7 +2577,7 @@ failover(TRef, Seqs, S) %% prepare_request returned a binary ... rt(#request{packet = #diameter_packet{msg = undefined}}, _) -> - false; %% TODO: Not what we should do. + false; %% Not what we should do but binaries are only parially supported %% ... or not. rt(#request{packet = #diameter_packet{msg = Msg}, @@ -2524,9 +2586,9 @@ rt(#request{packet = #diameter_packet{msg = Msg}, S) -> find_transport(get_destination(Dict, Msg), Req, S). -%%% --------------------------------------------------------------------------- -%%% # report_status/5 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # report_status/5 +%% --------------------------------------------------------------------------- report_status(Status, #watchdog{ref = Ref, @@ -2551,9 +2613,9 @@ send_event(SvcName, Info) -> send_event(#diameter_event{service = SvcName} = E) -> lists:foreach(fun({_, Pid}) -> Pid ! E end, subscriptions(SvcName)). -%%% --------------------------------------------------------------------------- -%%% # share_peer/5 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # share_peer/5 +%% --------------------------------------------------------------------------- share_peer(up, Caps, Aliases, TPid, #state{options = [_, {_, true} | _], service_name = Svc}) -> @@ -2562,9 +2624,9 @@ share_peer(up, Caps, Aliases, TPid, #state{options = [_, {_, true} | _], share_peer(_, _, _, _, _) -> ok. -%%% --------------------------------------------------------------------------- -%%% # share_peers/2 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # share_peers/2 +%% --------------------------------------------------------------------------- share_peers(Pid, #state{options = [_, {_, true} | _], local_peers = PDict}) -> @@ -2576,9 +2638,9 @@ share_peers(_, _) -> sp(Pid, Alias, Peers) -> lists:foreach(fun({P,C}) -> Pid ! {peer, P, [Alias], C} end, Peers). -%%% --------------------------------------------------------------------------- -%%% # remote_peer_up/4 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # remote_peer_up/4 +%% --------------------------------------------------------------------------- remote_peer_up(Pid, Aliases, Caps, #state{options = [_, _, {_, true} | _], service = Svc, @@ -2598,9 +2660,9 @@ rpu(Pid, Caps, PDict, Aliases) -> T = {Pid, Caps}, lists:foreach(fun(A) -> ?Dict:append(A, T, PDict) end, Aliases). -%%% --------------------------------------------------------------------------- -%%% # remote_peer_down/2 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # remote_peer_down/2 +%% --------------------------------------------------------------------------- remote_peer_down(Pid, #state{options = [_, _, {_, true} | _], shared_peers = PDict}) -> @@ -2609,13 +2671,13 @@ remote_peer_down(Pid, #state{options = [_, _, {_, true} | _], rpd(Pid, Alias, PDict) -> ?Dict:update(Alias, fun(Ps) -> lists:keydelete(Pid, 1, Ps) end, PDict). -%%% --------------------------------------------------------------------------- -%%% find_transport/[34] -%%% -%%% Return: {TransportPid, #diameter_caps{}, #diameter_app{}} -%%% | false -%%% | {error, Reason} -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% find_transport/[34] +%% +%% Return: {TransportPid, #diameter_caps{}, #diameter_app{}} +%% | false +%% | {error, Reason} +%% --------------------------------------------------------------------------- %% Initial call, from an arbitrary process. find_transport({alias, Alias}, Msg, Opts, #state{service = Svc} = S) -> @@ -2726,13 +2788,7 @@ get_avp_value(_, Name, [_MsgName | Avps]) -> undefined end; -%% Record might be an answer message in the common dictionary. -get_avp_value(Dict, Name, Rec) - when Dict /= ?BASE, element(1, Rec) == 'diameter_base_answer-message' -> - get_avp_value(?BASE, Name, Rec); - -%% Message is typically a record but not necessarily: diameter:call/4 -%% can be passed an arbitrary term. +%% Message is typically a record but not necessarily. get_avp_value(Dict, Name, Rec) -> try Dict:'#get-'(Name, Rec) @@ -2747,19 +2803,19 @@ avp_decode(Dict, Name, #diameter_avp{value = undefined, avp_decode(_, _, #diameter_avp{value = V}) -> V. -%%% --------------------------------------------------------------------------- -%%% # pick_peer(App, [DestRealm, DestHost], Filter, #state{}) -%%% -%%% Return: {TransportPid, #diameter_caps{}, App} -%%% | false -%%% | {error, Reason} -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # pick_peer/4 +%% +%% Return: {TransportPid, #diameter_caps{}, App} +%% | false +%% | {error, Reason} +%% --------------------------------------------------------------------------- %% Find transports to a given realm/host. pick_peer(#diameter_app{alias = Alias} = App, - [_,_] = RH, + [_Realm ,_Host] = RH, Filter, #state{local_peers = L, shared_peers = S, @@ -2907,9 +2963,9 @@ transports(#state{watchdogT = WatchdogT}) -> [{'is_pid', '$1'}], ['$1']}]). -%%% --------------------------------------------------------------------------- -%%% # service_info/2 -%%% --------------------------------------------------------------------------- +%% --------------------------------------------------------------------------- +%% # service_info/2 +%% --------------------------------------------------------------------------- %% The config passed to diameter:start_service/2. -define(CAP_INFO, ['Origin-Host', |