From d52611e9bd0628affa7b4f56a6126e4a99b69a7a Mon Sep 17 00:00:00 2001 From: Anders Svensson Date: Thu, 6 Jul 2017 12:07:36 +0200 Subject: 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. --- lib/diameter/src/base/diameter.erl | 2 +- lib/diameter/src/base/diameter_codec.erl | 8 ++++++- lib/diameter/src/base/diameter_config.erl | 4 +++- lib/diameter/src/base/diameter_gen.erl | 35 ++++++++++++++++++++---------- lib/diameter/src/base/diameter_service.erl | 2 +- lib/diameter/src/base/diameter_traffic.erl | 2 +- 6 files changed, 36 insertions(+), 17 deletions(-) (limited to 'lib/diameter/src/base') 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()}}). -- cgit v1.2.3