diff options
Diffstat (limited to 'lib/diameter/test')
-rw-r--r-- | lib/diameter/test/diameter_3xxx_SUITE.erl | 200 | ||||
-rw-r--r-- | lib/diameter/test/diameter_app_SUITE.erl | 51 | ||||
-rw-r--r-- | lib/diameter/test/diameter_traffic_SUITE.erl | 113 |
3 files changed, 320 insertions, 44 deletions
diff --git a/lib/diameter/test/diameter_3xxx_SUITE.erl b/lib/diameter/test/diameter_3xxx_SUITE.erl index 071b1a1177..44fc3a60aa 100644 --- a/lib/diameter/test/diameter_3xxx_SUITE.erl +++ b/lib/diameter/test/diameter_3xxx_SUITE.erl @@ -47,6 +47,7 @@ send_double_error/1, send_3xxx/1, send_5xxx/1, + counters/1, stop/1]). %% diameter callbacks @@ -111,7 +112,7 @@ all() -> groups() -> Tc = tc(), - [{?util:name([E,D]), [], [start] ++ Tc ++ [stop]} + [{?util:name([E,D]), [], [start] ++ Tc ++ [counters, stop]} || E <- ?ERRORS, D <- ?RFCS]. init_per_suite(Config) -> @@ -169,6 +170,203 @@ stop(_Config) -> ok = diameter:stop_service(?SERVER), ok = diameter:stop_service(?CLIENT). +%% counters/1 +%% +%% Check that counters are as expected. + +counters(Config) -> + Group = proplists:get_value(group, Config), + [_Errors, _Rfc] = G = ?util:name(Group), + [] = ?util:run([[fun counters/3, K, S, G] + || K <- [statistics, transport, connections], + S <- [?CLIENT, ?SERVER]]). + +counters(Key, Svc, Group) -> + counters(Key, Svc, Group, [_|_] = diameter:service_info(Svc, Key)). + +counters(statistics, Svc, [Errors, Rfc], L) -> + [{P, Stats}] = L, + true = is_pid(P), + stats(Svc, Errors, Rfc, lists:sort(Stats)); + +counters(_, _, _, _) -> + todo. + +stats(?CLIENT, E, rfc3588, L) + when E == answer; + E == answer_3xxx -> + [{{unknown,recv},2}, + {{{0,257,0},recv},1}, + {{{0,257,1},send},1}, + {{{0,275,0},recv},6}, + {{{0,275,1},send},10}, + {{unknown,recv,{'Result-Code',3001}},1}, + {{unknown,recv,{'Result-Code',3007}},1}, + {{{0,257,0},recv,{'Result-Code',2001}},1}, + {{{0,275,0},recv,{'Result-Code',2001}},1}, + {{{0,275,0},recv,{'Result-Code',3008}},2}, + {{{0,275,0},recv,{'Result-Code',3999}},1}, + {{{0,275,0},recv,{'Result-Code',5002}},1}, + {{{0,275,0},recv,{'Result-Code',5005}},1}] + = L; + +stats(?SERVER, E, rfc3588, L) + when E == answer; + E == answer_3xxx -> + [{{unknown,recv},1}, + {{unknown,send},2}, + {{{0,257,0},send},1}, + {{{0,257,1},recv},1}, + {{{0,275,0},send},6}, + {{{0,275,1},recv},8}, + {{unknown,recv,error},1}, + {{unknown,send,{'Result-Code',3001}},1}, + {{unknown,send,{'Result-Code',3007}},1}, + {{{0,257,0},send,{'Result-Code',2001}},1}, + {{{0,275,0},send,{'Result-Code',2001}},1}, + {{{0,275,0},send,{'Result-Code',3008}},2}, + {{{0,275,0},send,{'Result-Code',3999}},1}, + {{{0,275,0},send,{'Result-Code',5002}},1}, + {{{0,275,0},send,{'Result-Code',5005}},1}, + {{{0,275,1},recv,error},5}] + = L; + +stats(?CLIENT, answer, rfc6733, L) -> + [{{unknown,recv},2}, + {{{0,257,0},recv},1}, + {{{0,257,1},send},1}, + {{{0,275,0},recv},8}, + {{{0,275,1},send},10}, + {{unknown,recv,{'Result-Code',3001}},1}, + {{unknown,recv,{'Result-Code',3007}},1}, + {{{0,257,0},recv,{'Result-Code',2001}},1}, + {{{0,275,0},recv,{'Result-Code',3008}},2}, + {{{0,275,0},recv,{'Result-Code',3999}},1}, + {{{0,275,0},recv,{'Result-Code',5002}},1}, + {{{0,275,0},recv,{'Result-Code',5005}},3}, + {{{0,275,0},recv,{'Result-Code',5999}},1}] + = L; + +stats(?SERVER, answer, rfc6733, L) -> + [{{unknown,recv},1}, + {{unknown,send},2}, + {{{0,257,0},send},1}, + {{{0,257,1},recv},1}, + {{{0,275,0},send},8}, + {{{0,275,1},recv},8}, + {{unknown,recv,error},1}, + {{unknown,send,{'Result-Code',3001}},1}, + {{unknown,send,{'Result-Code',3007}},1}, + {{{0,257,0},send,{'Result-Code',2001}},1}, + {{{0,275,0},send,{'Result-Code',3008}},2}, + {{{0,275,0},send,{'Result-Code',3999}},1}, + {{{0,275,0},send,{'Result-Code',5002}},1}, + {{{0,275,0},send,{'Result-Code',5005}},3}, + {{{0,275,0},send,{'Result-Code',5999}},1}, + {{{0,275,1},recv,error},5}] + = L; + +stats(?CLIENT, answer_3xxx, rfc6733, L) -> + [{{unknown,recv},2}, + {{{0,257,0},recv},1}, + {{{0,257,1},send},1}, + {{{0,275,0},recv},8}, + {{{0,275,1},send},10}, + {{unknown,recv,{'Result-Code',3001}},1}, + {{unknown,recv,{'Result-Code',3007}},1}, + {{{0,257,0},recv,{'Result-Code',2001}},1}, + {{{0,275,0},recv,{'Result-Code',2001}},1}, + {{{0,275,0},recv,{'Result-Code',3008}},2}, + {{{0,275,0},recv,{'Result-Code',3999}},1}, + {{{0,275,0},recv,{'Result-Code',5002}},1}, + {{{0,275,0},recv,{'Result-Code',5005}},2}, + {{{0,275,0},recv,{'Result-Code',5999}},1}] + = L; + +stats(?SERVER, answer_3xxx, rfc6733, L) -> + [{{unknown,recv},1}, + {{unknown,send},2}, + {{{0,257,0},send},1}, + {{{0,257,1},recv},1}, + {{{0,275,0},send},8}, + {{{0,275,1},recv},8}, + {{unknown,recv,error},1}, + {{unknown,send,{'Result-Code',3001}},1}, + {{unknown,send,{'Result-Code',3007}},1}, + {{{0,257,0},send,{'Result-Code',2001}},1}, + {{{0,275,0},send,{'Result-Code',2001}},1}, + {{{0,275,0},send,{'Result-Code',3008}},2}, + {{{0,275,0},send,{'Result-Code',3999}},1}, + {{{0,275,0},send,{'Result-Code',5002}},1}, + {{{0,275,0},send,{'Result-Code',5005}},2}, + {{{0,275,0},send,{'Result-Code',5999}},1}, + {{{0,275,1},recv,error},5}] + = L; + +stats(?CLIENT, callback, rfc3588, L) -> + [{{unknown,recv},1}, + {{{0,257,0},recv},1}, + {{{0,257,1},send},1}, + {{{0,275,0},recv},6}, + {{{0,275,1},send},10}, + {{unknown,recv,{'Result-Code',3007}},1}, + {{{0,257,0},recv,{'Result-Code',2001}},1}, + {{{0,275,0},recv,{'Result-Code',2001}},2}, + {{{0,275,0},recv,{'Result-Code',3999}},1}, + {{{0,275,0},recv,{'Result-Code',5002}},1}, + {{{0,275,0},recv,{'Result-Code',5005}},2}] + = L; + +stats(?SERVER, callback, rfc3588, L) -> + [{{unknown,recv},1}, + {{unknown,send},1}, + {{{0,257,0},send},1}, + {{{0,257,1},recv},1}, + {{{0,275,0},send},6}, + {{{0,275,1},recv},8}, + {{unknown,recv,error},1}, + {{unknown,send,{'Result-Code',3007}},1}, + {{{0,257,0},send,{'Result-Code',2001}},1}, + {{{0,275,0},send,{'Result-Code',2001}},2}, + {{{0,275,0},send,{'Result-Code',3999}},1}, + {{{0,275,0},send,{'Result-Code',5002}},1}, + {{{0,275,0},send,{'Result-Code',5005}},2}, + {{{0,275,1},recv,error},5}] + = L; + +stats(?CLIENT, callback, rfc6733, L) -> + [{{unknown,recv},1}, + {{{0,257,0},recv},1}, + {{{0,257,1},send},1}, + {{{0,275,0},recv},8}, + {{{0,275,1},send},10}, + {{unknown,recv,{'Result-Code',3007}},1}, + {{{0,257,0},recv,{'Result-Code',2001}},1}, + {{{0,275,0},recv,{'Result-Code',2001}},2}, + {{{0,275,0},recv,{'Result-Code',3999}},1}, + {{{0,275,0},recv,{'Result-Code',5002}},1}, + {{{0,275,0},recv,{'Result-Code',5005}},3}, + {{{0,275,0},recv,{'Result-Code',5999}},1}] + = L; + +stats(?SERVER, callback, rfc6733, L) -> + [{{unknown,recv},1}, + {{unknown,send},1}, + {{{0,257,0},send},1}, + {{{0,257,1},recv},1}, + {{{0,275,0},send},8}, + {{{0,275,1},recv},8}, + {{unknown,recv,error},1}, + {{unknown,send,{'Result-Code',3007}},1}, + {{{0,257,0},send,{'Result-Code',2001}},1}, + {{{0,275,0},send,{'Result-Code',2001}},2}, + {{{0,275,0},send,{'Result-Code',3999}},1}, + {{{0,275,0},send,{'Result-Code',5002}},1}, + {{{0,275,0},send,{'Result-Code',5005}},3}, + {{{0,275,0},send,{'Result-Code',5999}},1}, + {{{0,275,1},recv,error},5}] + = L. + %% send_unknown_application/1 %% %% Send an unknown application that a callback (which shouldn't take diff --git a/lib/diameter/test/diameter_app_SUITE.erl b/lib/diameter/test/diameter_app_SUITE.erl index 6975e83830..84f8a66a8a 100644 --- a/lib/diameter/test/diameter_app_SUITE.erl +++ b/lib/diameter/test/diameter_app_SUITE.erl @@ -249,11 +249,10 @@ release() -> end. unversion(App) -> - T = lists:dropwhile(fun is_vsn_ch/1, lists:reverse(App)), - lists:reverse(case T of [$-|TT] -> TT; _ -> T end). - -is_vsn_ch(C) -> - $0 =< C andalso C =< $9 orelse $. == C. + {Name, [$-|Vsn]} = lists:splitwith(fun(C) -> C /= $- end, App), + true = is_app(Name), %% assert + Vsn = vsn_str(Vsn), %% + Name. app('$M_EXPR') -> %% could be anything but assume it's ok "erts"; @@ -322,11 +321,11 @@ acc_rel(Dir, Rel, {Vsn, _}, Acc) -> %% Write a rel file and return its name. write_rel(Dir, [Erts | Apps], Vsn) -> - true = is_vsn(Vsn), - Name = "diameter_test_" ++ Vsn, + VS = vsn_str(Vsn), + Name = "diameter_test_" ++ VS, ok = write_file(filename:join([Dir, Name ++ ".rel"]), {release, - {"diameter " ++ Vsn ++ " test release", Vsn}, + {"diameter " ++ VS ++ " test release", VS}, Erts, Apps}), Name. @@ -341,10 +340,34 @@ fetch(Key, List) -> write_file(Path, T) -> file:write_file(Path, io_lib:format("~p.", [T])). -%% Is a version string of the expected form? Return the argument -%% itself for 'false' for a useful badmatch. +%% Is a version string of the expected form? is_vsn(V) -> - is_list(V) - andalso length(V) == string:span(V, "0123456789.") - andalso V == string:join(string:tokens(V, [$.]), ".") %% no ".." - orelse {error, V}. + V = vsn_str(V), + true. + +%% Turn a from/to version in appup to a version string after ensuring +%% that it's valid version number of regexp. In the regexp case, the +%% regexp itself becomes the version string since there's no +%% requirement that a version in appup be anything but a string. The +%% restrictions placed on string-valued version numbers (that they be +%% '.'-separated integers) are our own. + +vsn_str(S) + when is_list(S) -> + {_, match} = {S, match(S, "^(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))*$")}, + {_, nomatch} = {S, match(S, "\\.0\\.0$")}, + S; + +vsn_str(B) + when is_binary(B) -> + {ok, _} = re:compile(B), + binary_to_list(B). + +match(S, RE) -> + re:run(S, RE, [{capture, none}]). + +%% Is an application name of the expected form? +is_app(S) + when is_list(S) -> + {_, match} = {S, match(S, "^([a-z]([a-z_]*|[a-zA-Z]*))$")}, + true. diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl index 7dd9f39f85..7ff6ba7ab9 100644 --- a/lib/diameter/test/diameter_traffic_SUITE.erl +++ b/lib/diameter/test/diameter_traffic_SUITE.erl @@ -41,6 +41,7 @@ send_eval/1, send_bad_answer/1, send_protocol_error/1, + send_experimental_result/1, send_arbitrary/1, send_unknown/1, send_unknown_short/1, @@ -301,6 +302,7 @@ tc() -> send_eval, send_bad_answer, send_protocol_error, + send_experimental_result, send_arbitrary, send_unknown, send_unknown_short, @@ -443,7 +445,7 @@ send_ok(Config) -> Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD}, {'Accounting-Record-Number', 1}], - ['ACA', _SessionId, {'Result-Code', ?SUCCESS} | _] + ['ACA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _] = call(Config, Req). %% Send an accounting ACR that the server answers badly to. @@ -459,7 +461,7 @@ send_eval(Config) -> Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD}, {'Accounting-Record-Number', 3}], - ['ACA', _SessionId, {'Result-Code', ?SUCCESS} | _] + ['ACA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _] = call(Config, Req). %% Send an accounting ACR that the server tries to answer with an @@ -480,12 +482,20 @@ send_protocol_error(Config) -> ?answer_message(?TOO_BUSY) = call(Config, Req). +%% Send a 3xxx Experimental-Result in an answer not setting the E-bit +%% and missing a Result-Code. +send_experimental_result(Config) -> + Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD}, + {'Accounting-Record-Number', 5}], + ['ACA', {'Session-Id', _} | _] + = call(Config, Req). + %% Send an ASR with an arbitrary non-mandatory AVP and expect success %% and the same AVP in the reply. send_arbitrary(Config) -> Req = ['ASR', {'AVP', [#diameter_avp{name = 'Product-Name', value = "XXX"}]}], - ['ASA', _SessionId, {'Result-Code', ?SUCCESS} | Avps] + ['ASA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | Avps] = call(Config, Req), {'AVP', [#diameter_avp{name = 'Product-Name', value = V}]} @@ -497,7 +507,7 @@ send_unknown(Config) -> Req = ['ASR', {'AVP', [#diameter_avp{code = 999, is_mandatory = false, data = <<17>>}]}], - ['ASA', _SessionId, {'Result-Code', ?SUCCESS} | Avps] + ['ASA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | Avps] = call(Config, Req), {'AVP', [#diameter_avp{code = 999, is_mandatory = false, @@ -513,7 +523,7 @@ send_unknown_short(Config, M, RC) -> Req = ['ASR', {'AVP', [#diameter_avp{code = 999, is_mandatory = M, data = <<17>>}]}], - ['ASA', _SessionId, {'Result-Code', RC} | Avps] + ['ASA', {'Session-Id', _}, {'Result-Code', RC} | Avps] = call(Config, Req), [#'diameter_base_Failed-AVP'{'AVP' = As}] = proplists:get_value('Failed-AVP', Avps), @@ -527,7 +537,7 @@ send_unknown_mandatory(Config) -> Req = ['ASR', {'AVP', [#diameter_avp{code = 999, is_mandatory = true, data = <<17>>}]}], - ['ASA', _SessionId, {'Result-Code', ?AVP_UNSUPPORTED} | Avps] + ['ASA', {'Session-Id', _}, {'Result-Code', ?AVP_UNSUPPORTED} | Avps] = call(Config, Req), [#'diameter_base_Failed-AVP'{'AVP' = As}] = proplists:get_value('Failed-AVP', Avps), @@ -547,7 +557,7 @@ send_unexpected_mandatory_decode(Config) -> Req = ['ASR', {'AVP', [#diameter_avp{code = 27, %% Session-Timeout is_mandatory = true, data = <<12:32>>}]}], - ['ASA', _SessionId, {'Result-Code', ?AVP_UNSUPPORTED} | Avps] + ['ASA', {'Session-Id', _}, {'Result-Code', ?AVP_UNSUPPORTED} | Avps] = call(Config, Req), [#'diameter_base_Failed-AVP'{'AVP' = As}] = proplists:get_value('Failed-AVP', Avps), @@ -583,7 +593,7 @@ send_error_bit(Config) -> %% Send a bad version and check that we get 5011. send_unsupported_version(Config) -> Req = ['STR', {'Termination-Cause', ?LOGOUT}], - ['STA', _SessionId, {'Result-Code', ?UNSUPPORTED_VERSION} | _] + ['STA', {'Session-Id', _}, {'Result-Code', ?UNSUPPORTED_VERSION} | _] = call(Config, Req). %% Send a request containing an AVP length > data size. @@ -603,14 +613,14 @@ send_zero_avp_length(Config) -> send_invalid_avp_length(Config) -> Req = ['STR', {'Termination-Cause', ?LOGOUT}], - ['STA', _SessionId, + ['STA', {'Session-Id', _}, {'Result-Code', ?INVALID_AVP_LENGTH}, - _OriginHost, - _OriginRealm, - _UserName, - _Class, - _ErrorMessage, - _ErrorReportingHost, + {'Origin-Host', _}, + {'Origin-Realm', _}, + {'User-Name', _}, + {'Class', _}, + {'Error-Message', _}, + {'Error-Reporting-Host', _}, {'Failed-AVP', [#'diameter_base_Failed-AVP'{'AVP' = [_]}]} | _] = call(Config, Req). @@ -628,14 +638,14 @@ send_invalid_reject(Config) -> send_unexpected_mandatory(Config) -> Req = ['STR', {'Termination-Cause', ?LOGOUT}], - ['STA', _SessionId, {'Result-Code', ?AVP_UNSUPPORTED} | _] + ['STA', {'Session-Id', _}, {'Result-Code', ?AVP_UNSUPPORTED} | _] = call(Config, Req). %% Send something long that will be fragmented by TCP. send_long(Config) -> Req = ['STR', {'Termination-Cause', ?LOGOUT}, {'User-Name', [lists:duplicate(1 bsl 20, $X)]}], - ['STA', _SessionId, {'Result-Code', ?SUCCESS} | _] + ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _] = call(Config, Req). %% Send something longer than the configure incoming_maxlen. @@ -677,7 +687,7 @@ send_any_2(Config) -> send_all_1(Config) -> Req = ['STR', {'Termination-Cause', ?LOGOUT}], Realm = lists:foldr(fun(C,A) -> [C,A] end, [], ?REALM), - ['STA', _SessionId, {'Result-Code', ?SUCCESS} | _] + ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _] = call(Config, Req, [{filter, {all, [{host, any}, {realm, Realm}]}}]). send_all_2(Config) -> @@ -697,9 +707,8 @@ send_timeout(Config) -> %% received the Session-Id. send_error(Config) -> Req = ['RAR', {'Re-Auth-Request-Type', ?AUTHORIZE_AUTHENTICATE}], - ?answer_message(SId, ?TOO_BUSY) - = call(Config, Req), - true = undefined /= SId. + ?answer_message([_], ?TOO_BUSY) + = call(Config, Req). %% Send a request with the detached option and receive it as a message %% from handle_answer instead. @@ -708,7 +717,7 @@ send_detach(Config) -> Ref = make_ref(), ok = call(Config, Req, [{extra, [{self(), Ref}]}, detach]), Ans = receive {Ref, T} -> T end, - ['STA', _SessionId, {'Result-Code', ?SUCCESS} | _] + ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _] = Ans. %% Send a request which can't be encoded and expect {error, encode}. @@ -721,11 +730,11 @@ send_destination_1(Config) -> = group(Config), Req = ['STR', {'Termination-Cause', ?LOGOUT}, {'Destination-Host', [?HOST(SN, ?REALM)]}], - ['STA', _SessionId, {'Result-Code', ?SUCCESS} | _] + ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _] = call(Config, Req, [{filter, {all, [host, realm]}}]). send_destination_2(Config) -> Req = ['STR', {'Termination-Cause', ?LOGOUT}], - ['STA', _SessionId, {'Result-Code', ?SUCCESS} | _] + ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _] = call(Config, Req, [{filter, {all, [host, realm]}}]). %% Send with filtering on and expect failure when specifying an @@ -789,7 +798,7 @@ send_bad_filter(Config, F) -> %% Specify multiple filter options and expect them be conjunctive. send_multiple_filters_1(Config) -> Fun = fun(#diameter_caps{}) -> true end, - ['STA', _SessionId, {'Result-Code', ?SUCCESS} | _] + ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _] = send_multiple_filters(Config, [host, {eval, Fun}]). send_multiple_filters_2(Config) -> E = {erlang, is_tuple, []}, @@ -800,7 +809,7 @@ send_multiple_filters_3(Config) -> E2 = {erlang, is_tuple, []}, E3 = {erlang, is_record, [diameter_caps]}, E4 = [{erlang, is_record, []}, diameter_caps], - ['STA', _SessionId, {'Result-Code', ?SUCCESS} | _] + ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _] = send_multiple_filters(Config, [{eval, E} || E <- [E1,E2,E3,E4]]). send_multiple_filters(Config, Fs) -> @@ -811,7 +820,7 @@ send_multiple_filters(Config, Fs) -> %% only the return value from the prepare_request callback being %% significant. send_anything(Config) -> - ['STA', _SessionId, {'Result-Code', ?SUCCESS} | _] + ['STA', {'Session-Id', _}, {'Result-Code', ?SUCCESS} | _] = call(Config, anything). %% =========================================================================== @@ -1144,6 +1153,13 @@ answer(Pkt, Req, _Peer, Name, #group{client_dict0 = Dict0}) -> [R | Vs] = Dict:'#get-'(answer(Ans, Es, Name)), [Dict:rec2msg(R) | Vs]. +%% Missing Result-Codec and inapproriate Experimental-Result-Code. +answer(Rec, Es, send_experimental_result) -> + [{5004, #diameter_avp{name = 'Experimental-Result'}}, + {5005, #diameter_avp{name = 'Result-Code'}}] + = Es, + Rec; + %% An inappropriate E-bit results in a decode error ... answer(Rec, Es, send_bad_answer) -> [{5004, #diameter_avp{name = 'Result-Code'}} | _] = Es, @@ -1175,7 +1191,9 @@ handle_error(Reason, _Req, [$C|_], _Peer, _, _Time) -> %% Note that diameter will set Result-Code and Failed-AVPs if %% #diameter_packet.errors is non-null. -handle_request(#diameter_packet{header = H, msg = M}, _, {_Ref, Caps}) -> +handle_request(#diameter_packet{header = H, msg = M, avps = As}, + _, + {_Ref, Caps}) -> #diameter_header{end_to_end_id = EI, hop_by_hop_id = HI} = H, @@ -1183,10 +1201,12 @@ handle_request(#diameter_packet{header = H, msg = M}, _, {_Ref, Caps}) -> V = EI bsr B, %% assert V = HI bsr B, %% #diameter_caps{origin_state_id = {_,[Id]}} = Caps, - answer(origin(Id), request(M, Caps)). + answer(origin(Id), request(M, [H|As], Caps)). answer(T, {Tag, Action, Post}) -> {Tag, answer(T, Action), Post}; +answer(_, {reply, [#diameter_header{} | _]} = T) -> + T; answer({A,C}, {reply, Ans}) -> answer(C, {reply, msg(Ans, A, diameter_gen_base_rfc3588)}); answer(pkt, {reply, Ans}) @@ -1195,6 +1215,41 @@ answer(pkt, {reply, Ans}) answer(_, T) -> T. +%% request/3 + +%% send_experimental_result +request(#diameter_base_accounting_ACR{'Accounting-Record-Number' = 5}, + [Hdr | Avps], + #diameter_caps{origin_host = {OH, _}, + origin_realm = {OR, _}}) -> + [H,R|T] = [A || N <- ['Origin-Host', + 'Origin-Realm', + 'Session-Id', + 'Accounting-Record-Type', + 'Accounting-Record-Number'], + #diameter_avp{} = A + <- [lists:keyfind(N, #diameter_avp.name, Avps)]], + Ans = [Hdr#diameter_header{is_request = false}, + H#diameter_avp{data = OH}, + R#diameter_avp{data = OR}, + #diameter_avp{name = 'Experimental-Result', + code = 297, + need_encryption = false, + data = [#diameter_avp{data = {?DIAMETER_DICT_COMMON, + 'Vendor-Id', + 123}}, + #diameter_avp{data + = {?DIAMETER_DICT_COMMON, + 'Experimental-Result-Code', + 3987}}]} + | T], + {reply, Ans}; + +request(Msg, _Avps, Caps) -> + request(Msg, Caps). + +%% request/2 + %% send_nok request(#diameter_base_accounting_ACR{'Accounting-Record-Number' = 0}, _) -> |