aboutsummaryrefslogtreecommitdiffstats
path: root/lib/megaco/src/binary/megaco_binary_encoder_lib.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/megaco/src/binary/megaco_binary_encoder_lib.erl')
-rw-r--r--lib/megaco/src/binary/megaco_binary_encoder_lib.erl317
1 files changed, 317 insertions, 0 deletions
diff --git a/lib/megaco/src/binary/megaco_binary_encoder_lib.erl b/lib/megaco/src/binary/megaco_binary_encoder_lib.erl
new file mode 100644
index 0000000000..842d6b70d1
--- /dev/null
+++ b/lib/megaco/src/binary/megaco_binary_encoder_lib.erl
@@ -0,0 +1,317 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-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 : Handle ASN.1 BER encoding of Megaco/H.248
+%%----------------------------------------------------------------------
+
+-module(megaco_binary_encoder_lib).
+
+%% API
+-export([
+ version_of/4,
+ decode_message/5, decode_message_dynamic/4,
+ decode_mini_message/4, decode_mini_message_dynamic/4,
+ encode_message/5,
+ encode_transaction/5,
+ encode_action_requests/5,
+ encode_action_request/5,
+ encode_action_reply/5
+ ]).
+
+-include_lib("megaco/src/engine/megaco_message_internal.hrl").
+
+
+%%----------------------------------------------------------------------
+%% Detect (check) which version a message is
+%% Return {ok, Version} | {error, Reason}
+%%----------------------------------------------------------------------
+
+version_of(_EC, Binary, dynamic, [AsnModV1|_AsnMods])
+ when is_binary(Binary) andalso is_atom(AsnModV1) ->
+ case (catch AsnModV1:decode_message_version(Binary)) of
+ {ok, PartialMsg} ->
+ V = (PartialMsg#'MegacoMessage'.mess)#'Message'.version,
+ {ok, V};
+ Error ->
+ Error
+ end;
+version_of(_EC, Binary, 1, AsnMods)
+ when is_binary(Binary) andalso is_list(AsnMods) ->
+ version_of(AsnMods, Binary, []);
+version_of(_EC, Binary, 2, [AsnModV1, AsnModV2, AsnModV3])
+ when is_binary(Binary) ->
+ version_of([AsnModV2, AsnModV1, AsnModV3], Binary, []);
+version_of(_EC, Binary, 3, [AsnModV1, AsnModV2, AsnModV3])
+ when is_binary(Binary) ->
+ version_of([AsnModV3, AsnModV1, AsnModV2], Binary, []).
+
+version_of([], _Binary, Err) ->
+ {error, {decode_failed, lists:reverse(Err)}};
+version_of([AsnMod|AsnMods], Binary, Errs) when is_atom(AsnMod) ->
+ case (catch asn1rt:decode(AsnMod, 'MegacoMessage', Binary)) of
+ {ok, M} ->
+ V = (M#'MegacoMessage'.mess)#'Message'.version,
+ {ok, V};
+ Err ->
+ version_of(AsnMods, Binary, [Err|Errs])
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Convert a 'MegacoMessage' record into a binary
+%% Return {ok, Binary} | {error, Reason}
+%%----------------------------------------------------------------------
+
+encode_message([native], MegaMsg, AsnMod, _TransMod, binary)
+ when is_record(MegaMsg, 'MegacoMessage') ->
+ asn1rt:encode(AsnMod, 'MegacoMessage', MegaMsg);
+encode_message(EC, MegaMsg, AsnMod, TransMod, binary)
+ when is_list(EC) andalso is_record(MegaMsg, 'MegacoMessage') ->
+ case (catch TransMod:tr_message(MegaMsg, encode, EC)) of
+ {'EXIT', Reason} ->
+ {error, Reason};
+ MegaMsg2 ->
+ asn1rt:encode(AsnMod, 'MegacoMessage', MegaMsg2)
+ end;
+encode_message(EC, MegaMsg, AsnMod, TransMod, io_list) ->
+ case encode_message(EC, MegaMsg, AsnMod, TransMod, binary) of
+ {ok, Bin} when is_binary(Bin) ->
+ {ok, Bin};
+ {ok, DeepIoList} ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin};
+ {error, Reason} ->
+ {error, Reason}
+ end;
+encode_message(EC, MegaMsg, _AsnMod, _TransMod, _Type)
+ when is_record(MegaMsg, 'MegacoMessage') ->
+ {error, {bad_encoding_config, EC}};
+encode_message(_EC, MegaMsg, _AsnMod, _TransMod, _Type) ->
+ {error, {no_megaco_message, MegaMsg}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a transaction (or transactions in the case of ack) record(s)
+%% into a binary
+%% Return {ok, Binary} | {error, Reason}
+%%----------------------------------------------------------------------
+
+%% Should handle encoding of all types of transactions:
+%% TransactionAck, TransactionPending, TransactionRequest
+%% and TransactionReply
+encode_transaction(EC, {Tag, _} = Trans, AsnMod, TransMod, Type)
+ when (Tag == transactionResponseAck) ->
+ do_encode_transaction(EC, Trans, AsnMod, TransMod, Type);
+encode_transaction(EC, {Tag, _} = Trans, AsnMod, TransMod, Type)
+ when (Tag == transactionPending) ->
+ do_encode_transaction(EC, Trans, AsnMod, TransMod, Type);
+encode_transaction(EC, {Tag, _} = Trans, AsnMod, TransMod, Type)
+ when (Tag == transactionRequest) ->
+ do_encode_transaction(EC, Trans, AsnMod, TransMod, Type);
+%% TransactionReply has been changed as of v3 so we cannot use
+%% the record definition in this common module.
+encode_transaction(EC, {Tag, _} = Trans, AsnMod, TransMod, Type)
+ when (Tag == transactionReply) ->
+ do_encode_transaction(EC, Trans, AsnMod, TransMod, Type);
+encode_transaction(_EC, T, _AsnMod, _TransMod, _Type) ->
+ {error, {no_megaco_transaction, T}}.
+
+do_encode_transaction([native], _Trans, _AsnMod, _TransMod, binary) ->
+ %% asn1rt:encode(AsnMod, element(1, T), T);
+ {error, not_implemented};
+do_encode_transaction(EC, _Trans, _AsnMod, _TransMod, binary)
+ when is_list(EC) ->
+ %% T2 = TransMod:tr_transaction(Trans, encode, EC),
+ %% asn1rt:encode(AsnMod, element(1, T), T2);
+ {error, not_implemented};
+do_encode_transaction(EC, Trans, AsnMod, TransMod, io_list) ->
+ case do_encode_transaction(EC, Trans, AsnMod, TransMod, binary) of
+ {ok, Bin} when is_binary(Bin) ->
+ {ok, Bin};
+ {ok, DeepIoList} ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin};
+ {error, Reason} ->
+ {error, Reason}
+ end;
+do_encode_transaction(EC, _Trans, _AsnMod, _TransMod, _Type) ->
+ {error, {bad_encoding_config, EC}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a list of ActionRequest record's into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_requests([native], _ARs, _AsnMod, _TransMod, binary) ->
+ %% asn1rt:encode(AsnMod, element(1, T), T);
+ {error, not_implemented};
+encode_action_requests(_EC, _ARs0, _AsnMod, _TransMod, binary) ->
+ {error, not_implemented};
+encode_action_requests(EC, ARs, AsnMod, TransMod, io_list) ->
+ case encode_action_requests(EC, ARs, AsnMod, TransMod, binary) of
+ {ok, Bin} when is_binary(Bin) ->
+ {ok, Bin};
+ {ok, DeepIoList} ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin};
+ {error, Reason} ->
+ {error, Reason}
+ end;
+encode_action_requests(EC, _ARs, _AsnMod, _TransMod, _Type) ->
+ {error, {bad_encoding_config, EC}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a ActionRequest record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_request([native], _ARs, _AsnMod, _TransMod, binary) ->
+ %% asn1rt:encode(AsnMod, element(1, T), T);
+ {error, not_implemented};
+encode_action_request(_EC, _ARs0, _AsnMod, _TransMod, binary) ->
+ {error, not_implemented};
+encode_action_request(EC, ARs, AsnMod, TransMod, io_list) ->
+ case encode_action_request(EC, ARs, AsnMod, TransMod, binary) of
+ {ok, Bin} when is_binary(Bin) ->
+ {ok, Bin};
+ {ok, DeepIoList} ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin};
+ {error, Reason} ->
+ {error, Reason}
+ end;
+encode_action_request(EC, _ARs, _AsnMod, _TransMod, _Type) ->
+ {error, {bad_encoding_config, EC}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a ActionReply record into a binary
+%% Return {ok, DeepIoList} | {error, Reason}
+%%----------------------------------------------------------------------
+encode_action_reply([native], _ARs, _AsnMod, _TransMod, binary) ->
+ %% asn1rt:encode(AsnMod, element(1, T), T);
+ {error, not_implemented};
+encode_action_reply(_EC, _ARs0, _AsnMod, _TransMod, binary) ->
+ {error, not_implemented};
+encode_action_reply(EC, ARs, AsnMod, TransMod, io_list) ->
+ case encode_action_reply(EC, ARs, AsnMod, TransMod, binary) of
+ {ok, Bin} when is_binary(Bin) ->
+ {ok, Bin};
+ {ok, DeepIoList} ->
+ Bin = erlang:list_to_binary(DeepIoList),
+ {ok, Bin};
+ {error, Reason} ->
+ {error, Reason}
+ end;
+encode_action_reply(EC, _ARs, _AsnMod, _TransMod, _Type) ->
+ {error, {bad_encoding_config, EC}}.
+
+
+%%----------------------------------------------------------------------
+%% Convert a binary into a 'MegacoMessage' record
+%% Return {ok, MegacoMessageRecord} | {error, Reason}
+%%----------------------------------------------------------------------
+
+decode_message_dynamic(EC, Bin,
+ [{AsnModV1, TransModV1},
+ {AsnModV2, TransModV2},
+ {AsnModV3, TransModV3}], Form)
+ when is_list(EC) andalso is_binary(Bin) ->
+ case AsnModV1:decode_message_version(Bin) of
+ {ok, PartialMsg} ->
+ V = (PartialMsg#'MegacoMessage'.mess)#'Message'.version,
+ case V of
+ 1 ->
+ decode_message(EC, Bin, AsnModV1, TransModV1, Form);
+ 2 ->
+ decode_message(EC, Bin, AsnModV2, TransModV2, Form);
+ 3 ->
+ decode_message(EC, Bin, AsnModV3, TransModV3, Form)
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end;
+decode_message_dynamic(EC, Bin, _Mods, _Type)
+ when is_binary(Bin) ->
+ {error, {bad_encoding_config, EC}};
+decode_message_dynamic(_EC, _BadBin, _Mods, _Type) ->
+ {error, no_binary}.
+
+
+decode_message(EC, Bin, AsnMod, TransMod, binary) ->
+ case asn1rt:decode(AsnMod, 'MegacoMessage', Bin) of
+ {ok, MegaMsg} ->
+ case EC of
+ [native] ->
+ {ok, MegaMsg};
+ _ ->
+ {ok, TransMod:tr_message(MegaMsg, decode, EC)}
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end;
+decode_message(EC, Bin, AsnMod, TransMod, io_list) ->
+ ShallowIoList = erlang:binary_to_list(Bin),
+ case asn1rt:decode(AsnMod, 'MegacoMessage', ShallowIoList) of
+ {ok, MegaMsg} ->
+ case EC of
+ [native] ->
+ {ok, MegaMsg};
+ _ ->
+ {ok, TransMod:tr_message(MegaMsg, decode, EC)}
+ end;
+ {error, Reason} ->
+ {error, Reason}
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Convert a binary into a partial 'MegacoMessage' record
+%% I.e. only version and Mid is fully decoded.
+%% Return {ok, MegacoMessageRecord} | {error, Reason}
+%%----------------------------------------------------------------------
+
+decode_mini_message(_, Bin, Mod, _) ->
+ case (catch Mod:decode_message_mId(Bin)) of
+ {ok, #'MegacoMessage'{mess = Mess} = MegaMsg} ->
+ Mess2 = Mess#'Message'{messageBody = undefined},
+ {ok, MegaMsg#'MegacoMessage'{mess = Mess2}};
+ Error ->
+ Error
+ end.
+
+
+decode_mini_message_dynamic(EC, Bin, [Mod1, Mod2, Mod3], Form) ->
+ case Mod1:decode_message_version(Bin) of
+ {ok, PartialMsg} ->
+ V = (PartialMsg#'MegacoMessage'.mess)#'Message'.version,
+ case V of
+ 1 ->
+ decode_mini_message(EC, Bin, Mod1, Form);
+ 2 ->
+ decode_mini_message(EC, Bin, Mod2, Form);
+ 3 ->
+ decode_mini_message(EC, Bin, Mod3, Form)
+ end;
+ Error ->
+ Error
+ end.
+