aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnders Svensson <[email protected]>2013-02-18 12:55:56 +0100
committerAnders Svensson <[email protected]>2013-02-18 12:55:56 +0100
commitfbe790cebb7ac6c713e0a4c440e11174ce49c51f (patch)
tree397b52c2ae7b07ba740b75bb50b263c0b14e8b77
parent1eb56b8359fdc2f695f7439d5343330f3d5a5692 (diff)
parentdf2189c22f7ca7660496e46322d8b825e9f28ba3 (diff)
downloadotp-fbe790cebb7ac6c713e0a4c440e11174ce49c51f.tar.gz
otp-fbe790cebb7ac6c713e0a4c440e11174ce49c51f.tar.bz2
otp-fbe790cebb7ac6c713e0a4c440e11174ce49c51f.zip
Merge branch 'anders/diameter/3xxx_callback/OTP-10686'
* anders/diameter/3xxx_callback/OTP-10686: Add 3xxx suite for testing application_opt() request_errors Minor suite simplification Add application_opt() request_errors
-rw-r--r--lib/diameter/doc/src/diameter.xml28
-rw-r--r--lib/diameter/include/diameter.hrl4
-rw-r--r--lib/diameter/src/base/diameter.erl3
-rw-r--r--lib/diameter/src/base/diameter_config.erl11
-rw-r--r--lib/diameter/src/base/diameter_traffic.erl205
-rw-r--r--lib/diameter/test/diameter_3xxx_SUITE.erl214
-rw-r--r--lib/diameter/test/diameter_failover_SUITE.erl6
-rw-r--r--lib/diameter/test/diameter_length_SUITE.erl43
-rw-r--r--lib/diameter/test/diameter_relay_SUITE.erl2
-rw-r--r--lib/diameter/test/diameter_tls_SUITE.erl2
-rw-r--r--lib/diameter/test/diameter_traffic_SUITE.erl28
-rw-r--r--lib/diameter/test/modules.mk3
12 files changed, 399 insertions, 150 deletions
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index ba9225da8b..accf21cf98 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -16,7 +16,7 @@
<header>
<copyright>
-<year>2011</year><year>2012</year>
+<year>2011</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -206,11 +206,13 @@ probably avoid it.</p>
<item>
<p>
Determines the manner in which incoming answer messages containing
-decode errors are handled.
+decode errors are handled.</p>
+
+<p>
If <c>callback</c> then errors result in a &app_handle_answer;
callback in the same fashion as for &app_handle_request;, with
errors communicated in the <c>errors</c> field of the
-<c>#diameter_packet{}</c> record passed to the callback.
+<c>#diameter_packet{}</c> passed to the callback.
If <c>report</c> then an answer containing errors is discarded
without a callback and a warning report is written to the log.
If <c>discard</c> then an answer containing errors is silently
@@ -224,6 +226,24 @@ question is as if a callback had taken place and returned
Defaults to <c>report</c> if unspecified.</p>
</item>
+<tag><c>{request_errors, answer_3xxx|callback}</c></tag>
+<item>
+<p>
+Determines the manner in which incoming requests are handled when an
+error other than 3007, DIAMETER_APPLICATION_UNSUPPORTED. (With which no
+application callback module can be associated.)</p>
+
+<p>
+If <c>answer_3xxx</c> then the request is answered by diameter
+without a &app_handle_request; callback taking place if a 3xxx series
+error (protocol errors) is detected.
+If <c>callback</c> then even 3xxx errors result in an application
+&app_handle_request; callback.</p>
+
+<p>
+Defaults to <c>answer_3xxx</c> if unspecified.</p>
+</item>
+
</taglist>
<marker id="call_opt"/>
@@ -534,7 +554,7 @@ Pkt = #diameter_packet{}
The RFC 3539 watchdog state machine has
transitioned into (<c>up</c>) or out of (<c>down</c>) the OKAY
state.
-If a <c>#diameter_packet{}</c> record is present in an <c>up</c> event
+If a <c>#diameter_packet{}</c> is present in an <c>up</c> event
then there has been a capabilties exchange on a newly established
transport connection and the record contains the received CER or CEA.
Otherwise a connection has reestablished without the loss or
diff --git a/lib/diameter/include/diameter.hrl b/lib/diameter/include/diameter.hrl
index 5ee898c3dd..513665cec1 100644
--- a/lib/diameter/include/diameter.hrl
+++ b/lib/diameter/include/diameter.hrl
@@ -143,6 +143,6 @@
init_state, %% option 'state', initial callback state
id, %% 32-bit unsigned application identifier = Dict:id()
mutable = false, %% boolean(), do traffic callbacks modify state?
- options = [{answer_errors, report}]}). %% | callback | discard
-
+ options = [{answer_errors, report}, %% | callback | discard
+ {request_errors, answer_3xxx}]}). %% | callback
-endif. %% -ifdef(diameter_hrl).
diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl
index f563d244f6..7359688404 100644
--- a/lib/diameter/src/base/diameter.erl
+++ b/lib/diameter/src/base/diameter.erl
@@ -306,7 +306,8 @@ call(SvcName, App, Message) ->
| {module, app_module()}
| {state, any()}
| {call_mutates_state, boolean()}
- | {answer_errors, callback|report|discard}.
+ | {answer_errors, callback|report|discard}
+ | {request_errors, callback|answer_3xxx}.
-type app_alias()
:: any().
diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
index 1486071573..889c75e3da 100644
--- a/lib/diameter/src/base/diameter_config.erl
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -672,13 +672,15 @@ app_acc({application, Opts}, Acc) ->
ModS = get_opt(state, Opts, Alias),
M = get_opt(call_mutates_state, Opts, false),
A = get_opt(answer_errors, Opts, report),
+ R = get_opt(request_errors, Opts, answer_3xxx),
[#diameter_app{alias = Alias,
dictionary = Dict,
id = cb(Dict, id),
module = init_mod(Mod),
init_state = ModS,
mutable = init_mutable(M),
- options = [{answer_errors, init_answers(A)}]}
+ options = [{answer_errors, init_answers(A)},
+ {request_errors, init_request_errors(R)}]}
| Acc];
app_acc(_, Acc) ->
Acc.
@@ -722,6 +724,13 @@ init_answers(A)
init_answers(A) ->
?THROW({answer_errors, A}).
+init_request_errors(P)
+ when callback == P;
+ answer_3xxx == P ->
+ P;
+init_request_errors(P) ->
+ ?THROW({request_errors, P}).
+
%% Get a single value at the specified key.
get_opt(Keys, List)
when is_list(Keys) ->
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 0de3825943..c3b9c195fb 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -205,16 +205,25 @@ recv_request({#diameter_app{id = Id, dictionary = Dict} = App, Caps},
Caps,
Dict0,
RecvData,
- diameter_codec:decode(Id, Dict, Pkt));
+ errors(Id, 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(#diameter_caps{} = Caps, TPid, Pkt, Dict0, _) ->
- As = collect_avps(Pkt),
- protocol_error(3007, TPid, Caps, Dict0, Pkt#diameter_packet{avps = As});
+recv_request(#diameter_caps{}
+ = Caps,
+ TPid,
+ #diameter_packet{errors = Es}
+ = Pkt,
+ Dict0,
+ _) ->
+ protocol_error(TPid,
+ Caps,
+ Dict0,
+ Pkt#diameter_packet{avps = collect_avps(Pkt),
+ errors = [3007 | Es]});
recv_request(false, _, _, _, _) -> %% transport has gone down
ok.
@@ -229,75 +238,25 @@ collect_avps(Pkt) ->
%% recv_R/6
-%% Wrong number of bits somewhere in the message: reply.
-%%
-%% DIAMETER_INVALID_AVP_BITS 3009
-%% A request was received that included an AVP whose flag bits are
-%% set to an unrecognized value, or that is inconsistent with the
-%% AVP's definition.
-%%
-recv_R(_App,
+%% Answer 3xxx errors ourselves ...
+recv_R(#diameter_app{options = [_, {request_errors, answer_3xxx} | _]},
TPid,
Caps,
Dict0,
_RecvData,
- #diameter_packet{errors = [Bs | _]} = Pkt)
- when is_bitstring(Bs) ->
- protocol_error(3009, TPid, Caps, Dict0, Pkt);
+ #diameter_packet{errors = [RC|_]} = Pkt)
+ when 3 == RC div 1000 ->
+ protocol_error(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.
-%%
-%% DIAMETER_COMMAND_UNSUPPORTED 3001
-%% The Request contained a Command-Code that the receiver did not
-%% recognize or support. This MUST be used when a Diameter node
-%% receives an experimental command that it does not understand.
-%%
-recv_R(#diameter_app{id = Id},
+%% ... or make a handle_request callback. Note that
+%% Pkt#diameter_packet.msg = undefined in the 3001 case.
+recv_R(App,
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, TPid, Caps, Dict0, Pkt);
-
-%% Error bit was set on a request.
-%%
-%% DIAMETER_INVALID_HDR_BITS 3008
-%% A request was received whose bits in the Diameter header were
-%% either set to an invalid combination, or to a value that is
-%% inconsistent with the command code's definition.
-%%
-recv_R(_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_R(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(App,
- TPid,
- Caps,
- Dict0,
- #recvdata{service_name = SvcName}
- = RecvData,
- Pkt) ->
+ #recvdata{service_name = SvcName}
+ = RecvData,
+ Pkt) ->
request_cb(cb(App, handle_request, [Pkt, SvcName, {TPid, Caps}]),
App,
TPid,
@@ -307,20 +266,21 @@ request_cb(App,
[],
Pkt).
-%% examine/1
+%% errors/1
%%
-%% Look for errors in a decoded message. It's odd/unfortunate that
-%% 501[15] aren't protocol errors.
+%% Look for errors in a decoded message, prepending the errors field
+%% with the first detected error. It's odd/unfortunate that 5011 isn't
+%% a protocol error.
%% DIAMETER_INVALID_MESSAGE_LENGTH 5015
%%
%% This error is returned when a request is received with an invalid
%% message length.
-examine(#diameter_packet{header = #diameter_header{length = Len},
- bin = Bin,
- errors = Es}
- = Pkt)
+errors(_, #diameter_packet{header = #diameter_header{length = Len},
+ bin = Bin,
+ errors = Es}
+ = Pkt)
when Len < 20;
0 /= Len rem 4;
8*Len /= bit_size(Bin) ->
@@ -330,13 +290,47 @@ examine(#diameter_packet{header = #diameter_header{length = Len},
%% This error is returned when a request was received, whose version
%% number is unsupported.
-examine(#diameter_packet{header = #diameter_header{version = V},
- errors = Es}
- = Pkt)
+errors(_, #diameter_packet{header = #diameter_header{version = V},
+ errors = Es}
+ = Pkt)
when V /= ?DIAMETER_VERSION ->
Pkt#diameter_packet{errors = [5011 | Es]};
-examine(Pkt) ->
+%% DIAMETER_INVALID_AVP_BITS 3009
+%% A request was received that included an AVP whose flag bits are
+%% set to an unrecognized value, or that is inconsistent with the
+%% AVP's definition.
+
+errors(_, #diameter_packet{errors = [Bs | Es]} = Pkt)
+ when is_bitstring(Bs) ->
+ Pkt#diameter_packet{errors = [3009 | Es]};
+
+%% DIAMETER_COMMAND_UNSUPPORTED 3001
+%% The Request contained a Command-Code that the receiver did not
+%% recognize or support. This MUST be used when a Diameter node
+%% receives an experimental command that it does not understand.
+
+errors(Id, #diameter_packet{header = #diameter_header{is_proxiable = P},
+ msg = M,
+ errors = Es}
+ = Pkt)
+ when ?APP_ID_RELAY /= Id, undefined == M; %% don't know the command
+ ?APP_ID_RELAY == Id, not P -> %% command isn't proxiable
+ Pkt#diameter_packet{errors = [3001 | Es]};
+
+%% DIAMETER_INVALID_HDR_BITS 3008
+%% A request was received whose bits in the Diameter header were
+%% either set to an invalid combination, or to a value that is
+%% inconsistent with the command code's definition.
+
+errors(_, #diameter_packet{header = #diameter_header{is_request = true,
+ is_error = true},
+ errors = Es}
+ = Pkt) ->
+ Pkt#diameter_packet{errors = [3008 | Es]};
+
+%% Green.
+errors(_, Pkt) ->
Pkt.
%% request_cb/8
@@ -365,7 +359,7 @@ request_cb({protocol_error, RC},
_RecvData,
Fs,
Pkt)
- when 3000 =< RC, RC < 4000 ->
+ when 3 == RC div 1000 ->
protocol_error(RC, TPid, Caps, Dict0, Fs, Pkt);
%% RFC 3588 says we must reply 3001 to anything unrecognized or
@@ -447,28 +441,36 @@ dict(Dict, Dict0, Rec) ->
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/5
+protocol_error(TPid,
+ #diameter_caps{origin_host = {OH,_},
+ origin_realm = {OR,_}},
+ Dict0,
+ Fs,
+ #diameter_packet{avps = Avps,
+ errors = [RC|_]}
+ = Pkt) ->
?LOG({error, RC}, Pkt),
- reply(answer_message({OH, OR, RC}, Dict0, Avps),
- Dict0,
- TPid,
- Fs,
- Pkt#diameter_packet{errors = [RC | Es]}).
+ reply(answer_message({OH, OR, RC}, Dict0, Avps), Dict0, TPid, Fs, Pkt).
%% Note that reply/5 may set the result code once more. It's set in
%% answer_message/3 in case reply/5 doesn't.
-%% protocol_error/5
+protocol_error(TPid, Caps, Dict0, Pkt) ->
+ protocol_error(TPid, Caps, Dict0, [], Pkt).
-protocol_error(RC, TPid, Caps, Dict0, Pkt) ->
- protocol_error(RC, TPid, Caps, Dict0, [], Pkt).
+protocol_error(RC,
+ TPid,
+ Caps,
+ Dict0,
+ Fs,
+ #diameter_packet{errors = Es}
+ = Pkt) ->
+ protocol_error(TPid,
+ Caps,
+ Dict0,
+ Fs,
+ Pkt#diameter_packet{errors = [RC | Es]}).
%% resend/7
%%
@@ -661,15 +663,15 @@ rc(RC) ->
%% rc/4
-rc(#diameter_packet{msg = Rec} = Pkt, RC, Failed, DictT) ->
- Pkt#diameter_packet{msg = rc(Rec, RC, Failed, DictT)};
+rc(#diameter_packet{msg = Rec} = Pkt, RC, Failed, Dict) ->
+ Pkt#diameter_packet{msg = rc(Rec, RC, Failed, Dict)};
-rc(Rec, RC, Failed, DictT)
+rc(Rec, RC, Failed, Dict)
when is_integer(RC) ->
set(Rec,
- lists:append([rc(Rec, {'Result-Code', RC}, DictT),
- failed_avp(Rec, Failed, DictT)]),
- DictT).
+ lists:append([rc(Rec, {'Result-Code', RC}, Dict),
+ failed_avp(Rec, Failed, Dict)]),
+ Dict).
%% Reply as name and tuple list ...
set([_|_] = Ans, Avps, _) ->
@@ -1268,11 +1270,12 @@ handle_answer(SvcName, App, {error, Req, Reason}) ->
handle_error(App, Req, Reason, SvcName);
handle_answer(SvcName,
- #diameter_app{dictionary = Dict}
+ #diameter_app{dictionary = Dict,
+ id = Id}
= App,
{answer, Req, Dict0, Pkt}) ->
Mod = dict(Dict, Dict0, Pkt),
- answer(examine(diameter_codec:decode(Mod, Pkt)),
+ answer(errors(Id, diameter_codec:decode(Mod, Pkt)),
SvcName,
Mod,
App,
diff --git a/lib/diameter/test/diameter_3xxx_SUITE.erl b/lib/diameter/test/diameter_3xxx_SUITE.erl
new file mode 100644
index 0000000000..a87d5347db
--- /dev/null
+++ b/lib/diameter/test/diameter_3xxx_SUITE.erl
@@ -0,0 +1,214 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Tests of application_opt() request_errors.
+%%
+
+-module(diameter_3xxx_SUITE).
+
+-export([suite/0,
+ all/0,
+ groups/0,
+ init_per_suite/1,
+ end_per_suite/1,
+ init_per_group/2,
+ end_per_group/2,
+ init_per_testcase/2,
+ end_per_testcase/2]).
+
+%% testcases
+-export([start/1,
+ send/1,
+ stop/1]).
+
+%% diameter callbacks
+-export([peer_up/3,
+ peer_down/3,
+ pick_peer/4,
+ prepare_request/3,
+ handle_answer/4,
+ handle_error/4,
+ handle_request/3]).
+
+-include("diameter.hrl").
+-include("diameter_gen_base_rfc6733.hrl").
+
+%% ===========================================================================
+
+-define(util, diameter_util).
+
+-define(CLIENT, "CLIENT").
+-define(SERVER, "SERVER").
+-define(REALM, "erlang.org").
+-define(HOST(Host, Realm), Host ++ [$.|Realm]).
+-define(DICT, diameter_gen_base_rfc6733).
+
+%% Config for diameter:start_service/2.
+-define(SERVICE(Name, RequestErrors),
+ [{'Origin-Host', Name ++ "." ++ ?REALM},
+ {'Origin-Realm', ?REALM},
+ {'Host-IP-Address', [{127,0,0,1}]},
+ {'Vendor-Id', 12345},
+ {'Product-Name', "OTP/diameter"},
+ {'Auth-Application-Id', [?DIAMETER_APP_ID_COMMON]},
+ {application, [{dictionary, ?DICT},
+ {module, ?MODULE},
+ {answer_errors, callback},
+ {request_errors, RequestErrors}]}]).
+
+-define(SUCCESS, ?'DIAMETER_BASE_RESULT-CODE_SUCCESS').
+-define(UNSUPPORTED, ?'DIAMETER_BASE_RESULT-CODE_COMMAND_UNSUPPORTED').
+
+-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_LOGOUT').
+
+-define(GROUPS, [answer_3xxx, callback]).
+-define(L, atom_to_list).
+
+%% ===========================================================================
+
+suite() ->
+ [{timetrap, {seconds, 60}}].
+
+all() ->
+ [{group, G} || G <- ?GROUPS].
+
+groups() ->
+ [{G, [], [start, send, stop]} || G <- ?GROUPS].
+
+init_per_suite(Config) ->
+ ok = diameter:start(),
+ Config.
+
+end_per_suite(_Config) ->
+ ok = diameter:stop().
+
+init_per_group(Group, Config) ->
+ [{group, Group} | Config].
+
+end_per_group(_, _) ->
+ ok.
+
+init_per_testcase(_Name, Config) ->
+ Config.
+
+end_per_testcase(_, _) ->
+ ok.
+
+origin(answer_3xxx) -> 0;
+origin(callback) -> 1;
+
+origin(0) -> answer_3xxx;
+origin(1) -> callback.
+
+%% ===========================================================================
+
+%% start/1
+
+start(Config) ->
+ Group = proplists:get_value(group, Config),
+ ok = diameter:start_service(?SERVER, ?SERVICE(?L(Group), Group)),
+ ok = diameter:start_service(?CLIENT, ?SERVICE(?CLIENT, callback)),
+ LRef = ?util:listen(?SERVER, tcp),
+ ?util:connect(?CLIENT,
+ tcp,
+ LRef,
+ [{capabilities, [{'Origin-State-Id', origin(Group)}]}]).
+
+%% stop/1
+
+stop(_Config) ->
+ ok = diameter:remove_transport(?CLIENT, true),
+ ok = diameter:remove_transport(?SERVER, true),
+ ok = diameter:stop_service(?SERVER),
+ ok = diameter:stop_service(?CLIENT).
+
+%% send/1
+%%
+%% Send a unknown command and expect a different result depending on
+%% whether or not the server gets a handle_request callback.
+
+%% Server handle_request discards the request.
+send(callback) ->
+ {error, timeout} = call();
+
+%% No handle_request, diameter answers.
+send(answer_3xxx) ->
+ #'diameter_base_answer-message'{'Result-Code' = ?UNSUPPORTED} = call();
+
+send(Config) ->
+ send(proplists:get_value(group, Config)).
+
+%% ===========================================================================
+
+call() ->
+ diameter:call(?CLIENT,
+ ?DICT,
+ #diameter_base_STR
+ {'Termination-Cause' = ?LOGOUT,
+ 'Auth-Application-Id' = ?DIAMETER_APP_ID_COMMON}).
+
+%% ===========================================================================
+%% diameter callbacks
+
+%% peer_up/3
+
+peer_up(_SvcName, _Peer, State) ->
+ State.
+
+%% peer_down/3
+
+peer_down(_SvcName, _Peer, State) ->
+ State.
+
+%% pick_peer/4
+
+pick_peer([Peer], _, ?CLIENT, _State) ->
+ {ok, Peer}.
+
+%% prepare_request/3
+
+prepare_request(#diameter_packet{msg = Req0} = Pkt0, ?CLIENT, {_Ref, Caps}) ->
+ #diameter_caps{origin_host = {OH, _},
+ origin_realm = {OR, DR}}
+ = Caps,
+ Req = Req0#diameter_base_STR{'Session-Id' = diameter:session_id(OH),
+ 'Origin-Host' = OH,
+ 'Origin-Realm' = OR,
+ 'Destination-Realm' = DR},
+ #diameter_packet{bin = <<H:5/binary, 275:24, T/binary>>}
+ = Pkt
+ = diameter_codec:encode(?DICT, Pkt0#diameter_packet{msg = Req}),
+
+ {send, Pkt#diameter_packet{bin = <<H/binary, 572:24, T/binary>>}}.
+
+%% handle_answer/4
+
+handle_answer(Pkt, _Req, ?CLIENT, _Peer) ->
+ Pkt#diameter_packet.msg.
+
+%% handle_error/4
+
+handle_error(Reason, _Req, ?CLIENT, _Peer) ->
+ {error, Reason}.
+
+%% handle_request/3
+
+handle_request(_, ?SERVER, _) ->
+ discard.
diff --git a/lib/diameter/test/diameter_failover_SUITE.erl b/lib/diameter/test/diameter_failover_SUITE.erl
index bb820a8bf2..0ea8ae2d4e 100644
--- a/lib/diameter/test/diameter_failover_SUITE.erl
+++ b/lib/diameter/test/diameter_failover_SUITE.erl
@@ -103,9 +103,9 @@
-define(SUCCESS, 2001).
%% Value of Termination-Cause determines client/server behaviour.
--define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
--define(MOVED, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_USER_MOVED').
--define(TIMEOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_SESSION_TIMEOUT').
+-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_LOGOUT').
+-define(MOVED, ?'DIAMETER_BASE_TERMINATION-CAUSE_USER_MOVED').
+-define(TIMEOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_SESSION_TIMEOUT').
%% ===========================================================================
diff --git a/lib/diameter/test/diameter_length_SUITE.erl b/lib/diameter/test/diameter_length_SUITE.erl
index 4e413e6a42..ffb19d2288 100644
--- a/lib/diameter/test/diameter_length_SUITE.erl
+++ b/lib/diameter/test/diameter_length_SUITE.erl
@@ -41,10 +41,10 @@
%% diameter callbacks
-export([peer_up/3,
peer_down/3,
- pick_peer/6,
- prepare_request/5,
- handle_answer/6,
- handle_error/6,
+ pick_peer/5,
+ prepare_request/4,
+ handle_answer/5,
+ handle_error/5,
handle_request/3]).
-include("diameter.hrl").
@@ -73,14 +73,14 @@
{answer_errors, callback}]}]).
-define(SUCCESS,
- ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_SUCCESS').
+ ?'DIAMETER_BASE_RESULT-CODE_SUCCESS').
-define(MISSING_AVP,
- ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_MISSING_AVP').
+ ?'DIAMETER_BASE_RESULT-CODE_MISSING_AVP').
-define(INVALID_MESSAGE_LENGTH,
- ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_INVALID_MESSAGE_LENGTH').
+ ?'DIAMETER_BASE_RESULT-CODE_INVALID_MESSAGE_LENGTH').
-define(LOGOUT,
- ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
+ ?'DIAMETER_BASE_TERMINATION-CAUSE_LOGOUT').
-define(GROUPS, [exit, handle, discard]).
@@ -196,21 +196,18 @@ send(discard) ->
= call(0);
send(Config) ->
- Group = proplists:get_value(group, Config),
- put({?MODULE, group}, Group),
- send(Group).
+ send(proplists:get_value(group, Config)).
%% ===========================================================================
call(Delta) ->
- Group = get({?MODULE, group}),
diameter:call(?CLIENT,
?DICT,
#diameter_base_STR
{'Termination-Cause' = ?LOGOUT,
'Auth-Application-Id' = ?DIAMETER_APP_ID_COMMON,
'Origin-State-Id' = [7]},
- [{extra, [Group, Delta]}]).
+ [{extra, [Delta]}]).
%% ===========================================================================
%% diameter callbacks
@@ -225,14 +222,14 @@ peer_up(_SvcName, _Peer, State) ->
peer_down(_SvcName, _Peer, State) ->
State.
-%% pick_peer/6
+%% pick_peer/5
-pick_peer([Peer], _, ?CLIENT, _State, _Group, _Delta) ->
+pick_peer([Peer], _, ?CLIENT, _State, _Delta) ->
{ok, Peer}.
-%% prepare_request/5
+%% prepare_request/4
-prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, _Group, Delta) ->
+prepare_request(Pkt, ?CLIENT, {_Ref, Caps}, Delta) ->
{send, resize(Delta, prepare(Pkt, Caps))}.
prepare(#diameter_packet{msg = Req0} = Pkt, Caps) ->
@@ -253,14 +250,14 @@ resize(Delta, #diameter_packet{bin = Bin} = Pkt) ->
resize(Delta, <<V, Len:24, T/binary>>) ->
<<V, (Len + Delta):24, T/binary>>.
-%% handle_answer/6
+%% handle_answer/5
-handle_answer(Pkt, _Req, ?CLIENT, _Peer, _Group, _Delta) ->
+handle_answer(Pkt, _Req, ?CLIENT, _Peer, _Delta) ->
Pkt#diameter_packet.msg.
-%% handle_error/6
+%% handle_error/5
-handle_error(Reason, _Req, ?CLIENT, _Peer, _Group, _Delta) ->
+handle_error(Reason, _Req, ?CLIENT, _Peer, _Delta) ->
{error, Reason}.
%% handle_request/3
@@ -280,8 +277,12 @@ handle_request(Pkt, ?SERVER, {_Ref, Caps}) ->
answer(Group, #diameter_packet{errors = Es}, Ans) ->
answer(Group, Es, Ans);
+%% No errors: just answer.
answer(_, [], Ans) ->
{reply, Ans};
+
+%% Otherwise an invalid length should only reach the callback if
+%% length_errors = handle.
answer(Group, [RC|_], Ans)
when RC == ?INVALID_MESSAGE_LENGTH, Group == handle;
RC /= ?INVALID_MESSAGE_LENGTH ->
diff --git a/lib/diameter/test/diameter_relay_SUITE.erl b/lib/diameter/test/diameter_relay_SUITE.erl
index f10d82bdf8..614eb4d4ca 100644
--- a/lib/diameter/test/diameter_relay_SUITE.erl
+++ b/lib/diameter/test/diameter_relay_SUITE.erl
@@ -107,7 +107,7 @@
-define(LOOP_DETECTED, 3005).
-define(UNABLE_TO_DELIVER, 3002).
--define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
+-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_LOGOUT').
-define(AUTHORIZE_ONLY, ?'DIAMETER_BASE_RE-AUTH-REQUEST-TYPE_AUTHORIZE_ONLY').
%% ===========================================================================
diff --git a/lib/diameter/test/diameter_tls_SUITE.erl b/lib/diameter/test/diameter_tls_SUITE.erl
index 6cc34b20c5..92a1113758 100644
--- a/lib/diameter/test/diameter_tls_SUITE.erl
+++ b/lib/diameter/test/diameter_tls_SUITE.erl
@@ -122,7 +122,7 @@
{capabilities, Caps}]}).
-define(SUCCESS, 2001).
--define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
+-define(LOGOUT, ?'DIAMETER_BASE_TERMINATION-CAUSE_LOGOUT').
%% ===========================================================================
diff --git a/lib/diameter/test/diameter_traffic_SUITE.erl b/lib/diameter/test/diameter_traffic_SUITE.erl
index 6727e88b66..d3d6fff705 100644
--- a/lib/diameter/test/diameter_traffic_SUITE.erl
+++ b/lib/diameter/test/diameter_traffic_SUITE.erl
@@ -178,27 +178,27 @@
diameter_gen_acct_rfc6733]]]).
-define(SUCCESS,
- ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_SUCCESS').
+ ?'DIAMETER_BASE_RESULT-CODE_SUCCESS').
-define(COMMAND_UNSUPPORTED,
- ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_COMMAND_UNSUPPORTED').
+ ?'DIAMETER_BASE_RESULT-CODE_COMMAND_UNSUPPORTED').
-define(TOO_BUSY,
- ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_TOO_BUSY').
+ ?'DIAMETER_BASE_RESULT-CODE_TOO_BUSY').
-define(APPLICATION_UNSUPPORTED,
- ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_APPLICATION_UNSUPPORTED').
+ ?'DIAMETER_BASE_RESULT-CODE_APPLICATION_UNSUPPORTED').
-define(INVALID_HDR_BITS,
- ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_INVALID_HDR_BITS').
+ ?'DIAMETER_BASE_RESULT-CODE_INVALID_HDR_BITS').
-define(INVALID_AVP_BITS,
- ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_INVALID_AVP_BITS').
+ ?'DIAMETER_BASE_RESULT-CODE_INVALID_AVP_BITS').
-define(AVP_UNSUPPORTED,
- ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_AVP_UNSUPPORTED').
+ ?'DIAMETER_BASE_RESULT-CODE_AVP_UNSUPPORTED').
-define(UNSUPPORTED_VERSION,
- ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_UNSUPPORTED_VERSION').
+ ?'DIAMETER_BASE_RESULT-CODE_UNSUPPORTED_VERSION').
-define(REALM_NOT_SERVED,
- ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_REALM_NOT_SERVED').
+ ?'DIAMETER_BASE_RESULT-CODE_REALM_NOT_SERVED').
-define(UNABLE_TO_DELIVER,
- ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_UNABLE_TO_DELIVER').
+ ?'DIAMETER_BASE_RESULT-CODE_UNABLE_TO_DELIVER').
-define(INVALID_AVP_LENGTH,
- ?'DIAMETER_BASE_RESULT-CODE_DIAMETER_INVALID_AVP_LENGTH').
+ ?'DIAMETER_BASE_RESULT-CODE_INVALID_AVP_LENGTH').
-define(EVENT_RECORD,
?'DIAMETER_BASE_ACCOUNTING-RECORD-TYPE_EVENT_RECORD').
@@ -208,11 +208,11 @@
?'DIAMETER_BASE_RE-AUTH-REQUEST-TYPE_AUTHORIZE_AUTHENTICATE').
-define(LOGOUT,
- ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_LOGOUT').
+ ?'DIAMETER_BASE_TERMINATION-CAUSE_LOGOUT').
-define(BAD_ANSWER,
- ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_BAD_ANSWER').
+ ?'DIAMETER_BASE_TERMINATION-CAUSE_BAD_ANSWER').
-define(USER_MOVED,
- ?'DIAMETER_BASE_TERMINATION-CAUSE_DIAMETER_USER_MOVED').
+ ?'DIAMETER_BASE_TERMINATION-CAUSE_USER_MOVED').
%% ===========================================================================
diff --git a/lib/diameter/test/modules.mk b/lib/diameter/test/modules.mk
index f575085843..32e5fb4613 100644
--- a/lib/diameter/test/modules.mk
+++ b/lib/diameter/test/modules.mk
@@ -42,7 +42,8 @@ MODULES = \
diameter_failover_SUITE \
diameter_dpr_SUITE \
diameter_event_SUITE \
- diameter_length_SUITE
+ diameter_length_SUITE \
+ diameter_3xxx_SUITE
HRL_FILES = \
diameter_ct.hrl