From 1a064fa6aece492352271ae164b29262d66f6b6d Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Mon, 22 Jan 2024 17:41:30 +0100 Subject: [PATCH] Decode/Encode Apn as string Change-Id: I1206e31272f03853aa8447fb263fff7757282b83 --- include/gsup_protocol.hrl | 2 +- src/apn_encdec.erl | 51 ++++++++++++++++++++++++++++++++ src/gsup_protocol.erl | 7 +++-- test/gsup_encode_decode_test.erl | 5 ++-- 4 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 src/apn_encdec.erl diff --git a/include/gsup_protocol.hrl b/include/gsup_protocol.hrl index 3082521..1c755ac 100644 --- a/include/gsup_protocol.hrl +++ b/include/gsup_protocol.hrl @@ -81,7 +81,7 @@ -type 'GSUPPdpInfo'() :: #{ pdp_context_id => integer(), pdp_address => 'GSUPPdpAddress'(), - access_point_name => binary(), + access_point_name => string(), quality_of_service => binary(), pdp_charging => integer() }. diff --git a/src/apn_encdec.erl b/src/apn_encdec.erl new file mode 100644 index 0000000..60a5ede --- /dev/null +++ b/src/apn_encdec.erl @@ -0,0 +1,51 @@ + +-module(apn_encdec). + +% decode APN Name Encoded Format +% TS 23.003 APN +-export([decode_apn/1, encode_apn/1]). + +decode_apn(ApnEnc) -> + decode_apn("", ApnEnc, 0). + +decode_apn(Result, [], 0) -> + Result; + +decode_apn(Result, << >>, 0) -> + Result; + +decode_apn("", ApnEnc, 0) -> + << NewElemLen:8, RemainEnc/bytes >> = ApnEnc, + case NewElemLen of + 0 -> ""; + _ -> decode_apn("", RemainEnc, NewElemLen) + end; + +decode_apn(Result, ApnEnc, 0) -> + << NewElemLen:8, RemainEnc/bytes >> = ApnEnc, + case NewElemLen of + 0 -> Result; + _ -> decode_apn(Result ++ ".", RemainEnc, NewElemLen) + end; + +decode_apn(Result, ApnEnc, RemainLen) when RemainLen > 0 -> + << Char:8, RemainEnc/bytes >> = ApnEnc, + decode_apn(Result ++ [Char], RemainEnc, RemainLen - 1). + +encode_apn(ApnStr) -> + encode_apn(<<>>, ApnStr, "", 0). + +encode_apn(ApnEnc, "", "", 0) -> + ApnEnc; + +encode_apn(ApnEnc, "", CurStr, Len) -> + CurBin = binary:list_to_bin(CurStr), + Result = << ApnEnc/binary, Len, CurBin/binary >>, + Result; + +encode_apn(ApnEnc, [ Char | RemainStr ], CurStr, Len) -> + case Char of + 46 -> CurBin = binary:list_to_bin(CurStr), + encode_apn(<>, RemainStr, "", 0); + _ -> encode_apn(ApnEnc, RemainStr, CurStr ++ [Char], Len + 1) + end. diff --git a/src/gsup_protocol.erl b/src/gsup_protocol.erl index 1dcc628..1aea289 100644 --- a/src/gsup_protocol.erl +++ b/src/gsup_protocol.erl @@ -267,7 +267,7 @@ decode_pdp_info(<>, Map) decode_pdp_info(<>, Map) -> ?CHECK_LEN(access_point_name, Len, 1, 100), - decode_pdp_info(Tail, Map#{access_point_name => APN}); + decode_pdp_info(Tail, Map#{access_point_name => apn_encdec:decode_apn(APN)}); decode_pdp_info(<>, Map) -> ?CHECK_LEN(quality_of_service, Len, 1, 20), @@ -620,9 +620,10 @@ encode_pdp_info(#{pdp_address := Value} = Map, Head) -> encode_pdp_info(maps:without([pdp_address], Map), <>); encode_pdp_info(#{access_point_name := Value} = Map, Head) -> - Len = size(Value), + ApnBin = apn_encdec:encode_apn(Value), + Len = size(ApnBin), ?CHECK_LEN(access_point_name, Len, 1, 100), - encode_pdp_info(maps:without([access_point_name], Map), <>); + encode_pdp_info(maps:without([access_point_name], Map), <>); encode_pdp_info(#{quality_of_service := Value} = Map, Head) -> Len = size(Value), diff --git a/test/gsup_encode_decode_test.erl b/test/gsup_encode_decode_test.erl index c80abdc..0637160 100644 --- a/test/gsup_encode_decode_test.erl +++ b/test/gsup_encode_decode_test.erl @@ -217,14 +217,13 @@ lu_res_test() -> msisdn => <<145,148,97,70,50,36,67>>, pdp_charging => 44799,pdp_info_complete => true, pdp_info_list => - [#{access_point_name => - <<4,116,101,115,116,3,97,112,110>>, + [#{access_point_name => "test.apn", pdp_charging => 65315,pdp_context_id => 1, pdp_address => #{address => #{}, pdp_type_org => 241, pdp_type_nr => 33}, quality_of_service => <<2>>}, - #{access_point_name => <<3,102,111,111,3,97,112,110>>, + #{access_point_name => "foo.apn", pdp_context_id => 2, pdp_address => #{address => #{}, pdp_type_org => 241,