aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnders Svensson <[email protected]>2017-08-30 18:04:04 +0200
committerAnders Svensson <[email protected]>2017-08-31 11:51:47 +0200
commitee62825c1ca752f401662529af7fe8fe247c2165 (patch)
tree99fef0fb4fb8f6b6c8c1f8a9645f63577f280427
parentff4a0956d132c3af002bfbe5d48f18e492d3763f (diff)
downloadotp-ee62825c1ca752f401662529af7fe8fe247c2165.tar.gz
otp-ee62825c1ca752f401662529af7fe8fe247c2165.tar.bz2
otp-ee62825c1ca752f401662529af7fe8fe247c2165.zip
Fix extraction of Experimental-Result for counter keys
The introduction of decode_format in commit 722fa415 (and then 55e65b26) meant the value was not necessarily the intended tuple.
-rw-r--r--lib/diameter/src/base/diameter_traffic.erl67
1 files changed, 44 insertions, 23 deletions
diff --git a/lib/diameter/src/base/diameter_traffic.erl b/lib/diameter/src/base/diameter_traffic.erl
index 27a41d6eb0..4388175c3a 100644
--- a/lib/diameter/src/base/diameter_traffic.erl
+++ b/lib/diameter/src/base/diameter_traffic.erl
@@ -1891,16 +1891,12 @@ str(T) ->
%% get_avp/3
%%
-%% Find an AVP in a message of one of three forms:
-%%
-%% - a message record (as generated from a .dia spec) or
-%% - a list of an atom message name followed by 2-tuple, avp name/value pairs.
-%% - a list of a #diameter_header{} followed by #diameter_avp{} records,
-%%
-%% In the first two forms a dictionary module is used at encode to
-%% identify the type of the AVP and its arity in the message in
-%% question. The third form allows messages to be sent as is, without
-%% a dictionary, which is needed in the case of relay agents, for one.
+%% Find an AVP in a message in one of the decoded formats, or as a
+%% header/avps list. There are only four AVPs that are extracted here:
+%% Result-Code and Experimental-Result in order when constructing
+%% counter keys, and Destination-Host/Realm when selecting a next-hop
+%% peer. Experimental-Result is the only of type Grouped, and is given
+%% special treatment in order to return the value as a record.
%% Messages will be header/avps list as a relay and the only AVP's we
%% look for are in the common dictionary. This is required since the
@@ -1909,12 +1905,12 @@ str(T) ->
get_avp(?RELAY, Name, Msg) ->
get_avp(?BASE, Name, Msg);
-%% Message is a header/avps list.
+%% Message as header/avps list.
get_avp(Dict, Name, [#diameter_header{} | Avps]) ->
try
- {Code, _, VId} = Dict:avp_header(Name),
- A = find_avp(Code, VId, Avps),
- (avp_decode(Dict, Name, ungroup(A)))#diameter_avp{name = Name}
+ {Code, _, Vid} = Dict:avp_header(Name),
+ A = find_avp(Code, Vid, Avps),
+ avp_decode(Dict, Name, ungroup(A))
catch
error: _ ->
undefined
@@ -1924,20 +1920,33 @@ get_avp(Dict, Name, [#diameter_header{} | Avps]) ->
get_avp(_, Name, [_MsgName | Avps]) ->
case find(Name, Avps) of
{_, V} ->
- #diameter_avp{name = Name, value = V};
+ #diameter_avp{name = Name, value = value(Name, V)};
_ ->
undefined
end;
-%% ... or record (but not necessarily).
+%% ... or record.
get_avp(Dict, Name, Rec) ->
- try
- #diameter_avp{name = Name, value = Dict:'#get-'(Name, Rec)}
+ try Dict:'#get-'(Name, Rec) of
+ V ->
+ #diameter_avp{name = Name, value = value(Name, V)}
catch
error:_ ->
undefined
end.
+value('Experimental-Result' = N, #{'Vendor-Id' := Vid,
+ 'Experimental-Result-Code' := RC}) ->
+ {N, Vid, RC};
+value('Experimental-Result' = N, [{'Experimental-Result-Code', RC},
+ {'Vendor-Id', Vid}]) ->
+ {N, Vid, RC};
+value('Experimental-Result' = N, [{'Vendor-Id', Vid},
+ {'Experimental-Result-Code', RC}]) ->
+ {N, Vid, RC};
+value(_, V) ->
+ V.
+
%% find/2
find(Key, Map)
@@ -1967,14 +1976,25 @@ ungroup(Avp) ->
%% avp_decode/3
-avp_decode(Dict, Name, #diameter_avp{value = undefined,
+%% Ensure Experimental-Result is decoded as record, since this format
+%% is used for counter keys.
+avp_decode(Dict, 'Experimental-Result' = N, #diameter_avp{data = Bin}
+ = Avp)
+ when is_binary(Bin) ->
+ {V,_} = Dict:avp(decode, Bin, N, decode_opts(Dict)),
+ Avp#diameter_avp{name = N, value = V};
+
+avp_decode(Dict, Name, #diameter_avp{value = X,
data = Bin}
= Avp)
- when is_binary(Bin) ->
+ when is_binary(Bin), X == undefined orelse X == false ->
V = Dict:avp(decode, Bin, Name, decode_opts(Dict)),
- Avp#diameter_avp{value = V};
-avp_decode(_, _, #diameter_avp{} = Avp) ->
- Avp.
+ Avp#diameter_avp{name = Name, value = V};
+
+avp_decode(_, Name, #diameter_avp{} = Avp) ->
+ Avp#diameter_avp{name = Name}.
+
+%% cb/3
cb(#diameter_app{module = [_|_] = M}, F, A) ->
eval(M, F, A).
@@ -1991,4 +2011,5 @@ decode_opts(Dict) ->
string_decode => false,
strict_mbit => false,
failed_avp => false,
+ module => Dict,
dictionary => Dict}.