I added a test function reproducing the issue:
+foobar() ->
+ State = #s6b_state{tx_timeout = 10000},
+ Imsi = "262422638508077",
+ SessionId = diameter:session_id(application:get_env(?ENV_APP_NAME, dia_s6b_origin_host, ?ENV_DEFAULT_ORIG_HOST)),
+ ASR = #'ASR'{'Session-Id' = SessionId,
+ 'Auth-Application-Id' = ?DIAMETER_APP_ID_S6b,
+ 'User-Name' = Imsi,
+ 'Auth-Session-State' = ?'AUTH-SESSION-STATE_NO_STATE_MAINTAINED'
+ },
+ lager:debug("S6b Tx ASR: ~p~n", [ASR]),
+ Ret = diameter_call(ASR, State),
+ ok = Ret.
I traced the problem by using the following commands in the shell:
erlang:trace(all, true, [call]).
erlang:trace_pattern({aaa_diameter_s6b, 'foobar', '_'}, true, [local]).
erlang:trace_pattern({aaa_diameter_s6b, '_', '_'}, [{'_', [], [{return_trace}]}], [local]).
erlang:trace_pattern({diameter, '_', '_'}, true, [local]).
erlang:trace_pattern({diameter, '_', '_'}, [{'_', [], [{return_trace}]}], [local]).
erlang:trace_pattern({diameter_codec, '_', '_'}, true, [local]).
erlang:trace_pattern({diameter_codec, '_', '_'}, [{'_', [], [{return_trace}]}], [local]).
erlang:trace_pattern({diameter_traffic, '_', '_'}, true, [local]).
erlang:trace_pattern({diameter_traffic, '_', '_'}, [{'_', [], [{return_trace}]}], [local]).
erlang:trace_pattern({diameter_types, 'UTF8String', '_'}, true, [local]).
erlang:trace_pattern({diameter_types, 'UTF8String', '_'}, [{'_', [], [{return_trace}]}], [local]).
erlang:trace_pattern({diameter_gen, 'enc1', '_'}, true, [local]).
erlang:trace_pattern({diameter_gen, 'enc1', '_'}, [{'_', [], [{return_trace}]}], [local]).
spawn(fun() -> aaa_diameter_s6b:foobar() end).
Then I use "flush()." to see the output of the trace.
Interesting parts here:
Shell got {trace,<0.546.0>,call,
{diameter_gen,enc1,
['User-Name',
{1,64,undefined},
50,
#{decode_format => record,
incoming_maxlen => 16777215,
module => diameter_3gpp_ts29_273_s6b,
restrict_connections => nodes,
sequence => {0,32},
share_peers => false,spawn_opt => [],
strict_mbit => true,string_decode => true,
traffic_counters => true,
use_shared_peers => false},
diameter_3gpp_ts29_273_s6b]}}
Shell got {trace,<0.546.0>,call,
{diameter_types,'UTF8String',
[encode,50,
#{decode_format => record,
incoming_maxlen => 16777215,
module => diameter_gen_base_rfc6733,
restrict_connections => nodes,
sequence => {0,32},
share_peers => false,spawn_opt => [],
strict_mbit => true,string_decode => true,
traffic_counters => true,
use_shared_peers => false}]}}
Shell got {trace,<0.546.0>,call,
{diameter_traffic,incr_error,
[send,
{{encode_failure,badarg,'ASR',
[{unicode,characters_to_binary,"2",
[{file,"unicode.erl"},
{line,895},
{error_info,#{module => erl_stdlib_errors}}]},
{diameter_types,'UTF8String',3,
[{file,"base/diameter_types.erl"},{line,363}]},
{diameter_gen,enc1,5,
[{file,"base/diameter_gen.erl"},{line,189}]},
{diameter_gen,enc,9,
[{file,"base/diameter_gen.erl"},{line,167}]},
{diameter_gen,'-encode/5-lc$^3/1-3-',5,
[{file,"base/diameter_gen.erl"},{line,106}]},
{diameter_gen,'-encode/5-lc$^3/1-3-',5,
[{file,"base/diameter_gen.erl"},{line,106}]},
{diameter_gen,encode_avps,3,
[{file,"base/diameter_gen.erl"},{line,71}]},
{diameter_codec,enc,3,
[{file,"base/diameter_codec.erl"},{line,161}]}]},
[{diameter_gen,encode_avps,3,
[{file,"base/diameter_gen.erl"},{line,84}]},
{diameter_codec,enc,3,
[{file,"base/diameter_codec.erl"},{line,161}]},
{diameter_codec,encode,3,
[{file,"base/diameter_codec.erl"},{line,88}]},
{diameter_traffic,encode,4,
[{file,"base/diameter_traffic.erl"},{line,1823}]},
{diameter_traffic,send_request,6,
[{file,"base/diameter_traffic.erl"},{line,1459}]},
{diameter_traffic,'-send_request/4-fun-0-',6,
[{file,"base/diameter_traffic.erl"},{line,1342}]}],
{diameter_header,1,undefined,274,16777272,3213723902,
3213723902,true,true,false,false}},
<0.508.0>,diameter_3gpp_ts29_273_s6b]}}
Fixed with:
diff --git a/src/aaa_diameter_s6b.erl b/src/aaa_diameter_s6b.erl
index c9afc37..94b4aea 100644
--- a/src/aaa_diameter_s6b.erl
+++ b/src/aaa_diameter_s6b.erl
@@ -146,8 +148,8 @@ handle_call({asr, Imsi}, _From, State) ->
SessionId = diameter:session_id(application:get_env(?ENV_APP_NAME, dia_s6b_origin_host, ?ENV_DEFAULT_ORIG_HOST)),
ASR = #'ASR'{'Session-Id' = SessionId,
'Auth-Application-Id' = ?DIAMETER_APP_ID_S6b,
- 'User-Name' = Imsi,
- 'Auth-Session-State' = ?'AUTH-SESSION-STATE_NO_STATE_MAINTAINED'
+ 'User-Name' = [Imsi],
+ 'Auth-Session-State' = [?'AUTH-SESSION-STATE_NO_STATE_MAINTAINED']
So it seems if I don't pass Imsi inside the "optional" array, then since Imsi itself is an aray of characters, the string is discarded and the first character taken instead of the full string. Then "diameter_types:'UTF8String'()" fails to convert an integer/character to binary.