aboutsummaryrefslogtreecommitdiffstats
path: root/lib/diameter/test/diameter_traffic_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/diameter/test/diameter_traffic_SUITE.erl')
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl372
1 files changed, 302 insertions, 70 deletions
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 669918f757..b03a9ce4d1 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2012. 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
@@ -38,6 +38,9 @@
result_codes/1,
send_ok/1,
send_nok/1,
+ send_eval/1,
+ send_bad_answer/1,
+ send_protocol_error/1,
send_arbitrary/1,
send_unknown/1,
send_unknown_mandatory/1,
@@ -46,6 +49,9 @@
send_unsupported_app/1,
send_error_bit/1,
send_unsupported_version/1,
+ send_invalid_avp_bits/1,
+ send_invalid_avp_length/1,
+ send_invalid_reject/1,
send_long/1,
send_nopeer/1,
send_noapp/1,
@@ -81,11 +87,11 @@
%% diameter callbacks
-export([peer_up/3,
peer_down/3,
- pick_peer/5, pick_peer/6,
- prepare_request/4, prepare_request/5,
- prepare_retransmit/4,
- handle_answer/5, handle_answer/6,
- handle_error/5,
+ pick_peer/6, pick_peer/7,
+ prepare_request/5, prepare_request/6,
+ prepare_retransmit/5,
+ handle_answer/6, handle_answer/7,
+ handle_error/6,
handle_request/3]).
-include("diameter.hrl").
@@ -108,14 +114,26 @@
-define(BASE, ?DIAMETER_DICT_COMMON).
-define(ACCT, ?DIAMETER_DICT_ACCOUNTING).
-%% Run tests cases in different encoding variants. Send outgoing
-%% messages as lists or records.
+%% Sequence mask for End-to-End and Hop-by-Hop identifiers.
+-define(CLIENT_MASK, {1,26}). %% 1 in top 6 bits
+
+%% How to construct messages, as record or list.
-define(ENCODINGS, [list, record]).
+%% How to send answers, in a diameter_packet or not.
+-define(CONTAINERS, [pkt, msg]).
+
+%% Send over multiple connections that are mapped onto
+%% [{E,P} || E <- ?ENCODINGS, P <- ?CONTAINERS].
+-define(CONNECTIONS, [c0,c1,c2,c3]).
+
%% Not really what we should be setting unless the message is sent in
%% the common application but diameter doesn't care.
-define(APP_ID, ?DIAMETER_APP_ID_COMMON).
+%% An Application-ID the server doesn't support.
+-define(BAD_APP, 42).
+
%% Config for diameter:start_service/2.
-define(SERVICE(Name),
[{'Origin-Host', Name ++ "." ++ ?REALM},
@@ -124,7 +142,8 @@
{'Vendor-Id', 12345},
{'Product-Name', "OTP/diameter"},
{'Auth-Application-Id', [?DIAMETER_APP_ID_COMMON]},
- {'Acct-Application-Id', [?DIAMETER_APP_ID_ACCOUNTING]}
+ {'Acct-Application-Id', [?DIAMETER_APP_ID_ACCOUNTING]},
+ {restrict_connections, false}
| [{application, [{dictionary, D},
{module, ?MODULE},
{answer_errors, callback}]}
@@ -150,6 +169,8 @@
?'DIAMETER_BASE_RESULT-CODE_DIAMETER_REALM_NOT_SERVED').
-define(UNABLE_TO_DELIVER,
?'DIAMETER_BASE_RESULT-CODE_DIAMETER_UNABLE_TO_DELIVER').
+-define(INVALID_AVP_LENGTH,
+ ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_INVALID_AVP_LENGTH').
-define(EVENT_RECORD,
?'DIAMETER_BASE_ACCOUNTING-RECORD-TYPE_EVENT_RECORD').
@@ -162,6 +183,8 @@
?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
-define(BAD_ANSWER,
?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_BAD_ANSWER').
+-define(USER_MOVED,
+ ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_USER_MOVED').
-define(A, list_to_atom).
-define(L, atom_to_list).
@@ -175,12 +198,17 @@ suite() ->
all() ->
[start, start_services, add_transports, result_codes]
- ++ [{group, name([E]), P} || E <- ?ENCODINGS, P <- [[], [parallel]]]
+ ++ [{group, ?util:name([R,C,A]), P} || R <- ?ENCODINGS,
+ C <- ?CONTAINERS,
+ A <- ?ENCODINGS,
+ P <- [[], [parallel]]]
++ [remove_transports, stop_services, stop].
groups() ->
Ts = tc(),
- [{name([E]), [], Ts} || E <- ?ENCODINGS].
+ [{?util:name([R,C,A]), [], Ts} || R <- ?ENCODINGS,
+ C <- ?CONTAINERS,
+ A <- ?ENCODINGS].
init_per_group(Name, Config) ->
[{group, Name} | Config].
@@ -199,6 +227,9 @@ end_per_testcase(_, _) ->
tc() ->
[send_ok,
send_nok,
+ send_eval,
+ send_bad_answer,
+ send_protocol_error,
send_arbitrary,
send_unknown,
send_unknown_mandatory,
@@ -207,6 +238,9 @@ tc() ->
send_unsupported_app,
send_error_bit,
send_unsupported_version,
+ send_invalid_avp_bits,
+ send_invalid_avp_length,
+ send_invalid_reject,
send_long,
send_nopeer,
send_noapp,
@@ -244,16 +278,19 @@ start(_Config) ->
start_services(_Config) ->
ok = diameter:start_service(?SERVER, ?SERVICE(?SERVER)),
- ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT)).
+ ok = diameter:start_service(?CLIENT, [{sequence, ?CLIENT_MASK}
+ | ?SERVICE(?CLIENT)]).
add_transports(Config) ->
LRef = ?util:listen(?SERVER, tcp, [{capabilities_cb, fun capx/2}]),
- CRef = ?util:connect(?CLIENT, tcp, LRef),
- ?util:write_priv(Config, "transport", {LRef, CRef}).
+ Cs = [?util:connect(?CLIENT, tcp, LRef, [{id, C},
+ {capabilities, [osi(C)]}])
+ || C <- ?CONNECTIONS],
+ ?util:write_priv(Config, "transport", [LRef | Cs]).
remove_transports(Config) ->
- {LRef, CRef} = ?util:read_priv(Config, "transport"),
- ?util:disconnect(?CLIENT, CRef, ?SERVER, LRef).
+ [LRef | Cs] = ?util:read_priv(Config, "transport"),
+ [?util:disconnect(?CLIENT, C, ?SERVER, LRef) || C <- Cs].
stop_services(_Config) ->
ok = diameter:stop_service(?CLIENT),
@@ -266,11 +303,15 @@ capx(_, #diameter_caps{origin_host = {OH,DH}}) ->
io:format("connection: ~p -> ~p~n", [DH,OH]),
ok.
+osi(Id) ->
+ [$c,N] = atom_to_list(Id),
+ {'Origin-State-Id', N - $0}.
+
%% ===========================================================================
%% Ensure that result codes have the expected values.
result_codes(_Config) ->
- {2001, 3001, 3002, 3003, 3004, 3007, 3008, 3009, 5001, 5011}
+ {2001, 3001, 3002, 3003, 3004, 3007, 3008, 3009, 5001, 5011, 5014}
= {?SUCCESS,
?COMMAND_UNSUPPORTED,
?UNABLE_TO_DELIVER,
@@ -280,13 +321,14 @@ result_codes(_Config) ->
?INVALID_HDR_BITS,
?INVALID_AVP_BITS,
?AVP_UNSUPPORTED,
- ?UNSUPPORTED_VERSION}.
+ ?UNSUPPORTED_VERSION,
+ ?INVALID_AVP_LENGTH}.
%% Send an ACR and expect success.
send_ok(Config) ->
Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
{'Accounting-Record-Number', 1}],
-
+
#diameter_base_accounting_ACA{'Result-Code' = ?SUCCESS}
= call(Config, Req).
@@ -294,10 +336,35 @@ send_ok(Config) ->
send_nok(Config) ->
Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
{'Accounting-Record-Number', 0}],
-
+
#'diameter_base_answer-message'{'Result-Code' = ?INVALID_AVP_BITS}
= call(Config, Req).
+%% Send an ACR and expect success.
+send_eval(Config) ->
+ Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
+ {'Accounting-Record-Number', 3}],
+
+ #diameter_base_accounting_ACA{'Result-Code' = ?SUCCESS}
+ = call(Config, Req).
+
+%% Send an accounting ACR that the server tries to answer with an
+%% inappropriate header, resulting in no answer being sent and the
+%% request timing out.
+send_bad_answer(Config) ->
+ Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
+ {'Accounting-Record-Number', 2}],
+ {error, timeout} = call(Config, Req).
+
+%% Send an ACR that the server callback answers explicitly with a
+%% protocol error.
+send_protocol_error(Config) ->
+ Req = ['ACR', {'Accounting-Record-Type', ?EVENT_RECORD},
+ {'Accounting-Record-Number', 4}],
+
+ #'diameter_base_answer-message'{'Result-Code' = ?TOO_BUSY}
+ = call(Config, Req).
+
%% Send an ASR with an arbitrary AVP and expect success and the same
%% AVP in the reply.
send_arbitrary(Config) ->
@@ -365,6 +432,29 @@ send_unsupported_version(Config) ->
#diameter_base_STA{'Result-Code' = ?UNSUPPORTED_VERSION}
= call(Config, Req).
+%% Send a request containing an incorrect AVP length.
+send_invalid_avp_bits(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+
+ #'diameter_base_answer-message'{'Result-Code' = ?INVALID_AVP_BITS}
+ = call(Config, Req).
+
+%% Send a request containing an AVP length that doesn't match the
+%% AVP's type.
+send_invalid_avp_length(Config) ->
+ Req = ['STR', {'Termination-Cause', ?LOGOUT}],
+
+ #'diameter_base_STA'{'Result-Code' = ?INVALID_AVP_LENGTH}
+ = call(Config, Req).
+
+%% Send a request containing 5xxx errors that the server rejects with
+%% 3xxx.
+send_invalid_reject(Config) ->
+ Req = ['STR', {'Termination-Cause', ?USER_MOVED}],
+
+ #'diameter_base_answer-message'{'Result-Code' = ?TOO_BUSY}
+ = call(Config, Req).
+
%% Send something long that will be fragmented by TCP.
send_long(Config) ->
Req = ['STR', {'Termination-Cause', ?LOGOUT},
@@ -539,21 +629,44 @@ call(Config, Req) ->
call(Config, Req, Opts) ->
Name = proplists:get_value(testcase, Config),
- [Enc] = name(proplists:get_value(group, Config)),
+ [Encoding, C, E] = ?util:name(proplists:get_value(group, Config)),
diameter:call(?CLIENT,
dict(Req),
- req(Req, Enc),
- [{extra, [Name]} | Opts]).
+ msg(Req, Encoding),
+ [{extra, [Name, client(E,C)]} | Opts]).
+
+client(E, C) ->
+ list_to_atom([$c, $0 + 2*codec(E) + container(C)]).
+
+client(N) ->
+ {codec(N bsr 1), container(N rem 2)}.
-req(['ACR' = H | T], record) ->
+codec(record) -> 0;
+codec(list) -> 1;
+codec(0) -> record;
+codec(1) -> list.
+
+%% Here we're just mapping booleans but the readable atoms are part of
+%% (constructed) group names, so it's good that they're readable.
+
+container(pkt) -> 0;
+container(msg) -> 1;
+container(0) -> pkt;
+container(1) -> msg.
+
+msg([H|T], record)
+ when H == 'ACR';
+ H == 'ACA' ->
?ACCT:'#new-'(?ACCT:msg2rec(H), T);
-req([H|T], record) ->
+msg([H|T], record) ->
?BASE:'#new-'(?BASE:msg2rec(H), T);
-req(T, _) ->
+msg(T, _) ->
T.
dict(['ACR' | _]) ->
?ACCT;
+dict(#diameter_base_accounting_ACR{}) ->
+ ?ACCT;
dict(_) ->
?BASE.
@@ -579,17 +692,6 @@ set(Dict, E, FV, Rec)
set(_, _, _, Rec) ->
Rec.
-%% Contruct and deconstruct names to work around group names being
-%% restricted to atoms. (Not really used yet.)
-
-name(Names)
- when is_list(Names) ->
- ?A(string:join([?L(A) || A <- Names], ","));
-
-name(A)
- when is_atom(A) ->
- [?A(S) || S <- string:tokens(?L(A), ",")].
-
%% ===========================================================================
%% diameter callbacks
@@ -603,28 +705,74 @@ peer_up(_SvcName, _Peer, State) ->
peer_down(_SvcName, _Peer, State) ->
State.
-%% pick_peer/5/6
+%% pick_peer/6-7
-pick_peer([Peer], _, ?CLIENT, _State, Name)
+pick_peer(Peers, _, ?CLIENT, _State, Name, Id)
when Name /= send_detach ->
- {ok, Peer}.
+ find(Id, Peers).
-pick_peer([_Peer], _, ?CLIENT, _State, send_nopeer, ?EXTRA) ->
+pick_peer(_Peers, _, ?CLIENT, _State, send_nopeer, _, ?EXTRA) ->
false;
-pick_peer([Peer], _, ?CLIENT, _State, send_detach, {_,_}) ->
- {ok, Peer}.
+pick_peer(Peers, _, ?CLIENT, _State, send_detach, Id, {_,_}) ->
+ find(Id, Peers).
+
+find(Id, Peers) ->
+ [P] = [P || P <- Peers, id(Id, P)],
+ {ok, P}.
+
+id(Id, {Pid, _Caps}) ->
+ [{ref, _}, {type, _}, {options, Opts} | _]
+ = diameter:service_info(?CLIENT, Pid),
+ lists:member({id, Id}, Opts).
-%% prepare_request/4/5
+%% prepare_request/5-6
-prepare_request(_Pkt, ?CLIENT, {_Ref, _Caps}, send_discard) ->
+prepare_request(_Pkt, ?CLIENT, {_Ref, _Caps}, send_discard, _) ->
{discard, unprepared};
-prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, Name) ->
+prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, Name, _) ->
{send, prepare(Pkt, Caps, Name)}.
-prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, send_detach, _) ->
- {send, prepare(Pkt, Caps)}.
+prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, send_detach, _, _) ->
+ {eval_packet, {send, prepare(Pkt, Caps)}, [fun log/2, detach]}.
+
+log(#diameter_packet{} = P, T) ->
+ io:format("~p: ~p~n", [T,P]).
+
+%% prepare/3
+
+prepare(Pkt, Caps, send_invalid_avp_bits) ->
+ Req = prepare(Pkt, Caps),
+ %% Last AVP in our STR is Termination-Cause of type Unsigned32:
+ %% set its length improperly.
+ #diameter_packet{header = #diameter_header{length = L},
+ bin = B}
+ = E
+ = diameter_codec:encode(?BASE, Pkt#diameter_packet{msg = Req}),
+ Offset = L - 7, %% to AVP Length
+ <<H:Offset/binary, 12:24/integer, T:4/binary>> = B,
+ E#diameter_packet{bin = <<H/binary, 13:24/integer, T/binary>>};
+
+prepare(Pkt, Caps, N)
+ when N == send_invalid_avp_length;
+ N == send_invalid_reject ->
+ Req = prepare(Pkt, Caps),
+ %% Second last AVP in our STR is Auth-Application-Id of type
+ %% Unsigned32: Send a value of length 8.
+ #diameter_packet{header = #diameter_header{length = L},
+ bin = B0}
+ = E
+ = diameter_codec:encode(?BASE, Pkt#diameter_packet{msg = Req}),
+ Offset = L - 7 - 12, %% to AVP Length
+ <<H0:Offset/binary, 12:24/integer, T:16/binary>> = B0,
+ <<V, L:24/integer, H/binary>> = H0, %% assert
+ E#diameter_packet{bin = <<V,
+ (L+4):24/integer,
+ H/binary,
+ 16:24/integer,
+ 0:32/integer,
+ T/binary>>};
prepare(Pkt, Caps, send_unsupported) ->
Req = prepare(Pkt, Caps),
@@ -638,7 +786,7 @@ prepare(Pkt, Caps, send_unsupported_app) ->
#diameter_packet{bin = <<H:8/binary, _ApplId:4/binary, T/binary>>}
= E
= diameter_codec:encode(?BASE, Pkt#diameter_packet{msg = Req}),
- E#diameter_packet{bin = <<H/binary, 42:32/integer, T/binary>>};
+ E#diameter_packet{bin = <<H/binary, ?BAD_APP:32/integer, T/binary>>};
prepare(Pkt, Caps, send_error_bit) ->
#diameter_packet{header = Hdr} = Pkt,
@@ -657,6 +805,8 @@ prepare(Pkt, Caps, send_anything) ->
prepare(Pkt, Caps, _Name) ->
prepare(Pkt, Caps).
+%% prepare/2
+
prepare(#diameter_packet{msg = Req}, Caps)
when is_record(Req, diameter_base_accounting_ACR);
'ACR' == hd(Req) ->
@@ -707,25 +857,42 @@ prepare(#diameter_packet{msg = Req}, Caps)
{'Destination-Realm', DR},
{'Auth-Application-Id', ?APP_ID}]).
-%% prepare_retransmit/4
+%% prepare_retransmit/5
-prepare_retransmit(_Pkt, false, _Peer, _Name) ->
+prepare_retransmit(_Pkt, false, _Peer, _Name, _Id) ->
discard.
-%% handle_answer/5/6
+%% handle_answer/6-7
-handle_answer(Pkt, Req, ?CLIENT, Peer, Name) ->
+handle_answer(Pkt, Req, ?CLIENT, Peer, Name, _Id) ->
answer(Pkt, Req, Peer, Name).
-handle_answer(Pkt, _Req, ?CLIENT, _Peer, send_detach, {Pid, Ref}) ->
+handle_answer(Pkt, _Req, ?CLIENT, _Peer, send_detach, _Id, {Pid, Ref}) ->
Pid ! {Ref, Pkt}.
-answer(#diameter_packet{msg = Rec, errors = []}, _Req, _Peer, _) ->
+answer(Pkt, Req, _Peer, Name) ->
+ #diameter_packet{header = H, msg = Rec, errors = Es} = Pkt,
+ ApplId = app(Req, Name),
+ #diameter_header{application_id = ApplId} = H, %% assert
+ answer(Rec, Es, Name).
+
+answer(Rec, [_|_], N)
+ when N == send_invalid_avp_bits;
+ N == send_invalid_avp_length;
+ N == send_invalid_reject ->
+ Rec;
+answer(Rec, [], _) ->
Rec.
-%% handle_error/5
+app(_, send_unsupported_app) ->
+ ?BAD_APP;
+app(Req, _) ->
+ Dict = dict(Req),
+ Dict:id().
+
+%% handle_error/6
-handle_error(Reason, _Req, ?CLIENT, _Peer, _Name) ->
+handle_error(Reason, _Req, ?CLIENT, _Peer, _Name, _Id) ->
{error, Reason}.
%% handle_request/3
@@ -733,16 +900,64 @@ handle_error(Reason, _Req, ?CLIENT, _Peer, _Name) ->
%% Note that diameter will set Result-Code and Failed-AVPs if
%% #diameter_packet.errors is non-null.
-handle_request(#diameter_packet{msg = M}, ?SERVER, {_Ref, Caps}) ->
- request(M, Caps).
+handle_request(#diameter_packet{header = H, msg = M}, ?SERVER, {_Ref, Caps}) ->
+ #diameter_header{end_to_end_id = EI,
+ hop_by_hop_id = HI}
+ = H,
+ {V,B} = ?CLIENT_MASK,
+ V = EI bsr B, %% assert
+ V = HI bsr B, %%
+ #diameter_caps{origin_state_id = {_,[N]}} = Caps,
+ answer(client(N), request(M, Caps)).
+
+answer(T, {Tag, Action, Post}) ->
+ {Tag, answer(T, Action), Post};
+answer({E,C}, {reply, Ans}) ->
+ answer(C, {reply, msg(Ans, E)});
+answer(pkt, {reply, Ans}) ->
+ {reply, #diameter_packet{msg = Ans}};
+answer(_, T) ->
+ T.
+%% send_nok
request(#diameter_base_accounting_ACR{'Accounting-Record-Number' = 0},
_) ->
- {protocol_error, ?INVALID_AVP_BITS};
+ {eval_packet, {protocol_error, ?INVALID_AVP_BITS}, [fun log/2, invalid]};
+%% send_bad_answer
request(#diameter_base_accounting_ACR{'Session-Id' = SId,
'Accounting-Record-Type' = RT,
- 'Accounting-Record-Number' = RN},
+ 'Accounting-Record-Number' = 2 = RN},
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}) ->
+ Ans = ['ACA', {'Result-Code', ?SUCCESS},
+ {'Session-Id', SId},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Accounting-Record-Type', RT},
+ {'Accounting-Record-Number', RN}],
+
+ {reply, #diameter_packet{header = #diameter_header{is_error = true},%% NOT
+ msg = Ans}};
+
+%% send_eval
+request(#diameter_base_accounting_ACR{'Session-Id' = SId,
+ 'Accounting-Record-Type' = RT,
+ 'Accounting-Record-Number' = 3 = RN},
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}) ->
+ Ans = ['ACA', {'Result-Code', ?SUCCESS},
+ {'Session-Id', SId},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'Accounting-Record-Type', RT},
+ {'Accounting-Record-Number', RN}],
+ {eval, {reply, Ans}, {erlang, now, []}};
+
+%% send_ok
+request(#diameter_base_accounting_ACR{'Session-Id' = SId,
+ 'Accounting-Record-Type' = RT,
+ 'Accounting-Record-Number' = 1 = RN},
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
{reply, ['ACA', {'Result-Code', ?SUCCESS},
@@ -752,26 +967,42 @@ request(#diameter_base_accounting_ACR{'Session-Id' = SId,
{'Accounting-Record-Type', RT},
{'Accounting-Record-Number', RN}]};
+%% send_protocol_error
+request(#diameter_base_accounting_ACR{'Accounting-Record-Number' = 4},
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, _}}) ->
+ Ans = ['answer-message', {'Result-Code', ?TOO_BUSY},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR}],
+ {reply, Ans};
+
request(#diameter_base_ASR{'Session-Id' = SId,
'AVP' = Avps},
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
- {reply, #diameter_base_ASA{'Result-Code' = ?SUCCESS,
- 'Session-Id' = SId,
- 'Origin-Host' = OH,
- 'Origin-Realm' = OR,
- 'AVP' = Avps}};
+ {reply, ['ASA', {'Result-Code', ?SUCCESS},
+ {'Session-Id', SId},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR},
+ {'AVP', Avps}]};
+
+%% send_invalid_reject
+request(#diameter_base_STR{'Termination-Cause' = ?USER_MOVED}, _Caps) ->
+ {protocol_error, ?TOO_BUSY};
+%% send_noreply
request(#diameter_base_STR{'Termination-Cause' = T},
_Caps)
when T /= ?LOGOUT ->
discard;
+%% send_destination_5
request(#diameter_base_STR{'Destination-Realm'= R},
#diameter_caps{origin_realm = {OR, _}})
when R /= undefined, R /= OR ->
{protocol_error, ?REALM_NOT_SERVED};
+%% send_destination_6
request(#diameter_base_STR{'Destination-Host'= [H]},
#diameter_caps{origin_host = {OH, _}})
when H /= OH ->
@@ -780,11 +1011,12 @@ request(#diameter_base_STR{'Destination-Host'= [H]},
request(#diameter_base_STR{'Session-Id' = SId},
#diameter_caps{origin_host = {OH, _},
origin_realm = {OR, _}}) ->
- {reply, #diameter_base_STA{'Result-Code' = ?SUCCESS,
- 'Session-Id' = SId,
- 'Origin-Host' = OH,
- 'Origin-Realm' = OR}};
+ {reply, ['STA', {'Result-Code', ?SUCCESS},
+ {'Session-Id', SId},
+ {'Origin-Host', OH},
+ {'Origin-Realm', OR}]};
+%% send_error
request(#diameter_base_RAR{}, _Caps) ->
receive after 2000 -> ok end,
{protocol_error, ?TOO_BUSY}.