aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnders Svensson <[email protected]>2017-07-06 12:07:36 +0200
committerAnders Svensson <[email protected]>2017-08-03 17:14:27 +0200
commitd52611e9bd0628affa7b4f56a6126e4a99b69a7a (patch)
tree6dc7cae62bd1ba105e4f2e2ccfd32ed923c9dceb
parent1b3b64af3d9a5441b6da37cf4e97b59cb043f33b (diff)
downloadotp-d52611e9bd0628affa7b4f56a6126e4a99b69a7a.tar.gz
otp-d52611e9bd0628affa7b4f56a6126e4a99b69a7a.tar.bz2
otp-d52611e9bd0628affa7b4f56a6126e4a99b69a7a.zip
Let messages and grouped AVPs be decoded to lists
That is, decode to the same format that encode already accepts. Only a message has its name at the head of the list since AVPs are already name/value pairs.
-rw-r--r--lib/diameter/doc/src/diameter.xml3
-rw-r--r--lib/diameter/src/base/diameter.erl2
-rw-r--r--lib/diameter/src/base/diameter_codec.erl8
-rw-r--r--lib/diameter/src/base/diameter_config.erl4
-rw-r--r--lib/diameter/src/base/diameter_gen.erl35
-rw-r--r--lib/diameter/src/base/diameter_service.erl2
-rw-r--r--lib/diameter/src/base/diameter_traffic.erl2
7 files changed, 38 insertions, 18 deletions
diff --git a/lib/diameter/doc/src/diameter.xml b/lib/diameter/doc/src/diameter.xml
index bfb6da41b5..e525ab3345 100644
--- a/lib/diameter/doc/src/diameter.xml
+++ b/lib/diameter/doc/src/diameter.xml
@@ -970,7 +970,8 @@ occur in the message in question.</p>
</item>
<tag>
-<marker id="record_decode"/><c>{record_decode, boolean() | map}</c></tag>
+<marker id="record_decode"/>
+<c>{record_decode, boolean() | list | map}</c></tag>
<item>
<p>
Whether or not to decode message and grouped AVPs to records in the
diff --git a/lib/diameter/src/base/diameter.erl b/lib/diameter/src/base/diameter.erl
index 4269c84cd2..b033632c47 100644
--- a/lib/diameter/src/base/diameter.erl
+++ b/lib/diameter/src/base/diameter.erl
@@ -338,7 +338,7 @@ call(SvcName, App, Message) ->
| {restrict_connections, restriction()}
| {sequence, sequence() | evaluable()}
| {share_peers, remotes()}
- | {record_decode, boolean() | map}
+ | {record_decode, boolean() | list | map}
| {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 0c43d52093..9043af145e 100644
--- a/lib/diameter/src/base/diameter_codec.erl
+++ b/lib/diameter/src/base/diameter_codec.erl
@@ -379,10 +379,16 @@ decode_avps(MsgName, Mod, AppMod, Opts, Pkt, Avps) -> %% ... or not
Opts#{dictionary => AppMod,
failed_avp => false}),
?LOGC([] /= Errors, decode_errors, Pkt#diameter_packet.header),
- Pkt#diameter_packet{msg = Rec,
+ Pkt#diameter_packet{msg = reformat(MsgName, Rec, Opts),
errors = Errors,
avps = As}.
+reformat(MsgName, Avps, #{decode_format := list}) ->
+ [MsgName | Avps];
+
+reformat(_, Msg, _) ->
+ Msg.
+
%%% ---------------------------------------------------------------------------
%%% # decode_header/1
%%% ---------------------------------------------------------------------------
diff --git a/lib/diameter/src/base/diameter_config.erl b/lib/diameter/src/base/diameter_config.erl
index a790b946c1..8f958a67b4 100644
--- a/lib/diameter/src/base/diameter_config.erl
+++ b/lib/diameter/src/base/diameter_config.erl
@@ -769,7 +769,9 @@ opt(K, true = B)
K == string_decode ->
B;
-opt(record_decode, map = T) ->
+opt(record_decode, T)
+ when T == list;
+ T == map ->
T;
opt(restrict_connections, T)
diff --git a/lib/diameter/src/base/diameter_gen.erl b/lib/diameter/src/base/diameter_gen.erl
index be2e221b7e..2381b73d07 100644
--- a/lib/diameter/src/base/diameter_gen.erl
+++ b/lib/diameter/src/base/diameter_gen.erl
@@ -178,14 +178,17 @@ enc_AVP(_Name, {_Dict, _AvpName, _Data} = T, Opts, _) ->
-> {parent_record(), [avp()], Failed}
when Failed :: [{5000..5999, #diameter_avp{}}].
-decode_avps(Name, Recs, #{module := Mod} = Opts) ->
+decode_avps(Name, Recs, #{module := Mod, record_decode := Fmt} = Opts) ->
{Avps, {Rec, AM, Failed}}
= mapfoldl(fun(T,A) -> decode(Name, Opts, Mod, T, A) end,
- {newrec(Mod, Name, Opts), #{}, []},
+ {newrec(Mod, Name, Fmt), #{}, []},
Recs),
%% AM counts the number of top-level AVPs, which missing/4 then
%% uses when adding 5005 errors.
- {Rec, Avps, Failed ++ missing(Name, Opts, Mod, AM)}.
+ Arities = Mod:avp_arity(Name),
+ {reformat(Rec, Arities, Fmt),
+ Avps,
+ Failed ++ missing(Arities, Opts, Mod, AM)}.
%% Append 5005 errors so that errors are reported in the order
%% encountered. Failed-AVP should typically contain the first
@@ -216,10 +219,10 @@ mapfoldl(_, Acc, [], List) ->
%% Vendor-Id if applicable. The value field of the missing AVP
%% should be of correct minimum length and contain zeros.
-missing(Name, Opts, Mod, AM) ->
+missing(Arities, Opts, Mod, AM) ->
lists:foldl(fun(T,A) -> missing(T, AM, Opts, Mod, A) end,
[],
- Mod:avp_arity(Name)).
+ Arities).
%% missing/5
@@ -631,7 +634,7 @@ too_many(FieldName, M, Map) ->
%% set/5
-set(_, _, _, _, undefined = No) ->
+set(_, _, _, _, false = No) ->
No;
set(1, F, Value, _, Map)
@@ -743,20 +746,28 @@ empty(Name, #{module := Mod} = Opts) ->
%% newrec/3
-newrec(_, _, #{record_decode := false}) ->
- undefined;
+newrec(_, _, false = No) ->
+ No;
-newrec(_, Name, #{record_decode := map}) ->
- #{':name' => Name};
+newrec(Mod, Name, true) ->
+ newrec(Mod, Name);
-newrec(Mod, Name, _) ->
- newrec(Mod, Name).
+newrec(_, Name, _) ->
+ #{':name' => Name}.
%% newrec/2
newrec(Mod, Name) ->
Mod:'#new-'(Mod:name2rec(Name)).
+%% reformat/3
+
+reformat(Map, Arities, list) ->
+ [{F,V} || {F,_} <- Arities, #{F := V} <- [Map]];
+
+reformat(Rec, _, _) ->
+ Rec.
+
%% def/1
def(1) ->
diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl
index 3e555f6263..7f7e3e3a3f 100644
--- a/lib/diameter/src/base/diameter_service.erl
+++ b/lib/diameter/src/base/diameter_service.erl
@@ -113,7 +113,7 @@
restrict_connections := diameter:restriction(),
incoming_maxlen := diameter:message_length(),
strict_mbit := boolean(),
- record_decode := boolean() | map,
+ record_decode := boolean() | map | list,
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 f7dec2441f..6594994cfa 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -76,7 +76,7 @@
service_name :: diameter:service_name(),
apps :: [#diameter_app{}],
sequence :: diameter:sequence(),
- codec :: #{record_decode := boolean() | map,
+ codec :: #{record_decode := boolean() | map | list,
string_decode := boolean(),
strict_mbit := boolean(),
incoming_maxlen := diameter:message_length()}}).