aboutsummaryrefslogtreecommitdiffstats
path: root/lib/megaco/examples/meas/megaco_codec_transform.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/megaco/examples/meas/megaco_codec_transform.erl')
-rw-r--r--lib/megaco/examples/meas/megaco_codec_transform.erl305
1 files changed, 305 insertions, 0 deletions
diff --git a/lib/megaco/examples/meas/megaco_codec_transform.erl b/lib/megaco/examples/meas/megaco_codec_transform.erl
new file mode 100644
index 0000000000..cfe832ff26
--- /dev/null
+++ b/lib/megaco/examples/meas/megaco_codec_transform.erl
@@ -0,0 +1,305 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2002-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: Megaco message transformation
+%%
+%% Usage: From a base message file, messages for every codec is
+%% generated. The file should have the following structure:
+%%
+%% {Codec, Messages}.
+%%
+%% Codec = pretty | compact | ber | per | erlang
+%% Messages = [{Name, binary()}]
+%% Name = atom
+%%
+%% The function messages/0 is used by the meas and mstone
+%% tools, but messages/1 can also be used if another base
+%% message file is to be used.
+%%
+%% The messages can also be exported to the old format,
+%% e.g. a directory for each of the codec's and the
+%% each message as a file in those directories.
+%%
+%% Pretty text: pretty
+%% Compact text: compact
+%% Binary ber: ber
+%% Binary per: per
+%% Erlang: erlang
+%%
+%%
+%% <message package>/pretty/<message-files>
+%% compact/<message-files>
+%% per/<message-files>
+%% ber/<message-files>
+%% erlang/<message-files>
+%%
+%%----------------------------------------------------------------------
+
+-module(megaco_codec_transform).
+
+-include_lib("kernel/include/file.hrl").
+
+-export([
+ codecs/0,
+ default_message_package/0,
+ messages/0, messages/1,
+ export_messages/0, export_messages/1
+ ]).
+
+-define(DEFAULT_MESSAGE_PACKAGE, time_test).
+-define(ALL_CODECS, [pretty, compact, per, ber, erlang]).
+-define(V3, v3).
+
+codecs() ->
+ ?ALL_CODECS.
+
+default_message_package() ->
+ ?DEFAULT_MESSAGE_PACKAGE.
+
+messages() ->
+ messages(?DEFAULT_MESSAGE_PACKAGE).
+
+messages(MessagePackage) when is_atom(MessagePackage) ->
+ %% Try the CWD first, and if that does not work try the installation directory
+ case load_messages(".", MessagePackage) of
+ {error, _Reason} ->
+ AppLibDir = code:lib_dir(megaco),
+ Dir = filename:join([AppLibDir, examples, meas]),
+ load_messages(Dir, MessagePackage);
+ Else ->
+ Else
+ end.
+
+load_messages(Dir, MessagePackage) ->
+ %% io:format("try loading messages from ~s~n", [Dir]),
+ Filename = filename:join([Dir, atom_to_list(MessagePackage) ++ ".msgs"]),
+ case file:consult(Filename) of
+ {ok, [{Codec, Msgs}]} when is_atom(Codec) andalso is_list(Msgs) ->
+ case lists:member(Codec, ?ALL_CODECS) of
+ true ->
+ messages(Codec, Msgs);
+ false ->
+ {error, {unknown_codec, Codec}}
+ end;
+
+ {ok, [{BadCodec, Msgs}]} when is_list(Msgs) ->
+ {error, {bad_codec, BadCodec}};
+
+ %% No codec specified, try with pretty
+ {ok, [Msgs]} when is_list(Msgs) ->
+ messages(pretty, Msgs);
+
+ {ok, Crap} ->
+ {error, {bad_messages, Crap}};
+
+ Error ->
+ Error
+ end.
+
+messages(BaseCodec, Msgs) ->
+ OutCodecs = lists:delete(BaseCodec, ?ALL_CODECS),
+ transform_messages(BaseCodec, Msgs, OutCodecs).
+
+
+export_messages() ->
+ export_messages(?DEFAULT_MESSAGE_PACKAGE).
+
+export_messages(MessagePackage) when is_atom(MessagePackage) ->
+ case messages(MessagePackage) of
+ TMsgs when is_list(TMsgs) ->
+ (catch export_messages(MessagePackage, TMsgs));
+ Error ->
+ Error
+ end.
+
+export_messages(MessagePackage, TMsgs) ->
+ case file:make_dir(MessagePackage) of
+ ok ->
+ ok;
+ {error, eexist} ->
+ ok;
+ Error ->
+ throw(Error)
+ end,
+ do_export_messages(MessagePackage, TMsgs).
+
+do_export_messages(_MessagePackage, []) ->
+ ok;
+do_export_messages(MessagePackage, [{Codec, Msgs} | TMsgs]) ->
+ ems(MessagePackage, Codec, Msgs),
+ do_export_messages(MessagePackage, TMsgs).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+transform_messages(BaseCodec, BaseMsgs, OutCodecs) ->
+ [{BaseCodec, BaseMsgs} |
+ [{Codec, tms(BaseMsgs, BaseCodec, Codec)} || Codec <- OutCodecs]].
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+tms(FromMsgs, FromCodec, ToCodec) ->
+ [{Name, tm(FromBin, FromCodec, ToCodec)} || {Name, FromBin} <- FromMsgs].
+
+tm(FromBin, FromCodec, ToCodec) ->
+ FromMsg = decode_message(FromCodec, FromBin),
+ encode_message(ToCodec, FromMsg).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+ems(MessagePackage, Codec, Msgs) ->
+ Dir = filename:join([MessagePackage, Codec]),
+ case file:make_dir(Dir) of
+ ok ->
+ ok;
+ {error, eexist} ->
+ ok;
+ Error ->
+ throw(Error)
+ end,
+ Extension = extension_of(Codec),
+ F = fun({Name, Bin}) -> em(MessagePackage, Codec, Name, Extension, Bin) end,
+ lists:foreach(F, Msgs).
+
+em(MessagePackage, Codec, Name, Extension, Bin) ->
+ Filename = filename:join([MessagePackage, Codec, atom_to_list(Name) ++ Extension]),
+ case file:open(Filename, [raw, binary, write]) of
+ {ok, Fd} ->
+ case file:write(Fd, Bin) of
+ ok ->
+ file:close(Fd),
+ ok;
+ {error, Reason} ->
+ S = format("failed writing ~w message ~w (~p bytes): ~p",
+ [Codec, Name, size(Bin), Reason]),
+ file:close(Fd),
+ throw({error, S})
+ end;
+
+ {error, Reason} ->
+ S = format("failed open file ~s: ~p", [Filename, Reason]),
+ throw({error, S})
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+decode_message(pretty, BinMsg) ->
+ Mod = megaco_pretty_text_encoder,
+ Conf = [{version3,?V3}],
+ do_decode(Mod, Conf, BinMsg);
+decode_message(compact, BinMsg) ->
+ Mod = megaco_compact_text_encoder,
+ Conf = [{version3,?V3}],
+ do_decode(Mod, Conf, BinMsg);
+decode_message(ber, BinMsg) ->
+ Mod = megaco_ber_bin_encoder,
+ Conf = [{version3,?V3}],
+ do_decode(Mod, Conf, BinMsg);
+decode_message(per, BinMsg) ->
+ Mod = megaco_per_bin_encoder,
+ Conf = [{version3,?V3}],
+ do_decode(Mod, Conf, BinMsg);
+decode_message(erlang, BinMsg) ->
+ Mod = megaco_erl_dist_encoder,
+ Conf = [{version3,?V3}],
+ do_decode(Mod, Conf, BinMsg).
+
+
+do_decode(Mod, Conf, Bin) ->
+ case (catch Mod:decode_message(Conf, Bin)) of
+ {ok, Msg} ->
+ Msg;
+ {error, Reason} ->
+ S = format("decode error: ~p", [Reason]),
+ throw({error, S});
+ {'EXIT', Reason} ->
+ S = format("decode exit: ~p", [Reason]),
+ throw({error, S});
+ Other ->
+ S = format("unknwon decode result: ~p", [Other]),
+ throw({error, S})
+ end.
+
+
+%% encode_message
+%% Note: See note above (decode_message)
+
+encode_message(pretty, Msg) ->
+ Mod = megaco_pretty_text_encoder,
+ Conf = [{version3,?V3}],
+ do_encode(Mod, Conf, Msg);
+encode_message(compact, Msg) ->
+ Mod = megaco_compact_text_encoder,
+ Conf = [{version3,?V3}],
+ do_encode(Mod, Conf, Msg);
+encode_message(ber, Msg) ->
+ Mod = megaco_ber_bin_encoder,
+ Conf = [{version3,?V3}],
+ do_encode(Mod, Conf, Msg);
+encode_message(per, Msg) ->
+ Mod = megaco_per_bin_encoder,
+ Conf = [{version3,?V3}],
+ do_encode(Mod, Conf, Msg);
+encode_message(erlang, Msg) ->
+ Mod = megaco_erl_dist_encoder,
+ Conf = [{version3,?V3}],
+ do_encode(Mod, Conf, Msg).
+
+
+do_encode(Mod, Conf, Msg) ->
+ case (catch Mod:encode_message(Conf, Msg)) of
+ {ok, Bin} ->
+ Bin;
+ {error, Reason} ->
+ S = format("encode error: ~p", [Reason]),
+ throw({error, S});
+ {'EXIT', Reason} ->
+ S = format("encode exit: ~p", [Reason]),
+ throw({error, S});
+ Other ->
+ S = format("unknwon encode result: ~p", [Other]),
+ throw({error, S})
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+extension_of(pretty) ->
+ ".txt";
+extension_of(compact) ->
+ ".txt";
+extension_of(ber) ->
+ ".bin";
+extension_of(per) ->
+ ".bin";
+extension_of(erlang) ->
+ ".bin".
+
+%% d(F) ->
+%% d(F, []).
+%% d(F, A) ->
+%% io:format(F ++ "~n", A).
+
+format(F, A) ->
+ lists:flatten(io_lib:format(F, A)).