diff options
Diffstat (limited to 'lib/diameter/src')
-rw-r--r-- | lib/diameter/src/base/diameter_peer_fsm.erl | 65 | ||||
-rw-r--r-- | lib/diameter/src/base/diameter_types.erl | 68 | ||||
-rw-r--r-- | lib/diameter/src/base/diameter_watchdog.erl | 19 |
3 files changed, 51 insertions, 101 deletions
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl index a6e902d752..282276827f 100644 --- a/lib/diameter/src/base/diameter_peer_fsm.erl +++ b/lib/diameter/src/base/diameter_peer_fsm.erl @@ -28,7 +28,8 @@ -behaviour(gen_server). %% Interface towards diameter_watchdog. --export([start/3]). +-export([start/3, + result_code/2]). %% gen_server callbacks -export([init/1, @@ -62,7 +63,6 @@ %% Keys in process dictionary. -define(CB_KEY, cb). %% capabilities callback -define(DPR_KEY, dpr). %% disconnect callback --define(DWA_KEY, dwa). %% outgoing DWA -define(REF_KEY, ref). %% transport_ref() -define(Q_KEY, q). %% transport start queue -define(START_KEY, start). %% start of connected transport @@ -177,14 +177,9 @@ init(T) -> proc_lib:init_ack({ok, self()}), gen_server:enter_loop(?MODULE, [], i(T)). -i({Ack, WPid, {M, Ref} = T, Opts, {Mask, - Nodes, - Dict0, - #diameter_service{capabilities = LCaps} - = Svc}}) -> +i({Ack, WPid, {M, Ref} = T, Opts, {Mask, Nodes, Dict0, Svc}}) -> erlang:monitor(process, WPid), wait(Ack, WPid), - putr(?DWA_KEY, dwa(LCaps)), diameter_stats:reg(Ref), {[Cs,Ds], Rest} = proplists:split(Opts, [capabilities_cb, disconnect_cb]), putr(?CB_KEY, {Ref, [F || {_,F} <- Cs]}), @@ -612,9 +607,7 @@ rcv(Name, _, #state{state = PS}) Name == 'CEA' -> {stop, {Name, PS}}; -rcv(N, Pkt, S) - when N == 'DWR'; - N == 'DPR' -> +rcv('DPR' = N, Pkt, S) -> handle_request(N, Pkt, S); %% DPA in response to DPR and with the expected identifiers. @@ -717,8 +710,8 @@ build_answer(Type, errors = Es} = Pkt, S) -> - RC = rc(H, Es), - {answer(Type, RC, Es, S), post(Type, RC, Pkt, S)}. + {RC, FailedAVP} = result_code(H, Es), + {answer(Type, RC, FailedAVP, S), post(Type, RC, Pkt, S)}. inband_security([]) -> ?NO_INBAND_SECURITY; @@ -734,7 +727,7 @@ cea(CEA, RC, Dict0) -> post('CER' = T, RC, Pkt, S) -> {T, caps(S), {RC, Pkt}}; -post(_, _, _, _) -> +post('DPR', _, _, _) -> ok. rejected({capabilities_cb, _F, Reason}, T, S) -> @@ -743,13 +736,10 @@ rejected({capabilities_cb, _F, Reason}, T, S) -> rejected(discard, T, _) -> close(T); rejected({N, Es}, T, S) -> - {answer('CER', N, Es, S), T}; + {answer('CER', N, failed_avp(N, Es), S), T}; rejected(N, T, S) -> rejected({N, []}, T, S). -answer(Type, RC, Es, S) -> - set(answer(Type, RC, S), failed_avp(RC, Es)). - failed_avp(RC, [{RC, Avp} | _]) -> [{'Failed-AVP', [[{'AVP', [Avp]}]]}]; failed_avp(RC, [_ | Es]) -> @@ -757,6 +747,9 @@ failed_avp(RC, [_ | Es]) -> failed_avp(_, [] = No) -> No. +answer(Type, RC, FailedAVP, S) -> + set(answer(Type, RC, S), FailedAVP). + answer(Type, RC, S) -> answer_message(answer(Type, S), RC). @@ -784,29 +777,29 @@ set(['answer-message' | _] = Ans, FailedAvp) -> set([_|_] = Ans, FailedAvp) -> Ans ++ FailedAvp. -%% rc/2 +%% result_code/2 -rc(#diameter_header{is_error = true}, _) -> - 3008; %% DIAMETER_INVALID_HDR_BITS +result_code(#diameter_header{is_error = true}, _) -> + {3008, []}; %% DIAMETER_INVALID_HDR_BITS -rc(_, [Bs|_]) +result_code(_, [Bs|_]) when is_bitstring(Bs) -> %% from old code - 3009; %% DIAMETER_INVALID_HDR_BITS + {3009, []}; %% DIAMETER_INVALID_HDR_BITS -rc(#diameter_header{version = ?DIAMETER_VERSION}, Es) -> +result_code(#diameter_header{version = ?DIAMETER_VERSION}, Es) -> rc(Es); -rc(_, _) -> - 5011. %% DIAMETER_UNSUPPORTED_VERSION +result_code(_, _) -> + {5011, []}. %% DIAMETER_UNSUPPORTED_VERSION %% rc/1 rc([]) -> - 2001; %% DIAMETER_SUCCESS -rc([{RC,_}|_]) -> - RC; + {2001, []}; %% DIAMETER_SUCCESS +rc([{RC, _} | _] = Es) -> + {RC, failed_avp(RC, Es)}; rc([RC|_]) -> - RC. + {RC, []}. %% DIAMETER_INVALID_HDR_BITS 3008 %% A request was received whose bits in the Diameter header were @@ -832,9 +825,6 @@ rc([RC|_]) -> %% answer/2 -answer('DWR', _) -> - getr(?DWA_KEY); - answer(Name, #state{service = #diameter_service{capabilities = Caps}}) -> a(Name, Caps). @@ -1019,15 +1009,6 @@ report({M, _, _, _, _} = T) report(_) -> ok. -%% dwa/1 - -dwa(#diameter_caps{origin_host = OH, - origin_realm = OR, - origin_state_id = OSI}) -> - ['DWA', {'Origin-Host', OH}, - {'Origin-Realm', OR}, - {'Origin-State-Id', OSI}]. - %% dpr/2 %% %% The RFC isn't clear on whether DPR should be send in a non-Open diff --git a/lib/diameter/src/base/diameter_types.erl b/lib/diameter/src/base/diameter_types.erl index 9ae289034c..8c07e84777 100644 --- a/lib/diameter/src/base/diameter_types.erl +++ b/lib/diameter/src/base/diameter_types.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -250,13 +250,10 @@ 'Address'(encode, zero) -> <<0:48>>; -'Address'(decode, <<1:16, B/binary>>) - when size(B) == 4 -> - list_to_tuple(binary_to_list(B)); - -'Address'(decode, <<2:16, B/binary>>) - when size(B) == 16 -> - list_to_tuple(v6dec(B, [])); +'Address'(decode, <<A:16, B/binary>>) + when 1 == A, 4 == size(B); + 2 == A, 16 == size(B) -> + list_to_tuple([N || <<N:A/unit:8>> <= B]); 'Address'(decode, <<A:16, _/binary>> = B) when 1 == A; @@ -264,30 +261,10 @@ ?INVALID_LENGTH(B); 'Address'(encode, T) -> - ipenc(diameter_lib:ipaddr(T)). - -ipenc(T) - when is_tuple(T), size(T) == 4 -> - B = list_to_binary(tuple_to_list(T)), - <<1:16, B/binary>>; - -ipenc(T) - when is_tuple(T), size(T) == 8 -> - B = v6enc(lists:reverse(tuple_to_list(T)), <<>>), - <<2:16, B/binary>>. - -v6dec(<<N:16, B/binary>>, Acc) -> - v6dec(B, [N | Acc]); - -v6dec(<<>>, Acc) -> - lists:reverse(Acc). - -v6enc([N | Rest], B) - when ?UINT(16,N) -> - v6enc(Rest, <<N:16, B/binary>>); - -v6enc([], B) -> - B. + Ns = tuple_to_list(diameter_lib:ipaddr(T)), %% length 4 or 8 + A = length(Ns) div 4, %% 1 or 2 + B = << <<N:A/unit:8>> || N <- Ns >>, + <<A:16, B/binary>>. %% -------------------- @@ -354,36 +331,13 @@ v6enc([], B) -> %% -------------------- 'UTF8String'(decode, Bin) -> - udec(Bin, []); + tl([0|_] = unicode:characters_to_list([0, Bin])); %% assert list return 'UTF8String'(encode = M, zero) -> 'UTF8String'(M, []); 'UTF8String'(encode, S) -> - uenc(S, []). - -udec(<<>>, Acc) -> - lists:reverse(Acc); - -udec(<<C/utf8, Rest/binary>>, Acc) -> - udec(Rest, [C | Acc]). - -uenc(E, Acc) - when E == []; - E == <<>> -> - list_to_binary(lists:reverse(Acc)); - -uenc(<<C/utf8, Rest/binary>>, Acc) -> - uenc(Rest, [<<C/utf8>> | Acc]); - -uenc([[] | Rest], Acc) -> - uenc(Rest, Acc); - -uenc([[H|T] | Rest], Acc) -> - uenc([H, T | Rest], Acc); - -uenc([C | Rest], Acc) -> - uenc(Rest, [<<C/utf8>> | Acc]). + <<_/binary>> = unicode:characters_to_binary(S). %% assert binary return %% -------------------- diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl index 88ccf630e2..7e75801718 100644 --- a/lib/diameter/src/base/diameter_watchdog.erl +++ b/lib/diameter/src/base/diameter_watchdog.erl @@ -201,7 +201,7 @@ common_dictionary(Apps) -> %% means a user won't be able either send of receive %% messages in the common dictionary: incoming request %% will be answered with 3007 and outgoing requests cannot - %% be sent. The dictionary returned here is oly used for + %% be sent. The dictionary returned here is only used for %% messages diameter sends and receives: CER/CEA, DPR/DPA %% and DWR/DWA. ?BASE @@ -545,10 +545,15 @@ recv(Name, Pkt, S) -> %% rcv/3 +rcv('DWR', Pkt, #watchdog{transport = TPid, + dictionary = Dict0, + sequence = Mask}) -> + send(TPid, {send, encode(dwa(Pkt), Mask, Dict0)}), + ?LOG(send, 'DWA'); + rcv(N, _, _) when N == 'CER'; N == 'CEA'; - N == 'DWR'; N == 'DWA'; N == 'DPR'; N == 'DPA' -> @@ -642,6 +647,9 @@ rcv('DWA', #watchdog{status = reopen, %% REOPEN Receive non-DWA Throwaway() REOPEN +rcv('DWR', #watchdog{status = reopen} = S) -> + S; %% ensure DWA: the RFC isn't explicit about answering + rcv(_, #watchdog{status = reopen} = S) -> throwaway(S). @@ -782,6 +790,13 @@ dwr(#diameter_caps{origin_host = OH, {'Origin-Realm', OR}, {'Origin-State-Id', OSI}]. +%% dwa/1 + +dwa(#diameter_packet{header = H, errors = Es}) -> + {RC, FailedAVP} = diameter_peer_fsm:result_code(H, Es), + ['DWA', {'Result-Code', RC} + | tl(getr(dwr)) ++ FailedAVP]. + %% restrict_nodes/1 restrict_nodes(false) -> |