aboutsummaryrefslogtreecommitdiffstats
path: root/lib/megaco/src/text/megaco_text_gen_v2.hrl
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/megaco/src/text/megaco_text_gen_v2.hrl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/megaco/src/text/megaco_text_gen_v2.hrl')
-rw-r--r--lib/megaco/src/text/megaco_text_gen_v2.hrl2794
1 files changed, 2794 insertions, 0 deletions
diff --git a/lib/megaco/src/text/megaco_text_gen_v2.hrl b/lib/megaco/src/text/megaco_text_gen_v2.hrl
new file mode 100644
index 0000000000..6cfcac8664
--- /dev/null
+++ b/lib/megaco/src/text/megaco_text_gen_v2.hrl
@@ -0,0 +1,2794 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
+%%
+%% 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 online 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%% Purpose: Encode V2 Megaco/H.248 text messages from internal form
+%% The following was changed:
+%% - MuxType (Nx64kToken)
+%% - auditItem (terminationAudit)
+%% - serviceChangeParm (auditItem)
+%%
+%% The following was added:
+%% - All IndAud stuff
+%%----------------------------------------------------------------------
+
+%% -define(d(F,A), io:format("~w:" ++ F ++ "~n", [?MODULE|A])).
+
+-define(META_ENC(Type, Item), Item) .
+%% -define(META_ENC(Type, Item), megaco_meta_package:encode(text, Type, Item)).
+%% -define(META_DEC(Type, Item), megaco_meta_package:decode(text, Type, Item)).
+
+enc_MegacoMessage(Val) ->
+ State = ?INIT_INDENT,
+ enc_MegacoMessage(Val, State).
+
+enc_MegacoMessage(#'MegacoMessage'{authHeader = asn1_NOVALUE,
+ mess = Mess}, State) ->
+ [
+ ?LWSP,
+ enc_Message(Mess, State)
+ ];
+enc_MegacoMessage(#'MegacoMessage'{authHeader = Auth,
+ mess = Mess}, State) ->
+ [
+ ?LWSP,
+ enc_AuthenticationHeader(Auth, State),
+ enc_Message(Mess, State)
+ ].
+
+%% Note that encoding the transaction this way
+%% make the message look a bit strange.
+enc_Transaction(Val) ->
+ State = ?INIT_INDENT,
+ enc_Transaction(Val, State).
+
+%% Note that encoding the action request's this way
+%% make the message look a bit strange.
+enc_ActionRequests(Val) ->
+ State = ?INIT_INDENT,
+ enc_TransactionRequest_actions(Val, State).
+
+%% Note that encoding the action request this way
+%% make the message look a bit strange.
+enc_ActionRequest(Val) ->
+ State = ?INIT_INDENT,
+ enc_ActionRequest(Val, State).
+
+enc_CommandRequest(Val) ->
+ State = ?INIT_INDENT,
+ enc_CommandRequest(Val, State).
+
+enc_ActionReply(Val) ->
+ State = ?INIT_INDENT,
+ enc_ActionReply(Val, State).
+
+enc_AuthenticationHeader(asn1_NOVALUE, _State) ->
+ [];
+enc_AuthenticationHeader(Val, State)
+ when is_record(Val, 'AuthenticationHeader') ->
+ [
+ ?AuthToken,
+ ?EQUAL,
+ enc_SecurityParmIndex(Val#'AuthenticationHeader'.secParmIndex, State),
+ ?COLON,
+ enc_SequenceNum(Val#'AuthenticationHeader'.seqNum, State),
+ ?COLON,
+ enc_AuthData(Val#'AuthenticationHeader'.ad, State),
+ ?SEP_INDENT(State)
+ ].
+
+enc_SecurityParmIndex({'SecurityParmIndex',Val}, State) ->
+ enc_SecurityParmIndex(Val, State);
+enc_SecurityParmIndex(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 8, 8)
+ ].
+
+enc_SequenceNum({'SequenceNum',Val}, State) ->
+ enc_SequenceNum(Val, State);
+enc_SequenceNum(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 8, 8)
+ ].
+
+enc_AuthData({'AuthData',Val}, State) ->
+ enc_AuthData(Val, State);
+enc_AuthData(Val, State) ->
+ [
+ "0x",
+ enc_HEXDIG(Val, State, 24, 64) %% OTP-4710
+ ].
+
+enc_Message(Val, State)
+ when is_record(Val, 'Message') ->
+ [
+ ?MegacopToken,
+ ?SLASH,
+ enc_version(Val#'Message'.version, State),
+ ?SEP,
+ enc_MId(Val#'Message'.mId, State),
+ ?SEP_INDENT(State),
+ enc_Message_messageBody(Val#'Message'.messageBody, State)
+ ].
+
+enc_version(Val, State) when is_integer(Val) andalso (Val >= 0) ->
+ enc_DIGIT(Val, State, 0, 99).
+
+enc_Message_messageBody({'Message_messageBody',Val}, State) ->
+ enc_Message_messageBody(Val, State);
+enc_Message_messageBody({Tag, Val}, State) ->
+ case Tag of
+ messageError ->
+ enc_ErrorDescriptor(Val, State);
+ transactions ->
+ enc_Message_messageBody_transactions(Val, State);
+ _ ->
+ error({invalid_messageBody_tag, Tag})
+ end.
+
+enc_Message_messageBody_transactions({'Message_messageBody_transactions',Val},
+ State) ->
+ enc_Message_messageBody_transactions(Val, State);
+enc_Message_messageBody_transactions(Val, State)
+ when is_list(Val) andalso (Val =/= []) ->
+ [enc_Transaction(T, State) || T <- Val].
+
+enc_MId({'MId',Val}, State) ->
+ enc_MId(Val, State);
+enc_MId({Tag, Val}, State) ->
+ case Tag of
+ ip4Address ->
+ enc_IP4Address(Val, State);
+ ip6Address ->
+ enc_IP6Address(Val, State);
+ domainName ->
+ enc_DomainName(Val, State);
+ deviceName ->
+ enc_PathName(Val, State);
+ mtpAddress ->
+ enc_mtpAddress(Val, State);
+ _ ->
+ error({invalid_MId_tag, Tag})
+ end.
+
+enc_mtpAddress(Val, State) ->
+ [
+ ?MtpToken,
+ ?LBRKT,
+ enc_OCTET_STRING(Val, State, 2, 4),
+ ?RBRKT
+ ].
+
+enc_DomainName(#'DomainName'{portNumber = asn1_NOVALUE,
+ name = Name}, State) ->
+ [
+ $<,
+ %% BUGBUG: (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" / ".")
+ enc_STRING(Name, State, 1, 64),
+ $>
+ ];
+enc_DomainName(#'DomainName'{portNumber = PortNumber,
+ name = Name}, State) ->
+ [
+ $<,
+ %% BUGBUG: (ALPHA / DIGIT) *63(ALPHA / DIGIT / "-" / ".")
+ enc_STRING(Name, State, 1, 64),
+ $>,
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_IP4Address(#'IP4Address'{portNumber = asn1_NOVALUE,
+ address = [A1, A2, A3, A4]}, State) ->
+ [
+ $[,
+ enc_V4hex(A1, State),
+ ?DOT,
+ enc_V4hex(A2, State),
+ ?DOT,
+ enc_V4hex(A3, State),
+ ?DOT,
+ enc_V4hex(A4, State),
+ $]
+ ];
+enc_IP4Address(#'IP4Address'{portNumber = PortNumber,
+ address = [A1, A2, A3, A4]}, State) ->
+ [
+ $[,
+ enc_V4hex(A1, State),
+ ?DOT,
+ enc_V4hex(A2, State),
+ ?DOT,
+ enc_V4hex(A3, State),
+ ?DOT,
+ enc_V4hex(A4, State),
+ $],
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_V4hex(Val, State) ->
+ enc_DIGIT(Val, State, 0, 255).
+
+enc_IP6Address(#'IP6Address'{portNumber = asn1_NOVALUE,
+ address = Addr}, State)
+ when is_list(Addr) andalso (length(Addr) == 16) ->
+ [
+ $[,
+ enc_IP6Address_address(Addr, State),
+ $]
+ ];
+enc_IP6Address(#'IP6Address'{portNumber = PortNumber,
+ address = Addr}, State)
+ when is_list(Addr) andalso (length(Addr) =:= 16) ->
+ [
+ $[,
+ enc_IP6Address_address(Addr, State),
+ $],
+ $:,
+ enc_portNumber(PortNumber, State)
+ ].
+
+enc_IP6Address_address([0, 0|Addr], State) ->
+ enc_IP6Address_address2(Addr, 1, false, true, State);
+enc_IP6Address_address(Addr, State) ->
+ enc_IP6Address_address2(Addr, 0, false, false, State).
+
+enc_IP6Address_address2([0,0], 0, _Padding, _First, _State) ->
+ [$0];
+enc_IP6Address_address2([0,0], PadN, false, true, _State) when PadN > 0 ->
+ [$:, $:]; % Padding from the beginning (all zero's)
+enc_IP6Address_address2([0,0], PadN, false, false, _State) when PadN > 0 ->
+ [$:]; % Padding in the middle or end
+enc_IP6Address_address2([0,0], _, true, _First, _State) ->
+ [$0];
+enc_IP6Address_address2([N1,N2], 0, _Padding, _First, State) ->
+ [enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], 1, _Padding, _First, State) ->
+ [$0, $:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], PadN, false, true, State) when PadN > 1 ->
+ [$:, $:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], PadN, false, false, State) when PadN > 1 ->
+ [$:, enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([N1,N2], _PadN, true, _First, State) ->
+ [enc_hex4([N1, N2], State)];
+enc_IP6Address_address2([0, 0|Ns], PadN, false, First, State) ->
+ enc_IP6Address_address2(Ns, PadN+1, false, First, State);
+enc_IP6Address_address2([0, 0|Ns], _PadN, true, _First, State) ->
+ [
+ $0,
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], 0, Padded, _First, State) ->
+ [
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, Padded, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], 1, Padded, _First, State) ->
+ [
+ $0,
+ $:,
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, Padded, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], PadN, false, true, State) when PadN > 1 ->
+ %% Padding from the beginning
+ [
+ $:,
+ $:,
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], PadN, false, false, State)
+ when PadN > 1 ->
+ [
+ $:, %% The other ':' has already added
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ];
+enc_IP6Address_address2([N1, N2|Ns], _PadN, true, _First, State) ->
+ [
+ enc_hex4([N1, N2], State),
+ $:,
+ enc_IP6Address_address2(Ns, 0, true, false, State)
+ ].
+
+
+enc_hex4([0,0], _State) ->
+ $0;
+enc_hex4([0,N], _State) ->
+ hex(N);
+enc_hex4([N1, N2], _State) when N2 =< 15 ->
+ [hex(N1), $0, hex(N2)];
+enc_hex4([N1, N2], _State) ->
+ [hex(N1), hex(N2)].
+
+enc_PathName({'PathName',Val}, State) ->
+ enc_PathName(Val, State);
+enc_PathName(Val, State) ->
+ %% BUGBUG: ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+ %% BUGBUG: ["@" pathDomainName ]
+ enc_STRING(Val, State, 1, 64).
+
+enc_Transaction(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_Transaction({'Transaction',Val}, State) ->
+ enc_Transaction(Val, State);
+enc_Transaction({Tag, Val}, State) ->
+ case Tag of
+ transactionRequest ->
+ enc_TransactionRequest(Val, State);
+ transactionPending ->
+ enc_TransactionPending(Val, State);
+ transactionReply ->
+ enc_TransactionReply(Val, State);
+ transactionResponseAck ->
+ enc_TransactionResponseAck(Val, State);
+ _ ->
+ error({invalid_Transaction_tag, Tag})
+ end.
+
+enc_TransactionResponseAck([Mand], State) ->
+ [
+ ?ResponseAckToken,
+ ?LBRKT_INDENT(State),
+ [enc_TransactionAck(Mand, State)],
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionResponseAck([Mand | Opt], State) ->
+ [
+ ?ResponseAckToken,
+ ?LBRKT_INDENT(State),
+ [enc_TransactionAck(Mand, State) |
+ [[?COMMA_INDENT(State), enc_TransactionAck(Val, State)] || Val <- Opt]],
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_TransactionAck(Val, State)
+ when is_record(Val, 'TransactionAck') ->
+ [
+ enc_TransactionId(Val#'TransactionAck'.firstAck, ?INC_INDENT(State)),
+ case Val#'TransactionAck'.lastAck of
+ asn1_NOVALUE ->
+ [];
+ LastAck ->
+ ["-",enc_TransactionId(LastAck, State)]
+ end
+ ].
+
+enc_TransactionId({'TransactionId',Val}, State) ->
+ enc_TransactionId(Val, State);
+enc_TransactionId(Val, State) ->
+ enc_UINT32(Val, State).
+
+enc_TransactionRequest(#'TransactionRequest'{transactionId = Tid,
+ actions = Acts}, State) ->
+ [
+ ?TransToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_TransactionRequest_actions(Acts, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionRequest(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_TransactionRequest_actions(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_TransactionRequest_actions({'TransactionRequest_actions',Val}, State) ->
+ enc_TransactionRequest_actions(Val, State);
+enc_TransactionRequest_actions([Mand], State) ->
+ [enc_ActionRequest(Mand, State)];
+enc_TransactionRequest_actions([Mand | Opt], State) ->
+ [enc_ActionRequest(Mand, State) |
+ [[?COMMA_INDENT(State), enc_ActionRequest(Val, State)] || Val <- Opt]].
+
+enc_TransactionPending(#'TransactionPending'{transactionId = Tid}, State) ->
+ [?PendingToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionPending(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_TransactionReply(#'TransactionReply'{transactionId = Tid,
+ immAckRequired = asn1_NOVALUE,
+ transactionResult = Res},
+ State) ->
+ [
+ ?ReplyToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_TransactionReply_transactionResult(Res, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionReply(#'TransactionReply'{transactionId = Tid,
+ immAckRequired = Req,
+ transactionResult = Res}, State) ->
+ [
+ ?ReplyToken,
+ ?EQUAL,
+ enc_TransactionId(Tid, State),
+ ?LBRKT_INDENT(State),
+ enc_immAckRequired(Req, State),
+ enc_TransactionReply_transactionResult(Res, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TransactionReply(Bin, _State) when is_binary(Bin) ->
+ [Bin].
+
+enc_immAckRequired(Val, _State) ->
+ case Val of
+ asn1_NOVALUE ->
+ [];
+ 'NULL' ->
+ [?ImmAckRequiredToken, ?COMMA_INDENT(?INC_INDENT(_State))]
+ end.
+
+enc_TransactionReply_transactionResult({'TransactionReply_transactionResult',
+ Val}, State) ->
+ enc_TransactionReply_transactionResult(Val, State);
+enc_TransactionReply_transactionResult({Tag, Val}, State) ->
+ case Tag of
+ transactionError ->
+ enc_ErrorDescriptor(Val, State);
+ actionReplies ->
+ enc_TransactionReply_transactionResult_actionReplies(Val, State);
+ _ ->
+ error({invalid_TransactionReply_transactionResult_tag, Tag})
+ end.
+
+enc_TransactionReply_transactionResult_actionReplies({'TransactionReply_transactionResult_actionReplies',Val}, State) ->
+ enc_TransactionReply_transactionResult_actionReplies(Val, State);
+enc_TransactionReply_transactionResult_actionReplies([Mand], State) ->
+ [enc_ActionReply(Mand, State)];
+enc_TransactionReply_transactionResult_actionReplies([Mand | Opt], State) ->
+ [enc_ActionReply(Mand, State),
+ [[?COMMA_INDENT(State), enc_ActionReply(Val, State)] || Val <- Opt]].
+
+enc_ErrorDescriptor(#'ErrorDescriptor'{errorText = asn1_NOVALUE,
+ errorCode = Code}, State) ->
+ [
+ ?ErrorToken,
+ ?EQUAL,
+ enc_ErrorCode(Code, State),
+ ?LBRKT,
+ ?RBRKT
+ ];
+enc_ErrorDescriptor(#'ErrorDescriptor'{errorText = Text,
+ errorCode = Code}, State) ->
+ [
+ ?ErrorToken,
+ ?EQUAL,
+ enc_ErrorCode(Code, State),
+ ?LBRKT,
+ enc_ErrorText(Text, State),
+ ?RBRKT
+ ].
+
+enc_ErrorCode({'ErrorCode',Val}, State)->
+ enc_ErrorCode(Val, State);
+enc_ErrorCode(Val, State) ->
+ enc_DIGIT(Val, State, 0, 999).
+
+enc_ErrorText({'ErrorText',Val}, State) ->
+ enc_ErrorText(Val, State);
+enc_ErrorText(Val, State) ->
+ enc_QUOTED_STRING(Val, State).
+
+enc_ContextID({'ContextID',Val}, State) ->
+ enc_ContextID(Val, State);
+enc_ContextID(Val, State) ->
+ case Val of
+ ?megaco_all_context_id -> $*;
+ ?megaco_null_context_id -> $-;
+ ?megaco_choose_context_id -> $$;
+ Int when is_integer(Int) -> enc_UINT32(Int, State)
+ end.
+
+enc_ActionRequest(Bin, _State) when is_binary(Bin) ->
+ [Bin]; %% Already encoded...
+enc_ActionRequest(Val, State)
+ when is_record(Val, 'ActionRequest') ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(Val#'ActionRequest'.contextId, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'ActionRequest'.contextAttrAuditReq],
+ fun enc_ContextAttrAuditRequest/2}] ++
+ decompose_ContextRequest(Val#'ActionRequest'.contextRequest) ++
+ [{Val#'ActionRequest'.commandRequests,
+ fun enc_CommandRequest/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% OTP-5085
+enc_ActionReply(#'ActionReply'{contextId = Id,
+ errorDescriptor = ED,
+ contextReply = CtxRep,
+ commandReply = CmdRep},
+ State) ->
+ [
+ ?CtxToken,
+ ?EQUAL,
+ enc_ContextID(Id, State),
+ ?LBRKT_INDENT(State),
+ do_enc_ActionReply(ED, CtxRep, CmdRep, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+do_enc_ActionReply(asn1_NOVALUE, CtxRep, CmdRep, State)
+ when (CtxRep =/= asn1_NOVALUE) orelse (CmdRep =/= []) ->
+ [
+ enc_list(decompose_ContextRequest(CtxRep) ++
+ [{CmdRep, fun enc_CommandReply/2}],
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, CtxRep, CmdRep, State)
+ when (CtxRep =/= asn1_NOVALUE) orelse (CmdRep =/= []) ->
+ [
+ enc_list(decompose_ContextRequest(CtxRep) ++
+ [{CmdRep, fun enc_CommandReply/2},
+ {[ED], fun enc_ErrorDescriptor/2}], % Indention cosmetics
+ ?INC_INDENT(State))
+ ];
+do_enc_ActionReply(ED, asn1_NOVALUE, [], State)
+ when (ED =/= asn1_NOVALUE) ->
+ [
+ enc_ErrorDescriptor(ED, ?INC_INDENT(State))
+ ].
+
+
+decompose_ContextRequest(asn1_NOVALUE) ->
+ [{[], dummy}] ;
+decompose_ContextRequest(Val)
+ when is_record(Val, 'ContextRequest') ->
+ OptPriority =
+ case Val#'ContextRequest'.priority of
+ asn1_NOVALUE -> {[], dummy};
+ Prio -> {[Prio], fun enc_priority/2}
+ end,
+ OptEmergency =
+ case Val#'ContextRequest'.emergency of
+ asn1_NOVALUE -> {[], dummy};
+ false -> {[?EmergencyOffToken], fun(Elem, _) -> Elem end};
+ true -> {[?EmergencyToken], fun(Elem, _) -> Elem end}
+ end,
+ OptTopologyReq =
+ case Val#'ContextRequest'.topologyReq of
+ asn1_NOVALUE ->
+ {[], dummy};
+ {'ContextRequest_topologyReq', asn1_NOVALUE} ->
+ {[], dummy};
+ {'ContextRequest_topologyReq', List} ->
+ {List, fun enc_TopologyRequest/2};
+ List ->
+ {[List], fun enc_TopologyRequest/2}
+ end,
+ [OptPriority, OptEmergency, OptTopologyReq].
+
+enc_priority(Val, State) ->
+ [
+ ?PriorityToken,
+ ?EQUAL,
+ enc_UINT16(Val, State)
+ ].
+
+enc_ContextAttrAuditRequest(Val, State)
+ when is_record(Val, 'ContextAttrAuditRequest') ->
+ [
+ ?ContextAuditToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'ContextAttrAuditRequest'.topology],
+ fun('NULL', _) -> ?TopologyToken end},
+ {[Val#'ContextAttrAuditRequest'.emergency],
+ fun('NULL', _) -> ?EmergencyToken end},
+ {[Val#'ContextAttrAuditRequest'.priority],
+ fun('NULL', _) -> ?PriorityToken end}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_CommandRequest(#'CommandRequest'{optional = asn1_NOVALUE,
+ wildcardReturn = asn1_NOVALUE,
+ command = Cmd}, State) ->
+ [
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = 'NULL',
+ wildcardReturn = asn1_NOVALUE,
+ command = Cmd}, State) ->
+ [
+ "O-",
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = asn1_NOVALUE,
+ wildcardReturn = 'NULL',
+ command = Cmd}, State) ->
+ [
+ "W-",
+ enc_Command(Cmd, State)
+ ];
+enc_CommandRequest(#'CommandRequest'{optional = 'NULL',
+ wildcardReturn = 'NULL',
+ command = Cmd}, State) ->
+ [
+ "O-",
+ "W-",
+ enc_Command(Cmd, State)
+ ].
+
+enc_Command({'Command',Val}, State) ->
+ enc_Command(Val, State);
+enc_Command({Tag, Val}, State) ->
+ case Tag of
+ addReq ->
+ [?AddToken, enc_AmmRequest(Val, State)];
+ moveReq ->
+ [?MoveToken, enc_AmmRequest(Val, State)];
+ modReq ->
+ [?ModifyToken, enc_AmmRequest(Val, State)];
+ subtractReq ->
+ [?SubtractToken, enc_SubtractRequest(Val, State)];
+ auditCapRequest ->
+ [?AuditCapToken, enc_AuditRequest(Val, State)];
+ auditValueRequest ->
+ [?AuditValueToken, enc_AuditRequest(Val, State)];
+ notifyReq ->
+ [?NotifyToken, enc_NotifyRequest(Val, State)];
+ serviceChangeReq ->
+ [?ServiceChangeToken, enc_ServiceChangeRequest(Val, State)];
+ _ ->
+ error({invalid_Command_tag, Tag})
+ end.
+
+enc_CommandReply({'CommandReply',Val}, State) ->
+ enc_CommandReply(Val, State);
+enc_CommandReply({Tag, Val}, State) ->
+ case Tag of
+ addReply ->
+ [?AddToken, enc_AmmsReply(Val, State)];
+ moveReply ->
+ [?MoveToken, enc_AmmsReply(Val, State)];
+ modReply ->
+ [?ModifyToken, enc_AmmsReply(Val, State)];
+ subtractReply ->
+ [?SubtractToken, enc_AmmsReply(Val, State)];
+ auditCapReply ->
+ [?AuditCapToken, enc_AuditReply(Val, State)];
+ auditValueReply ->
+ [?AuditValueToken, enc_AuditReply(Val, State)];
+ notifyReply ->
+ [?NotifyToken, enc_NotifyReply(Val, State)];
+ serviceChangeReply ->
+ [?ServiceChangeToken, enc_ServiceChangeReply(Val, State)];
+ _ ->
+ error({invalid_CommandReply_tag, Tag})
+ end.
+
+enc_TopologyRequest(Val, State)
+ when is_list(Val) ->
+ [
+ ?TopologyToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val, fun enc_TopologyRequest1/2}],?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_TopologyRequest1(#'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = Dir,
+ streamID = asn1_NOVALUE},
+ State) ->
+ [
+ fun(S) ->
+ [
+ enc_TerminationID(From, S),
+ ?COMMA_INDENT(S),
+ enc_TerminationID(To, S),
+ ?COMMA_INDENT(S),
+ case Dir of
+ bothway -> ?BothwayToken;
+ isolate -> ?IsolateToken;
+ oneway -> ?OnewayToken
+ end
+ ]
+ end(?INC_INDENT(State))
+ ];
+enc_TopologyRequest1(#'TopologyRequest'{terminationFrom = From,
+ terminationTo = To,
+ topologyDirection = Dir,
+ streamID = SID},
+ State) ->
+ [
+ fun(S) ->
+ [
+ enc_TerminationID(From, S),
+ ?COMMA_INDENT(S),
+ enc_TerminationID(To, S),
+ ?COMMA_INDENT(S),
+ case Dir of
+ bothway -> ?BothwayToken;
+ isolate -> ?IsolateToken;
+ oneway -> ?OnewayToken
+ end,
+ ?COMMA_INDENT(S),
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(SID, S)
+ ]
+ end(?INC_INDENT(State))
+ ].
+
+enc_AmmRequest(Val, State)
+ when is_record(Val, 'AmmRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'AmmRequest'.terminationID, State),
+ enc_opt_brackets(
+ enc_list([{Val#'AmmRequest'.descriptors, fun enc_ammDescriptor/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_ammDescriptor({Tag, Desc}, State) ->
+ case Tag of
+ mediaDescriptor -> enc_MediaDescriptor(Desc, State);
+ modemDescriptor -> enc_ModemDescriptor(Desc, State);
+ muxDescriptor -> enc_MuxDescriptor(Desc, State);
+ eventsDescriptor -> enc_EventsDescriptor(Desc, State);
+ eventBufferDescriptor -> enc_EventBufferDescriptor(Desc, State);
+ signalsDescriptor -> enc_SignalsDescriptor(Desc, State);
+ digitMapDescriptor -> enc_DigitMapDescriptor(Desc, State);
+ auditDescriptor -> enc_AuditDescriptor(Desc, State);
+ _ ->
+ error({invalid_ammDescriptor_tag, Tag})
+ end.
+
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = asn1_NOVALUE}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State)
+ ];
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = []}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State)
+ ];
+enc_AmmsReply(#'AmmsReply'{terminationID = ID,
+ terminationAudit = Res}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationIDList1(ID, State),
+ case lists:flatten(enc_TerminationAudit(Res, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_SubtractRequest(Val, State)
+ when is_record(Val, 'SubtractRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'SubtractRequest'.terminationID, State),
+ case Val#'SubtractRequest'.auditDescriptor of
+ asn1_NOVALUE ->
+ [];
+ AuditDescr ->
+ [
+ ?LBRKT_INDENT(State) ,
+ enc_AuditDescriptor(AuditDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_AuditRequest(Val, State)
+ when is_record(Val, 'AuditRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1([Val#'AuditRequest'.terminationID], State),
+ case Val#'AuditRequest'.auditDescriptor of
+ asn1_NOVALUE ->
+ [];
+ AuditDescr ->
+ [
+ ?LBRKT_INDENT(State) ,
+ enc_AuditDescriptor(AuditDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+%% auditReply = (AuditValueToken / AuditCapToken )
+%% ( contextTerminationAudit / auditOther)
+%% auditOther = EQUAL TerminationID LBRKT
+%% terminationAudit RBRKT
+%% terminationAudit = auditReturnParameter *(COMMA auditReturnParameter)
+%%
+%% contextTerminationAudit = EQUAL CtxToken ( terminationIDList /
+%% LBRKT errorDescriptor RBRKT )
+enc_AuditReply({Tag, Val}, State) ->
+ case Tag of
+ contextAuditResult ->
+ [
+ ?EQUAL,
+ ?CtxToken,
+ enc_TerminationIDListN(Val, State)
+ ];
+ error ->
+ [
+ ?EQUAL,
+ ?CtxToken,
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ auditResult when is_record(Val, 'AuditResult') ->
+ enc_auditOther(Val, State);
+ auditResult ->
+ error({invalid_auditResult, Val});
+ _ ->
+ error({invalid_AuditReply_tag, Tag})
+ end.
+
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = asn1_NOVALUE}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State)
+ ];
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = []}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State)
+ ];
+enc_auditOther(#'AuditResult'{terminationID = ID,
+ terminationAuditResult = Res}, State) ->
+ [
+ ?EQUAL,
+ enc_TerminationID(ID, State),
+ case lists:flatten(enc_TerminationAudit(Res, ?INC_INDENT(State))) of
+ [] ->
+ [];
+ L ->
+ [
+ ?LBRKT_INDENT(State),
+ L,
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = asn1_NOVALUE,
+ auditPropertyToken = asn1_NOVALUE},
+ _State) ->
+ [
+ ?AuditToken,
+ [?LBRKT, ?RBRKT]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = [],
+ auditPropertyToken = asn1_NOVALUE},
+ _State) ->
+ [
+ ?AuditToken,
+ [?LBRKT, ?RBRKT]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = List,
+ auditPropertyToken = asn1_NOVALUE},
+ State) ->
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_auditItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ ];
+%% - v2 -
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = asn1_NOVALUE,
+ auditPropertyToken = Prop},
+ State) ->
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_auditPropertyToken(Prop, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ ];
+enc_AuditDescriptor(#'AuditDescriptor'{auditToken = List,
+ auditPropertyToken = Prop},
+ State) ->
+ [
+ ?AuditToken,
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_auditItem/2}], ?INC_INDENT(State)),
+ ?COMMA_INDENT(State),
+ enc_auditPropertyToken(Prop, ?INC_INDENT(State)), % v2
+ ?RBRKT_INDENT(State)
+ ]
+ ].
+
+enc_auditItem(signalsToken, _State) ->
+ ?SignalsToken;
+enc_auditItem(eventBufferToken, _State) ->
+ ?EventBufferToken;
+enc_auditItem(eventsToken, _State) ->
+ ?EventsToken;
+enc_auditItem(Val, State) ->
+ enc_auditReturnItem(Val, State).
+
+
+enc_auditReturnItem(muxToken, _State) ->
+ ?MuxToken;
+enc_auditReturnItem(modemToken, _State) ->
+ ?ModemToken;
+enc_auditReturnItem(mediaToken, _State) ->
+ ?MediaToken;
+enc_auditReturnItem(digitMapToken, _State) ->
+ ?DigitMapToken;
+enc_auditReturnItem(statsToken, _State) ->
+ ?StatsToken;
+enc_auditReturnItem(observedEventsToken, _State) ->
+ ?ObservedEventsToken;
+enc_auditReturnItem(packagesToken, _State) ->
+ ?PackagesToken.
+
+
+%% - v2 begin -
+
+enc_auditPropertyToken([], _State) ->
+ [];
+enc_auditPropertyToken([Param | Params], State) ->
+ [enc_IndAudauditReturnParameter(Param, State),
+ [[?COMMA_INDENT(State),
+ enc_IndAudauditReturnParameter(P, State)] || P <- Params]].
+
+
+enc_IndAudauditReturnParameter({Tag, Val}, State) ->
+ case Tag of
+ indAudMediaDescriptor ->
+ enc_IndAudMediaDescriptor(Val, State);
+ indAudEventsDescriptor ->
+ enc_IndAudEventsDescriptor(Val, State);
+ indAudSignalsDescriptor ->
+ enc_IndAudSignalsDescriptor(Val, State);
+ indAudDigitMapDescriptor ->
+ enc_IndAudDigitMapDescriptor(Val, State);
+ indAudEventBufferDescriptor ->
+ enc_IndAudEventBufferDescriptor(Val, State);
+ indAudStatisticsDescriptor ->
+ enc_IndAudStatisticsDescriptor(Val, State);
+ indAudPackagesDescriptor ->
+ enc_IndAudPackagesDescriptor(Val, State);
+ _ ->
+ error({invalid_IndAudauditReturnParameter_tag, Tag})
+ end.
+
+%% The ASN.1 does not limit to just one of termStateDescr or streams,
+%% but the ABNF seams to do that...
+enc_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = asn1_NOVALUE,
+ streams = Val}, State) ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudMediaDescriptor_streams(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudMediaDescriptor(#'IndAudMediaDescriptor'{termStateDescr = Val,
+ streams = asn1_NOVALUE},
+ State) ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudTerminationStateDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudMediaDescriptor_streams({Tag, Val}, State) ->
+ case Tag of
+ oneStream ->
+ enc_IndAudStreamParms(Val, State);
+ multiStream ->
+ enc_IndAudMediaDescriptor_multiStream(Val, State);
+ _ ->
+ error({invalid_IndAudMediaDescriptor_streams_tag, Tag})
+ end.
+
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [],
+ eventBufferControl = asn1_NOVALUE,
+ serviceState = 'NULL'}, _State) ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(_State),
+ ?ServiceStatesToken,
+ ?RBRKT_INDENT(_State)
+ ];
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [],
+ eventBufferControl = 'NULL',
+ serviceState = asn1_NOVALUE}, _State) ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(_State),
+ ?BufferToken,
+ ?RBRKT_INDENT(_State)
+ ];
+enc_IndAudTerminationStateDescriptor(
+ #'IndAudTerminationStateDescriptor'{propertyParms = [Parms],
+ eventBufferControl = asn1_NOVALUE,
+ serviceState = asn1_NOVALUE}, State) ->
+ #'IndAudPropertyParm'{name = Name} = Parms,
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_IndAudStreamParms(#'IndAudStreamParms'{localControlDescriptor = Val,
+ localDescriptor = asn1_NOVALUE,
+ remoteDescriptor = asn1_NOVALUE},
+ State) ->
+ [
+ enc_IndAudLocalControlDescriptor(Val, ?INC_INDENT(State))
+ ].
+
+enc_IndAudLocalControlDescriptor(Val, State)
+ when is_record(Val, 'IndAudLocalControlDescriptor') ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'IndAudLocalControlDescriptor'.streamMode],
+ fun('NULL', _) -> ?ModeToken end},
+ {[Val#'IndAudLocalControlDescriptor'.reserveValue],
+ fun('NULL', _) -> ?ReservedValueToken end},
+ {[Val#'IndAudLocalControlDescriptor'.reserveGroup],
+ fun('NULL', _) -> ?ReservedGroupToken end},
+ {Val#'IndAudLocalControlDescriptor'.propertyParms,
+ fun enc_IndAudPropertyParm/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudPropertyParm(#'IndAudPropertyParm'{name = PkgdName}, State) ->
+ enc_PkgdName(PkgdName, State).
+
+enc_IndAudMediaDescriptor_multiStream([Val], State) ->
+ [
+ enc_IndAudStreamDescriptor(Val, ?INC_INDENT(State))
+ ];
+enc_IndAudMediaDescriptor_multiStream(Vals, _State) when is_list(Vals) ->
+ error({invalid_IndAudMediaDescriptor_multiStream_length, Vals});
+enc_IndAudMediaDescriptor_multiStream(Val, _State) ->
+ error({invalid_IndAudMediaDescriptor_multiStream, Val}).
+
+enc_IndAudStreamDescriptor(#'IndAudStreamDescriptor'{streamID = SID,
+ streamParms = Parms},
+ State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(SID, State),
+ ?LBRKT_INDENT(State),
+ enc_IndAudStreamParms(Parms, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventBufferDescriptor(Val, State)
+ when is_record(Val, 'IndAudEventBufferDescriptor') ->
+ #'IndAudEventBufferDescriptor'{eventName = EvName,
+ streamID = ID} = Val,
+ [
+ ?EventBufferToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(EvName, State),
+ enc_IndAudEventBufferDescriptor_eventSpec(ID, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventBufferDescriptor_eventSpec(asn1_NOVALUE, _State) ->
+ [
+ ];
+enc_IndAudEventBufferDescriptor_eventSpec({eventParameterName, ParamName},
+ State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_Name(ParamName, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_IndAudEventBufferDescriptor_eventSpec(ID, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_eventStream(ID, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudEventsDescriptor(Val, State)
+ when is_record(Val, 'IndAudEventsDescriptor') ->
+ #'IndAudEventsDescriptor'{requestID = ReqID,
+ pkgdName = Name,
+ streamID = asn1_NOVALUE} = Val,
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(ReqID, State),
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_IndAudSignalsDescriptor(Val, State) ->
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(State),
+ enc_IndAudSignalsDescriptor_value(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudSignalsDescriptor_value({signal, Val}, State) ->
+ enc_IndAudSignal(Val, State);
+enc_IndAudSignalsDescriptor_value({seqSigList, Val}, State) ->
+ enc_IndAudSeqSigList(Val, State).
+
+enc_IndAudSignal(#'IndAudSignal'{signalName = SignalName,
+ streamID = asn1_NOVALUE}, State) ->
+ [
+ enc_SignalName(SignalName, State)
+ ].
+
+enc_IndAudSeqSigList(#'IndAudSeqSigList'{id = ID,
+ signalList = Parm},
+ State) ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(ID, State),
+ ?LBRKT_INDENT(State),
+ enc_IndAudSignal(Parm, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_IndAudDigitMapDescriptor(#'IndAudDigitMapDescriptor'{digitMapName = Name},
+ State) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ].
+
+enc_IndAudStatisticsDescriptor(#'IndAudStatisticsDescriptor'{statName = Name},
+ State) ->
+ [
+ ?StatsToken,
+ ?LBRKT_INDENT(State),
+ enc_PkgdName(Name, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_IndAudPackagesDescriptor(#'IndAudPackagesDescriptor'{packageName = N,
+ packageVersion = V},
+ State) ->
+ [
+ ?PackagesToken,
+ ?LBRKT_INDENT(State),
+ enc_Name(N, State),
+ "-",
+ enc_UINT16(V, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+%% - v2 end -
+
+
+enc_TerminationAudit({'TerminationAudit',Val}, State) ->
+ enc_TerminationAudit(Val, State);
+enc_TerminationAudit([], _State) ->
+ [];
+enc_TerminationAudit([Mand | Opt], State) ->
+ [enc_AuditReturnParameter(Mand, State),
+ [[?COMMA_INDENT(State), enc_AuditReturnParameter(Val, State)] || Val <- Opt]].
+
+enc_AuditReturnParameter({'AuditReturnParameter',Val}, State) ->
+ enc_AuditReturnParameter(Val, State);
+enc_AuditReturnParameter({Tag, Val}, State) ->
+ case Tag of
+ mediaDescriptor ->
+ enc_MediaDescriptor(Val, State);
+ modemDescriptor ->
+ enc_ModemDescriptor(Val, State);
+ muxDescriptor ->
+ enc_MuxDescriptor(Val, State);
+ eventsDescriptor ->
+ enc_EventsDescriptor(Val, State);
+ signalsDescriptor ->
+ enc_SignalsDescriptor(Val, State);
+ digitMapDescriptor ->
+ enc_DigitMapDescriptor(Val, State);
+ observedEventsDescriptor ->
+ enc_ObservedEventsDescriptor(Val, State);
+ eventBufferDescriptor ->
+ enc_EventBufferDescriptor(Val, State);
+ statisticsDescriptor ->
+ enc_StatisticsDescriptor(Val, State);
+ packagesDescriptor ->
+ enc_PackagesDescriptor(Val, State);
+ errorDescriptor ->
+ enc_ErrorDescriptor(Val, State);
+ emptyDescriptors ->
+ enc_EmptyDescriptors(Val, State);
+ _ ->
+ error({invalid_AuditReturnParameter_tag, Tag})
+ end.
+
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = asn1_NOVALUE}, _State) ->
+ [];
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = []}, _State) ->
+ [];
+enc_EmptyDescriptors(#'AuditDescriptor'{auditToken = List}, State) ->
+ enc_list([{List, fun enc_auditReturnItem/2}], ?INC_INDENT(State)).
+
+
+enc_NotifyRequest(Val, State)
+ when is_record(Val, 'NotifyRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'NotifyRequest'.terminationID, State),
+ ?LBRKT_INDENT(State),
+ %% BUGBUG: Mismatch between ASN.1 and ABNF
+ %% BUGBUG: The following ought to be a 'choice'
+ case Val#'NotifyRequest'.errorDescriptor of
+ asn1_NOVALUE ->
+ OED = Val#'NotifyRequest'.observedEventsDescriptor,
+ enc_ObservedEventsDescriptor(OED, ?INC_INDENT(State));
+ ErrorDescr ->
+ enc_ErrorDescriptor(ErrorDescr, ?INC_INDENT(State))
+ end,
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_NotifyReply(Val, State)
+ when is_record(Val, 'NotifyReply') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ case Val#'NotifyReply'.terminationID of
+ asn1_NOVALUE ->
+ error(asn1_not_compliant_with_abnf);
+ TermId ->
+ enc_TerminationIDList1(TermId, State)
+ end,
+ case Val#'NotifyReply'.errorDescriptor of
+ asn1_NOVALUE ->
+ [];
+ ErrorDescr ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(ErrorDescr, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end
+ ].
+
+enc_ObservedEventsDescriptor(Val, State)
+ when is_record(Val, 'ObservedEventsDescriptor') ->
+ [
+ ?ObservedEventsToken,
+ ?EQUAL,
+ enc_RequestID(Val#'ObservedEventsDescriptor'.requestId, State),
+ ?LBRKT_INDENT(State),
+ enc_observedEventsDescriptors(Val#'ObservedEventsDescriptor'.observedEventLst, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_observedEventsDescriptors([Mand | Opt], State) ->
+ [enc_ObservedEvent(Mand, State),
+ [[?COMMA_INDENT(State), enc_ObservedEvent(Val, State)] || Val <- Opt]].
+
+%% ;time per event, because it might be buffered
+%% observedEvent = [ TimeStamp LWSP COLON] LWSP
+%% pkgdName [ LBRKT observedEventParameter
+%% *(COMMA observedEventParameter) RBRKT ]
+%%
+%% ;at-most-once eventStream, every eventParameterName at most once
+%% observedEventParameter = eventStream / eventOther
+enc_ObservedEvent(Val, State)
+ when is_record(Val, 'ObservedEvent') ->
+ [
+ case Val#'ObservedEvent'.timeNotation of
+ asn1_NOVALUE ->
+ [];
+ TimeStamp ->
+ [
+ enc_TimeNotation(TimeStamp, State),
+ ?LWSP,
+ ?COLON
+ ]
+ end,
+ ?LWSP,
+ enc_EventName(Val#'ObservedEvent'.eventName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'ObservedEvent'.streamID], fun enc_eventStream/2},
+ {Val#'ObservedEvent'.eventParList, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_EventName({'EventName',Val}, State) ->
+ enc_EventName(Val, State);
+enc_EventName(Val, State) ->
+ PkgdName = ?META_ENC(event, Val),
+ enc_PkgdName(PkgdName, State).
+
+enc_eventStream(Val, State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val, State)
+ ].
+
+%% The value is already encoded
+enc_eventOther(#megaco_event_parameter{name = Name,
+ value = Value}, State)
+ when is_list(Value) ->
+ [
+ enc_Name(Name, State),
+ ?EqualToken,
+ Value
+ ];
+%% Special treatment of the ds parameter of the dd/ce event
+enc_eventOther(#'EventParameter'{eventParameterName = "ds" = Name,
+ value = [DigitString],
+ extraInfo = asn1_NOVALUE}, State) ->
+ [
+ enc_Name(Name, State),
+ ?EqualToken,
+ enc_DigitString(DigitString, State)
+ ];
+enc_eventOther(#'EventParameter'{eventParameterName = Name,
+ value = Value,
+ extraInfo = Extra}, State) ->
+ [
+ enc_Name(Name, State),
+ enc_propertyParmValues(Value, Extra, State)
+ ].
+
+enc_ServiceChangeRequest(Val, State)
+ when is_record(Val, 'ServiceChangeRequest') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'ServiceChangeRequest'.terminationID, State),
+ ?LBRKT_INDENT(State),
+ enc_ServiceChangeParm(Val#'ServiceChangeRequest'.serviceChangeParms,
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% serviceChangeReply = ServiceChangeToken EQUAL TerminationID
+%% [LBRKT (errorDescriptor /
+%% serviceChangeReplyDescriptor) RBRKT]
+%% serviceChangeReplyDescriptor = ServicesToken LBRKT
+%% servChgReplyParm *(COMMA servChgReplyParm) RBRKT
+%%
+%% ;at-most-once. Version is REQUIRED on first ServiceChange response
+%% servChgReplyParm = (serviceChangeAddress / serviceChangeMgcId /
+%% serviceChangeProfile / serviceChangeVersion )
+enc_ServiceChangeReply(Val, State)
+ when is_record(Val, 'ServiceChangeReply') ->
+ [
+ %% Assume that Token is added elsewhere
+ ?EQUAL,
+ enc_TerminationIDList1(Val#'ServiceChangeReply'.terminationID, State),
+ enc_ServiceChangeResult(Val#'ServiceChangeReply'.serviceChangeResult, State)
+ ].
+
+enc_ServiceChangeResult({'ServiceChangeResult',Val}, State) ->
+ enc_ServiceChangeResult(Val, State);
+enc_ServiceChangeResult({Tag, Val}, State) ->
+ case Tag of
+ errorDescriptor ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_ErrorDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ serviceChangeResParms ->
+ case enc_ServiceChangeResParm(Val, ?INC_INDENT(?INC_INDENT(State))) of
+ [] ->
+ [];
+ ResParms ->
+ [
+ ?LBRKT_INDENT(State),
+ ?ServicesToken,
+ fun(_S) ->
+ [
+ ?LBRKT_INDENT(_S),
+ ResParms,
+ ?RBRKT_INDENT(_S)
+ ]
+ end(?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+ _ ->
+ error({invalid_ServiceChangeResult_tag, Tag})
+ end.
+
+%% Required length of termination ID list is 1
+enc_TerminationIDList1({'TerminationIDList',Val}, State) ->
+ enc_TerminationIDList1(Val, State);
+enc_TerminationIDList1([Singleton], State) ->
+ enc_TerminationID(Singleton, State).
+
+%% No required length of termination ID list
+enc_TerminationIDListN({'TerminationIDList',Val}, State) ->
+ enc_TerminationIDListN(Val, State);
+enc_TerminationIDListN([TID], State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_TerminationID(TID, State),
+ ?RBRKT_INDENT(State)
+ ];
+enc_TerminationIDListN(TIDs, State) ->
+ [
+ ?LBRKT_INDENT(State),
+ enc_list([{TIDs, fun enc_TerminationID/2}], State),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+%% TerminationID = "ROOT" / pathNAME / "$" / "*"
+%% ; Total length of pathNAME must not exceed 64 chars.
+%% pathNAME = ["*"] NAME *("/" / "*"/ ALPHA / DIGIT /"_" / "$" )
+%% ["@" pathDomainName ]
+enc_TerminationID(Tid, State)
+ when is_record(Tid, megaco_term_id) ->
+ List = [{Tid#megaco_term_id.id, fun enc_tid_component/2 }],
+ enc_list(List, State, fun(_S) -> ?SLASH end, false).
+
+enc_tid_component(Component, State) when is_list(Component) ->
+ [enc_tid_sub_component(Sub, State) || Sub <- Component];
+enc_tid_component(Invalid, _State) ->
+ error({invalid_id_list_component, Invalid}).
+
+enc_tid_sub_component(all = _Sub, _State) ->
+ ?megaco_all;
+enc_tid_sub_component(choose = _Sub, _State) ->
+ ?megaco_choose;
+enc_tid_sub_component(Char, _State) when is_integer(Char) ->
+ Char;
+enc_tid_sub_component(Invalid, _State) ->
+ error({invalid_id_list_sub_component, Invalid}).
+
+%% enc_tid_sub_component(Sub, _State) ->
+%% case Sub of
+%% all -> ?megaco_all;
+%% choose -> ?megaco_choose;
+%% Char when is_integer(Char) -> Char
+%% end.
+
+%% mediaDescriptor = MediaToken LBRKT mediaParm *(COMMA mediaParm) RBRKT
+%% ; at-most-once per item
+%% ; and either streamParm or streamDescriptor but not both
+%% mediaParm = (streamParm / streamDescriptor /
+%% terminationStateDescriptor)
+%% ; at-most-once
+%% streamParm = ( localDescriptor / remoteDescriptor /
+%% localControlDescriptor )
+%% streamDescriptor = StreamToken EQUAL StreamID LBRKT streamParm
+%% *(COMMA streamParm) RBRKT
+enc_MediaDescriptor(Val, State)
+ when is_record(Val, 'MediaDescriptor') ->
+ [
+ ?MediaToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'MediaDescriptor'.termStateDescr],
+ fun enc_TerminationStateDescriptor/2} |
+ decompose_streams(Val#'MediaDescriptor'.streams)],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+decompose_streams(asn1_NOVALUE) ->
+ [];
+decompose_streams({'MediaDescriptor_streams',Val}) ->
+ decompose_streams(Val);
+decompose_streams({Tag, Val}) ->
+ case Tag of
+ oneStream ->
+ decompose_StreamParms(Val);
+ multiStream ->
+ [{Val, fun enc_StreamDescriptor/2}];
+ _ ->
+ error({invalid_streams_tag, Tag})
+ end.
+
+decompose_StreamParms(Val)
+ when is_record(Val, 'StreamParms') ->
+ [
+ {[Val#'StreamParms'.localControlDescriptor],
+ fun enc_LocalControlDescriptor/2},
+ {[Val#'StreamParms'.localDescriptor],
+ fun enc_localDescriptor/2},
+ {[Val#'StreamParms'.remoteDescriptor],
+ fun enc_remoteDescriptor/2}
+ ].
+
+enc_StreamDescriptor(Val, State)
+ when is_record(Val, 'StreamDescriptor') ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val#'StreamDescriptor'.streamID, State),
+ ?LBRKT_INDENT(State),
+ enc_list(decompose_StreamParms(Val#'StreamDescriptor'.streamParms),
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% localControlDescriptor = LocalControlToken LBRKT localParm
+%% *(COMMA localParm) RBRKT
+%%
+%% ; at-most-once per item
+%% localParm = ( streamMode / propertyParm /
+%% reservedValueMode / reservedGroupMode )
+%% reservedValueMode = ReservedValueToken EQUAL ( "ON" / "OFF" )
+%% reservedGroupMode = ReservedGroupToken EQUAL ( "ON" / "OFF" )
+%%
+%% reservedMode = ReservedToken EQUAL ( "ON" / "OFF" )
+%%
+%% streamMode = ModeToken EQUAL streamModes
+enc_LocalControlDescriptor(
+ #'LocalControlDescriptor'{streamMode = asn1_NOVALUE,
+ reserveValue = asn1_NOVALUE,
+ reserveGroup = asn1_NOVALUE,
+ propertyParms = []}, _State) ->
+ error({invalid_LocalControlDescriptor, empty});
+enc_LocalControlDescriptor(
+ #'LocalControlDescriptor'{streamMode = SM,
+ reserveValue = RV,
+ reserveGroup = RG,
+ propertyParms = PPs}, State) ->
+ [
+ ?LocalControlToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[SM], fun enc_StreamMode/2},
+ {[RG], fun enc_reservedGroupMode/2},
+ {[RV], fun enc_reservedValueMode/2},
+ {PPs, fun enc_PropertyParm/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_reservedGroupMode(Val, _State) ->
+ [
+ ?ReservedGroupToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+enc_reservedValueMode(Val, _State) ->
+ [
+ ?ReservedValueToken,
+ ?EQUAL,
+ case Val of
+ false -> ?OffToken;
+ true -> ?OnToken
+ end
+ ].
+
+enc_StreamMode({'StreamMode',Val}, State) ->
+ enc_StreamMode(Val, State);
+enc_StreamMode(Val, _State) ->
+ [
+ ?ModeToken,
+ ?EQUAL,
+ case Val of
+ sendOnly -> ?SendonlyToken;
+ recvOnly -> ?RecvonlyToken;
+ sendRecv -> ?SendrecvToken;
+ inactive -> ?InactiveToken;
+ loopBack -> ?LoopbackToken
+ end
+ ].
+
+enc_Name({'Name',Val}, State) ->
+ enc_Name(Val, State);
+enc_Name(Val, State) ->
+ %% BUGBUG: NAME = ALPHA *63(ALPHA / DIGIT / "_" )
+ enc_STRING(Val, State, 1, 64).
+
+enc_PkgdName({'PkgdName', Val}, State) ->
+ enc_PkgdName(Val, State);
+enc_PkgdName(Val, _State) ->
+ %% BUGBUG: pkgdName = (NAME / "*") SLASH (ItemID / "*" )
+ %% enc_OCTET_STRING(Val, _State, 1, 64).
+ if
+ is_list(Val) ->
+ Length = length(Val),
+ if
+ (Length >= 1) ->
+ if
+ (Length =< 64) ->
+ Val;
+ true ->
+ error({pkgdName_toolong, Length, 64})
+ end;
+ true ->
+ error({pkgdName_tooshort, Length, 1})
+ end;
+ true ->
+ error({invalid_PkgdName, Val})
+ end.
+
+enc_localDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ [
+ ?LocalToken,
+ ?LBRKT,
+ enc_LocalRemoteDescriptor(Val, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_remoteDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ [
+ ?RemoteToken,
+ ?LBRKT,
+ enc_LocalRemoteDescriptor(Val, State),
+ ?RBRKT_INDENT(State)
+ ].
+
+%% When text encoding the protocol, the descriptors consist of session
+%% descriptions as defined in SDP (RFC2327), except that the "s=", "t="
+%% and "o=" lines are optional. When multiple session descriptions are
+%% provided in one descriptor, the "v=" lines are required as delimiters;
+%% otherwise they are optional. Implementations shall accept session
+%% descriptions that are fully conformant to RFC2327. When binary
+%% encoding the protocol the descriptor consists of groups of properties
+%% (tag-value pairs) as specified in Annex C. Each such group may
+%% contain the parameters of a session description.
+enc_LocalRemoteDescriptor(Val, State)
+ when is_record(Val, 'LocalRemoteDescriptor') ->
+ case Val#'LocalRemoteDescriptor'.propGrps of
+ [] ->
+ [];
+ [OptV | MandV] ->
+ [?LfToken,
+ enc_PropertyGroup(OptV, opt_v, State) |
+ [enc_PropertyGroup(M, mand_v, State) || M <- MandV]]
+ end.
+
+enc_PropertyGroup({'PropertyGroup',Val}, RequiresV, State) ->
+ enc_PropertyGroup(Val, RequiresV, State);
+enc_PropertyGroup([H | _T] = List, mand_v, State)
+ when is_record(H, 'PropertyParm') andalso (H#'PropertyParm'.name =:= "v") ->
+ enc_PropertyGroup(List, opt_v, State);
+enc_PropertyGroup(PG, opt_v, State) ->
+ [
+ [[enc_PropertyGroupParm(PP, State), ?CrToken, ?LfToken] || PP <- PG]
+ ].
+
+enc_PropertyGroupParm(Val, State)
+ when is_record(Val, 'PropertyParm') ->
+ [OctetString] = Val#'PropertyParm'.value,
+ [
+ enc_PkgdName(Val#'PropertyParm'.name, State),
+ ?EqualToken,
+ enc_OCTET_STRING(OctetString, State, 0, infinity)
+ ].
+
+%% propertyParm = pkgdName parmValue
+%% parmValue = (EQUAL alternativeValue/ INEQUAL VALUE)
+%% alternativeValue = ( VALUE / LSBRKT VALUE *(COMMA VALUE) RSBRKT /
+%% LSBRKT VALUE DOT DOT VALUE RSBRKT )
+enc_PropertyParm(Val, State)
+ when is_record(Val, 'PropertyParm') ->
+ PkgdName = ?META_ENC(property, Val#'PropertyParm'.name),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_propertyParmValues(Val#'PropertyParm'.value,
+ Val#'PropertyParm'.extraInfo,
+ State)
+ ].
+
+enc_propertyParmValues([Single], asn1_NOVALUE, State) ->
+ [
+ ?EqualToken,
+ enc_Value(Single, State)
+ ];
+enc_propertyParmValues([Single], {relation, Rel}, State) ->
+ case Rel of
+ greaterThan -> [$>, enc_Value(Single, State)];
+ smallerThan -> [$<, enc_Value(Single, State)];
+ unequalTo -> [$#, enc_Value(Single, State)]
+ end;
+enc_propertyParmValues([Low, High], {range, true}, State)->
+ %% Exact two values
+ [
+ ?EqualToken,
+ ?LSBRKT,
+ enc_Value(Low, State),
+ ?COLON,
+ enc_Value(High, State),
+ ?RSBRKT
+ ];
+enc_propertyParmValues(Values, {sublist, true}, State)->
+ %% sublist (i.e. A AND B AND ...)
+ [
+ ?EqualToken,
+ ?LSBRKT,
+ enc_list([{Values, fun enc_Value/2}], State),
+ ?RSBRKT
+ ];
+enc_propertyParmValues(Values, {sublist, false}, State) ->
+ %% alternatives (i.e. A OR B OR ...)
+ [
+ ?EqualToken,
+ ?LBRKT,
+ enc_list([{Values, fun enc_Value/2}], State),
+ ?RBRKT
+ ];
+enc_propertyParmValues(V, EI, _State) ->
+ error({invalid_property_parm_values, V, EI}).
+
+enc_TerminationStateDescriptor(Val, State)
+ when is_record(Val, 'TerminationStateDescriptor') ->
+ [
+ ?TerminationStateToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val#'TerminationStateDescriptor'.propertyParms,
+ fun enc_PropertyParm/2},
+ {[Val#'TerminationStateDescriptor'.eventBufferControl],
+ fun enc_eventBufferControl/2},
+ {[Val#'TerminationStateDescriptor'.serviceState],
+ fun enc_serviceState/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_eventBufferControl(Val, _State) ->
+ [
+
+ ?BufferToken,
+ ?EQUAL,
+ case Val of
+ off -> ?OffToken;
+ lockStep -> ?LockStepToken
+ end
+ ].
+
+enc_serviceState({'ServiceState',Val}, State) ->
+ enc_serviceState(Val, State);
+enc_serviceState(Val, _State) ->
+ [
+ ?ServiceStatesToken,
+ ?EQUAL,
+ case Val of
+ test -> ?TestToken;
+ outOfSvc -> ?OutOfSvcToken;
+ inSvc -> ?InSvcToken
+ end
+ ].
+
+enc_MuxDescriptor(Val, State)
+ when is_record(Val, 'MuxDescriptor') ->
+ [
+ ?MuxToken,
+ ?EQUAL,
+ enc_MuxType(Val#'MuxDescriptor'.muxType, State),
+ enc_TerminationIDListN(Val#'MuxDescriptor'.termList, State)
+ ].
+
+enc_MuxType({'MuxType',Val}, State) ->
+ enc_MuxType(Val, State);
+enc_MuxType(Val, _State) ->
+ case Val of
+ h221 -> ?H221Token;
+ h223 -> ?H223Token;
+ h226 -> ?H226Token;
+ v76 -> ?V76Token;
+ %% extensionParameter
+ nx64k -> ?Nx64kToken % v2
+ end.
+
+enc_StreamID({'StreamID',Val}, State) ->
+ enc_StreamID(Val, State);
+enc_StreamID(Val, State) ->
+ enc_UINT16(Val, State).
+
+enc_EventsDescriptor(Val, State)
+ when is_record(Val, 'EventsDescriptor') ->
+ #'EventsDescriptor'{requestID = RequestId,
+ eventList = Events} = Val,
+ if
+ RequestId == asn1_NOVALUE, Events == [] ->
+ [
+ ?EventsToken
+ ];
+
+ RequestId /= asn1_NOVALUE, Events /= [] ->
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RequestId, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Events, fun enc_RequestedEvent/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end.
+
+enc_RequestedEvent(Val, State)
+ when is_record(Val, 'RequestedEvent') ->
+%% d("enc_RequestedEvent -> entry with"
+%% "~n Val: ~p", [Val]),
+ PkgdName = ?META_ENC(event, Val#'RequestedEvent'.pkgdName),
+%% d("enc_RequestedEvent -> entry with"
+%% "~n PkgdName: ~p", [PkgdName]),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'RequestedEvent'.streamID], fun enc_eventStream/2},
+ {Val#'RequestedEvent'.evParList, fun enc_eventOther/2} |
+ decompose_requestedActions(Val#'RequestedEvent'.eventAction)],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+decompose_requestedActions(asn1_NOVALUE) ->
+ [];
+
+%%
+%% This in the ABNF:
+%% at-most-once each of KeepActiveToken , eventDM and eventStream
+%% at most one of either embedWithSig or embedNoSig but not both
+%% KeepActiveToken and embedWithSig must not both be present
+%%
+
+%% embedWithSig
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD})
+ when (KA =/= true) andalso
+ (SD =/= asn1_NOVALUE) andalso
+ (SD =/= []) ->
+%% d("decompose_requestedActions -> entry with"
+%% "~n EDM: ~p"
+%% "~n SE: ~p"
+%% "~n SD: ~p", [EDM, SE, SD]),
+ [
+ {[EDM], fun enc_EventDM/2},
+ {[{SE, SD}], fun enc_embedWithSig/2}
+ ];
+
+%% embedNoSig
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD})
+ when (SD =:= asn1_NOVALUE) orelse (SD =:= []) ->
+%% d("decompose_requestedActions -> entry with"
+%% "~n KA: ~p"
+%% "~n EDM: ~p"
+%% "~n SE: ~p", [KA, EDM, SE]),
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[SE], fun enc_embedNoSig/2}
+ ];
+
+%% Fallback, if everything else failes....
+decompose_requestedActions(#'RequestedActions'{keepActive = KA,
+ eventDM = EDM,
+ secondEvent = SE,
+ signalsDescriptor = SD}) ->
+%% d("decompose_requestedActions -> entry with"
+%% "~n KA: ~p"
+%% "~n EDM: ~p"
+%% "~n SE: ~p"
+%% "~n SD: ~p", [KA, EDM, SE, SD]),
+ [
+ {[KA], fun enc_keepActive/2},
+ {[EDM], fun enc_EventDM/2},
+ {[{SE, SD}], fun enc_embedWithSig/2}
+ ].
+
+
+enc_embedNoSig(#'SecondEventsDescriptor'{requestID = RID,
+ eventList = Evs}, State) ->
+%% d("enc_embedNoSig -> entry with"
+%% "~n RID: ~p"
+%% "~n Evs: ~p", [RID, Evs]),
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_embedFirst(RID, Evs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_embedWithSig({asn1_NOVALUE, SD}, State) ->
+%% d("enc_embedWithSig -> entry with"
+%% "~n SD: ~p", [SD]),
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(SD, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_embedWithSig({#'SecondEventsDescriptor'{requestID = RID,
+ eventList = Evs}, SD}, State) ->
+%% d("enc_embedWithSig -> entry with"
+%% "~n RID: ~p"
+%% "~n Evs: ~p"
+%% "~n SD: ~p", [RID, Evs, SD]),
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(SD, ?INC_INDENT(State)),
+ ?COMMA_INDENT(?INC_INDENT(State)),
+ enc_embedFirst(RID, Evs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_keepActive(Val, _State) ->
+%% d("enc_keepActive -> entry with"
+%% "~n Val: ~p", [Val]),
+ case Val of
+ true -> [?KeepActiveToken];
+ false -> []
+ end.
+
+enc_EventDM({'EventDM',Val}, State) ->
+ enc_EventDM(Val, State);
+enc_EventDM({Tag, Val}, State) ->
+%% d("enc_EventDM -> entry with"
+%% "~n Tag: ~p"
+%% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ digitMapName ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Val, State)
+ ];
+ digitMapValue ->
+ [
+ ?DigitMapToken,
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+ _ ->
+ error({invalid_EventDM_tag, Tag})
+ end.
+
+enc_embedFirst(RID, Evs, State)
+ when (RID =/= asn1_NOVALUE) andalso is_list(Evs) andalso (Evs =/= []) ->
+%% d("enc_embedFirst -> entry with"
+%% "~n RID: ~p"
+%% "~n Evs: ~p", [RID, Evs]),
+ [
+ ?EventsToken,
+ ?EQUAL,
+ enc_RequestID(RID, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Evs, fun enc_SecondRequestedEvent/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_embedFirst(_RID, _Evs, _State) ->
+%% d("enc_embedFirst -> entry"),
+ [
+ ?EventsToken
+ ].
+
+enc_SecondRequestedEvent(#'SecondRequestedEvent'{pkgdName = N,
+ streamID = SID,
+ evParList = EPL,
+ eventAction = EA},
+ State) ->
+%% d("enc_SecondRequestedEvent -> entry with"
+%% "~n N: ~p"
+%% "~n SID: ~p"
+%% "~n EPL: ~p"
+%% "~n EA: ~p", [N, SID, EPL, EA]),
+ PkgdName = ?META_ENC(event, N),
+ [
+ enc_PkgdName(PkgdName, State),
+ enc_opt_brackets(
+ enc_list(
+ [{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2} |
+ decompose_secondRequestedActions(EA)],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+decompose_secondRequestedActions(asn1_NOVALUE) ->
+ [];
+decompose_secondRequestedActions(Val)
+ when is_record(Val, 'SecondRequestedActions') ->
+%% d("decompose_secondRequestedActions -> entry with"
+%% "~n Val: ~p", [Val]),
+ [
+ {[Val#'SecondRequestedActions'.keepActive],
+ fun enc_keepActive/2},
+ {[Val#'SecondRequestedActions'.eventDM],
+ fun enc_EventDM/2},
+ {[Val#'SecondRequestedActions'.signalsDescriptor],
+ fun enc_embeddedSignalsDescriptor/2}
+ ].
+
+enc_embeddedSignalsDescriptor(Val, State) ->
+ [
+ ?EmbedToken,
+ ?LBRKT_INDENT(State),
+ enc_SignalsDescriptor(Val, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_EventBufferDescriptor({'EventBufferDescriptor',Val}, State) ->
+ enc_EventBufferDescriptor(Val, State);
+enc_EventBufferDescriptor([], _State) ->
+ [
+ ?EventBufferToken
+ ];
+enc_EventBufferDescriptor(EventSpecs, State)
+ when is_list(EventSpecs) and (length(EventSpecs) >= 1) ->
+ [
+ ?EventBufferToken,
+ ?LBRKT_INDENT(State),
+ enc_eventSpecs(EventSpecs, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ];
+enc_EventBufferDescriptor(EventSpecs, _State) ->
+ error({bad_eventSpecs, EventSpecs}).
+
+enc_eventSpecs([Mand | Opt], State) ->
+ [enc_eventSpec(Mand, State),
+ [[?COMMA_INDENT(State), enc_eventSpec(Val, State)] || Val <- Opt]].
+
+enc_eventSpec(#'EventSpec'{eventName = Name,
+ streamID = SID,
+ eventParList = EPL}, State) ->
+ [
+ enc_EventName(Name, State),
+ enc_opt_brackets(
+ enc_list([{[SID], fun enc_eventStream/2},
+ {EPL, fun enc_eventOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_SignalsDescriptor({'SignalsDescriptor',Val}, State) ->
+ enc_SignalsDescriptor(Val, State);
+enc_SignalsDescriptor([], _State) ->
+ [
+ ?SignalsToken
+ ];
+enc_SignalsDescriptor(List, State) when is_list(List) ->
+% d("enc_SignalsDescriptor -> entry with"
+% "~n List: ~p", [List]),
+ [
+ ?SignalsToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_SignalRequest/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_SignalRequest({'SignalRequest',Val}, State) ->
+ enc_SignalRequest(Val, State);
+enc_SignalRequest({Tag, Val}, State) ->
+% d("enc_SignalsDescriptor -> entry with"
+% "~n Tag: ~p"
+% "~n Val: ~p", [Tag, Val]),
+ case Tag of
+ signal ->
+ enc_Signal(Val, State);
+ seqSigList ->
+ enc_SeqSigList(Val, State);
+ _ ->
+ error({invalid_SignalRequest_tag, Tag})
+ end.
+
+
+enc_SeqSigList(Val, State)
+ when is_record(Val, 'SeqSigList') ->
+ [
+ ?SignalListToken,
+ ?EQUAL,
+ enc_UINT16(Val#'SeqSigList'.id, State),
+ ?LBRKT_INDENT(State),
+ enc_list([{Val#'SeqSigList'.signalList, fun enc_Signal/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_Signal(Val, State)
+ when is_record(Val, 'Signal') ->
+ [
+ enc_SignalName(Val#'Signal'.signalName, State),
+ enc_opt_brackets(
+ enc_list([{[Val#'Signal'.streamID], fun enc_sigStream/2},
+ {[Val#'Signal'.sigType], fun enc_sigSignalType/2},
+ {[Val#'Signal'.duration], fun enc_sigDuration/2},
+ {[Val#'Signal'.notifyCompletion], fun enc_notifyCompletion/2},
+ {[Val#'Signal'.keepActive], fun enc_keepActive/2},
+ {Val#'Signal'.sigParList, fun enc_sigOther/2}],
+ ?INC_INDENT(State)),
+ State)
+ ].
+
+enc_sigStream(Val, State) ->
+ [
+ ?StreamToken,
+ ?EQUAL,
+ enc_StreamID(Val, State)
+ ].
+
+enc_sigSignalType(Val, State) ->
+ [
+ ?SignalTypeToken,
+ ?EQUAL,
+ enc_SignalType(Val, State)
+ ].
+
+enc_sigDuration(Val, State) ->
+ [
+ ?DurationToken,
+ ?EQUAL,
+ enc_UINT16(Val, State)
+ ].
+
+enc_notifyCompletion(List, State) when is_list(List) ->
+ [
+ ?NotifyCompletionToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_notifyCompletionItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_notifyCompletionItem(Val, _State) ->
+ case Val of
+ onTimeOut -> ?TimeOutToken;
+ onInterruptByEvent -> ?InterruptByEventToken;
+ onInterruptByNewSignalDescr -> ?InterruptByNewSignalsDescrToken;
+ otherReason -> ?OtherReasonToken
+ end.
+
+enc_SignalType({'SignalType',Val}, State) ->
+ enc_SignalType(Val, State);
+enc_SignalType(Val, _State) ->
+ case Val of
+ brief -> ?BriefToken;
+ onOff -> ?OnOffToken;
+ timeOut -> ?TimeOutToken
+ end.
+
+enc_SignalName({'SignalName',Val}, State)->
+ enc_SignalName(Val, State);
+enc_SignalName(Val, State) ->
+ PkgdName = ?META_ENC(signal, Val),
+ enc_PkgdName(PkgdName, State).
+
+enc_sigOther(Val, State)
+ when is_record(Val, 'SigParameter') ->
+ [
+ enc_Name(Val#'SigParameter'.sigParameterName, State),
+ enc_propertyParmValues(Val#'SigParameter'.value,
+ Val#'SigParameter'.extraInfo,
+ State)
+ ].
+
+enc_RequestID({'RequestID',Val}, State) ->
+ enc_RequestID(Val, State);
+enc_RequestID(Val, _State) when (Val =:= ?megaco_all_request_id) ->
+ "*";
+enc_RequestID(Val, State) ->
+ enc_UINT32(Val, State).
+
+enc_ModemDescriptor(MD, _State) ->
+ error({deprecated, MD}).
+
+%% Corr1:
+%% As of corr 1 ModemDescriptor has been deprecated.
+%% 7.1.2: ...shall not be included as part of a transmitted content and,
+%% if received, shall either be ignored or processed at the option
+%% of the implementation. ...
+%% enc_ModemDescriptor(#'ModemDescriptor'{mtl = [Val],
+%% mpl = [],
+%% nonStandardData = asn1_NOVALUE},
+%% State) ->
+%% [
+%% ?ModemToken,
+%% ?EQUAL,
+%% enc_ModemType(Val, State)
+%% ];
+%% enc_ModemDescriptor(Val, State)
+%% when is_record(Val, 'ModemDescriptor') ->
+%% [
+%% ?ModemToken,
+%% ?LSBRKT,
+%% enc_list([{Val#'ModemDescriptor'.mtl, fun enc_ModemType/2}], State),
+%% ?RSBRKT,
+%% enc_opt_brackets(
+%% enc_list([{Val#'ModemDescriptor'.mpl, fun enc_PropertyParm/2}],
+%% ?INC_INDENT(State)),
+%% State)
+%% %% BUGBUG: Is PropertyParm == NAME parmValue?
+%% ].
+
+%% enc_ModemDescriptor(Val, State)
+%% when is_record(Val, 'ModemDescriptor') ->
+%% [
+%% ?ModemToken,
+%% %% BUGBUG: Does never generate: EQUAL modemType
+%% ?LSBRKT,
+%% enc_list([{Val#'ModemDescriptor'.mtl, fun enc_ModemType/2}], State),
+%% ?RSBRKT,
+%% enc_opt_brackets(
+%% enc_list([{Val#'ModemDescriptor'.mpl, fun enc_PropertyParm/2}],
+%% ?INC_INDENT(State)),
+%% State)
+%% %% BUGBUG: Is PropertyParm == NAME parmValue?
+%% ].
+
+%% Corr1: See ModemDescriptor above
+%% enc_ModemType({'ModemType',Val}, State)->
+%% enc_ModemType(Val, State);
+%% enc_ModemType(Val, _State) ->
+%% %% BUGBUG: Does not handle extensionParameter
+%% case Val of
+%% v18 -> ?V18Token;
+%% v22 -> ?V22Token;
+%% v22bis -> ?V22bisToken;
+%% v32 -> ?V32Token;
+%% v32bis -> ?V32bisToken;
+%% v34 -> ?V34Token;
+%% v90 -> ?V90Token;
+%% v91 -> ?V91Token;
+%% synchISDN -> ?SynchISDNToken
+%% end.
+
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = asn1_NOVALUE,
+ digitMapValue = Value} = Val,
+ State)
+ when (Value =/= asn1_NOVALUE) ->
+ case is_empty_DigitMapValue(Value) of
+ true ->
+ error({invalid_DigitMapDescriptor, Val});
+ false ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Value, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = asn1_NOVALUE},
+ State)
+ when (Name =/= asn1_NOVALUE) ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ];
+enc_DigitMapDescriptor(#'DigitMapDescriptor'{digitMapName = Name,
+ digitMapValue = Value},
+ State)
+ when (Name =/= asn1_NOVALUE) andalso (Value =/= asn1_NOVALUE) ->
+ case is_empty_DigitMapValue(Value) of
+ true ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State)
+ ];
+ false ->
+ [
+ ?DigitMapToken,
+ ?EQUAL,
+ enc_DigitMapName(Name, State),
+ ?LBRKT_INDENT(State),
+ enc_DigitMapValue(Value, ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ]
+ end;
+enc_DigitMapDescriptor(BadVal, _State) ->
+ error({invalid_DigitMapDescriptor, BadVal}).
+
+enc_DigitMapName({'DigitMapName',Val}, State) ->
+ enc_DigitMapName(Val, State);
+enc_DigitMapName(Val, State) ->
+ enc_Name(Val, State).
+
+is_empty_DigitMapValue(#'DigitMapValue'{startTimer = asn1_NOVALUE,
+ shortTimer = asn1_NOVALUE,
+ longTimer = asn1_NOVALUE,
+ digitMapBody = [],
+ durationTimer = asn1_NOVALUE}) ->
+ true;
+is_empty_DigitMapValue(#'DigitMapValue'{}) ->
+ false.
+
+enc_DigitMapValue(Val, State)
+ when is_record(Val, 'DigitMapValue') ->
+ [
+ enc_timer(Val#'DigitMapValue'.startTimer, $T, State),
+ enc_timer(Val#'DigitMapValue'.shortTimer, $S, State),
+ enc_timer(Val#'DigitMapValue'.longTimer, $L, State),
+ enc_timer(Val#'DigitMapValue'.durationTimer, $Z, State),
+ %% BUGBUG: digitMapBody not handled at all
+ enc_STRING(Val#'DigitMapValue'.digitMapBody, State, 0, infinity)
+ ].
+
+enc_timer(asn1_NOVALUE, _Prefix, _State) ->
+ [];
+enc_timer(Timer, Prefix, State) ->
+ [
+ Prefix,
+ ?COLON,
+ enc_DIGIT(Timer, State, 0, 99),
+ ?COMMA_INDENT(State)
+ ].
+
+
+enc_ServiceChangeParm(Val, State)
+ when is_record(Val, 'ServiceChangeParm') ->
+ [
+ ?ServicesToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{[Val#'ServiceChangeParm'.serviceChangeMethod],
+ fun enc_ServiceChangeMethod/2},
+ {[Val#'ServiceChangeParm'.serviceChangeAddress],
+ fun enc_ServiceChangeAddress/2},
+ {[Val#'ServiceChangeParm'.serviceChangeVersion],
+ fun enc_serviceChangeVersion/2},
+ {[Val#'ServiceChangeParm'.serviceChangeProfile],
+ fun enc_ServiceChangeProfile/2},
+ {[{reason, Val#'ServiceChangeParm'.serviceChangeReason}],
+ fun enc_serviceChangeReason/2},
+ {[Val#'ServiceChangeParm'.serviceChangeDelay],
+ fun enc_serviceChangeDelay/2},
+ {[Val#'ServiceChangeParm'.serviceChangeMgcId],
+ fun enc_serviceChangeMgcId/2},
+ {[Val#'ServiceChangeParm'.timeStamp],
+ fun enc_TimeNotation/2},
+ {Val#'ServiceChangeParm'.serviceChangeInfo,
+ fun enc_AuditDescriptor/2}],
+ ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+
+enc_ServiceChangeMethod({'ServiceChangeMethod',Val}, State) ->
+ enc_ServiceChangeMethod(Val, State);
+enc_ServiceChangeMethod(Val, _State) ->
+ [
+ ?MethodToken,
+ ?EQUAL,
+ case Val of
+ failover -> ?FailoverToken;
+ forced -> ?ForcedToken;
+ graceful -> ?GracefulToken;
+ restart -> ?RestartToken;
+ disconnected -> ?DisconnectedToken;
+ handOff -> ?HandOffToken
+ end
+ %% BUGBUG: extension
+ ].
+
+enc_ServiceChangeAddress({'ServiceChangeAddress',Val}, State) ->
+ enc_ServiceChangeAddress(Val, State);
+enc_ServiceChangeAddress({Tag, Val}, State) ->
+ [
+ ?ServiceChangeAddressToken,
+ ?EQUAL,
+ case Tag of
+ portNumber ->
+ enc_portNumber(Val, State);
+ ip4Address ->
+ enc_IP4Address(Val, State);
+ ip6Address ->
+ enc_IP6Address(Val, State);
+ domainName ->
+ enc_DomainName(Val, State);
+ deviceName ->
+ enc_PathName(Val, State);
+ mtpAddress ->
+ enc_mtpAddress(Val, State);
+ _ ->
+ error({invalid_ServiceChangeAddress_tag, Tag})
+ end
+ ].
+
+enc_serviceChangeVersion(Val, State) ->
+ [
+ ?VersionToken,
+ ?EQUAL,
+ enc_version(Val, State)
+ ].
+
+enc_ServiceChangeProfile(#'ServiceChangeProfile'{profileName = Name,
+ version = Version},
+ State) ->
+ [
+ ?ProfileToken,
+ ?EQUAL,
+ enc_Name(Name, State),
+ ?SLASH,
+ enc_version(Version, State)
+ ].
+
+enc_serviceChangeReason({reason, Val}, State) ->
+ case Val of
+ asn1_NOVALUE ->
+ [];
+ [List] when is_list(List) ->
+ [
+ ?ReasonToken,
+ ?EQUAL,
+ enc_QUOTED_STRING(List,State) % OTP-4632 enc_Value(List, State)
+ ]
+ end.
+
+enc_serviceChangeDelay(Val, State) ->
+ [
+ ?DelayToken,
+ ?EQUAL,
+ enc_UINT32(Val, State)
+ ].
+
+enc_serviceChangeMgcId(Val, State) ->
+ [
+ ?MgcIdToken,
+ ?EQUAL,
+ enc_MId(Val, State)
+ ].
+
+enc_portNumber(Val, State) when is_integer(Val) andalso (Val >= 0) ->
+ enc_UINT16(Val, State).
+
+enc_ServiceChangeResParm(Val, State)
+ when is_record(Val, 'ServiceChangeResParm') ->
+ enc_list([{[Val#'ServiceChangeResParm'.serviceChangeAddress],
+ fun enc_ServiceChangeAddress/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeVersion],
+ fun enc_serviceChangeVersion/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeProfile],
+ fun enc_ServiceChangeProfile/2},
+ {[Val#'ServiceChangeResParm'.serviceChangeMgcId],
+ fun enc_serviceChangeMgcId/2},
+ {[Val#'ServiceChangeResParm'.timeStamp],
+ fun enc_TimeNotation/2}],
+ State).
+
+enc_PackagesDescriptor({'PackagesDescriptor',Val}, State) ->
+ enc_PackagesDescriptor(Val, State);
+enc_PackagesDescriptor(Val, State) ->
+ [
+ ?PackagesToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{Val, fun enc_PackagesItem/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_PackagesItem(Val, State)
+ when is_record(Val, 'PackagesItem') ->
+ PkgdName = ?META_ENC(package, Val#'PackagesItem'.packageName),
+ [
+ enc_Name(PkgdName, State),
+ "-",
+ enc_UINT16(Val#'PackagesItem'.packageVersion, State)
+ ].
+
+enc_StatisticsDescriptor({'StatisticsDescriptor',Val}, State) ->
+ enc_StatisticsDescriptor(Val, State);
+enc_StatisticsDescriptor(List, State) when is_list(List) ->
+ [
+ ?StatsToken,
+ ?LBRKT_INDENT(State),
+ enc_list([{List, fun enc_StatisticsParameter/2}], ?INC_INDENT(State)),
+ ?RBRKT_INDENT(State)
+ ].
+
+enc_StatisticsParameter(Val, State)
+ when is_record(Val, 'StatisticsParameter') ->
+ PkgdName = ?META_ENC(statistics, Val#'StatisticsParameter'.statName),
+ case Val#'StatisticsParameter'.statValue of
+ asn1_NOVALUE ->
+ [
+ enc_PkgdName(PkgdName, State)
+ ];
+ [StatVal] when is_list(StatVal) ->
+ [
+ enc_PkgdName(PkgdName, State),
+ ?EQUAL,
+ enc_Value(StatVal, State)
+ ]
+ end.
+
+enc_TimeNotation(Val, State)
+ when is_record(Val, 'TimeNotation') ->
+ [
+ enc_STRING(Val#'TimeNotation'.date, State, 8, 8), % "yyyymmdd"
+ "T",
+ enc_STRING(Val#'TimeNotation'.time, State, 8, 8) % "hhmmssss"
+ ].
+
+%% BUGBUG: Does not verify that string must contain at least one char
+%% BUGBUG: This violation of the is required in order to comply with
+%% BUGBUG: the dd/ce ds parameter that may possibly be empty.
+enc_Value({'Value',Val}, State) ->
+ enc_Value(Val, State);
+enc_Value(String, _State) ->
+ case quoted_string_count(String, 0, true, false) of
+ {_, 0, _} ->
+ [?DQUOTE, String, ?DQUOTE];
+ {false, _, _} ->
+ [?DQUOTE, String, ?DQUOTE];
+ {true, _, _} ->
+ [String]
+ end.
+
+quoted_string_count([?DoubleQuoteToken | T], 0 = Count, _IsSafe, _MaybeQuoted) ->
+ %% Already a quoted string. Make sure it ends
+ quoted_string_count(T, Count + 1, true, true);
+quoted_string_count([?DoubleQuoteToken], Count, IsSafe, true = MaybeQuoted) ->
+ %% An explicitly quoted string
+ {IsSafe, Count, MaybeQuoted};
+quoted_string_count([H | T], Count, IsSafe, MaybeQuoted) ->
+ case ?classify_char(H) of
+ safe_char_upper -> quoted_string_count(T, Count + 1, IsSafe, MaybeQuoted);
+ safe_char -> quoted_string_count(T, Count + 1, IsSafe, MaybeQuoted);
+ rest_char -> quoted_string_count(T, Count + 1, false, MaybeQuoted);
+ white_space -> quoted_string_count(T, Count + 1, false, MaybeQuoted);
+ _ -> error({illegal_char, H})
+ end;
+quoted_string_count([], _Count, _IsSafe, true = _MaybeQuoted) ->
+ error({illegal_char, ?DoubleQuoteToken});
+quoted_string_count([], Count, IsSafe, MaybeQuoted) ->
+ {IsSafe, Count, MaybeQuoted}.
+
+enc_DigitString(String, _State) when is_list(String) ->
+ [?DQUOTE, String, ?DQUOTE].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Encode an octet string, escape } by \ if necessary
+enc_OCTET_STRING(List, State, Min, Max) ->
+ do_enc_OCTET_STRING(List, State, Min, Max, 0).
+
+do_enc_OCTET_STRING([H | T], State, Min, Max, Count) ->
+ case H of
+ $} ->
+ [$\\, H | do_enc_OCTET_STRING(T, State, Min, Max, Count + 1)];
+ _ ->
+ [H | do_enc_OCTET_STRING(T, State, Min, Max, Count + 1)]
+ end;
+do_enc_OCTET_STRING([], _State, Min, Max, Count) ->
+ verify_count(Count, Min, Max),
+ [].
+
+enc_QUOTED_STRING(String, _State) when is_list(String) ->
+ case quoted_string_count(String, 0, true, false) of
+ {_IsSafe, Count, false = _QuotedString} ->
+ verify_count(Count, 1, infinity),
+ [?DQUOTE, String, ?DQUOTE];
+ {_IsSafe, Count, true = _QuotedString} ->
+ verify_count(Count, 3, infinity), % quotes not included in the count
+ [String]
+ end.
+
+%% The internal format of hex digits is a list of octets
+%% Min and Max means #hexDigits
+%% Leading zeros are prepended in order to fulfill Min
+enc_HEXDIG(Octets, State, Min, Max) when is_list(Octets) ->
+ do_enc_HEXDIG(Octets, State, Min, Max, 0, []).
+
+do_enc_HEXDIG([Octet | Rest], State, Min, Max, Count, Acc)
+ when (Octet >= 0) andalso (Octet =< 255) ->
+ Hex = hex(Octet), % OTP-4921
+ if
+ Octet =< 15 ->
+ Acc2 = [[$0|Hex]|Acc], % OTP-4921
+ do_enc_HEXDIG(Rest, State, Min, Max, Count + 2, ["0" | Acc2]);
+ true ->
+ Acc2 = [Hex|Acc], % OTP-4921
+ do_enc_HEXDIG(Rest, State, Min, Max, Count + 2, Acc2)
+ end;
+do_enc_HEXDIG([], State, Min, Max, Count, Acc)
+ when is_integer(Min) andalso (Count < Min) ->
+ do_enc_HEXDIG([0], State, Min, Max, Count, Acc);
+do_enc_HEXDIG([], _State, Min, Max, Count, Acc) -> %% OTP-4710
+ verify_count(Count, Min, Max),
+ lists:reverse(Acc).
+
+enc_DIGIT(Val, State, Min, Max) ->
+ enc_integer(Val, State, Min, Max).
+
+enc_STRING(String, _State, Min, Max) when is_list(String) ->
+ verify_count(length(String), Min, Max),
+ String.
+
+enc_UINT16(Val, State) ->
+ enc_integer(Val, State, 0, 65535).
+
+enc_UINT32(Val, State) ->
+ enc_integer(Val, State, 0, 4294967295).
+
+enc_integer(Val, _State, Min, Max) ->
+ verify_count(Val, Min, Max),
+ integer_to_list(Val).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Encodes a list of elements with separator tokens between
+%% the elements. Optional asn1_NOVALUE values are ignored.
+
+enc_list(List, State) ->
+ enc_list(List, State, fun(_S) -> ?COMMA_INDENT(_S) end, false).
+
+enc_list([], _State, _SepEncoder, _NeedsSep) ->
+ [];
+enc_list([{Elems, ElemEncoder} | Tail], State, SepEncoder, NeedsSep) ->
+ case do_enc_list(Elems, State, ElemEncoder, SepEncoder, NeedsSep) of
+ [] ->
+ enc_list(Tail, State, SepEncoder, NeedsSep);
+ List ->
+ [List,
+ enc_list(Tail, State, SepEncoder, true)]
+ end;
+enc_list(A, B, C, D) ->
+ error({invlid_list, A, B, C, D}).
+
+do_enc_list(asn1_NOVALUE, _State, _ElemEncoder, _SepEncoder, _NeedsSep) ->
+ [];
+do_enc_list([], _State, _ElemEncoder, _SepEncoder, _NeedsSep) ->
+ [];
+do_enc_list([asn1_NOVALUE | T], State, ElemEncoder, SepEncoder, NeedsSep) ->
+ do_enc_list(T, State, ElemEncoder, SepEncoder, NeedsSep);
+do_enc_list([H | T], State, ElemEncoder, SepEncoder, NeedsSep)
+ when is_function(ElemEncoder) andalso is_function(SepEncoder) ->
+ case ElemEncoder(H, State) of
+ [] ->
+ do_enc_list(T, State, ElemEncoder, SepEncoder, NeedsSep);
+ List when NeedsSep =:= true ->
+ [SepEncoder(State),
+ List, do_enc_list(T, State, ElemEncoder, SepEncoder, true)];
+ List when NeedsSep =:= false ->
+ [List,
+ do_enc_list(T, State, ElemEncoder, SepEncoder, true)]
+ end.
+
+%% Add brackets if list is non-empty
+enc_opt_brackets([], _State) ->
+ [];
+enc_opt_brackets(List, _State) when is_list(List) ->
+ [?LBRKT_INDENT(_State), List, ?RBRKT_INDENT(_State)].
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Int -> list of hex chars
+hex(Int) ->
+ hexi(get_lo_bits(Int, 4), []).
+
+hexi({0, Lo}, Ack) ->
+ [hex4(Lo) | Ack];
+hexi({Hi, Lo} , Ack) ->
+ hexi(get_lo_bits(Hi, 4), [hex4(Lo) | Ack]).
+
+hex4(Int) when Int < 10 ->
+ Int + $0;
+hex4(Int) ->
+ ($A - 10) + Int.
+
+get_lo_bits(Int, Size) ->
+ Lo = Int band ones_mask(Size),
+ Hi = Int bsr Size,
+ {Hi, Lo}.
+
+ones_mask(Ones) ->
+ (1 bsl Ones) - 1.
+
+%% Verify that Count is within the range of Min and Max
+verify_count(Count, Min, Max) ->
+ if
+ is_integer(Count) ->
+ if
+ is_integer(Min) andalso (Count >= Min) ->
+ if
+ is_integer(Max) andalso (Count =< Max) ->
+ Count;
+ Max =:= infinity ->
+ Count;
+ true ->
+ error({count_too_large, Count, Max})
+ end;
+ true ->
+ error({count_too_small, Count, Min})
+ end;
+ true ->
+ error({count_not_an_integer, Count})
+ end.
+
+
+%% -------------------------------------------------------------------
+
+error(Reason) ->
+ erlang:error(Reason).
+
+
+%% -------------------------------------------------------------------
+
+%% d(F) ->
+%% d(F,[]).
+%% d(F, A) ->
+%% %% d(true, F, A).
+%% d(get(dbg), F, A).
+
+%% d(true, F, A) ->
+%% io:format("~p:" ++ F ++ "~n", [?MODULE | A]);
+%% d(_, _, _) ->
+%% ok.
+
+