aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAnders Svensson <[email protected]>2015-02-16 09:11:50 +0100
committerAnders Svensson <[email protected]>2015-02-17 02:29:19 +0100
commitebe60da137dafe659d9577e1c6411bcc1ea431af (patch)
tree6a307424b19e0f4667e4245feabe360cbf3afc79 /lib
parent60ddb0dc9e5c1e28aa01548b01310744fd9ede15 (diff)
downloadotp-ebe60da137dafe659d9577e1c6411bcc1ea431af.tar.gz
otp-ebe60da137dafe659d9577e1c6411bcc1ea431af.tar.bz2
otp-ebe60da137dafe659d9577e1c6411bcc1ea431af.zip
Don't discard component diameter_avp list on Grouped AVP decode error
The AVPs of an incoming Diameter message diameter_codec:decode/2,3 are decoded into a diameter_packet record in two ways: as a message-specific record in the 'msg' field and as a deep list of diameter_avp records in the 'avps' field. The record decode came first; the diameter_avp decode came later to support the Diameter relay application, but can also be convenient for non-relay applications. The diameter_avp representation can be used with outgoing messages, but what exactly is supported for isn't clearly documented. In the diameter_avp list representation, it's AVPs of type Grouped that lead to nesting: instead of a diameter_avp record, a Grouped AVP is represented by a diameter_avp list whose head is the Grouped AVP itself, and whose tail is the list of component AVPs. The diameter_avp decode was broken in the case of decode errors: the Grouped AVP was represented as a bare diameter_avp, and the component records were lost. The decode now produces the intended list. Note that component AVPs that could not be decoded will have 'undefined' in their data field.
Diffstat (limited to 'lib')
-rw-r--r--lib/diameter/include/diameter_gen.hrl15
1 files changed, 11 insertions, 4 deletions
diff --git a/lib/diameter/include/diameter_gen.hrl b/lib/diameter/include/diameter_gen.hrl
index 49287b3f70..8916286275 100644
--- a/lib/diameter/include/diameter_gen.hrl
+++ b/lib/diameter/include/diameter_gen.hrl
@@ -323,12 +323,19 @@ d(Name, Avp, Acc) ->
%% decode is packed into 'AVP'.
Mod = dict(Failed), %% Dictionary to decode in.
+ %% On decode, a Grouped AVP is represented as a #diameter_avp{}
+ %% list with AVP as head and component AVPs as tail. On encode,
+ %% data can be a list of component AVPs.
+
try Mod:avp(decode, Data, AvpName) of
V ->
{Avps, T} = Acc,
{H, A} = ungroup(V, Avp),
{[H | Avps], pack_avp(Name, A, T)}
catch
+ throw: {?TAG, {grouped, RC, ComponentAvps}} ->
+ {Avps, {Rec, Failed}} = Acc,
+ {[[Avp | ComponentAvps] | Avps], {Rec, [{RC, Avp} | Failed]}};
error: Reason ->
d(undefined == Failed orelse is_failed(),
Reason,
@@ -599,11 +606,11 @@ value(_, Avp) ->
| no_return().
grouped_avp(decode, Name, Data) ->
- {Rec, Avps, []} = decode_avps(Name, diameter_codec:collect_avps(Data)),
+ {Rec, Avps, Es} = decode_avps(Name, diameter_codec:collect_avps(Data)),
+ [] == Es orelse throw({?TAG, {grouped, 5004, Avps}}), %% decode failure
{Rec, Avps};
-%% A failed match here will result in 5004. Note that this is the only
-%% AVP type that doesn't just return the decoded record, also
-%% returning the list of component AVP's.
+%% Note that this is the only AVP type that doesn't just return the
+%% decoded record, also returning the list of component AVP's.
grouped_avp(encode, Name, Data) ->
encode_avps(Name, Data).