From 722fa41564381dff0b7aa2b465193db30bb2f02f Mon Sep 17 00:00:00 2001
From: Anders Svensson
Date: Thu, 6 Jul 2017 09:58:07 +0200
Subject: Add service_opt() record_decode
To control whether or not messages and grouped AVPs are decoded to
records, in #diameter_packet.msg and #diameter_avp.value respectively.
The decode became unnecessary for diameter's needs in parent commit,
which decoupled it from the checking of AVP arities.
---
lib/diameter/doc/src/diameter.xml | 23 ++++++++++++++++++++++
lib/diameter/src/base/diameter.erl | 1 +
lib/diameter/src/base/diameter_codec.erl | 3 ++-
lib/diameter/src/base/diameter_config.erl | 3 +++
lib/diameter/src/base/diameter_gen.erl | 15 +++++++++++++-
lib/diameter/src/base/diameter_peer_fsm.erl | 9 ++++++---
lib/diameter/src/base/diameter_service.erl | 1 +
lib/diameter/src/base/diameter_traffic.erl | 9 ++++++---
lib/diameter/src/base/diameter_watchdog.erl | 9 ++++++---
lib/diameter/test/diameter_codec_SUITE.erl | 1 +
.../diameter_test_unknown.erl | 1 +
lib/diameter/test/diameter_codec_test.erl | 3 ++-
12 files changed, 66 insertions(+), 12 deletions(-)
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index 2cbe48ecce..663c9cc785 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -969,6 +969,29 @@ occur in the message in question.
+
+{record_decode, boolean()}
+-
+
+Whether or not to decode message and grouped AVPs to records in the
+msg field of diameter_packet records and value field of
+diameter_avp records respectively.
+If false then the fields are set to the same value.
+
+
+Defaults to true.
+
+
+
+Disabling the record is useful for applications in which the records
+aren't used/needed.
+AVP values are available in the avps field of
+diameter_packet records regardless of whether or not there is a record
+decode.
+
+
+
+
{string_decode, boolean()}
-
diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl
index bd92e16fba..f411656e90 100644
--- a/lib/diameter/src/base/diameter.erl
+++ b/lib/diameter/src/base/diameter.erl
@@ -338,6 +338,7 @@ call(SvcName, App, Message) ->
| {restrict_connections, restriction()}
| {sequence, sequence() | evaluable()}
| {share_peers, remotes()}
+ | {record_decode, boolean()}
| {string_decode, boolean()}
| {strict_mbit, boolean()}
| {incoming_maxlen, message_length()}
diff --git a/lib/diameter/src/base/diameter_codec.erl b/lib/diameter/src/base/diameter_codec.erl
index 93c1b28f4c..5e4c6e6d8f 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -287,7 +287,8 @@ rec2msg(Mod, Rec) ->
%% longer *the* decode.
decode(Mod, Pkt) ->
- Opts = #{string_decode => true,
+ Opts = #{record_decode => true,
+ string_decode => true,
strict_mbit => true,
rfc => 6733},
decode(Mod, Opts, Pkt).
diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
index 34018ae6d3..46a3e362ac 100644
--- a/lib/diameter/src/base/diameter_config.erl
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -713,6 +713,7 @@ make_config(SvcName, Opts) ->
{nodes, restrict_connections},
{16#FFFFFF, incoming_maxlen},
{true, strict_mbit},
+ {true, record_decode},
{true, string_decode},
{[], spawn_opt}]),
@@ -756,6 +757,7 @@ opt(K, false = B)
K == monitor;
K == restrict_connections;
K == strict_mbit;
+ K == record_decode;
K == string_decode ->
B;
@@ -763,6 +765,7 @@ opt(K, true = B)
when K == share_peers;
K == use_shared_peers;
K == strict_mbit;
+ K == record_decode;
K == string_decode ->
B;
diff --git a/lib/diameter/src/base/diameter_gen.erl b/lib/diameter/src/base/diameter_gen.erl
index 6f11583868..4879ad8f6c 100644
--- a/lib/diameter/src/base/diameter_gen.erl
+++ b/lib/diameter/src/base/diameter_gen.erl
@@ -174,7 +174,7 @@ enc_AVP(_Name, {_Dict, _AvpName, _Data} = T, Opts, _) ->
decode_avps(Name, Recs, #{module := Mod} = Opts) ->
{Avps, {Rec, AM, Failed}}
= mapfoldl(fun(T,A) -> decode(Name, Opts, Mod, T, A) end,
- {newrec(Mod, Name), #{}, []},
+ {newrec(Mod, Name, Opts), #{}, []},
Recs),
%% AM counts the number of top-level AVPs, which missing/4 then
%% uses when adding 5005 errors.
@@ -624,6 +624,9 @@ too_many(FieldName, M, Map) ->
%% set/5
+set(_, _, _, _, undefined = No) ->
+ No;
+
set(1, F, Value, Mod, Rec) ->
Mod:'#set-'({F, Value}, Rec);
@@ -723,5 +726,15 @@ empty(Name, #{module := Mod} = Opts) ->
%% ------------------------------------------------------------------------------
+%% newrec/3
+
+newrec(_, _, #{record_decode := false}) ->
+ undefined;
+
+newrec(Mod, Name, _) ->
+ newrec(Mod, Name).
+
+%% newrec/2
+
newrec(Mod, Name) ->
Mod:'#new-'(Mod:name2rec(Name)).
diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl
index 1b0dc417e5..f2fbb70270 100644
--- a/lib/diameter/src/base/diameter_peer_fsm.erl
+++ b/lib/diameter/src/base/diameter_peer_fsm.erl
@@ -128,7 +128,8 @@
%% outgoing DPR; boolean says whether or not
%% the request was sent explicitly with
%% diameter:call/4.
- codec :: #{string_decode := boolean(),
+ codec :: #{record_decode := true,
+ string_decode := boolean(),
strict_mbit := boolean(),
rfc := 3588 | 6733,
ordered_encode := false},
@@ -253,11 +254,13 @@ i({Ack, WPid, {M, Ref} = T, Opts, {SvcOpts, Nodes, Dict0, Svc}}) ->
length_errors = LengthErr,
strict = Strictness,
incoming_maxlen = Maxlen,
- codec = maps:with([string_decode,
+ codec = maps:with([record_decode,
+ string_decode,
strict_mbit,
rfc,
ordered_encode],
- SvcOpts#{ordered_encode => false})}.
+ SvcOpts#{ordered_encode => false,
+ record_decode => true})}.
%% The transport returns its local ip addresses so that different
%% transports on the same service can use different local addresses.
%% The local addresses are put into Host-IP-Address avps here when
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index a976a8b998..6dc4889c82 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -113,6 +113,7 @@
restrict_connections := diameter:restriction(),
incoming_maxlen := diameter:message_length(),
strict_mbit := boolean(),
+ record_decode := boolean(),
string_decode := boolean(),
spawn_opt := list() | {module(), atom(), list()}}}).
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 85378babea..228d9802ad 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -76,7 +76,8 @@
service_name :: diameter:service_name(),
apps :: [#diameter_app{}],
sequence :: diameter:sequence(),
- codec :: #{string_decode := boolean(),
+ codec :: #{record_decode := boolean(),
+ string_decode := boolean(),
strict_mbit := boolean(),
incoming_maxlen := diameter:message_length()}}).
%% Note that incoming_maxlen is currently handled in diameter_peer_fsm,
@@ -102,7 +103,8 @@ make_recvdata([SvcName, PeerT, Apps, SvcOpts | _]) ->
peerT = PeerT,
apps = Apps,
sequence = Mask,
- codec = maps:with([string_decode,
+ codec = maps:with([record_decode,
+ string_decode,
strict_mbit,
ordered_encode,
incoming_maxlen],
@@ -1933,7 +1935,8 @@ choose(false, _, X) -> X.
%% Decode options sufficient for AVP extraction.
decode_opts(Dict) ->
- #{string_decode => false,
+ #{record_decode => true,
+ string_decode => false,
strict_mbit => false,
failed_avp => false,
dictionary => Dict}.
diff --git a/lib/diameter/src/base/diameter_watchdog.erl b/lib/diameter/src/base/diameter_watchdog.erl
index a63425d92a..c3dc8c3bf0 100644
--- a/lib/diameter/src/base/diameter_watchdog.erl
+++ b/lib/diameter/src/base/diameter_watchdog.erl
@@ -72,7 +72,8 @@
restrict := boolean(),
suspect := non_neg_integer(), %% OKAY -> SUSPECT
okay := non_neg_integer()}, %% REOPEN -> OKAY
- codec :: #{string_decode := false,
+ codec :: #{record_decode := false,
+ string_decode := false,
strict_mbit := boolean(),
failed_avp := false,
rfc := 3588 | 6733,
@@ -135,7 +136,8 @@ i({Ack, T, Pid, {Opts,
putr(restart, {T, Opts, Svc, SvcOpts}), %% save seeing it in trace
putr(dwr, dwr(Caps)), %%
Nodes = restrict_nodes(Restrict),
- CodecKeys = [string_decode,
+ CodecKeys = [record_decode,
+ string_decode,
strict_mbit,
incoming_maxlen,
spawn_opt,
@@ -155,7 +157,8 @@ i({Ack, T, Pid, {Opts,
suspect => 1,
okay => 3},
Opts)),
- codec = maps:with(CodecKeys, SvcOpts#{string_decode := false,
+ codec = maps:with(CodecKeys, SvcOpts#{record_decode := false,
+ string_decode := false,
ordered_encode => false})}.
wait(Ref, Pid) ->
diff --git a/lib/diameter/test/diameter_codec_SUITE.erl b/lib/diameter/test/diameter_codec_SUITE.erl
index 9f08f49f9f..31332537e9 100644
--- a/lib/diameter/test/diameter_codec_SUITE.erl
+++ b/lib/diameter/test/diameter_codec_SUITE.erl
@@ -292,6 +292,7 @@ recode(Msg, Dict) ->
opts(Mod) ->
#{dictionary => Mod,
+ record_decode => true,
string_decode => false,
strict_mbit => true,
rfc => 6733,
diff --git a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
index 700910878c..fe602c9ee5 100644
--- a/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
+++ b/lib/diameter/test/diameter_codec_SUITE_data/diameter_test_unknown.erl
@@ -78,6 +78,7 @@ dec('BR', #diameter_packet
opts(Mod) ->
#{dictionary => Mod,
+ record_decode => true,
string_decode => true,
strict_mbit => true,
rfc => 6733,
diff --git a/lib/diameter/test/diameter_codec_test.erl b/lib/diameter/test/diameter_codec_test.erl
index b548f85cb8..7595e7edfc 100644
--- a/lib/diameter/test/diameter_codec_test.erl
+++ b/lib/diameter/test/diameter_codec_test.erl
@@ -219,7 +219,8 @@ opts(Mod) ->
dictionary => Mod}.
opts() ->
- #{string_decode => true,
+ #{record_decode => true,
+ string_decode => true,
strict_mbit => true,
rfc => 6733,
failed_avp => false}.
--
cgit v1.2.3