📄 megaco_text_mini_parser.hrl
字号:
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%%%----------------------------------------------------------------------%% Purpose : Define semantic text parser actions%%-----------------------------------------------------------------------include_lib("megaco/include/megaco.hrl").-include_lib("megaco/include/megaco_message_v2.hrl").-include("megaco_text_tokens.hrl").-define(d(F,A), io:format("DBG:"++F++"~n",A)).make_safe_token({_TokenTag, Line, Text}) -> {safeToken, Line, Text}.% ensure_value({safeToken, _Line, Text}) ->% ensure_value(Text);% ensure_value({'QuotedChars', _Line, Text}) ->% ensure_value(Text);% ensure_value(Text) when list(Text) ->% Text. %% BUGBUG: ensure length% %% NAME = ALPHA *63(ALPHA / DIGIT / "_" )% ensure_NAME({_TokenTag, _Line, Text}) ->% Text. %% BUGBUG: ensure length and chars% ensure_requestID({safeToken, _Line, "*"}) ->% ?megaco_all_request_id;% ensure_requestID(RequestId) ->% ensure_uint32(RequestId).% ensure_streamID(StreamId) ->% ensure_uint16(StreamId).ensure_auth_header(SpiToken, SnToken, AdToken) -> Spi = ensure_hex(SpiToken, 8, 8), Sn = ensure_hex(SnToken, 8, 8), Ad = ensure_hex(AdToken, 24, 64), #'AuthenticationHeader'{secParmIndex = Spi, seqNum = Sn, ad = Ad}.%% ContextID = (UINT32 / "*" / "-" / "$")% ensure_contextID({_TokenTag, _Line, Text}) ->% case Text of% "*" -> ?megaco_all_context_id;% "-" -> ?megaco_null_context_id;% "\$" -> ?megaco_choose_context_id;% Int -> ensure_uint32(Int)% end.ensure_domainAddress([{_T, _L, _A} = Addr0], Port) -> Addr = ensure_ip4addr(Addr0), {ip4Address, #'IP4Address'{address = Addr, portNumber = Port}};ensure_domainAddress([colon,colon], Port) -> Addr = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}};ensure_domainAddress(Addr0, Port) -> Addr = ensure_ip6addr(Addr0), {ip6Address, #'IP6Address'{address = Addr, portNumber = Port}}.ensure_ip4addr({TokenTag, Line, Addr}) -> case string:tokens(Addr, [$.]) of [T1, T2, T3, T4] -> A1 = ensure_uint({TokenTag, Line, T1}, 0, 255), A2 = ensure_uint({TokenTag, Line, T2}, 0, 255), A3 = ensure_uint({TokenTag, Line, T3}, 0, 255), A4 = ensure_uint({TokenTag, Line, T4}, 0, 255), [A1, A2, A3, A4]; _ -> return_error(Line, {bad_IP4address, Addr}) end.ensure_ip6addr([colon,colon|T]) -> [H1|T1] = lists:reverse(T), case do_ensure_ip6addr(T1, true, [ensure_hex4_or_ip4addr(H1)], 1) of {true, A} when length(A) == 16 -> A; {true, B} when length(B) < 16 -> lists:duplicate(16 - length(B), 0) ++ B; {true, C} -> throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}}) end;ensure_ip6addr(L) -> case lists:reverse(L) of [colon, colon| T] -> case do_ensure_ip6addr(T, true, [], 1) of {true, A} when length(A) == 16 -> A; {true, B} when length(B) < 16 -> B ++ lists:duplicate(16 - length(B), 0); {true, C} -> throw({error, {?MODULE, {bad_mid_ip6addr_length, C}}}) end; [H|L1] -> % A (last element) could be an ip4 address case do_ensure_ip6addr(L1,false,[ensure_hex4_or_ip4addr(H)],1) of {false, A} when length(A) == 16 -> A; %% allow a pad even if the address is full (i.e. 16) {true, B} when length(B) =< 17 -> do_ensure_ip6addr_padding(B, 0); {Pad, C} -> throw({error, {?MODULE, {bad_mid_ip6addr_length, Pad, C}}}) end end.do_ensure_ip6addr([], Pad, Acc, _) -> {Pad, lists:flatten(Acc)};do_ensure_ip6addr([colon,colon|T], false, Acc, Line) -> do_ensure_ip6addr(T, true, [pad|Acc], Line);do_ensure_ip6addr([colon,colon|T], true, Acc, Line) -> return_error(Line, {bad_mid_duplicate_padding, T, Acc});do_ensure_ip6addr([colon|T], Pad, Acc, Line) -> do_ensure_ip6addr(T, Pad, Acc, Line);do_ensure_ip6addr([{_, Line, _} = A|T], Pad, Acc, _) -> do_ensure_ip6addr(T, Pad, [ensure_hex4(A)|Acc], Line).do_ensure_ip6addr_padding([], _) -> [];do_ensure_ip6addr_padding([pad|T], N) -> lists:duplicate(16 - (N + length(T)), 0) ++ T;do_ensure_ip6addr_padding([H|T], N) -> [H|do_ensure_ip6addr_padding(T, N+1)].ensure_hex4_or_ip4addr({TokenTag, Line, Addr} = V) -> case string:tokens(Addr, [$.]) of [T1, T2, T3, T4] -> A1 = ensure_uint({TokenTag, Line, T1}, 0, 255), A2 = ensure_uint({TokenTag, Line, T2}, 0, 255), A3 = ensure_uint({TokenTag, Line, T3}, 0, 255), A4 = ensure_uint({TokenTag, Line, T4}, 0, 255), [A1, A2, A3, A4]; _ -> ensure_hex4(V) %% %% BMK BMK BMK %% %% Here we should test for hexseq %% return_error(Line, {bad_IP4address, Addr}) end.ensure_hex4({_TokenTag, Line, Hex4}) when length(Hex4) =< 4, length(Hex4) > 0 -> case (catch do_ensure_hex4(Hex4)) of IL when list(IL), length(IL) == 2 -> IL; Error -> return_error(Line, {bad_hex4, Hex4, Error}) end.do_ensure_hex4([_H1, _H2, _H3, _H4] = H) -> hex_to_int(H, []);do_ensure_hex4([H2, H3, H4]) -> hex_to_int([$0, H2, H3, H4], []);do_ensure_hex4([H3, H4]) -> hex_to_int([$0, $0, H3, H4], []);do_ensure_hex4([H4]) -> hex_to_int([$0, $0, $0, H4], []).ensure_domainName({_TokenTag, _Line, Name}, Port) -> %% BUGBUG: validate name {domainName, #'DomainName'{name = Name, portNumber = Port}}.%% extensionParameter= "X" ("-" / "+") 1*6(ALPHA / DIGIT)% ensure_extensionParameter({_TokenTag, Line, Text}) ->% case Text of% [X, S | _Chars] ->% if% X /= $X, X /= $x,% S /= $+, S /= $- ->% return_error(Line, {bad_extension_parameter, Text});% true ->% {extension_parameter, Text}% end;% _ ->% return_error(Line, {bad_extension_parameter, Text})% end.ensure_message(MegacopToken, MID) -> #'ServiceChangeProfile'{profileName = Name, version = Version} = ensure_profile(MegacopToken), case Name of "megaco" -> #'Message'{version = Version, mId = MID}; [$!] -> #'Message'{version = Version, mId = MID} end.%% modemType = (V32bisToken / V22bisToken / V18Token / %% V22Token / V32Token / V34Token / V90Token / %% V91Token / SynchISDNToken / extensionParameter)% ensure_modemType({_TokenTag, _Line, Text} = Token) ->% case Text of% "v32b" -> v32bis;% "v22b" -> v22bis;% "v18" -> v18;% "v22" -> v22;% "v32" -> v32;% "v34" -> v34;% "v90" -> v90;% "v91" -> v91;% "synchisdn" -> synchISDN;% "sn" -> synchISDN;% [$x | _] -> ensure_extensionParameter(Token)% end.%% An mtp address is five octets longensure_mtpAddress({_TokenTag, _Line, Addr}) -> %% BUGBUG: validate address {mtpAddress, Addr}.%% MuxType = ( H221Token / H223Token / H226Token / V76Token / extensionParameter )% ensure_muxType({_TokenTag, _Line, Text} = Token) ->% case Text of% "h221" -> h221;% "h223" -> h223;% "h226" -> h226;% "v76" -> v76;% "nx64k" -> nx64k; % v2% [$x | _] -> ensure_extensionParameter(Token)% end.%% packagesItem = NAME "-" UINT16%% NAME = ALPHA *63(ALPHA / DIGIT / "_" )% ensure_packagesItem({TokenTag, Line, Text}) ->% case string:tokens(Text, [$-]) of% [Name, Version] ->% #'PackagesItem'{packageName = ensure_NAME({TokenTag, Line, Name}),% packageVersion = ensure_uint({TokenTag, Line, Version}, 0, 99)};% _ ->% return_error(Line, {bad_PackagesItem, Text})% end.%% pkgdName = (PackageName / "*") SLASH (ItemID / "*" )%% PackageName = NAME%% ItemID = NAME% ensure_pkgdName({TokenTag, Line, Text}) ->% case string:tokens(Text, [$/]) of% [Name, Item] ->% ensure_name_or_star({TokenTag, Line, Name}),% ensure_name_or_star({TokenTag, Line, Item}),% Text;% _ ->% return_error(Line, {bad_pkgdName, Text})% end.% ensure_name_or_star({_, _, Name}) when Name == "*" ->% Name;% ensure_name_or_star(Name) ->% ensure_NAME(Name).%% v2 - start% merge_indAudMediaDescriptor({termStateDescr, Val}) ->% #'IndAudMediaDescriptor'{termStateDescr = Val};% merge_indAudMediaDescriptor({streamParm, Val}) ->% #'IndAudMediaDescriptor'{streams = {oneStream, Val}};% merge_indAudMediaDescriptor({streamDescr, Val}) ->% #'IndAudMediaDescriptor'{streams = {multiStream, [Val]}}.% merge_indAudLocalControlDescriptor(Parms) ->% do_merge_indAudLocalControlDescriptor(Parms, % #'IndAudLocalControlDescriptor'{}). % do_merge_indAudLocalControlDescriptor([Parm | Parms], Desc) ->% case Parm of% modeToken when Desc#'IndAudLocalControlDescriptor'.streamMode == asn1_NOVALUE ->% Desc2 = Desc#'IndAudLocalControlDescriptor'{streamMode = 'NULL'},% do_merge_indAudLocalControlDescriptor(Parms, Desc2);% reservedGroupToken when Desc#'IndAudLocalControlDescriptor'.reserveGroup == asn1_NOVALUE ->% Desc2 = Desc#'IndAudLocalControlDescriptor'{reserveGroup = 'NULL'},% do_merge_indAudLocalControlDescriptor(Parms, Desc2);% reservedValueToken when Desc#'IndAudLocalControlDescriptor'.reserveValue == asn1_NOVALUE ->% Desc2 = Desc#'IndAudLocalControlDescriptor'{reserveValue = 'NULL'},% do_merge_indAudLocalControlDescriptor(Parms, Desc2);% {pkgdName, Val} when Desc#'IndAudLocalControlDescriptor'.propertyParms == asn1_NOVALUE ->% PropParms = [#'IndAudPropertyParm'{name = Val}],% Desc2 = Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms},% do_merge_indAudLocalControlDescriptor(Parms, Desc2);% {pkgdName, Val} when list(Desc#'IndAudLocalControlDescriptor'.propertyParms) ->% PropParms = Desc#'IndAudLocalControlDescriptor'.propertyParms,% PropParms2 = [#'IndAudPropertyParm'{name = Val} | PropParms],% Desc2 = Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms2},% do_merge_indAudLocalControlDescriptor(Parms, Desc2)% end;% do_merge_indAudLocalControlDescriptor([], Desc) ->% case Desc#'IndAudLocalControlDescriptor'.propertyParms of% [_ | _] = PropParms -> % List has more then one element% PropParms2= lists:reverse(PropParms),% Desc#'IndAudLocalControlDescriptor'{propertyParms = PropParms2};% _ ->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -