aboutsummaryrefslogtreecommitdiffstats
path: root/lib/megaco/examples
diff options
context:
space:
mode:
Diffstat (limited to 'lib/megaco/examples')
-rw-r--r--lib/megaco/examples/meas/Makefile132
-rw-r--r--lib/megaco/examples/meas/meas.sh.skel41
-rw-r--r--lib/megaco/examples/meas/megaco_codec_meas.erl655
-rw-r--r--lib/megaco/examples/meas/megaco_codec_mstone1.erl408
-rw-r--r--lib/megaco/examples/meas/megaco_codec_mstone2.erl400
-rw-r--r--lib/megaco/examples/meas/megaco_codec_mstone_lib.erl534
-rw-r--r--lib/megaco/examples/meas/megaco_codec_transform.erl305
-rw-r--r--lib/megaco/examples/meas/modules.mk35
-rw-r--r--lib/megaco/examples/meas/mstone1.sh.skel239
-rw-r--r--lib/megaco/examples/meas/time_test.msgs149
-rw-r--r--lib/megaco/examples/simple/Makefile153
-rw-r--r--lib/megaco/examples/simple/megaco_simple_mg.erl437
-rw-r--r--lib/megaco/examples/simple/megaco_simple_mgc.erl455
-rw-r--r--lib/megaco/examples/simple/modules.mk27
14 files changed, 3970 insertions, 0 deletions
diff --git a/lib/megaco/examples/meas/Makefile b/lib/megaco/examples/meas/Makefile
new file mode 100644
index 0000000000..0a6cbb44a6
--- /dev/null
+++ b/lib/megaco/examples/meas/Makefile
@@ -0,0 +1,132 @@
+#
+# %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%
+
+include $(ERL_TOP)/make/target.mk
+
+ifeq ($(TYPE),debug)
+ERL_COMPILE_FLAGS += -Ddebug -W
+endif
+
+EBIN = .
+MEGACO_INCLUDEDIR = ../../include
+
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(MEGACO_VSN)
+
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/megaco-$(VSN)
+EXAMPLE_RELSYSDIR = $(RELSYSDIR)/examples
+MEAS_RELSYSDIR = $(EXAMPLE_RELSYSDIR)/meas
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+include modules.mk
+
+ERL_FILES = $(MODULES:%=%.erl)
+
+TARGET_FILES = \
+ $(ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR))
+
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+ifeq ($(WARN_UNUSED_WARS),true)
+ERL_COMPILE_FLAGS += +warn_unused_vars
+endif
+
+ifeq ($(USE_MEGACO_HIPE),true)
+ERL_COMPILE_FLAGS += +native
+endif
+
+ifeq ($(USE_VERBOSE_STATS),true)
+ERL_COMPILE_FLAGS += -DVERBOSE_STATS=true
+endif
+
+ifneq ($(MSTONE_TIME),)
+ERL_COMPILE_FLAGS += -DMSTONE_TIME=$(MSTONE_TIME)
+endif
+
+ERL_COMPILE_FLAGS += \
+ -pa $(ERL_TOP)/lib/megaco/ebin \
+ -I../include
+
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+debug:
+ @${MAKE} TYPE=debug opt
+
+opt: $(TARGET_FILES)
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f errs core *~
+
+docs:
+
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+
+release_spec: opt
+ $(INSTALL_DIR) $(EXAMPLE_RELSYSDIR)
+ $(INSTALL_DIR) $(MEAS_RELSYSDIR)
+ $(INSTALL_DATA) $(MESSAGE_PACKAGES) $(MEAS_RELSYSDIR)
+ $(INSTALL_DATA) $(SCRIPT_SKELETONS) $(MEAS_RELSYSDIR)
+ $(INSTALL_DATA) $(TARGET_FILES) $(MEAS_RELSYSDIR)
+ $(INSTALL_DATA) $(ERL_FILES) $(MEAS_RELSYSDIR)
+
+
+release_docs_spec:
+
+
+# ----------------------------------------------------
+# Include dependencies
+# ----------------------------------------------------
+
+megaco_codec_transform.$(EMULATOR): megaco_codec_transform.erl
+
+megaco_codec_meas.$(EMULATOR): megaco_codec_meas.erl
+
+megaco_codec_mstone1.$(EMULATOR): megaco_codec_mstone1.erl
+
+megaco_codec_mstone2.$(EMULATOR): megaco_codec_mstone2.erl
+
+megaco_codec_mstone_lib.$(EMULATOR): megaco_codec_mstone_lib.erl
+
diff --git a/lib/megaco/examples/meas/meas.sh.skel b/lib/megaco/examples/meas/meas.sh.skel
new file mode 100644
index 0000000000..4bbc6a5f7e
--- /dev/null
+++ b/lib/megaco/examples/meas/meas.sh.skel
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2007-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%
+
+#
+# Skeleton for a script intended to run the meas test.
+#
+
+ERL_HOME=<path to otp top dir>
+MEGACO_HOME=$ERL_HOME/lib/erlang/lib/<megaco dir>
+MEAS_HOME=$MEGACO_HOME/examples/meas
+PATH=$ERL_HOME/bin:$PATH
+
+# MEAS_TIME_TEST="-s megaco_codec_meas start time_test"
+MEAS_DEFAULT="-s megaco_codec_meas t"
+STOP="-s init stop"
+
+ERL="erl \
+ -noshell \
+ -pa $MEAS_HOME \
+ $MEAS_DEFAULT \
+ $STOP"
+
+echo $ERL
+$ERL | tee meas.log
+
diff --git a/lib/megaco/examples/meas/megaco_codec_meas.erl b/lib/megaco/examples/meas/megaco_codec_meas.erl
new file mode 100644
index 0000000000..88b34105ac
--- /dev/null
+++ b/lib/megaco/examples/meas/megaco_codec_meas.erl
@@ -0,0 +1,655 @@
+%%
+%% %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: Measure megaco codec's encoding & decoding time's
+%%
+%% Measurement process consists of:
+%% For each message in a directory:
+%% Pre: Read message from the file, close the file
+%% Measurement: 1) measure decode
+%% 2) measure encode (of the previously decoded message)
+%% Post: Print average
+%% For each directory:
+%% A summery is written, both to the console and to a file,
+%% in an excel compatible format.
+%%
+%% megaco_codec_meas:t().
+%% megaco_codec_meas:t([pretty, compact]).
+%% megaco_codec_meas:t([per, pretty, compact]).
+%%
+%%----------------------------------------------------------------------
+
+-module(megaco_codec_meas).
+
+%% -compile(export_all).
+
+
+%% API
+-export([start/0, start/1]).
+-export([start1/0]).
+
+%% Internal exports
+-export([do_measure_codec/7, do_measure_codec_loop/7]).
+-export([flex_scanner_handler/1]).
+
+
+-include_lib("kernel/include/file.hrl").
+
+-define(V3, v3).
+
+-define(MEASURE_TIMEOUT, 100000). % 100 sec
+
+-ifndef(MEASURE_COUNT_TIME).
+-define(MEASURE_COUNT_TIME, 1*1000*1000). % 1 seconds
+-endif.
+
+-ifndef(MEASURE_TIME).
+-define(MEASURE_TIME, 10000).
+-endif.
+
+-ifndef(MEASURE_CODECS).
+-define(MEASURE_CODECS, megaco_codec_transform:codecs()).
+-endif.
+
+-define(DEFAULT_MESSAGE_PACKAGE, megaco_codec_transform:default_message_package()).
+
+-record(stat, {name, ecount, etime, dcount, dtime, size}).
+
+
+%% Runs the measurement on all "official" codecs
+
+start1() ->
+ put(everbose,true),
+ start().
+
+start() ->
+ meas_init(?DEFAULT_MESSAGE_PACKAGE, ?MEASURE_CODECS).
+
+start([MessagePackage]) ->
+ do_start(MessagePackage, ?MEASURE_CODECS);
+start(MessagePackage) ->
+ do_start(MessagePackage, ?MEASURE_CODECS).
+
+do_start(MessagePackageRaw, Codecs) ->
+ MessagePackage = parse_message_package(MessagePackageRaw),
+ meas_init(MessagePackage, Codecs).
+
+parse_message_package(MessagePackageRaw) when is_list(MessagePackageRaw) ->
+ list_to_atom(MessagePackageRaw);
+parse_message_package(MessagePackage) when is_atom(MessagePackage) ->
+ MessagePackage;
+parse_message_package(BadMessagePackage) ->
+ throw({error, {bad_message_package, BadMessagePackage}}).
+
+
+%% Dirs is a list of directories containing files,
+%% each with a single megaco message.
+%%
+%% Note that it is a requirement that each dir has
+%% the name of the codec with which the messages has
+%% been encoded:
+%%
+%% pretty | compact | ber | per | erlang
+%%
+
+meas_init(MessagePackage, Codecs) ->
+ %% process_flag(trap_exit, true),
+ io:format("~nRun meas on message package: ~p~n~n", [MessagePackage]),
+ display_os_info(),
+ display_system_info(),
+ display_app_info(),
+ io:format("~n", []),
+ Started = now(),
+ case megaco_codec_transform:messages(MessagePackage) of
+ Messages when is_list(Messages) ->
+ ExpandedMessages = expand_messages(Codecs, Messages),
+ Results = t1(ExpandedMessages, []),
+ display_time(Started, now()),
+ store_results(Results);
+ Error ->
+ Error
+ end.
+
+display_os_info() ->
+ V = case os:version() of
+ {Major, Minor, Release} ->
+ lists:flatten(
+ io_lib:format("~w.~w.~w", [Major, Minor, Release]));
+ Str ->
+ Str
+ end,
+ case os:type() of
+ {OsFam, OsName} ->
+ io:format("OS: ~p-~p: ~s~n", [OsFam, OsName, V]);
+ OsFam ->
+ io:format("OS: ~p: ~s~n", [OsFam, V])
+ end.
+
+display_system_info() ->
+ SysArch = string:strip(erlang:system_info(system_architecture),right,$\n),
+ SysVer = string:strip(erlang:system_info(system_version),right,$\n),
+ io:format("System architecture: ~s~n", [SysArch]),
+ io:format("System version: ~s~n", [SysVer]),
+ ok.
+
+
+display_app_info() ->
+ display_megaco_info(),
+ display_asn1_info().
+
+display_megaco_info() ->
+ MI = megaco:module_info(),
+ {value, {attributes, Attr}} = lists:keysearch(attributes, 1, MI),
+ {value, {app_vsn, Ver}} = lists:keysearch(app_vsn, 1, Attr),
+ FlexStr =
+ case megaco_flex_scanner:is_enabled() of
+ true ->
+ case megaco_flex_scanner:is_reentrant_enabled() of
+ true ->
+ "reentrant flex";
+ false ->
+ "non-reentrant flex"
+ end;
+ false ->
+ "no flex"
+ end,
+ io:format("Megaco version: ~s (~s)~n", [Ver, FlexStr]).
+
+display_asn1_info() ->
+ AI = megaco_ber_bin_drv_media_gateway_control_v1:info(),
+ Vsn =
+ case lists:keysearch(vsn, 1, AI) of
+ {value, {vsn, V}} when is_atom(V) ->
+ atom_to_list(V);
+ {value, {vsn, V}} when is_list(V) ->
+ V;
+ _ ->
+ "unknown"
+ end,
+ io:format("ASN.1 version: ~s~n", [Vsn]).
+
+
+%% {MegaSec, Sec, MicroSec}
+display_time(Start, Fin) ->
+ FormatDate1 = format_timestamp(Start),
+ FormatDate2 = format_timestamp(Fin),
+ FormatDiff = format_diff(Start, Fin),
+ io:format("Started: ~s~n", [FormatDate1]),
+ io:format("Finished: ~s~n", [FormatDate2]),
+ io:format(" ~s~n~n~n", [FormatDiff]),
+ ok.
+
+format_timestamp({_N1, _N2, N3} = Now) ->
+ {Date, Time} = calendar:now_to_datetime(Now),
+ {YYYY,MM,DD} = Date,
+ {Hour,Min,Sec} = Time,
+ FormatDate =
+ io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w",
+ [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]),
+ lists:flatten(FormatDate).
+
+format_diff(Start, Fin) ->
+ DateTime1 = calendar:now_to_universal_time(Start),
+ DateTime2 = calendar:now_to_universal_time(Fin),
+ T1 = calendar:datetime_to_gregorian_seconds(DateTime1),
+ T2 = calendar:datetime_to_gregorian_seconds(DateTime2),
+ {_, Diff} = calendar:gregorian_seconds_to_datetime(T2 - T1),
+ Tmp =
+ case Diff of
+ {0, 0, S} ->
+ io_lib:format("~.2.0w sec", [S]);
+ {0, M, S} ->
+ io_lib:format("~w min ~.2.0w sec", [M,S]);
+ {H, M, S} ->
+ io_lib:format("~w hour ~w min ~.2.0w sec", [H,M,S])
+ end,
+ lists:flatten(Tmp).
+
+
+
+t1([], Results) ->
+ lists:reverse(Results);
+t1([{Id, Codec, Conf, _, _} = ECodec|EMsgs], Results) ->
+ case (catch measure(ECodec)) of
+ {'EXIT', Reason} ->
+ error("measure of codec ~p exited: ~n~p", [Codec, Reason]),
+ t1(EMsgs, Results);
+ {error, Reason} ->
+ error("skipping codec ~p: ~n~p", [Codec, Reason]),
+ t1(EMsgs, Results);
+ {ok, Res} ->
+ t1(EMsgs, [{Id, Conf, Res}| Results])
+ end.
+
+
+measure({Id, Codec, Conf, Count, Msgs}) ->
+ io:format("measure using codec ~p ~p~n ", [Codec, Conf]),
+ {Init, Conf1} = measure_init(Conf),
+ Conf2 = [{version3,?V3}|Conf1],
+ Res = measure(Id, Codec, Conf2, Msgs, [], Count),
+ measure_fin(Init),
+ Res.
+
+
+expand_messages(Codecs, Messages) ->
+ ECodecs = expand_codecs(Codecs, []),
+ expand_messages(ECodecs, Messages, []).
+
+expand_messages([], _, EMessages) ->
+ lists:reverse(EMessages);
+expand_messages([{Id, Codec, Conf, Count} | ECodecs], Messages, EMessages) ->
+ case lists:keysearch(Id, 1, Messages) of
+ {value, {Id, Msgs}} ->
+ expand_messages(ECodecs, Messages,
+ [{Id, Codec, Conf, Count, Msgs}|EMessages]);
+ false ->
+ exit({error, {no_such_codec_data, Id}})
+ end.
+
+expand_codecs([], ECodecs) ->
+ lists:reverse(lists:flatten(ECodecs));
+expand_codecs([Codec|Codecs], ECodecs) when is_atom(Codec) ->
+ ECodec = expand_codec(Codec),
+ expand_codecs(Codecs, [ECodec|ECodecs]).
+
+expand_codec(Codec) ->
+ case Codec of
+ pretty ->
+ [{Codec, megaco_pretty_text_encoder, [flex_scanner], 2000},
+ {Codec, megaco_pretty_text_encoder, [], 1000}];
+ compact ->
+ [{Codec, megaco_compact_text_encoder, [flex_scanner], 3000},
+ {Codec, megaco_compact_text_encoder, [], 1500}];
+ ber ->
+ [{Codec, megaco_ber_bin_encoder, [driver,native], 4000},
+ {Codec, megaco_ber_bin_encoder, [native], 3000},
+ {Codec, megaco_ber_bin_encoder, [driver], 3000},
+ {Codec, megaco_ber_bin_encoder, [], 1000}];
+ per ->
+ [{Codec, megaco_per_bin_encoder, [driver,native], 4000},
+ {Codec, megaco_per_bin_encoder, [native], 3000},
+ {Codec, megaco_per_bin_encoder, [driver], 3000},
+ {Codec, megaco_per_bin_encoder, [], 1000}];
+ erlang ->
+ [
+ {Codec, megaco_erl_dist_encoder, [megaco_compressed,compressed], 500},
+ {Codec, megaco_erl_dist_encoder, [compressed], 400},
+ {Codec, megaco_erl_dist_encoder, [megaco_compressed], 10000},
+ {Codec, megaco_erl_dist_encoder, [], 10000}
+ ];
+ Else ->
+ exit({error, {invalid_codec, Else}})
+ end.
+
+
+measure_init([flex_scanner]) ->
+ start_flex_scanner();
+measure_init(Conf) ->
+ {undefined, Conf}.
+
+
+measure_fin(Pid) when is_pid(Pid) ->
+ stop_flex_scanner(Pid),
+ ok;
+measure_fin(_) ->
+ ok.
+
+
+measure(_Dir, _Codec, _Conf, [], [], _MCount) ->
+ {error, no_messages};
+
+measure(_Dir, _Codec, _Conf, [], Res, _MCount) ->
+
+ Eavg = avg([Etime/Ecnt || #stat{ecount = Ecnt, etime = Etime} <- Res]),
+ Davg = avg([Dtime/Dcnt || #stat{dcount = Dcnt, dtime = Dtime} <- Res]),
+ Savg = avg([Size || #stat{size = Size} <- Res]),
+
+ io:format("~n Measurment on ~p messages:"
+ "~n Average size: ~w bytes, "
+ "~n encode: ~w microsec, "
+ "~n decode: ~w microsec~n~n",
+ [length(Res), Savg, Eavg, Davg]),
+
+ {ok, lists:reverse(Res)};
+
+measure(Dir, Codec, Conf, [{Name, Bin}|Msgs], Results, MCount) ->
+ io:format(" ~p", [Name]),
+ case (catch do_measure(Dir, Codec, Conf, Name, Bin, MCount)) of
+ {ok, Stat} ->
+ measure(Dir, Codec, Conf, Msgs, [Stat | Results], MCount);
+
+ {error, S} ->
+ io:format("~n~s failed: ~n", [Name]),
+ error(S,[]),
+ measure(Dir, Codec, Conf, Msgs, Results, MCount);
+
+ {info, S} ->
+ case get(verbose) of
+ true ->
+ io:format("~n", []),
+ info(S,[]);
+ _ ->
+ io:format("~n~s skipped~n", [Name])
+ end,
+ measure(Dir, Codec, Conf, Msgs, Results, MCount)
+
+ end.
+
+
+do_measure(_Id, Codec, Conf, Name, BinMsg, MCount) ->
+ %% io:format("~n~s~n", [binary_to_list(BinMsg)]),
+ {Version, NewBin} = detect_version(Codec, Conf, BinMsg),
+ {Msg, Dcnt, Dtime} = measure_decode(Codec, Conf, Version, NewBin, MCount),
+ {_, Ecnt, Etime} = measure_encode(Codec, Conf, Version, Msg, MCount),
+
+ {ok, #stat{name = Name,
+ ecount = Ecnt, etime = Etime,
+ dcount = Dcnt, dtime = Dtime,
+ size = size(NewBin)}}.
+
+detect_version(Codec, Conf, Bin) ->
+ case (catch Codec:version_of(Conf, Bin)) of
+ {ok, V} ->
+ io:format("[~w]", [V]),
+ {ok, M} = Codec:decode_message(Conf, V, Bin),
+ {ok, NewBin} = Codec:encode_message(Conf, V, M),
+ io:format("[~w]", [size(NewBin)]),
+ {V, NewBin};
+ Error ->
+ io:format("~nversion detection failed:~n~p", [Error]),
+ Error
+ end.
+
+
+measure_decode(Codec, Conf, Version, Bin, MCount) ->
+ case measure_codec(Codec, decode_message, Conf, Version, Bin, MCount) of
+ {ok, Res} ->
+ Res;
+ {error, Reason} ->
+ S = format("decode failed for ~p:~n~p", [Codec, Reason]),
+ throw({error, S})
+ end.
+
+measure_encode(Codec, Conf, Version, Bin, MCount) ->
+ case measure_codec(Codec, encode_message, Conf, Version, Bin, MCount) of
+ {ok, Res} ->
+ Res;
+ {error, Reason} ->
+ S = format("encode failed for ~p:~n~p", [Codec, Reason]),
+ throw({error, S})
+ end.
+
+
+measure_codec(Codec, Func, Conf, Version, Bin, MCount) ->
+ Pid = spawn_link(?MODULE, do_measure_codec,
+ [self(), Codec, Func, Conf, Version, Bin, MCount]),
+ receive
+ {measure_result, Pid, Func, Res} ->
+ {ok, Res};
+ {error, Pid, Error} ->
+ {error, Error};
+ Else ->
+ {error, {unexpected_result, Else}}
+ after ?MEASURE_TIMEOUT ->
+ Info =
+ case (catch process_info(Pid)) of
+ I when is_list(I) ->
+ exit(Pid, kill),
+ I;
+ _ ->
+ undefined
+ end,
+ {error, {timeout, MCount, Info}}
+ end.
+
+
+do_measure_codec(Parent, Codec, Func, Conf, Version, Bin, MCount) ->
+ {ok, Count} = measure_warmup(Codec, Func, Conf, Version, Bin, MCount),
+ Res = timer:tc(?MODULE, do_measure_codec_loop,
+ [Codec, Func, Conf, Version, Bin, Count, dummy]),
+ case Res of
+ {Time, {ok, M}} ->
+ %% io:format("~w ", [Time]),
+ Parent ! {measure_result, self(), Func, {M, Count, Time}};
+ {_Time, Error} ->
+ Parent ! {error, self(), Error}
+ end,
+ unlink(Parent). % Make sure Parent don't get our exit signal
+
+
+%% This function does more mor less what the real measure function
+%% above does. But with the diff:
+%% 1) Warmup to ensure that all used code are loaded
+%% 2) To aproximate the encoding time, to ensure that
+%% the real encode is done with enough iterations.
+measure_warmup(Codec, Func, Conf, Version, M, MCount) ->
+ Res = timer:tc(?MODULE, do_measure_codec_loop,
+ [Codec, Func, Conf, Version, M, MCount, dummy]),
+ case Res of
+ {Time, {ok, _}} ->
+ %% OK so far, now calculate the count:
+ Count = round(?MEASURE_COUNT_TIME/(Time/MCount)),
+ %% io:format("~w ", [Count]),
+ {ok, Count};
+ {_Time, Error} ->
+ {error, {warmup_failed, Error}}
+ end.
+
+
+do_measure_codec_loop(_Codec, _Func, _Conf, _Version, _Bin, 0, M) ->
+ {ok, M};
+do_measure_codec_loop(Codec, Func, Conf, Version, Bin, Count, _) ->
+ {ok, M} = apply(Codec, Func, [Conf, Version, Bin]),
+ do_measure_codec_loop(Codec, Func, Conf, Version, Bin, Count - 1, M).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+store_results(Results) ->
+ io:format("storing: ~n", []),
+ store_excel_message_size(Results),
+ store_excel_decode_time(Results),
+ store_excel_encode_time(Results),
+ store_excel_total_time(Results),
+ io:format("~n", []),
+ ok.
+
+
+store_excel_message_size(Res) ->
+ Filename = "message_size.xls",
+ io:format(" creating ~s~n", [Filename]),
+ {ok, Fd} = file:open(Filename,[write]),
+ Sizes = message_sizes(Res, []),
+ store_excel_tab(Fd, Sizes),
+ ok.
+
+store_excel_decode_time(Res) ->
+ Filename = "decode_time.xls",
+ io:format(" creating ~s~n", [Filename]),
+ {ok, Fd} = file:open(Filename,[write]),
+ Decodes = dec_times(Res, []),
+ store_excel_tab(Fd, Decodes),
+ ok.
+
+store_excel_encode_time(Res) ->
+ Filename = "encode_time.xls",
+ io:format(" creating ~s~n", [Filename]),
+ {ok, Fd} = file:open(Filename,[write]),
+ Encodes = enc_times(Res, []),
+ store_excel_tab(Fd, Encodes),
+ ok.
+
+store_excel_total_time(Res) ->
+ Filename = "total_time.xls",
+ io:format(" creating ~s~n", [Filename]),
+ {ok, Fd} = file:open(Filename,[write]),
+ Totals = tot_times(Res, []),
+ store_excel_tab(Fd, Totals),
+ ok.
+
+
+message_sizes([], Sizes) ->
+ lists:reverse(Sizes);
+message_sizes([{Dir, Conf, Res}|T], Acc) ->
+ Sizes = [Size || #stat{size = Size} <- Res],
+ Avg = avg(Sizes),
+ message_sizes(T, [{Dir, Conf, Avg, Sizes}|Acc]).
+
+dec_times([], Times) ->
+ lists:reverse(Times);
+dec_times([{Dir, Conf, Res}|T], Acc) ->
+ Times = [Time/Count || #stat{dcount = Count, dtime = Time} <- Res],
+ Avg = avg(Times),
+ dec_times(T, [{Dir, Conf, Avg, Times}|Acc]).
+
+enc_times([], Times) ->
+ lists:reverse(Times);
+enc_times([{Dir, Conf, Res}|T], Acc) ->
+ Times = [Time/Count || #stat{ecount = Count, etime = Time} <- Res],
+ Avg = avg(Times),
+ enc_times(T, [{Dir, Conf, Avg, Times}|Acc]).
+
+tot_times([], Times) ->
+ lists:reverse(Times);
+tot_times([{Dir, Conf, Res}|T], Acc) ->
+ Times = [(Etime/Ecnt)+(Dtime/Dcnt) || #stat{ecount = Ecnt,
+ etime = Etime,
+ dcount = Dcnt,
+ dtime = Dtime} <- Res],
+ Avg = avg(Times),
+ tot_times(T, [{Dir, Conf, Avg, Times}|Acc]).
+
+
+avg(Vals) ->
+ round(lists:sum(Vals)/length(Vals)).
+
+
+store_excel_tab(_Fd, []) ->
+ ok; % Just in case there was something wrong with the test
+store_excel_tab(Fd, Res) ->
+ %% For all elements of this list, the Values is of the same length...
+ [{_, _, _, Values}|_] = Res,
+ store_excel_tab_header(Fd, length(Values), 1),
+ store_excel_tab1(Fd, Res).
+
+store_excel_tab1(Fd, []) ->
+ io:format(Fd, "~n", []);
+store_excel_tab1(Fd, [{Dir, Conf, Avg, Values}|T]) when is_list(Conf) ->
+ io:format(Fd, "~s~s (~w)",
+ [filename:basename(Dir), config_to_string(Conf), Avg]),
+ store_excel_tab_row(Fd, Values),
+ store_excel_tab1(Fd, T).
+
+config_to_string([]) ->
+ "";
+config_to_string([C]) when is_atom(C) ->
+ io_lib:format("_~w", [C]);
+config_to_string([C|Cs]) when is_atom(C) ->
+ lists:flatten(io_lib:format("_~w", [C]) ++ config_to_string(Cs)).
+
+store_excel_tab_header(Fd, 0, _) ->
+ io:format(Fd, "~n", []);
+store_excel_tab_header(Fd, N, M) ->
+ io:format(Fd, "\t~w", [M]),
+ store_excel_tab_header(Fd, N-1, M+1).
+
+store_excel_tab_row(Fd, []) ->
+ io:format(Fd, "~n", []);
+store_excel_tab_row(Fd, [Value|Values]) ->
+ io:format(Fd, "\t~w", [round(Value)]),
+ store_excel_tab_row(Fd, Values).
+
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+start_flex_scanner() ->
+ Pid = proc_lib:spawn(?MODULE, flex_scanner_handler, [self()]),
+ receive
+ {flex_scanner_started, Pid, Conf} ->
+ {Pid, [Conf]};
+ {flex_scanner_error, {failed_loading_flex_scanner_driver, Reason}} ->
+ throw({error, {failed_loading_flex_scanner_driver, Reason}});
+ {flex_scanner_error, Reason} ->
+ throw({error, {failed_loading_flex_scanner_driver, Reason}})
+ after 10000 ->
+ exit(Pid, kill),
+ throw({error, {failed_starting_flex_scanner, timeout}})
+ end.
+
+stop_flex_scanner(Pid) ->
+ Pid ! stop_flex_scanner.
+
+flex_scanner_handler(Pid) ->
+ case (catch megaco_flex_scanner:start()) of
+ {ok, Port} when is_port(Port) ->
+ Pid ! {flex_scanner_started, self(), {flex, Port}},
+ flex_scanner_handler(Pid, Port);
+ {ok, Ports} when is_tuple(Ports) ->
+ Pid ! {flex_scanner_started, self(), {flex, Ports}},
+ flex_scanner_handler(Pid, Ports);
+ {error, {load_driver, {open_error, Reason}}} ->
+ Error = {failed_loading_flex_scanner_driver, Reason},
+ Pid ! {flex_scanner_error, Error},
+ exit(Error);
+ Else ->
+ Error = {unknown_result_from_start_flex_scanner, Else},
+ Pid ! {flex_scanner_error, Error},
+ exit(Error)
+ end.
+
+flex_scanner_handler(Pid, PortOrPorts) ->
+ receive
+ {ping, Pinger} ->
+ Pinger ! {pong, self()},
+ flex_scanner_handler(Pid, PortOrPorts);
+ {'EXIT', Port, Reason} ->
+ case megaco_flex_scanner:is_scanner_port(Port, PortOrPorts) of
+ true ->
+ Pid ! {flex_scanner_exit, Reason},
+ exit({flex_scanner_exit, Reason});
+ false ->
+ info("exit signal from unknown port ~p"
+ "~n Reason: ~p", [Port, Reason]),
+ flex_scanner_handler(Pid, PortOrPorts)
+ end;
+ stop_flex_scanner ->
+ megaco_flex_scanner:stop(PortOrPorts),
+ exit(normal);
+ Other ->
+ info("flex scanner handler got something:~n~p", [Other]),
+ flex_scanner_handler(Pid, PortOrPorts)
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+info(F, A) ->
+ io:format(F ++ "~n", A).
+
+
+error(F, A) ->
+ io:format("ERROR: " ++ F ++ "~n", A).
+
+
+format(F, A) ->
+ lists:flatten(io_lib:format(F, A)).
diff --git a/lib/megaco/examples/meas/megaco_codec_mstone1.erl b/lib/megaco/examples/meas/megaco_codec_mstone1.erl
new file mode 100644
index 0000000000..9ab7822df8
--- /dev/null
+++ b/lib/megaco/examples/meas/megaco_codec_mstone1.erl
@@ -0,0 +1,408 @@
+%%
+%% %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: mstone measurement
+%%
+%%----------------------------------------------------------------------
+
+-module(megaco_codec_mstone1).
+
+
+%% API
+-export([
+ start/0, start/1, start/2,
+ start_flex/0, start_flex/1, start_flex/2,
+ start_no_drv/0, start_no_drv/1, start_no_drv/2,
+ start_only_drv/0, start_only_drv/1, start_only_drv/2
+ ]).
+
+%% Internal exports
+-export([mstone_runner_init/5]).
+
+
+-define(LIB, megaco_codec_mstone_lib).
+
+-ifndef(MSTONE_TIME).
+-define(MSTONE_TIME, 10).
+-endif.
+-define(MSTONE_RUN_TIME, timer:minutes(?MSTONE_TIME)).
+
+-ifndef(MSTONE_VERSION3).
+-define(MSTONE_VERSION3, v3).
+-endif.
+-define(VERSION3, ?MSTONE_VERSION3).
+
+-ifndef(MSTONE_CODECS).
+-define(MSTONE_CODECS, megaco_codec_transform:codecs()).
+-endif.
+
+-define(DEFAULT_MESSAGE_PACKAGE, megaco_codec_transform:default_message_package()).
+-define(DEFAULT_FACTOR, 1).
+-define(DEFAULT_DRV_INCLUDE, ignore).
+
+%% -define(VERBOSE_STATS,true).
+
+-ifndef(MSTONE_RUNNER_MIN_HEAP_SZ).
+-define(MSTONE_RUNNER_MIN_HEAP_SZ, 16#ffff).
+-endif.
+-define(MSTONE_RUNNER_OPTS,
+ [link, {min_heap_size, ?MSTONE_RUNNER_MIN_HEAP_SZ}]).
+
+-record(mstone, {id, count, codec, econf, heap_size, reds}).
+
+
+start() ->
+ start(?DEFAULT_FACTOR).
+
+start([Factor]) ->
+ start(?DEFAULT_MESSAGE_PACKAGE, Factor);
+start([MessagePackage, Factor]) ->
+ start(MessagePackage, Factor);
+start(Factor) ->
+ start(?DEFAULT_MESSAGE_PACKAGE, Factor).
+
+start(MessagePackage, Factor) ->
+ do_start(MessagePackage, Factor, ?DEFAULT_DRV_INCLUDE).
+
+
+start_flex() ->
+ start_flex(?DEFAULT_FACTOR).
+
+start_flex([Factor]) ->
+ start_flex(?DEFAULT_MESSAGE_PACKAGE, Factor);
+start_flex([MessagePackage, Factor]) ->
+ start_flex(MessagePackage, Factor);
+start_flex(Factor) ->
+ start_flex(?DEFAULT_MESSAGE_PACKAGE, Factor).
+
+start_flex(MessagePackage, Factor) ->
+ do_start(MessagePackage, Factor, flex).
+
+
+start_only_drv() ->
+ start_only_drv(?DEFAULT_FACTOR).
+
+start_only_drv([Factor]) ->
+ start_only_drv(?DEFAULT_MESSAGE_PACKAGE, Factor);
+start_only_drv([MessagePackage, Factor]) ->
+ start_only_drv(MessagePackage, Factor);
+start_only_drv(Factor) ->
+ start_only_drv(?DEFAULT_MESSAGE_PACKAGE, Factor).
+
+start_only_drv(MessagePackage, Factor) ->
+ do_start(MessagePackage, Factor, only_drv).
+
+
+start_no_drv() ->
+ start_no_drv(?DEFAULT_FACTOR).
+
+start_no_drv([Factor]) ->
+ start_no_drv(?DEFAULT_MESSAGE_PACKAGE, Factor);
+start_no_drv([MessagePackage, Factor]) ->
+ start_no_drv(MessagePackage, Factor);
+start_no_drv(Factor) ->
+ start_no_drv(?DEFAULT_MESSAGE_PACKAGE, Factor).
+
+start_no_drv(MessagePackage, Factor) ->
+ do_start(MessagePackage, Factor, no_drv).
+
+
+do_start(MessagePackageRaw, FactorRaw, DrvInclude) ->
+ Factor = parse_factor(FactorRaw),
+ MessagePackage = parse_message_package(MessagePackageRaw),
+ mstone_init(MessagePackage, Factor, DrvInclude).
+
+
+
+parse_factor(FactorAtom) when is_atom(FactorAtom) ->
+ case (catch list_to_integer(atom_to_list(FactorAtom))) of
+ Factor when is_integer(Factor) andalso (Factor > 0) ->
+ Factor;
+ _ ->
+ io:format("ERROR: Bad factor value: ~p~n", [FactorAtom]),
+ throw({error, {bad_factor, FactorAtom}})
+ end;
+parse_factor(FactorRaw) when is_list(FactorRaw) ->
+ case (catch list_to_integer(FactorRaw)) of
+ Factor when is_integer(Factor) andalso (Factor > 0) ->
+ Factor;
+ _ ->
+ io:format("ERROR: Bad factor value: ~p~n", [FactorRaw]),
+ throw({error, {bad_factor, FactorRaw}})
+ end;
+parse_factor(Factor) when is_integer(Factor) andalso (Factor > 0) ->
+ Factor;
+parse_factor(BadFactor) ->
+ throw({error, {bad_factor, BadFactor}}).
+
+
+parse_message_package(MessagePackageRaw) when is_list(MessagePackageRaw) ->
+ list_to_atom(MessagePackageRaw);
+parse_message_package(MessagePackage) when is_atom(MessagePackage) ->
+ MessagePackage;
+parse_message_package(BadMessagePackage) ->
+ throw({error, {bad_message_package, BadMessagePackage}}).
+
+
+%% Codecs is a list of megaco codec shortnames:
+%%
+%% pretty | compact | ber | per | erlang
+%%
+
+mstone_init(MessagePackage, Factor, DrvInclude) ->
+%% io:format("mstone_init -> entry with"
+%% "~n MessagePackage: ~p"
+%% "~n Factor: ~p"
+%% "~n DrvInclude: ~p"
+%% "~n", [MessagePackage, Factor, DrvInclude]),
+ Codecs = ?MSTONE_CODECS,
+ mstone_init(MessagePackage, Factor, Codecs, DrvInclude).
+
+mstone_init(MessagePackage, Factor, Codecs, DrvInclude) ->
+ Parent = self(),
+ Pid = spawn(
+ fun() ->
+ process_flag(trap_exit, true),
+ do_mstone(MessagePackage, Factor, Codecs, DrvInclude),
+ Parent ! {done, self()}
+ end),
+ receive
+ {done, Pid} ->
+ ok
+ end.
+
+do_mstone(MessagePackage, Factor, Codecs, DrvInclude) ->
+ io:format("~n", []),
+ ?LIB:set_default_sched_bind(),
+ ?LIB:display_os_info(),
+ ?LIB:display_system_info(),
+ ?LIB:display_app_info(),
+ io:format("~n", []),
+ (catch asn1rt_driver_handler:load_driver()),
+ {Pid, Conf} = ?LIB:start_flex_scanner(),
+ put(flex_scanner_conf, Conf),
+ EMessages = ?LIB:expanded_messages(MessagePackage, Codecs, DrvInclude),
+ EMsgs = duplicate(Factor, EMessages),
+ MStone = t1(EMsgs),
+ ?LIB:stop_flex_scanner(Pid),
+ io:format("~n", []),
+ io:format("MStone: ~p~n", [MStone]).
+
+duplicate(N, Elements) ->
+ duplicate(N, Elements, []).
+
+duplicate(_N, [], Acc) ->
+ lists:flatten(Acc);
+duplicate(N, [H|T], Acc) ->
+ duplicate(N, T, [lists:duplicate(N, H)|Acc]).
+
+t1(EMsgs) ->
+ io:format(" * starting runners [~w] ", [length(EMsgs)]),
+ t1(EMsgs, []).
+
+t1([], Runners) ->
+ io:format(" done~n * await runners ready ", []),
+ await_runners_ready(Runners),
+ io:format(" done~n * now snooze", []),
+ receive after 5000 -> ok end,
+ io:format("~n * release them~n", []),
+ lists:foreach(fun(P) -> P ! {go, self()} end, Runners),
+ t2(1, [], Runners);
+t1([H|T], Runners) ->
+ Runner = init_runner(H),
+ io:format(".", []),
+ t1(T, [Runner|Runners]).
+
+await_runners_ready([]) ->
+ ok;
+await_runners_ready(Runners) ->
+ receive
+ {ready, Runner} ->
+ io:format(".", []),
+ %% i("runner ~w ready", [Runner]),
+ await_runners_ready(lists:delete(Runner, Runners));
+ {'EXIT', Pid, Reason} ->
+ case lists:member(Pid, Runners) of
+ true ->
+ io:format("~nERROR: "
+ "received (unexpected) exit signal "
+ "from from runner ~p:"
+ "~n~p~n", [Pid, Reason]),
+ exit(Reason);
+ false ->
+ await_runners_ready(Runners)
+ end
+ end.
+
+-ifdef(VERBOSE_STATS).
+print_runner_stats(RunnerStats) ->
+ Sorted = lists:keysort(2, RunnerStats),
+ lists:foreach(fun(#mstone{id = Id,
+ count = Num,
+ codec = Codec,
+ econf = EConf,
+ heap_size = HeapSz,
+ reds = Reds}) ->
+ i("runner: ~w"
+ "~n Count: ~w"
+ "~n Codec: ~w"
+ "~n Encoding config: ~p"
+ "~n Heap size: ~p"
+ "~n Reductions: ~p",
+ [Id, Num, Codec, EConf, HeapSz, Reds]) end,
+ Sorted),
+ ok.
+-else.
+print_runner_stats(_) ->
+ ok.
+-endif.
+
+t2(_, Acc, []) ->
+ i("~n~w runners", [length(Acc)]),
+ print_runner_stats(Acc),
+
+ HeapSzAcc = lists:sort([HS || #mstone{heap_size = HS} <- Acc]),
+ i("Runner heap size data:"
+ "~n Min: ~w"
+ "~n Max: ~w"
+ "~n Avg: ~w",
+ [hd(HeapSzAcc),
+ hd(lists:reverse(HeapSzAcc)),
+ (lists:sum(HeapSzAcc) div length(HeapSzAcc))]),
+
+ RedsAcc = lists:sort([R || #mstone{reds = R} <- Acc]),
+ i("Runner reductions data:"
+ "~n Min: ~w"
+ "~n Max: ~w"
+ "~n Avg: ~w",
+ [hd(RedsAcc),
+ hd(lists:reverse(RedsAcc)),
+ (lists:sum(RedsAcc) div length(RedsAcc))]),
+
+ lists:sum([Num || #mstone{count = Num} <- Acc]);
+t2(N, Acc, Runners) ->
+ receive
+ {'EXIT', Pid, {runner_done, Codec, Conf, Num, Info}} ->
+ {value, {_, HeapSz}} = lists:keysearch(heap_size, 1, Info),
+ {value, {_, Reds}} = lists:keysearch(reductions, 1, Info),
+ MStone = #mstone{id = N,
+ count = Num,
+ codec = Codec,
+ econf = Conf,
+ heap_size = HeapSz,
+ reds = Reds},
+ t2(N + 1, [MStone|Acc], lists:delete(Pid, Runners))
+ end.
+
+init_runner({Codec, Mod, Conf, Msgs}) ->
+ Conf1 = runner_conf(Conf),
+ Conf2 = [{version3,?VERSION3}|Conf1],
+ Pid = spawn_opt(?MODULE, mstone_runner_init,
+ [Codec, self(), Mod, Conf2, Msgs],
+ ?MSTONE_RUNNER_OPTS),
+ Pid.
+
+runner_conf([flex_scanner]) ->
+ get(flex_scanner_conf);
+runner_conf(Conf) ->
+ Conf.
+
+
+
+detect_versions(Codec, _Conf, [], []) ->
+ exit({no_messages_found_for_codec, Codec});
+detect_versions(_Codec, _Conf, [], Acc) ->
+ lists:reverse(Acc);
+detect_versions(Codec, Conf, [{_Name, Bin}|Bins], Acc) ->
+ Data = ?LIB:detect_version(Codec, Conf, Bin),
+ detect_versions(Codec, Conf, Bins, [Data|Acc]).
+
+
+mstone_runner_init(_Codec, Parent, Mod, Conf, Msgs0) ->
+ Msgs = detect_versions(Mod, Conf, Msgs0, []),
+ warmup(Mod, Conf, Msgs, []),
+ Parent ! {ready, self()},
+ receive
+ {go, Parent} ->
+ ok
+ end,
+ erlang:send_after(?MSTONE_RUN_TIME, self(), stop),
+ mstone_runner_loop(Parent, Mod, Conf, 0, Msgs).
+
+mstone_runner_loop(Parent, Mod, Conf, N, Msgs1) ->
+ receive
+ stop ->
+ exit({runner_done, Mod, Conf, N, mstone_runner_process_info()})
+ after 0 ->
+ {Inc, Msgs2} = mstone_all(Mod, Conf, Msgs1, []),
+ mstone_runner_loop(Parent, Mod, Conf, N+Inc, Msgs2)
+ end.
+
+mstone_runner_process_info() ->
+ PI = process_info(self()),
+ FL = [heap_size, stack_size, reductions],
+ lists:filter(fun({Key, _}) -> lists:member(Key, FL) end, PI).
+
+
+mstone_all(_Codec, _Conf, [], Acc) ->
+ {length(Acc), lists:reverse(Acc)};
+mstone_all(Codec, Conf, [{V, Bin}|Bins], Acc) when is_binary(Bin) ->
+ {ok, Msg} = apply(Codec, decode_message, [Conf, V, Bin]),
+ mstone_all(Codec, Conf, Bins, [{V, Msg}|Acc]);
+mstone_all(Codec, Conf, [{V, Msg}|Msgs], Acc) ->
+ {ok, Bin} = apply(Codec, encode_message, [Conf, V, Msg]),
+ mstone_all(Codec, Conf, Msgs, [{V, Bin}|Acc]).
+
+warmup(_Codec, _Conf, [], Acc) ->
+ lists:reverse(Acc);
+warmup(Codec, Conf, [{V, M}|Msgs], Acc) ->
+%% io:format("~p warmup -> entry with"
+%% "~n Codec: ~p"
+%% "~n Conf: ~p"
+%% "~n", [self(), Codec, Conf]),
+ case (catch apply(Codec, decode_message, [Conf, V, M])) of
+ {ok, Msg} ->
+ case (catch apply(Codec, encode_message, [Conf, V, Msg])) of
+ {ok, Bin} ->
+ warmup(Codec, Conf, Msgs, [Bin|Acc]);
+ EncodeError ->
+ emsg("failed encoding message: ~n~p", [EncodeError])
+ end;
+ DecodeError ->
+ emsg("failed decoding message: "
+ "~n DecodeError: ~p"
+ "~n V: ~p"
+ "~n M: ~p", [DecodeError, V, M])
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+emsg(F, A) ->
+ error_logger:error_msg(F ++ "~n", A).
+
+%% i(F) ->
+%% i(F, []).
+i(F, A) ->
+ io:format(F ++ "~n", A).
+
diff --git a/lib/megaco/examples/meas/megaco_codec_mstone2.erl b/lib/megaco/examples/meas/megaco_codec_mstone2.erl
new file mode 100644
index 0000000000..f3588f2e3d
--- /dev/null
+++ b/lib/megaco/examples/meas/megaco_codec_mstone2.erl
@@ -0,0 +1,400 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-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%
+%%
+
+%%
+%%----------------------------------------------------------------------
+%%
+%% megaco_codec_mstone2:start().
+%% megaco_codec_mstone2:start_no_drv().
+%% megaco_codec_mstone2:start_only_drv().
+%%
+%%----------------------------------------------------------------------
+%% Purpose: mstone 2 measurement
+%% This module implement a simple performence measurment case.
+%% The architecture is as followes:
+%% - One loader process:
+%% It keeps a list of all codec combinations, including
+%% all the messages (in a list) for each codec.
+%% Initially it creates a timer (finished) (circa 10 minutes).
+%% It spawns a worker process for each codec config (it also
+%% creates a monitor to each process so it knows when they
+%% exit). When the result comes in from a process (in the
+%% form of a DOWN message), spawns a new worker process for
+%% this codec config and update's the statistics.
+%% When the finished timer expires, it will stop respawing
+%% the worker processes, and instead just wait for them all
+%% to finish.
+%% The test is finished by printing the statistics.
+%% - A worker process for each codec combination.
+%% This process is spawned by the loader process. It receives
+%% at start a list of messages. It shall decode and then
+%% encode each message. When all messages has been processed
+%% it exits (normally).
+%%----------------------------------------------------------------------
+
+-module(megaco_codec_mstone2).
+
+
+%% Exports
+-export([
+ start/0, start/1,
+ start_flex/0, start_flex/1,
+ start_no_drv/0, start_no_drv/1,
+ start_only_drv/0, start_only_drv/1
+ ]).
+
+
+%%%----------------------------------------------------------------------
+%%% Macros
+%%%----------------------------------------------------------------------
+
+-define(LIB, megaco_codec_mstone_lib).
+
+-ifndef(MSTONE_TIME).
+-define(MSTONE_TIME, 10).
+-endif.
+-define(MSTONE_RUN_TIME, timer:minutes(?MSTONE_TIME)).
+
+-ifndef(MSTONE_VERSION3).
+-define(MSTONE_VERSION3, v3).
+-endif.
+-define(VERSION3, ?MSTONE_VERSION3).
+
+-ifndef(MSTONE_CODECS).
+-define(MSTONE_CODECS, megaco_codec_transform:codecs()).
+-endif.
+
+-define(DEFAULT_MESSAGE_PACKAGE, megaco_codec_transform:default_message_package()).
+-define(DEFAULT_FACTOR, 1).
+-define(DEFAULT_DRV_INCLUDE, ignore).
+
+-ifndef(MSTONE_RUNNER_MIN_HEAP_SZ).
+%% -define(MSTONE_RUNNER_MIN_HEAP_SZ, 16#7fff).
+-define(MSTONE_RUNNER_MIN_HEAP_SZ, 16#ffff).
+%% -define(MSTONE_RUNNER_MIN_HEAP_SZ, 16#17ffe).
+%% -define(MSTONE_RUNNER_MIN_HEAP_SZ, 16#1ffff).
+%% -define(MSTONE_RUNNER_OPTS, [link]).
+-endif.
+-define(MSTONE_RUNNER_OPTS,
+ [link, {min_heap_size, ?MSTONE_RUNNER_MIN_HEAP_SZ}]).
+
+
+%%%----------------------------------------------------------------------
+%%% Records
+%%%----------------------------------------------------------------------
+
+-record(codec_data, {ref, mod, config = [], msgs = []}).
+
+-record(state, {timer, running = [], idle = [], flex_handler, flex_conf}).
+
+
+%%%----------------------------------------------------------------------
+%%% API
+%%%----------------------------------------------------------------------
+
+start() ->
+ start(?DEFAULT_MESSAGE_PACKAGE).
+
+start([MessagePackage]) ->
+ do_start(MessagePackage, ?DEFAULT_DRV_INCLUDE);
+start(MessagePackage) ->
+ do_start(MessagePackage, ?DEFAULT_DRV_INCLUDE).
+
+
+start_flex() ->
+ start_flex(?DEFAULT_MESSAGE_PACKAGE).
+
+start_flex([MessagePackage]) ->
+ do_start(MessagePackage, flex);
+start_flex(MessagePackage) ->
+ do_start(MessagePackage, flex).
+
+
+start_no_drv() ->
+ start_no_drv(?DEFAULT_MESSAGE_PACKAGE).
+
+start_no_drv([MessagePackage]) ->
+ do_start(MessagePackage, no_drv);
+start_no_drv(MessagePackage) ->
+ do_start(MessagePackage, no_drv).
+
+
+start_only_drv() ->
+ start_only_drv(?DEFAULT_MESSAGE_PACKAGE).
+
+start_only_drv([MessagePackage]) ->
+ do_start(MessagePackage, only_drv);
+start_only_drv(MessagePackage) ->
+ do_start(MessagePackage, only_drv).
+
+
+do_start(MessagePackageRaw, DrvInclude) ->
+%% io:format("do_start -> entry with"
+%% "~n MessagePackageRaw: ~p"
+%% "~n DrvInclude: ~p"
+%% "~n", [MessagePackageRaw, DrvInclude]),
+ MessagePackage = parse_message_package(MessagePackageRaw),
+ mstone_init(MessagePackage, DrvInclude).
+
+parse_message_package(MessagePackageRaw) when is_list(MessagePackageRaw) ->
+ list_to_atom(MessagePackageRaw);
+parse_message_package(MessagePackage) when is_atom(MessagePackage) ->
+ MessagePackage;
+parse_message_package(BadMessagePackage) ->
+ throw({error, {bad_message_package, BadMessagePackage}}).
+
+
+mstone_init(MessagePackage, DrvInclude) ->
+ io:format("~n", []),
+ ?LIB:set_default_sched_bind(),
+ ?LIB:display_os_info(),
+ ?LIB:display_system_info(),
+ ?LIB:display_app_info(),
+ io:format("~n", []),
+ Ref = erlang:monitor(process,
+ spawn(fun() ->
+ loader(MessagePackage, DrvInclude)
+ end)),
+ receive
+ {'DOWN', Ref, process, _Pid, {done, Result}} ->
+ display_result(Result);
+ {'DOWN', Ref, process, _Pid, Result} ->
+ io:format("Unexpected result:~n~p~n", [Result]),
+ ok
+ end.
+
+
+%%%----------------------------------------------------------------------
+%%% Internal functions
+%%%----------------------------------------------------------------------
+
+display_result(Result) ->
+ {value, {worker_cnt, WC}} = lists:keysearch(worker_cnt, 1, Result),
+ CodecStat =
+ [{Mod, Conf, Cnt} || {{codec_cnt, Mod, Conf}, Cnt} <- Result],
+ MStone = lists:sum([Cnt || {_, _, Cnt} <- CodecStat]),
+ io:format("Number of procs spawned: ~w~n"
+ "MStone: ~w~n"
+ "~n", [WC, MStone]),
+ display_worker_result(lists:keysort(3, CodecStat)),
+ ok.
+
+display_worker_result([]) ->
+ io:format("~n", []);
+display_worker_result([{Mod, Conf, Cnt}|Res]) ->
+ io:format("~s: ~w~n", [image_of(Mod, Conf), Cnt]),
+ display_worker_result(Res).
+
+image_of(megaco_per_bin_encoder, Conf) ->
+ bin_image("per_bin", Conf);
+image_of(megaco_ber_bin_encoder, Conf) ->
+ bin_image("ber_bin", Conf);
+image_of(megaco_pretty_text_encoder, Conf) ->
+ text_image("pretty", Conf);
+image_of(megaco_compact_text_encoder, Conf) ->
+ text_image("compact", Conf);
+image_of(megaco_erl_dist_encoder, Conf) ->
+ erl_image("erl_dist", Conf).
+
+bin_image(Bin, Conf) ->
+ Drv =
+ case lists:member(driver, Conf) of
+ true ->
+ [driver];
+ false ->
+ []
+ end,
+ Nat =
+ case lists:member(native, Conf) of
+ true ->
+ [native];
+ false ->
+ []
+ end,
+ io_lib:format("~s ~w", [Bin, Drv ++ Nat]).
+
+text_image(Txt, Conf) ->
+ Flex =
+ case lists:keysearch(flex, 1, Conf) of
+ false ->
+ [];
+ _ ->
+ [flex]
+ end,
+ io_lib:format("~s ~w", [Txt, Flex]).
+
+erl_image(Erl, Conf) ->
+ MC =
+ case lists:member(megaco_compressed, Conf) of
+ true ->
+ [megaco_compressed];
+ false ->
+ []
+ end,
+ C =
+ case lists:member(compressed, Conf) of
+ true ->
+ [compressed];
+ false ->
+ []
+ end,
+ io_lib:format("~s ~w", [Erl, MC ++ C]).
+
+
+%%%----------------------------------------------------------------------
+
+loader(MessagePackage, DrvInclude) ->
+ loader(?MSTONE_CODECS, MessagePackage, DrvInclude).
+
+
+%% Codecs is a list of megaco codec shortnames:
+%%
+%% pretty | compact | ber | per | erlang
+%%
+
+loader(Codecs, MessagePackage, DrvInclude) ->
+ process_flag(trap_exit, true),
+ case (catch init(Codecs, MessagePackage, DrvInclude)) of
+ {ok, State} ->
+ loader_loop(running, State);
+ Error ->
+ exit(Error)
+ end.
+
+init(Codecs, MessagePackage, DrvInclude) ->
+ ets:new(mstone, [set, private, named_table, {keypos, 1}]),
+ ets:insert(mstone, {worker_cnt, 0}),
+ {Pid, FlexConf} = ?LIB:start_flex_scanner(),
+ io:format("prepare messages", []),
+ EMessages = ?LIB:expanded_messages(MessagePackage, Codecs, DrvInclude),
+ io:format("~ninit codec data", []),
+ CodecData = init_codec_data(EMessages, FlexConf),
+ Timer = erlang:send_after(?MSTONE_RUN_TIME, self(), mstone_finished),
+ io:format("~n", []),
+ {ok, #state{timer = Timer,
+ idle = CodecData,
+ flex_handler = Pid,
+ flex_conf = FlexConf}}.
+
+init_codec_data(EMsgs, FlexConf) ->
+ [init_codec_data(Codec, Mod, Conf, Msgs, FlexConf) ||
+ {Codec, Mod, Conf, Msgs} <- EMsgs].
+
+init_codec_data(Codec, Mod, Conf0, Msgs0, FlexConf)
+ when is_atom(Codec) andalso
+ is_atom(Mod) andalso
+ is_list(Conf0) andalso
+ is_list(Msgs0) ->
+ io:format(".", []),
+ Conf = [{version3,?VERSION3}|init_codec_conf(FlexConf, Conf0)],
+ Msgs = [?LIB:detect_version(Mod, Conf, Bin) || {_, Bin} <- Msgs0],
+ ets:insert(mstone, {{codec_cnt, Mod, Conf}, 0}),
+ #codec_data{mod = Mod, config = Conf, msgs = Msgs}.
+
+
+init_codec_conf(FlexConf, [flex_scanner]) ->
+ FlexConf;
+init_codec_conf(_, Conf) ->
+ Conf.
+
+
+%% -- Main loop --
+
+loader_loop(finishing, #state{flex_handler = Pid, running = []}) ->
+ %% we are done
+ io:format("~n", []),
+ ?LIB:stop_flex_scanner(Pid),
+ exit({done, lists:sort(ets:tab2list(mstone))});
+
+loader_loop(finishing, State) ->
+ receive
+ {'DOWN', Ref, process, _Pid, {mstone_done, Codec, Conf, Cnt}} ->
+ loader_loop(finishing, done_worker(Ref, Codec, Conf, Cnt, State))
+ end;
+
+loader_loop(running, #state{idle = []} = State) ->
+ receive
+ mstone_finished ->
+ loader_loop(finishing, State);
+
+ {'DOWN', Ref, process, _Pid, {mstone_done, Codec, Conf, Cnt}} ->
+ loader_loop(running, done_worker(Ref, Codec, Conf, Cnt, State))
+ end;
+
+loader_loop(running, State) ->
+ receive
+ mstone_finished ->
+ loader_loop(finishing, State);
+
+ {'DOWN', Ref, process, _Pid, {mstone_done, Codec, Conf, Cnt}} ->
+ State2 = done_worker(Ref, Codec, Conf, Cnt, State),
+ loader_loop(running, State2)
+
+ after 0 ->
+ loader_loop(running, start_worker(State))
+ end.
+
+done_worker(Ref, Codec, Conf, Cnt,
+ #state{running = Running, idle = Idle} = State) ->
+ %% io:format("worker ~w ~w done with ~w~n", [Codec, Conf, Cnt]),
+ ets:update_counter(mstone, worker_cnt, 1),
+ ets:update_counter(mstone, {codec_cnt, Codec, Conf}, Cnt),
+ Running2 = lists:keydelete(Ref, #codec_data.ref, Running),
+ CD = Running -- Running2,
+ State#state{running = Running2, idle = lists:append(Idle, CD)}.
+
+start_worker(#state{running = Running, idle = [H|T]} = State) ->
+ #codec_data{mod = Codec, config = Conf, msgs = Msgs} = H,
+ Worker = fun() -> worker(Codec, Conf, Msgs, 0) end,
+ Ref = erlang:monitor(process, spawn(Worker)),
+ CD = H#codec_data{ref = Ref},
+ State#state{running = [CD | Running], idle = T}.
+
+
+%%%----------------------------------------------------------------------
+
+worker(Codec, Conf, [], Cnt) ->
+ exit({mstone_done, Codec, Conf, Cnt});
+worker(Codec, Conf, [{V, Msg}|Msgs], Cnt) ->
+ work(Codec, Conf, V, Msg),
+ worker(Codec, Conf, Msgs, Cnt + 1).
+
+work(Codec, Conf, V, M) ->
+ case (catch apply(Codec, decode_message, [Conf, V, M])) of
+ {ok, Msg} ->
+ case (catch apply(Codec, encode_message, [Conf, V, Msg])) of
+ {ok, Bin} when is_binary(Bin) ->
+ ok;
+ EncodeError ->
+ emsg("failed encoding message: ~n~p", [EncodeError]),
+ exit({mstone_worker_encode_failure, EncodeError})
+ end;
+ DecodeError ->
+ emsg("failed decoding message: ~n~p", [DecodeError]),
+ exit({mstone_worker_decode_failure, DecodeError})
+ end.
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+emsg(F, A) ->
+ error_logger:error_msg(F ++ "~n", A).
+
+
diff --git a/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl b/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl
new file mode 100644
index 0000000000..31df945777
--- /dev/null
+++ b/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl
@@ -0,0 +1,534 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2006-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: Misc utility functions for the mstone modules
+%%----------------------------------------------------------------------
+
+-module(megaco_codec_mstone_lib).
+
+
+%% API
+-export([start_flex_scanner/0, stop_flex_scanner/1,
+ expanded_messages/2, expanded_messages/3,
+ set_default_sched_bind/0,
+ display_os_info/0,
+ display_system_info/0,
+ display_alloc_info/0,
+ display_app_info/0,
+ detect_version/3]).
+
+%% Internal exports
+-export([flex_scanner_handler/1]).
+
+-include_lib("kernel/include/file.hrl").
+
+
+%%----------------------------------------------------------------------
+%%
+%% D e t e c t V e r s i o n
+%%
+%%----------------------------------------------------------------------
+
+detect_version(Codec, Conf, Bin) ->
+ case (catch Codec:version_of(Conf, Bin)) of
+ {ok, V} ->
+ case (catch Codec:decode_message(Conf, V, Bin)) of
+ {ok, M} ->
+ case (catch Codec:encode_message(Conf, V, M)) of
+ {ok, NewBin} ->
+ {V, NewBin};
+ Error1 ->
+ error({encode_failed, Error1, Codec, Conf, M})
+ end;
+ Error2 ->
+ error({decode_failed, Error2, Codec, Conf, Bin})
+ end;
+ Error3 ->
+ error({version_of_failed, Error3, Codec, Conf, Bin})
+ end.
+
+
+%%----------------------------------------------------------------------
+%%
+%% S c h e d u l e r b i n d t y p e
+%%
+%%----------------------------------------------------------------------
+
+set_default_sched_bind() ->
+ (catch erlang:system_flag(scheduler_bind_type, default_bind)).
+
+
+%%----------------------------------------------------------------------
+%%
+%% D i s p l a y O s I n f o
+%%
+%%----------------------------------------------------------------------
+
+display_os_info() ->
+ V = case os:version() of
+ {Major, Minor, Release} ->
+ lists:flatten(
+ io_lib:format("~w.~w.~w", [Major, Minor, Release]));
+ Str ->
+ Str
+ end,
+ case os:type() of
+ {OsFam, OsName} ->
+ io:format("OS: ~p-~p: ~s~n", [OsFam, OsName, V]);
+ OsFam ->
+ io:format("OS: ~p: ~s~n", [OsFam, V])
+ end.
+
+
+%%----------------------------------------------------------------------
+%%
+%% D i s p l a y S y s t e m I n f o
+%%
+%%----------------------------------------------------------------------
+
+display_system_info() ->
+ SysArch = system_architecture(),
+ OtpRel = otp_release(),
+ SysVer = system_version(),
+ SysHT = heap_type(),
+ SysGHSz = global_heaps_size(),
+ SysSMP = smp_support(),
+ SysNumSched = schedulers(),
+ SysProcLimit = process_limit(),
+ SysThreads = threads(),
+ SysTPSz = thread_pool_size(),
+ SchedBindings = scheduler_bindings(),
+ SchedBindType = scheduler_bind_type(),
+ CpuTopology = cpu_topology(),
+ io:format("System architecture: ~s~n", [SysArch]),
+ io:format("OTP release: ~s~n", [OtpRel]),
+ io:format("System version: ~s~n", [SysVer]),
+ io:format("Heap type: ~s~n", [SysHT]),
+ io:format("Global heap size: ~s~n", [SysGHSz]),
+ io:format("Thread support: ~s~n", [SysThreads]),
+ io:format("Thread pool size: ~s~n", [SysTPSz]),
+ io:format("Process limit: ~s~n", [SysProcLimit]),
+ io:format("SMP support: ~s~n", [SysSMP]),
+ io:format("Num schedulers: ~s~n", [SysNumSched]),
+ io:format("Scheduler bindings: ~s~n", [SchedBindings]),
+ io:format("Scheduler bind type: ~s~n", [SchedBindType]),
+ io:format("Cpu topology: ~s~n", [CpuTopology]),
+ ok.
+
+
+system_architecture() ->
+ string:strip(system_info(system_architecture, string),right,$\n).
+
+otp_release() ->
+ system_info(otp_release, string).
+
+system_version() ->
+ string:strip(system_info(system_version, string),right,$\n).
+
+heap_type() ->
+ system_info(heap_type, any).
+
+global_heaps_size() ->
+ system_info(global_heaps_size, any).
+
+smp_support() ->
+ system_info(smp_support, any).
+
+schedulers() ->
+ system_info(schedulers, any).
+
+process_limit() ->
+ system_info(process_limit, any).
+
+threads() ->
+ system_info(threads, any).
+
+thread_pool_size() ->
+ system_info(thread_pool_size, any).
+
+scheduler_bindings() ->
+ system_info(scheduler_bindings, any).
+
+scheduler_bind_type() ->
+ system_info(scheduler_bind_type, any).
+
+cpu_topology() ->
+ system_info(cpu_topology, any).
+
+system_info(Tag, Type) ->
+ case (catch erlang:system_info(Tag)) of
+ {'EXIT', _} ->
+ "-";
+ Info when is_list(Info) andalso (Type =:= string) ->
+ Info;
+ Info ->
+ lists:flatten(io_lib:format("~w", [Info]))
+ end.
+
+
+
+%%----------------------------------------------------------------------
+%%
+%% D i s p l a y A l l o c a t o r I n f o
+%%
+%%----------------------------------------------------------------------
+
+display_alloc_info() ->
+ io:format("Allocator memory information:~n", []),
+ AllocInfo = alloc_info(),
+ display_alloc_info(AllocInfo).
+
+display_alloc_info([]) ->
+ ok;
+display_alloc_info([{Alloc, Mem}|AllocInfo]) ->
+ io:format(" ~15w: ~10w~n", [Alloc, Mem]),
+ display_alloc_info(AllocInfo).
+
+alloc_info() ->
+ case erlang:system_info(allocator) of
+ {_Allocator, _Version, Features, _Settings} ->
+ alloc_info(Features);
+ _ ->
+ []
+ end.
+
+alloc_info(Allocators) ->
+ Allocs = [temp_alloc, sl_alloc, std_alloc, ll_alloc, eheap_alloc,
+ ets_alloc, binary_alloc, driver_alloc],
+ alloc_info(Allocators, Allocs, []).
+
+alloc_info([], _, Acc) ->
+ lists:reverse(Acc);
+alloc_info([Allocator | Allocators], Allocs, Acc) ->
+ case lists:member(Allocator, Allocs) of
+ true ->
+ Instances0 = erlang:system_info({allocator, Allocator}),
+ Instances =
+ if
+ is_list(Instances0) ->
+ [Instance || Instance <- Instances0,
+ element(1, Instance) =:= instance];
+ true ->
+ []
+ end,
+ AllocatorMem = alloc_mem_info(Instances),
+ alloc_info(Allocators, Allocs, [{Allocator, AllocatorMem} | Acc]);
+
+ false ->
+ alloc_info(Allocators, Allocs, Acc)
+ end.
+
+
+alloc_mem_info(Instances) ->
+ alloc_mem_info(Instances, []).
+
+alloc_mem_info([], Acc) ->
+ lists:sum([Mem || {instance, _, Mem} <- Acc]);
+alloc_mem_info([{instance, N, Info}|Instances], Acc) ->
+ InstanceMemInfo = alloc_instance_mem_info(Info),
+ alloc_mem_info(Instances, [{instance, N, InstanceMemInfo} | Acc]).
+
+alloc_instance_mem_info(InstanceInfo) ->
+ MBCS = alloc_instance_mem_info(mbcs, InstanceInfo),
+ SBCS = alloc_instance_mem_info(sbcs, InstanceInfo),
+ MBCS + SBCS.
+
+alloc_instance_mem_info(Key, InstanceInfo) ->
+ case lists:keysearch(Key, 1, InstanceInfo) of
+ {value, {Key, Info}} ->
+ case lists:keysearch(blocks_size, 1, Info) of
+ {value, {blocks_size, Mem, _, _}} ->
+ Mem;
+ _ ->
+ 0
+ end;
+ _ ->
+ 0
+ end.
+
+
+%%----------------------------------------------------------------------
+%%
+%% D i s p l a y A p p I n f o
+%%
+%%----------------------------------------------------------------------
+
+display_app_info() ->
+ display_megaco_info(),
+ display_asn1_info().
+
+display_megaco_info() ->
+ MI = megaco:module_info(),
+ {value, {attributes, Attr}} = lists:keysearch(attributes, 1, MI),
+ {value, {app_vsn, Ver}} = lists:keysearch(app_vsn, 1, Attr),
+ io:format("Megaco version: ~s~n", [Ver]).
+
+display_asn1_info() ->
+ AI = megaco_ber_bin_drv_media_gateway_control_v1:info(),
+ Vsn =
+ case lists:keysearch(vsn, 1, AI) of
+ {value, {vsn, V}} when is_atom(V) ->
+ atom_to_list(V);
+ {value, {vsn, V}} when is_list(V) ->
+ V;
+ _ ->
+ "unknown"
+ end,
+ io:format("ASN.1 version: ~s~n", [Vsn]).
+
+
+%%----------------------------------------------------------------------
+%%
+%% E x p a n d M e s s a g e s
+%%
+%%----------------------------------------------------------------------
+
+expanded_messages(Codecs, DrvInclude) ->
+ MessagePackage = time_test,
+ expanded_messages(MessagePackage, Codecs, DrvInclude).
+
+expanded_messages(MessagePackage, Codecs, DrvInclude) ->
+ ECodecs = expand_codecs(Codecs, DrvInclude),
+ Messages = megaco_codec_transform:messages(MessagePackage),
+ expanded_messages2(ECodecs, Messages, []).
+
+expanded_messages2([], _Messages, EMessages) ->
+ lists:reverse(EMessages);
+expanded_messages2([{Codec, Mod, Conf}|ECodecs], Messages, EMessages) ->
+ case lists:keysearch(Codec, 1, Messages) of
+ {value, {Codec, Msgs}} ->
+ expanded_messages2(ECodecs, Messages,
+ [{Codec, Mod, Conf, Msgs}|EMessages]);
+ false ->
+ exit({error, {no_such_codec_data, Codec}})
+ end.
+
+
+%%----------------------------------------------------------------------
+%%
+%% E x p a n d C o d e c s
+%%
+%%----------------------------------------------------------------------
+
+expand_codecs(Codecs, DrvInclude) ->
+ expand_codecs(Codecs, DrvInclude, []).
+
+expand_codecs([], _, ECodecs) ->
+ lists:reverse(lists:flatten(ECodecs));
+expand_codecs([Codec|Codecs], DrvInclude, ECodecs) when is_atom(Codec) ->
+ ECodec = expand_codec(Codec, DrvInclude),
+ expand_codecs(Codecs, DrvInclude, [ECodec|ECodecs]).
+
+expand_codec(Codec, flex) ->
+ case Codec of
+ pretty ->
+ [{Codec, megaco_pretty_text_encoder, [flex_scanner]},
+ {Codec, megaco_pretty_text_encoder, [flex_scanner]},
+ {Codec, megaco_pretty_text_encoder, [flex_scanner]},
+ {Codec, megaco_pretty_text_encoder, [flex_scanner]},
+ {Codec, megaco_pretty_text_encoder, [flex_scanner]},
+ {Codec, megaco_pretty_text_encoder, [flex_scanner]},
+ {Codec, megaco_pretty_text_encoder, [flex_scanner]},
+ {Codec, megaco_pretty_text_encoder, [flex_scanner]}];
+ compact ->
+ [{Codec, megaco_compact_text_encoder, [flex_scanner]},
+ {Codec, megaco_compact_text_encoder, [flex_scanner]},
+ {Codec, megaco_compact_text_encoder, [flex_scanner]},
+ {Codec, megaco_compact_text_encoder, [flex_scanner]},
+ {Codec, megaco_compact_text_encoder, [flex_scanner]},
+ {Codec, megaco_compact_text_encoder, [flex_scanner]},
+ {Codec, megaco_compact_text_encoder, [flex_scanner]},
+ {Codec, megaco_compact_text_encoder, [flex_scanner]}];
+ ber ->
+ [];
+ per ->
+ [];
+ erlang ->
+ [];
+ Else ->
+ error({invalid_codec, Else})
+ end;
+expand_codec(Codec, only_drv) ->
+ case Codec of
+ pretty ->
+ [{Codec, megaco_pretty_text_encoder, [flex_scanner]},
+ {Codec, megaco_pretty_text_encoder, [flex_scanner]}];
+ compact ->
+ [{Codec, megaco_compact_text_encoder, [flex_scanner]},
+ {Codec, megaco_compact_text_encoder, [flex_scanner]}];
+ ber ->
+ [{Codec, megaco_ber_bin_encoder, [driver,native]},
+ {Codec, megaco_ber_bin_encoder, [driver]},
+ {Codec, megaco_ber_bin_encoder, [driver,native]},
+ {Codec, megaco_ber_bin_encoder, [driver]}];
+ per ->
+ [{Codec, megaco_per_bin_encoder, [driver,native]},
+ {Codec, megaco_per_bin_encoder, [native]},
+ {Codec, megaco_per_bin_encoder, [driver,native]},
+ {Codec, megaco_per_bin_encoder, [native]}];
+ erlang ->
+ Encoder = megaco_erl_dist_encoder,
+ [
+ {Codec, Encoder, [megaco_compressed,compressed]},
+ {Codec, Encoder, [compressed]},
+ {Codec, Encoder, [megaco_compressed,compressed]},
+ {Codec, Encoder, [compressed]}
+ ];
+ Else ->
+ error({invalid_codec, Else})
+ end;
+expand_codec(Codec, no_drv) ->
+ case Codec of
+ pretty ->
+ [{Codec, megaco_pretty_text_encoder, []},
+ {Codec, megaco_pretty_text_encoder, []}];
+ compact ->
+ [{Codec, megaco_compact_text_encoder, []},
+ {Codec, megaco_compact_text_encoder, []}];
+ ber ->
+ [{Codec, megaco_ber_bin_encoder, [native]},
+ {Codec, megaco_ber_bin_encoder, []},
+ {Codec, megaco_ber_bin_encoder, [native]},
+ {Codec, megaco_ber_bin_encoder, []}];
+ per ->
+ [{Codec, megaco_per_bin_encoder, [native]},
+ {Codec, megaco_per_bin_encoder, []},
+ {Codec, megaco_per_bin_encoder, [native]},
+ {Codec, megaco_per_bin_encoder, []}];
+ erlang ->
+ Encoder = megaco_erl_dist_encoder,
+ [
+ {Codec, Encoder, [megaco_compressed]},
+ {Codec, Encoder, []},
+ {Codec, Encoder, [megaco_compressed]},
+ {Codec, Encoder, []}
+ ];
+ Else ->
+ error({invalid_codec, Else})
+ end;
+expand_codec(Codec, _) ->
+ case Codec of
+ pretty ->
+ [{Codec, megaco_pretty_text_encoder, [flex_scanner]},
+ {Codec, megaco_pretty_text_encoder, []}];
+ compact ->
+ [{Codec, megaco_compact_text_encoder, [flex_scanner]},
+ {Codec, megaco_compact_text_encoder, []}];
+ ber ->
+ [{Codec, megaco_ber_bin_encoder, [driver,native]},
+ {Codec, megaco_ber_bin_encoder, [native]},
+ {Codec, megaco_ber_bin_encoder, [driver]},
+ {Codec, megaco_ber_bin_encoder, []}];
+ per ->
+ [{Codec, megaco_per_bin_encoder, [driver,native]},
+ {Codec, megaco_per_bin_encoder, [native]},
+ {Codec, megaco_per_bin_encoder, [driver]},
+ {Codec, megaco_per_bin_encoder, []}];
+ erlang ->
+ Encoder = megaco_erl_dist_encoder,
+ [
+ {Codec, Encoder, [megaco_compressed,compressed]},
+ {Codec, Encoder, [compressed]},
+ {Codec, Encoder, [megaco_compressed]},
+ {Codec, Encoder, []}
+ ];
+ Else ->
+ error({invalid_codec, Else})
+ end.
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%%----------------------------------------------------------------------
+%%
+%% S t a r t F l e x S c a n n e r H a n d l e r
+%%
+%%----------------------------------------------------------------------
+
+start_flex_scanner() ->
+ Pid = proc_lib:spawn(?MODULE, flex_scanner_handler, [self()]),
+ receive
+ {flex_scanner_started, Pid, Conf} ->
+ {Pid, [Conf]};
+ {flex_scanner_error, {failed_loading_flex_scanner_driver, Reason}} ->
+ error({failed_loading_flex_scanner_driver, Reason});
+ {flex_scanner_error, Reason} ->
+ error({failed_loading_flex_scanner_driver, Reason})
+ after 10000 ->
+ exit(Pid, kill),
+ error({failed_starting_flex_scanner, timeout})
+ end.
+
+%%----------------------------------------------------------------------
+%%
+%% S t o p F l e x S c a n n e r H a n d l e r
+%%
+%%----------------------------------------------------------------------
+
+stop_flex_scanner(Pid) ->
+ Pid ! stop_flex_scanner.
+
+flex_scanner_handler(Pid) ->
+ case (catch megaco_flex_scanner:start()) of
+ {ok, PortOrPorts} ->
+ Pid ! {flex_scanner_started, self(), {flex, PortOrPorts}},
+ flex_scanner_handler_loop(Pid, PortOrPorts);
+ {error, {load_driver, {open_error, Reason}}} ->
+ Error = {failed_loading_flex_scanner_driver, Reason},
+ Pid ! {flex_scanner_error, Error},
+ exit(Error);
+ Else ->
+ Error = {unknown_result_from_start_flex_scanner, Else},
+ Pid ! {flex_scanner_error, Error},
+ exit(Error)
+ end.
+
+flex_scanner_handler_loop(Pid, PortOrPorts) ->
+ receive
+ {ping, Pinger} ->
+ Pinger ! {pong, self()},
+ flex_scanner_handler_loop(Pid, PortOrPorts);
+ {'EXIT', Port, Reason} when (Port =:= PortOrPorts) ->
+ Pid ! {flex_scanner_exit, Reason},
+ exit({flex_scanner_exit, Reason});
+ {'EXIT', Port, Reason} when is_port(Port) ->
+ case megaco_flex_scanner:is_scanner_port(Port, PortOrPorts) of
+ true ->
+ Pid ! {flex_scanner_exit, Reason},
+ exit({flex_scanner_exit, Reason});
+ false ->
+ %% Just ignore this crap
+ flex_scanner_handler_loop(Pid, PortOrPorts)
+ end;
+ stop_flex_scanner ->
+ megaco_flex_scanner:stop(PortOrPorts),
+ exit(normal);
+ _Other ->
+ flex_scanner_handler_loop(Pid, PortOrPorts)
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+error(Reason) ->
+ throw({error, Reason}).
+
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)).
diff --git a/lib/megaco/examples/meas/modules.mk b/lib/megaco/examples/meas/modules.mk
new file mode 100644
index 0000000000..8f1b45c8a6
--- /dev/null
+++ b/lib/megaco/examples/meas/modules.mk
@@ -0,0 +1,35 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %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%
+
+SCRIPT_SKELETONS = \
+ meas.sh.skel \
+ mstone1.sh.skel
+
+MESSAGE_PACKAGES = \
+ time_test.msgs
+
+MODULES = \
+ megaco_codec_transform \
+ megaco_codec_mstone_lib \
+ megaco_codec_mstone1 \
+ megaco_codec_mstone2 \
+ megaco_codec_meas
+
+README = MEAS_README
+
diff --git a/lib/megaco/examples/meas/mstone1.sh.skel b/lib/megaco/examples/meas/mstone1.sh.skel
new file mode 100644
index 0000000000..b7c7e41007
--- /dev/null
+++ b/lib/megaco/examples/meas/mstone1.sh.skel
@@ -0,0 +1,239 @@
+#!/bin/sh
+
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2007-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%
+
+# Skeleton for a script intended to run the mstone1(N)
+# performance test.
+#
+
+# Get the name of the program
+program=`echo $0 | sed 's#.*/##g'`
+
+usage="\
+Usage: $program [options]
+
+This shell script is used to run the mstone 1 (factor) performance
+test. It is not intended to test the megaco stack but instead to
+give a \"performance value\" of the host on which it is run.
+
+Options:
+ -help display this help and exit.
+ -mp <message package> message package to use for test
+ default is time_test
+ -h <num> default process heap size
+ -a <num> async thread pool size (default is 0)
+ -f <factor> normally the test is run with 16 processes
+ (factor 1), one for each codec config. The test
+ can however be run with other factors, e.g.
+ factor 10 means that 10 processes will be started
+ for each megaco codec config.
+ The options -s and -f cannot both be present.
+ -s <num sched> normally the test is run with a fixed factor,
+ but if this option is given, the number of
+ schedulers is fixed (to the value set by this option)
+ and the factor is the variable.
+ The options -s and -f cannot both be present.
+ -d <drv-mode> driver mode for the test:
+ std - all codec config(s) will be used
+ flex - only the text codec config(s) utilizing the
+ flex scanner will be used
+ nd - only codec config(s) without drivers will be used
+ od - only codec config(s) with drivers will be used
+ -- everything after this is just passed on to erl.
+"
+
+ERL_HOME=<path to otp top dir>
+MEGACO_HOME=$ERL_HOME/lib/erlang/lib/<megaco dir>
+MEAS_HOME=$MEGACO_HOME/examples/meas
+PATH=$ERL_HOME/bin:$PATH
+
+MODULE=megaco_codec_mstone1
+STARTF="start"
+FACTOR=""
+MSG_PACK=time_test
+
+while test $# != 0; do
+ # echo "DBG: Value = $1"
+ case $1 in
+ -help)
+ echo "$usage" ;
+ exit 0;;
+
+ -mp)
+ MSG_PACK="$2";
+ shift ; shift ;;
+
+ -h)
+ PHS="+h $2";
+ shift ; shift ;;
+
+ -a)
+ ATP="+A $2";
+ shift ; shift ;;
+
+ -d)
+ case $2 in
+ std)
+ STARTF="start";
+ shift ; shift ;;
+ flex)
+ STARTF="start_flex";
+ shift ; shift ;;
+ nd)
+ STARTF="start_no_drv";
+ shift ; shift ;;
+ od)
+ STARTF="start_only_drv";
+ shift ; shift ;;
+ *)
+ echo "unknown driver mode: $2";
+ echo "$usage" ;
+ exit 0
+ esac;;
+
+ -f)
+ if [ "x$SCHED" != "x" ]; then
+ echo "option(s) -s and -f cannot both be given" ;
+ echo "$usage" ;
+ exit 0
+ fi
+ FACTOR="$2";
+ TYPE=factor;
+ shift ; shift ;;
+
+ -s)
+ if [ "x$FACTOR" != "x" ]; then
+ echo "option(s) -f and -s cannot both be given" ;
+ echo "$usage" ;
+ exit 0
+ fi
+ SCHED="$2";
+ TYPE=sched;
+ shift ; shift ;;
+
+ --)
+ shift ;
+ break;;
+
+ *)
+ echo "unknown option: $1";
+ echo "$usage" ;
+ exit 0
+ esac
+done
+
+if [ $TYPE = factor ]; then
+
+ MSTONE="-s $MODULE $STARTF $MSG_PACK $FACTOR"
+
+ # SCHEDS="no_smp 01 02 04"
+ # SCHEDS="no_smp 01 02 04 08"
+ # SCHEDS="no_smp 01 02 04 08 16"
+ # SCHEDS="no_smp 01 02 04 08 16 32"
+ # SCHEDS="no_smp 01 02 04 08 16 32 64"
+ SCHEDS="no_smp 01 02 03 04 05 06 07 08"
+
+ for i in `echo $SCHEDS`; do
+ case $i in
+ no_smp)
+ SMP_INFO="No SMP"
+ SMP_OPTS="-smp disable" # THIS IS THE R12B WAY TO DISABLE SMP
+ LOG="mstone1-f$FACTOR-s00.log"
+ ;;
+
+ 01)
+ SMP_INFO="SMP: 1 scheduler"
+ SMP_OPTS="-smp +S $i"
+ LOG="mstone1-f$FACTOR-s$i.log"
+ ;;
+
+ *)
+ SMP_INFO="SMP: $i schedulers"
+ SMP_OPTS="-smp +S $i"
+ LOG="mstone1-f$FACTOR-s$i.log"
+ ;;
+ esac
+
+ echo ""
+ echo "---------------------------------------------"
+ echo "$SMP_INFO"
+ echo ""
+
+ ERL="erl \
+ -noshell \
+ $PHS \
+ $ATP \
+ $SMP_OPTS \
+ -pa $MEAS_HOME \
+ $MSTONE \
+ $* \
+ -s init stop"
+
+ echo $ERL
+ $ERL | tee $LOG
+ done
+
+elif [ $TYPE = sched ]; then
+
+ MSTONE="-s $MODULE $STARTF $MSG_PACK"
+
+ # FACTORS="01 02 03 04"
+ # FACTORS="01 02 03 04 05 06 07 08 09 10"
+ FACTORS="01 02 04 08 16 32"
+ # FACTORS="001 010 100"
+
+ case $SCHED in
+ no_smp)
+ SMP_OPTS="-smp disable" # THIS IS THE R12B WAY TO DISABLE SMP
+ ;;
+
+ *)
+ SMP_OPTS="-smp +S $SCHED"
+ ;;
+ esac
+
+ for i in `echo $FACTORS`; do
+ LOG="mstone1-s$SCHED-f$i.log"
+
+ echo ""
+ echo "---------------------------------------------"
+ echo "Factor $i"
+ echo ""
+
+ ERL="erl \
+ -noshell \
+ $PHS \
+ $ATP \
+ $SMP_OPTS \
+ -pa $MEAS_HOME \
+ $MSTONE $i \
+ $* \
+ -s init stop"
+
+ echo $ERL
+ $ERL | tee $LOG
+ done
+
+
+else
+ echo "Either option -f or -s must be specified"
+ echo "$usage" ;
+ exit 0
+
+fi
diff --git a/lib/megaco/examples/meas/time_test.msgs b/lib/megaco/examples/meas/time_test.msgs
new file mode 100644
index 0000000000..d8ac2bf1a2
--- /dev/null
+++ b/lib/megaco/examples/meas/time_test.msgs
@@ -0,0 +1,149 @@
+{pretty, [{msg01a,<<"MEGACO/1 [123.123.123.4]:55555\nTransaction = 9999 {\n\tContext = - {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocalControl {\n\t\t\t\t\t\tMode = SendReceive,\n\t\t\t\t\t\ttdmc/gain=2,\n\t\t\t\t\t\ttdmc/ec=g165\n\t\t\t\t\t},\n\t\t\t\t\tLocal { \nv=0\nc=IN IP4 $ \nm=audio $ RTP/AVP 0\na=fmtp:PCMU VAD=X-NNVAD\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tEvents = 2222 {\n\t\t\t\tal/of\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg01b,<<"MEGACO/1 [123.123.123.4]:55555\nTransaction = 9999 {\n\tContext = - {\n\t\tModify = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocalControl {\n\t\t\t\t\t\tMode = SendReceive,\n\t\t\t\t\t\ttdmc/gain=2,\n\t\t\t\t\t\ttdmc/ec=g165\n\t\t\t\t\t},\n\t\t\t\t\tLocal { \nv=0\nc=IN IP4 $ \nm=audio $ RTP/AVP 0\na=fmtp:PCMU VAD=X-NNVAD\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tEvents = 2222 {\n\t\t\t\tal/of\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg02,<<"MEGACO/1 [123.123.123.4]:55555\nTransaction = 9999 {\n\tContext = - {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocalControl {\n\t\t\t\t\t\tMode = SendReceive,\n\t\t\t\t\t\ttdmc/gain=2,\n\t\t\t\t\t\ttdmc/ec=g165\n\t\t\t\t\t},\n\t\t\t\t\tLocal { \nv=0\nc=IN IP4 $ \nm=audio $ RTP/AVP 0\na=fmtp:PCMU VAD=X-NNVAD\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tEvents = 2222 {\n\t\t\t\tal/of {\n\t\t\t\t\tstrict=exact\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg03,<<"MEGACO/1 [124.124.124.222]:55555\nTransaction = 10000 {\n\tContext = - {\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg04,<<"MEGACO/1 [124.124.124.222]\nTransaction = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901 mg col boot\"\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg05,<<"MEGACO/1 [123.123.123.4]:55555\nReply = 9998 {\n\tContext = - {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1\n\t\t\t}\n\t\t\t}\n\t}\n}">>},
+ {msg06a,<<"MEGACO/1 [124.124.124.222]:55555\nReply = 9999 {\n\tContext = - {\n\t\tModify = 11111111/00000000/00000000\n\t}\n}">>},
+ {msg06b,<<"MEGACO/1 [125.125.125.111]:55555\nReply = 9999 {\n\tContext = - {\n\t\tModify = 11111111/11111111/00000000\n\t}\n}">>},
+ {msg07,<<"MEGACO/1 [123.123.123.4]:55555\nReply = 10000 {\n\tContext = - {\n\t\tNotify = 11111111/00000000/00000000\n\t}\n}">>},
+ {msg08a,<<"MEGACO/1 [123.123.123.4]:55555\nTransaction = 10001 {\n\tContext = - {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tEvents = 2223 {\n\t\t\t\tal/on,\n\t\t\t\tdd/ce {\n\t\t\t\t\tDigitMap = dialplan00\n\t\t\t\t}\n\t\t\t},\n\t\t\tSignals {\n\t\t\t\tcg/rt\n\t\t\t},\n\t\t\tDigitMap = dialplan00 {\n\t\t\t\t(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg08b,<<"MEGACO/1 [123.123.123.4]:55555\nTransaction = 10001 {\n\tContext = - {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tEvents = 2223 {\n\t\t\t\tal/on,\n\t\t\t\tdd/ce {\n\t\t\t\t\tDigitMap = dialplan00\n\t\t\t\t}\n\t\t\t},\n\t\t\tSignals {\n\t\t\t\tcg/rt\n\t\t\t},\n\t\t\tDigitMap = dialplan00 {\n\t\t\t\tT:1,\n\t\t\t\tS:23,\n\t\t\t\tL:99,\n\t\t\t\t(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg09,<<"MEGACO/1 [124.124.124.222]:55555\nTransaction = 10002 {\n\tContext = - {\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2223 {\n\t\t\t\t19990729T22010001:dd/ce {\n\t\t\t\t\tds=916135551212\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg10,<<"MEGACO/1 [123.123.123.4]:55555\nTransaction = 10003 {\n\tContext = $ {\n\t\tAdd = 11111111/00000000/00000000,\n\t\tAdd = $ {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocalControl {\n\t\t\t\t\t\tMode = ReceiveOnly,\n\t\t\t\t\t\tnt/jit=40\n\t\t\t\t\t},\n\t\t\t\t\tLocal { \nv=0\nc=IN IP4 $ \nm=audio $ RTP/AVP 4\na=ptime:30\nv=0\nc=IN IP4 $ \nm=audio $ RTP/AVP 0\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg11,<<"MEGACO/1 [124.124.124.222]:55555\nReply = 10003 {\n\tContext = 2000 {\n\t\tAdd = 11111111/00000000/00000000,\n\t\tAdd = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocal { \nv=0\nc=IN IP4 124.124.124.222\nm=audio 2222 RTP/AVP 4\na=a=ptime:30\na=recvonly\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg12,<<"MEGACO/1 [123.123.123.4]:55555\nTransaction = 50003 {\n\tContext = $ {\n\t\tAdd = 11111111/11111111/00000000 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocalControl {\n\t\t\t\t\t\tMode = SendReceive\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tSignals {\n\t\t\t\tal/ri\n\t\t\t}\n\t\t},\n\t\tAdd = $ {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocalControl {\n\t\t\t\t\t\tMode = SendReceive,\n\t\t\t\t\t\tnt/jit=40\n\t\t\t\t\t},\n\t\t\t\t\tLocal { \nv=0\nc=IN IP4 $ \nm=audio $ RTP/AVP 4\na=ptime:30\n\n\t\t\t\t\t},\n\t\t\t\t\tRemote { \nv=0\nc=IN IP4 124.124.124.222\nm=audio 2222 RTP/AVP 4\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg13,<<"MEGACO/1 [125.125.125.111]:55555\nReply = 50003 {\n\tContext = 5000 {\n\t\tAdd = 11111111/11111111/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocal { \nv=0\nc=IN IP4 125.125.125.111\nm=audio 1111 RTP/AVP 4\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg14,<<"MEGACO/1 [123.123.123.4]:55555\nTransaction = 10005 {\n\tContext = 2000 {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tSignals {\n\t\t\t\tcg/rt\n\t\t\t}\n\t\t},\n\t\tModify = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tRemote { \nv=0\nc=IN IP4 125.125.125.111\nm=audio 1111 RTP/AVP 4\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg15,<<"MEGACO/1 [124.124.124.222]:55555\nReply = 10005 {\n\tContext = 2000 {\n\t\tModify = 11111111/00000000/00000000,\n\t\tModify = 11111111/00000000/11111111\n\t}\n}">>},
+ {msg16,<<"MEGACO/1 [125.125.125.111]:55555\nTransaction = 50005 {\n\tContext = 5000 {\n\t\tNotify = 11111111/11111111/00000000 {\n\t\t\tObservedEvents = 1234 {\n\t\t\t\t19990729T22020002:al/of\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg17,<<"MEGACO/1 [123.123.123.4]:55555\nReply = 50005 {\n\tContext = - {\n\t\tNotify = 11111111/11111111/00000000\n\t}\n}">>},
+ {msg18,<<"MEGACO/1 [123.123.123.4]:55555\nTransaction = 50006 {\n\tContext = 5000 {\n\t\tModify = 11111111/11111111/00000000 {\n\t\t\tEvents = 1235 {\n\t\t\t\tal/on\n\t\t\t},\n\t\t\tSignals\n\t\t}\n\t}\n}">>},
+ {msg19,<<"MEGACO/1 [125.125.125.111]:55555\nReply = 50006 {\n\tContext = 5000 {\n\t\tModify = 11111111/00000000/11111111\n\t}\n}">>},
+ {msg20,<<"MEGACO/1 [123.123.123.4]:55555\nTransaction = 10006 {\n\tContext = 2000 {\n\t\tModify = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocalControl {\n\t\t\t\t\t\tMode = SendReceive\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tSignals\n\t\t}\n\t}\n}">>},
+ {msg21,<<"MEGACO/1 [123.123.123.4]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia,\n\t\t\t\tEvents,\n\t\t\t\tSignals,\n\t\t\t\tDigitMap,\n\t\t\t\tStatistics,\n\t\t\t\tPackages\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg22a,<<"MEGACO/1 [125.125.125.111]:55555\nReply = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocalControl {\n\t\t\t\t\t\tMode = SendReceive,\n\t\t\t\t\t\tnt/jit=40\n\t\t\t\t\t},\n\t\t\t\t\tLocal { \nv=0\nc=IN IP4 125.125.125.111\nm=audio 1111 RTP/AVP 4\na=ptime:30\n\n\t\t\t\t\t},\n\t\t\t\t\tRemote { \nv=0\nc=IN IP4 124.124.124.222\nm=audio 2222 RTP/AVP 4\na=ptime:30\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tPackages {\n\t\t\t\tnt-1,\n\t\t\t\tnt-1\n\t\t\t},\n\t\t\tStatistics {\n\t\t\t\trtp/ps = 1200,\n\t\t\t\tnt/os = 62300,\n\t\t\t\trtp/pr = 700,\n\t\t\t\tnt/or = 45100,\n\t\t\t\trtp/pl = 0.2,\n\t\t\t\trtp/jit = 20,\n\t\t\t\trtp/delay = 40\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg23a,<<"MEGACO/1 [125.125.125.111]:55555\nTransaction = 50008 {\n\tContext = 5000 {\n\t\tNotify = 11111111/11111111/00000000 {\n\t\t\tObservedEvents = 1235 {\n\t\t\t\t19990729T24020002:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg23b,<<"MEGACO/1 [125.125.125.111]:55555\nTransaction = 50008 {\n\tContext = 5000 {\n\t\tNotify = 11111111/11111111/00000000 {\n\t\t\tObservedEvents = 1235 {\n\t\t\t\t19990729T24020002:al/on\n\t\t\t}\n\t\t}\n\t},\n\tContext = 5001 {\n\t\tNotify = 11111111/11111111/11111111 {\n\t\t\tObservedEvents = 1235 {\n\t\t\t\t19990729T24020002:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg23c,<<"MEGACO/1 [125.125.125.111]:55555\nTransaction = 50008 {\n\tContext = 5000 {\n\t\tNotify = 11111111/11111111/00000000 {\n\t\t\tObservedEvents = 1235 {\n\t\t\t\t19990729T24020002:al/on\n\t\t\t}\n\t\t}\n\t}\n}Transaction = 50009 {\n\tContext = 5001 {\n\t\tNotify = 11111111/11111111/11111111 {\n\t\t\tObservedEvents = 1235 {\n\t\t\t\t19990729T24020002:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg23d,<<"MEGACO/1 [125.125.125.111]:55555\nTransaction = 50008 {\n\tContext = 5000 {\n\t\tNotify = 11111111/11111111/00000000 {\n\t\t\tObservedEvents = 1235 {\n\t\t\t\t19990729T24020002:al/on\n\t\t\t}\n\t\t}\n\t},\n\tContext = 5001 {\n\t\tNotify = 11111111/11111111/11111111 {\n\t\t\tObservedEvents = 1235 {\n\t\t\t\t19990729T24020002:al/on\n\t\t\t}\n\t\t}\n\t}\n}Transaction = 50009 {\n\tContext = 5003 {\n\t\tNotify = 11111111/11111111/00000000 {\n\t\t\tObservedEvents = 1235 {\n\t\t\t\t19990729T24020002:al/on\n\t\t\t}\n\t\t}\n\t},\n\tContext = 5004 {\n\t\tNotify = 11111111/11111111/11111111 {\n\t\t\tObservedEvents = 1235 {\n\t\t\t\t19990729T24020002:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg24,<<"MEGACO/1 [123.123.123.4]:55555\nTransaction = 50009 {\n\tContext = 5000 {\n\t\tSubtract = 11111111/11111111/00000000 {\n\t\t\tAudit {\n\t\t\t\tStatistics\n\t\t\t}\n\t\t},\n\t\tSubtract = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tStatistics\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg25,<<"MEGACO/1 [125.125.125.111]:55555\nReply = 50009 {\n\tContext = 5000 {\n\t\tSubtract = 11111111/11111111/00000000 {\n\t\t\tStatistics {\n\t\t\t\tnt/os = 45123,\n\t\t\t\tnt/dur = 40\n\t\t\t}\n\t\t},\n\t\tSubtract = 11111111/11111111/11111111 {\n\t\t\tStatistics {\n\t\t\t\trtp/ps = 1245,\n\t\t\t\tnt/os = 62345\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg30a,<<"MEGACO/1 [125.125.125.111]:55555\nTransactionResponseAck {\n\t9\n}">>},
+ {msg30b,<<"MEGACO/1 [125.125.125.111]:55555\nTransactionResponseAck {\n\t9-13\n}">>},
+ {msg30c,<<"MEGACO/1 [125.125.125.111]:55555\nTransactionResponseAck {\n\t9-13,\n\t15,\n\t33-40,\n\t50-60,\n\t70-80,\n\t85-90,\n\t101-105,\n\t109-119,\n\t121-130,\n\t140-160,\n\t170-175,\n\t180-189,\n\t201-205,\n\t209-219,\n\t221-230,\n\t240-260,\n\t270-275,\n\t280-289,\n\t301-305,\n\t309-319,\n\t321-330,\n\t340-360,\n\t370-375,\n\t380-389,\n\t401-405,\n\t409-419,\n\t421-430,\n\t440-460,\n\t470-475,\n\t480-489,\n\t501-505,\n\t509-519,\n\t521-530,\n\t540-560,\n\t570-575,\n\t580-589\n}">>},
+ {msg30d,<<"MEGACO/1 [125.125.125.111]:55555\nTransactionResponseAck {\n\t9-13,\n\t15,\n\t33-40,\n\t50-60,\n\t70-80,\n\t85-90\n}TransactionResponseAck {\n\t101-105,\n\t109-119,\n\t121-130,\n\t140-160,\n\t170-175,\n\t180-189\n}TransactionResponseAck {\n\t201-205,\n\t209-219,\n\t221-230,\n\t240-260,\n\t270-275,\n\t280-289\n}TransactionResponseAck {\n\t301-305,\n\t309-319,\n\t321-330,\n\t340-360,\n\t370-375,\n\t380-389\n}TransactionResponseAck {\n\t401-405,\n\t409-419,\n\t421-430,\n\t440-460,\n\t470-475,\n\t480-489\n}TransactionResponseAck {\n\t501-505,\n\t509-519,\n\t521-530,\n\t540-560,\n\t570-575,\n\t580-589\n}">>},
+ {msg51a,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tTerminationState {\n\t\t\t\t\t\ttdmc/gain\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg51b,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tTerminationState {\n\t\t\t\t\t\tnt/jit\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg51c,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tTerminationState {\n\t\t\t\t\t\tServiceStates\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg51d,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tTerminationState {\n\t\t\t\t\t\tBuffer\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg51e,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tLocalControl {\n\t\t\t\t\t\t\tMode\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg51f,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tLocalControl {\n\t\t\t\t\t\t\tReservedValue\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg51g,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tLocalControl {\n\t\t\t\t\t\t\tReservedGroup\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg51h,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tStream = 123 {\n\t\t\t\t\t\t\tLocalControl {\n\t\t\t\t\t\t\t\t\tnt/jit\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg51i,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tStream = 123 {\n\t\t\t\t\t\t\tLocalControl {\n\t\t\t\t\t\t\t\t\tMode,\n\t\t\t\t\t\t\t\t\tReservedValue,\n\t\t\t\t\t\t\t\t\tReservedGroup,\n\t\t\t\t\t\t\t\t\tnt/jit,\n\t\t\t\t\t\t\t\t\ttdmc/ec\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg52,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tEvents = 1235 {\n\t\t\t\t\ttonedet/std\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg53,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tEventBuffer {\n\t\t\t\t\ttonedet/std {\n\t\t\t\t\t\tStream = 1\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg54a,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tSignals {\n\t\t\t\t\ttonegen/pt\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg54b,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tSignals {\n\t\t\t\t\tdg/d0\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg54c,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tSignals {\n\t\t\t\t\tSignalList = 4321 {\n\t\t\t\t\t\tct/ct\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg55,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tDigitMap = dialplan00\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg56,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tStatistics {\n\t\t\t\t\tnt/dur\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg57,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tPackages {\n\t\t\t\t\tal-1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg58a,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tTerminationState {\n\t\t\t\t\t\ttdmc/gain\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tEvents = 1235 {\n\t\t\t\t\ttonedet/std\n\t\t\t\t},\n\t\t\t\tEventBuffer {\n\t\t\t\t\ttonedet/std {\n\t\t\t\t\t\tStream = 1\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tSignals {\n\t\t\t\t\ttonegen/pt\n\t\t\t\t},\n\t\t\t\tDigitMap = dialplan00,\n\t\t\t\tStatistics {\n\t\t\t\t\tnt/dur\n\t\t\t\t},\n\t\t\t\tPackages {\n\t\t\t\t\tal-1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg58b,<<"MEGACO/2 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tTerminationState {\n\t\t\t\t\t\tBuffer\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tEvents = 1235 {\n\t\t\t\t\ttonedet/std\n\t\t\t\t},\n\t\t\t\tEventBuffer {\n\t\t\t\t\ttonedet/std {\n\t\t\t\t\t\tStream = 1\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tSignals {\n\t\t\t\t\tSignalList = 4321 {\n\t\t\t\t\t\tct/ct\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tDigitMap = dialplan00,\n\t\t\t\tStatistics {\n\t\t\t\t\tnt/dur\n\t\t\t\t},\n\t\t\t\tPackages {\n\t\t\t\t\tal-1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg61a,<<"MEGACO/2 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergencyOffToken,\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg61b,<<"MEGACO/2 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg61c,<<"MEGACO/2 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71a,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b01,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b02,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tEmergency,\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b03,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tEmergencyOff,\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b04,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tBothway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tIsolate\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b05,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b06,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergencyOff,\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b07,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tBothway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tOneway\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b08,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tBothway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tBothway\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b09,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergencyOff,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tIsolate,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tOneway\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b10,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergencyOff,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tIsolate,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tOneway,\n\t\t\tOnewayBoth\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b11,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergencyOff,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tIsolate,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tOneway,\n\t\t\tOnewayExternal\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b12,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tOneway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tBothway\n\t\t},\n\t\tIEPSCall = ON,\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b13,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tBothway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tBothway\n\t\t},\n\t\tIEPSCall = OFF,\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b14,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tOneway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tOneway\n\t\t},\n\t\tContextAttr {\n\t\t\ttdmc/gain=2\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b15,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tIsolate,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tIsolate\n\t\t},\n\t\tContextAttr {\n\t\t\ttdmc/gain>2\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b16,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tIsolate,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tBothway\n\t\t},\n\t\tContextAttr {\n\t\t\ttdmc/gain = [ 2:10 ] \n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b17,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tOneway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tBothway\n\t\t},\n\t\tContextAttr {\n\t\t\tnt/jit = [\n\t\t\t40,\n\t\t\t50,\n\t\t\t50\n\t\t]\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b18,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tOneway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tIsolate\n\t\t},\n\t\tIEPSCall = ON,\n\t\tContextAttr {\n\t\t\ttdmc/gain = {\n\t\t\t2,\n\t\t\t4,\n\t\t\t8\n\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b19,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tOneway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tBothway\n\t\t},\n\t\tIEPSCall = OFF,\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b20,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tOneway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tIsolate\n\t\t},\n\t\tIEPSCall = OFF,\n\t\tContextAttr {\n\t\t\ttdmc/gain = {\n\t\t\t2,\n\t\t\t4,\n\t\t\t8\n\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b21,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tOneway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tIsolate\n\t\t},\n\t\tIEPSCall = OFF,\n\t\tContextAttr {\n\t\t\tContextList = {\n\t\t\t\t10191,\n\t\t\t\t10192\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71b22,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tOneway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tIsolate\n\t\t},\n\t\tIEPSCall = OFF,\n\t\tContextAttr {\n\t\t\ttdmc/gain = {\n\t\t\t2,\n\t\t\t4,\n\t\t\t8\n\t\t}\n\t\t},\n\t\tContextAttr {\n\t\t\tContextList = {\n\t\t\t\t10191,\n\t\t\t\t10192\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c01,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tEmergency,\n\t\t\tPriority\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c02,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tEmergency\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c03,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tPriority\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c04,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tEmergency,\n\t\t\tPriority\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c05,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tPriority\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c06,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tEmergency\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c07,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tTopology\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c08,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tPriority,\n\t\t\tIEPSCall\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c09,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tEmergency,\n\t\t\tPriority,\n\t\t\tIEPSCall,\n\t\t\ttdmc/gain,\n\t\t\tnt/jit\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c10,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tEmergency,\n\t\t\tPriority,\n\t\t\tIEPSCall,\n\t\t\ttdmc/gain,\n\t\t\tnt/jit,\n\t\t\tPriority = 10\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c11,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tEmergency,\n\t\t\tPriority,\n\t\t\tIEPSCall,\n\t\t\ttdmc/gain,\n\t\t\tnt/jit,\n\t\t\tPriority = 10,\n\t\t\tEmergencyValue = Emergency\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c12,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tEmergency,\n\t\t\tPriority,\n\t\t\tIEPSCall,\n\t\t\ttdmc/gain,\n\t\t\tnt/jit,\n\t\t\tPriority = 10,\n\t\t\tEmergencyValue = Emergency,\n\t\t\tIEPSCall = OFF\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c13,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tEmergency,\n\t\t\tPriority,\n\t\t\tIEPSCall,\n\t\t\ttdmc/gain,\n\t\t\tnt/jit,\n\t\t\tPriority = 10,\n\t\t\tEmergencyValue = EmergencyOff,\n\t\t\tIEPSCall = ON\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c14,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tEmergency,\n\t\t\tPriority,\n\t\t\tIEPSCall,\n\t\t\ttdmc/gain,\n\t\t\tnt/jit,\n\t\t\tPriority = 10,\n\t\t\tEmergencyValue = Emergency,\n\t\t\tIEPSCall = ON,\n\t\t\tORLgc\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71c15,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tEmergency,\n\t\t\tPriority,\n\t\t\tIEPSCall,\n\t\t\ttdmc/gain,\n\t\t\tnt/jit,\n\t\t\tPriority = 10,\n\t\t\tORLgc\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71d01,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tEmergency,\n\t\t\tPriority\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71d02,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tBothway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tOneway\n\t\t},\n\t\tIEPSCall = ON,\n\t\tContextAttr {\n\t\t\ttdmc/gain#2\n\t\t},\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tEmergency,\n\t\t\tPriority,\n\t\t\tIEPSCall,\n\t\t\ttdmc/gain,\n\t\t\tnt/jit\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71d03,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tBothway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tOneway\n\t\t},\n\t\tIEPSCall = OFF,\n\t\tContextAttr {\n\t\t\ttdmc/gain#2\n\t\t},\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tEmergency,\n\t\t\tPriority,\n\t\t\tIEPSCall,\n\t\t\ttdmc/gain,\n\t\t\tnt/jit\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg71d04,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 9898 {\n\tContext = 1 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tBothway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tOneway\n\t\t},\n\t\tIEPSCall = OFF,\n\t\tContextAttr {\n\t\t\ttdmc/gain#2\n\t\t},\n\t\tContextAttr {\n\t\t\tContextList = {\n\t\t\t\t10191,\n\t\t\t\t10192\n\t\t\t}\n\t\t},\n\t\tContextAudit {\n\t\t\tTopology,\n\t\t\tEmergency,\n\t\t\tPriority,\n\t\t\tIEPSCall,\n\t\t\ttdmc/gain,\n\t\t\tnt/jit,\n\t\t\tPriority = 10,\n\t\t\tEmergencyValue = Emergency,\n\t\t\tIEPSCall = ON,\n\t\t\tORLgc\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000000:al/of\n\t\t\t}\n\t\t},\n\t\tNotify = 11111111/00000000/00000000 {\n\t\t\tObservedEvents = 2222 {\n\t\t\t\t19990729T22000111:al/on\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg72a01,<<"MEGACO/3 [123.123.123.4]:55555\nReply = 10003 {\n\tContext = 2000 {\n\t\tEmergencyOff,\n\t\tAdd = 11111111/00000000/00000000,\n\t\tAdd = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocal { \nv=0\r\nc=IN IP4 124.124.124.222\r\nm=audio 2222 RTP/AVP 4\r\na=a=ptime:30\r\na=recvonly\r\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg72a02,<<"MEGACO/3 [123.123.123.4]:55555\nReply = 10003 {\n\tContext = 2000 {\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tBothway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tIsolate\n\t\t},\n\t\tAdd = 11111111/00000000/00000000,\n\t\tAdd = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocal { \nv=0\r\nc=IN IP4 124.124.124.222\r\nm=audio 2222 RTP/AVP 4\r\na=a=ptime:30\r\na=recvonly\r\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg72a03,<<"MEGACO/3 [123.123.123.4]:55555\nReply = 10003 {\n\tContext = 2000 {\n\t\tPriority = 15,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tBothway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tOneway\n\t\t},\n\t\tAdd = 11111111/00000000/00000000,\n\t\tAdd = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocal { \nv=0\r\nc=IN IP4 124.124.124.222\r\nm=audio 2222 RTP/AVP 4\r\na=a=ptime:30\r\na=recvonly\r\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg72b01,<<"MEGACO/3 [123.123.123.4]:55555\nReply = 10003 {\n\tContext = 2000 {\n\t\tPriority = 15,\n\t\tEmergencyOff,\n\t\tAdd = 11111111/00000000/00000000,\n\t\tAdd = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocal { \nv=0\r\nc=IN IP4 124.124.124.222\r\nm=audio 2222 RTP/AVP 4\r\na=a=ptime:30\r\na=recvonly\r\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tError = 502 { } \n\t}\n}">>},
+ {msg72b02,<<"MEGACO/3 [123.123.123.4]:55555\nReply = 10003 {\n\tContext = 2000 {\n\t\tPriority = 15,\n\t\tEmergencyOff,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tIsolate,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tOneway\n\t\t},\n\t\tAdd = 11111111/00000000/00000000,\n\t\tAdd = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocal { \nv=0\r\nc=IN IP4 124.124.124.222\r\nm=audio 2222 RTP/AVP 4\r\na=a=ptime:30\r\na=recvonly\r\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tError = 502 { } \n\t}\n}">>},
+ {msg72b03,<<"MEGACO/3 [123.123.123.4]:55555\nReply = 10003 {\n\tContext = 2000 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tOneway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tBothway\n\t\t},\n\t\tIEPSCall = ON,\n\t\tAdd = 11111111/00000000/00000000,\n\t\tAdd = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocal { \nv=0\r\nc=IN IP4 124.124.124.222\r\nm=audio 2222 RTP/AVP 4\r\na=a=ptime:30\r\na=recvonly\r\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tError = 502 { } \n\t}\n}">>},
+ {msg72b04,<<"MEGACO/3 [123.123.123.4]:55555\nReply = 10003 {\n\tContext = 2000 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tOneway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tBothway\n\t\t},\n\t\tIEPSCall = OFF,\n\t\tAdd = 11111111/00000000/00000000,\n\t\tAdd = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocal { \nv=0\r\nc=IN IP4 124.124.124.222\r\nm=audio 2222 RTP/AVP 4\r\na=a=ptime:30\r\na=recvonly\r\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tError = 502 { } \n\t}\n}">>},
+ {msg72c01,<<"MEGACO/3 [123.123.123.4]:55555\nReply = 10003 {\n\tContext = 2000 {\n\t\tPriority = 15,\n\t\tAdd = 11111111/00000000/00000000,\n\t\tAdd = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocal { \nv=0\r\nc=IN IP4 124.124.124.222\r\nm=audio 2222 RTP/AVP 4\r\na=a=ptime:30\r\na=recvonly\r\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tError = 502 { \"Just another error string\" } \n\t}\n}">>},
+ {msg72c02,<<"MEGACO/3 [123.123.123.4]:55555\nReply = 10003 {\n\tContext = 2000 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tOneway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tOneway\n\t\t},\n\t\tContextAttr {\n\t\t\ttdmc/gain=2\n\t\t},\n\t\tAdd = 11111111/00000000/00000000,\n\t\tAdd = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocal { \nv=0\r\nc=IN IP4 124.124.124.222\r\nm=audio 2222 RTP/AVP 4\r\na=a=ptime:30\r\na=recvonly\r\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tError = 502 { \"Just another error string\" } \n\t}\n}">>},
+ {msg72c03,<<"MEGACO/3 [123.123.123.4]:55555\nReply = 10003 {\n\tContext = 2000 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tOneway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tIsolate\n\t\t},\n\t\tIEPSCall = ON,\n\t\tContextAttr {\n\t\t\ttdmc/gain = {\n\t\t\t2,\n\t\t\t4,\n\t\t\t8\n\t\t}\n\t\t},\n\t\tAdd = 11111111/00000000/00000000,\n\t\tAdd = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocal { \nv=0\r\nc=IN IP4 124.124.124.222\r\nm=audio 2222 RTP/AVP 4\r\na=a=ptime:30\r\na=recvonly\r\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tError = 502 { \"Just another error string\" } \n\t}\n}">>},
+ {msg72c04,<<"MEGACO/3 [123.123.123.4]:55555\nReply = 10003 {\n\tContext = 2000 {\n\t\tPriority = 15,\n\t\tEmergency,\n\t\tTopology {\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/00001111,\n\t\t\tOneway,\n\t\t\t11111111/00001111/00000000,\n\t\t\t11111111/00001111/00001111,\n\t\t\tIsolate\n\t\t},\n\t\tIEPSCall = OFF,\n\t\tContextAttr {\n\t\t\ttdmc/gain = {\n\t\t\t2,\n\t\t\t4,\n\t\t\t8\n\t\t}\n\t\t},\n\t\tAdd = 11111111/00000000/00000000,\n\t\tAdd = 11111111/00000000/11111111 {\n\t\t\tMedia {\n\t\t\t\tStream = 1 {\n\t\t\t\t\tLocal { \nv=0\r\nc=IN IP4 124.124.124.222\r\nm=audio 2222 RTP/AVP 4\r\na=a=ptime:30\r\na=recvonly\r\n\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tError = 502 { \"Just another error string\" } \n\t}\n}">>},
+ {msg73a,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 7302 {\n\tContext = 7301 {\n\t\tAdd = 11111111/00001111/00000000 {\n\t\t\tStatistics {\n\t\t\t\trtp/ps,\n\t\t\t\tnt/os = 62300,\n\t\t\t\trtp/pr = 700,\n\t\t\t\tnt/or = 45100,\n\t\t\t\trtp/pl = 0.2,\n\t\t\t\trtp/jit = 20,\n\t\t\t\trtp/delay = 40\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg73b01,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 7312 {\n\tContext = 7311 {\n\t\tAuditValue = 11111111/00001111/00000000 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tStatistics {\n\t\t\t\t\t\t\tnt/dur\n\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg73b02,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 7312 {\n\tContext = 7311 {\n\t\tAuditValue = 11111111/00001111/00000000 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tStream = 303 {\n\t\t\t\t\t\tStatistics {\n\t\t\t\t\t\t\t\tnt/dur\n\t\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg73c01,<<"MEGACO/3 [124.124.124.222]:55555\nReply = 8899 {\n\tContext = 606 {\n\t\tMove = 11111111/00001111/00000000 {\n\t\t\tMedia {\n\t\t\t\tStream = 505 {\n\t\t\t\t\tStatistics {\n\t\t\t\t\t\trtp/ps,\n\t\t\t\t\t\tnt/os = 62300,\n\t\t\t\t\t\trtp/pr = 700,\n\t\t\t\t\t\tnt/or = 45100,\n\t\t\t\t\t\trtp/pl = 0.2,\n\t\t\t\t\t\trtp/jit = 20,\n\t\t\t\t\t\trtp/delay = 40\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg73c02,<<"MEGACO/3 [124.124.124.222]:55555\nReply = 8899 {\n\tContext = 606 {\n\t\tMove = 11111111/00001111/00000000 {\n\t\t\tMedia {\n\t\t\t\tStream = 505 {\n\t\t\t\t\tStatistics {\n\t\t\t\t\t\trtp/ps,\n\t\t\t\t\t\tnt/os = 62300,\n\t\t\t\t\t\trtp/pr = 700,\n\t\t\t\t\t\tnt/or = 45100,\n\t\t\t\t\t\trtp/pl = 0.2,\n\t\t\t\t\t\trtp/jit = 20,\n\t\t\t\t\t\trtp/delay = 40\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg74a01,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 7421 {\n\tContext = 7411 {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tSignals {\n\t\t\t\tcg/rt {\n\t\t\t\t\tSPADirection = Internal\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg74a02,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 7422 {\n\tContext = 7412 {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tSignals {\n\t\t\t\tcg/rt {\n\t\t\t\t\tSPADirection = Both\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg74a03,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 7423 {\n\tContext = 7413 {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tSignals {\n\t\t\t\tcg/rt {\n\t\t\t\t\tSPADirection = External,\n\t\t\t\t\tSPARequestID = 7433\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg74a04,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 7424 {\n\tContext = 7414 {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tSignals {\n\t\t\t\tcg/rt {\n\t\t\t\t\tSPADirection = Both,\n\t\t\t\t\tSPARequestID = 7434\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg74a05,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 7425 {\n\tContext = 7415 {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tSignals {\n\t\t\t\tal/ri {\n\t\t\t\t\tStream = 7401,\n\t\t\t\t\tSignalType = Brief,\n\t\t\t\t\tDuration = 7499,\n\t\t\t\t\tNotifyCompletion = {\n\t\t\t\t\t\tTimeOut,\n\t\t\t\t\t\tOtherReason\n\t\t\t\t\t},\n\t\t\t\t\tKeepActive,\n\t\t\t\t\tSPADirection = Both,\n\t\t\t\t\tSPARequestID = 7435\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg74a06,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 7426 {\n\tContext = 7416 {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tSignals {\n\t\t\t\tal/ri {\n\t\t\t\t\tStream = 7401,\n\t\t\t\t\tSignalType = Brief,\n\t\t\t\t\tDuration = 7499,\n\t\t\t\t\tNotifyCompletion = {\n\t\t\t\t\t\tTimeOut,\n\t\t\t\t\t\tOtherReason\n\t\t\t\t\t},\n\t\t\t\t\tKeepActive,\n\t\t\t\t\tSPADirection = Internal,\n\t\t\t\t\tSPARequestID = 7436\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg75a01,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 7502 {\n\tContext = 7501 {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901 mg col boot\"\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg75a02,<<"MEGACO/3 [124.124.124.222]:55555\nTransaction = 7502 {\n\tContext = 7501 {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tMethod = Restart,\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1,\n\t\t\t\tReason = \"901 mg col boot\",\n\t\t\t\tServiceChangeInc\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg76a01,<<"MEGACO/3 [125.125.125.111]:55555\nTransaction = 50076 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tStream = 123 {\n\t\t\t\t\t\tLocalControl {\n\t\t\t\t\t\t\t\tReservedValue,\n\t\t\t\t\t\t\t\tReservedGroup,\n\t\t\t\t\t\t\t\tnt/jit,\n\t\t\t\t\t\t\t\ttdmc/ec,\n\t\t\t\t\t\t\t\tMode = ReceiveOnly\n\t\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg76a02,<<"MEGACO/3 [125.125.125.111]:55555\nTransaction = 50076 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tStream = 123 {\n\t\t\t\t\t\tLocalControl {\n\t\t\t\t\t\t\t\tReservedValue,\n\t\t\t\t\t\t\t\tReservedGroup,\n\t\t\t\t\t\t\t\ttdmc/gain,\n\t\t\t\t\t\t\t\ttdmc/gain=2,\n\t\t\t\t\t\t\t\ttdmc/gain,\n\t\t\t\t\t\t\t\ttdmc/gain=3,\n\t\t\t\t\t\t\t\tMode = ReceiveOnly\n\t\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg76b01,<<"MEGACO/3 [125.125.125.111]:55555\nTransaction = 50076 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tMedia {\n\t\t\t\t\tTerminationState {\n\t\t\t\t\t\tServiceStates = OutOfService\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg77a01,<<"MEGACO/3 [125.125.125.111]:55555\nTransaction = 50007 {\n\tContext = - {\n\t\tAuditValue = 11111111/11111111/11111111 {\n\t\t\tAudit {\n\t\t\t\tSignals {\n\t\t\t\t\ttonegen/pt {\n\t\t\t\t\t\tSPARequestID = 7701\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg78a01,<<"MEGACO/3 [125.125.125.111]:55555\nTransaction = 10001 {\n\tContext = - {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tEvents = 2223 {\n\t\t\t\tal/on {\n\t\t\t\t\tstrict=state\n\t\t\t\t},\n\t\t\t\tal/on {\n\t\t\t\t\tStream = 7801,\n\t\t\t\t\tstrict=state,\n\t\t\t\t\tKeepActive,\n\t\t\t\t\tDigitMap = dialplan00,\n\t\t\t\t\tImmediateNotify\n\t\t\t\t}\n\t\t\t},\n\t\t\tSignals {\n\t\t\t\tcg/rt\n\t\t\t},\n\t\t\tDigitMap = dialplan00 {\n\t\t\t\t(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg78a02,<<"MEGACO/3 [125.125.125.111]:55555\nTransaction = 10001 {\n\tContext = - {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tEvents = 2223 {\n\t\t\t\tal/on {\n\t\t\t\t\tstrict=state\n\t\t\t\t},\n\t\t\t\tal/on {\n\t\t\t\t\tStream = 7802,\n\t\t\t\t\tstrict=state,\n\t\t\t\t\tKeepActive,\n\t\t\t\t\tDigitMap = dialplan00,\n\t\t\t\t\tNeverNotify\n\t\t\t\t}\n\t\t\t},\n\t\t\tSignals {\n\t\t\t\tcg/rt\n\t\t\t},\n\t\t\tDigitMap = dialplan00 {\n\t\t\t\t(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg78a03,<<"MEGACO/3 [125.125.125.111]:55555\nTransaction = 10001 {\n\tContext = - {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tEvents = 2223 {\n\t\t\t\tal/on {\n\t\t\t\t\tstrict=state\n\t\t\t\t},\n\t\t\t\tal/on {\n\t\t\t\t\tStream = 7803,\n\t\t\t\t\tstrict=state,\n\t\t\t\t\tKeepActive,\n\t\t\t\t\tDigitMap = dialplan00,\n\t\t\t\t\tRegulatedNotify\n\t\t\t\t}\n\t\t\t},\n\t\t\tSignals {\n\t\t\t\tcg/rt\n\t\t\t},\n\t\t\tDigitMap = dialplan00 {\n\t\t\t\t(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg78a04,<<"MEGACO/3 [125.125.125.111]:55555\nTransaction = 10001 {\n\tContext = - {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tEvents = 2223 {\n\t\t\t\tal/on {\n\t\t\t\t\tstrict=state\n\t\t\t\t},\n\t\t\t\tal/on {\n\t\t\t\t\tStream = 7824,\n\t\t\t\t\tstrict=state,\n\t\t\t\t\tKeepActive,\n\t\t\t\t\tDigitMap = dialplan00,\n\t\t\t\t\tRegulatedNotify {\n\t\t\t\t\t\tEmbed {\n\t\t\t\t\t\t\tEvents = 7814 {\n\t\t\t\t\t\t\t\tal/on\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tSignals {\n\t\t\t\tcg/rt\n\t\t\t},\n\t\t\tDigitMap = dialplan00 {\n\t\t\t\t(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg78a05,<<"MEGACO/3 [125.125.125.111]:55555\nTransaction = 10001 {\n\tContext = - {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tEvents = 2223 {\n\t\t\t\tal/on {\n\t\t\t\t\tstrict=state\n\t\t\t\t},\n\t\t\t\tal/on {\n\t\t\t\t\tStream = 7805,\n\t\t\t\t\tstrict=state,\n\t\t\t\t\tKeepActive,\n\t\t\t\t\tDigitMap = dialplan00,\n\t\t\t\t\tRegulatedNotify {\n\t\t\t\t\t\tEmbed {\n\t\t\t\t\t\t\tSignals\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tSignals {\n\t\t\t\tcg/rt\n\t\t\t},\n\t\t\tDigitMap = dialplan00 {\n\t\t\t\t(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg78a06,<<"MEGACO/3 [125.125.125.111]:55555\nTransaction = 10001 {\n\tContext = - {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tEvents = 2223 {\n\t\t\t\tal/on {\n\t\t\t\t\tstrict=state\n\t\t\t\t},\n\t\t\t\tal/on {\n\t\t\t\t\tStream = 7826,\n\t\t\t\t\tstrict=state,\n\t\t\t\t\tKeepActive,\n\t\t\t\t\tDigitMap = dialplan00,\n\t\t\t\t\tRegulatedNotify {\n\t\t\t\t\t\tEmbed {\n\t\t\t\t\t\t\tSignals {\n\t\t\t\t\t\t\t\tcg/rt {\n\t\t\t\t\t\t\t\t\tSPADirection = External\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tEvents = 7816 {\n\t\t\t\t\t\t\t\tal/on\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tSignals {\n\t\t\t\tcg/rt\n\t\t\t},\n\t\t\tDigitMap = dialplan00 {\n\t\t\t\t(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg78a07,<<"MEGACO/3 [125.125.125.111]:55555\nTransaction = 10001 {\n\tContext = - {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tEvents = 2223 {\n\t\t\t\tal/on {\n\t\t\t\t\tstrict=state\n\t\t\t\t},\n\t\t\t\tal/on {\n\t\t\t\t\tStream = 7827,\n\t\t\t\t\tstrict=state,\n\t\t\t\t\tKeepActive,\n\t\t\t\t\tDigitMap = dialplan00,\n\t\t\t\t\tRegulatedNotify {\n\t\t\t\t\t\tEmbed {\n\t\t\t\t\t\t\tSignals {\n\t\t\t\t\t\t\t\tcg/rt {\n\t\t\t\t\t\t\t\t\tSPADirection = External\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tEvents = 7817 {\n\t\t\t\t\t\t\t\tal/on\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tResetEventsDescriptor\n\t\t\t\t}\n\t\t\t},\n\t\t\tSignals {\n\t\t\t\tcg/rt\n\t\t\t},\n\t\t\tDigitMap = dialplan00 {\n\t\t\t\t(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg78a08,<<"MEGACO/3 [125.125.125.111]:55555\nTransaction = 10001 {\n\tContext = - {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tEvents = 2223 {\n\t\t\t\tal/on {\n\t\t\t\t\tstrict=state\n\t\t\t\t},\n\t\t\t\tal/on {\n\t\t\t\t\tStream = 7836,\n\t\t\t\t\tstrict=state,\n\t\t\t\t\tKeepActive,\n\t\t\t\t\tDigitMap = dialplan00,\n\t\t\t\t\tRegulatedNotify {\n\t\t\t\t\t\tEmbed {\n\t\t\t\t\t\t\tSignals {\n\t\t\t\t\t\t\t\tcg/rt {\n\t\t\t\t\t\t\t\t\tSPADirection = External\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tEvents = 7826 {\n\t\t\t\t\t\t\t\tal/of {\n\t\t\t\t\t\t\t\t\tStream = 7816,\n\t\t\t\t\t\t\t\t\tKeepActive,\n\t\t\t\t\t\t\t\t\tDigitMap = dialplan00,\n\t\t\t\t\t\t\t\t\tRegulatedNotify {\n\t\t\t\t\t\t\t\t\t\tEmbed {\n\t\t\t\t\t\t\t\t\t\t\tSignals {\n\t\t\t\t\t\t\t\t\t\t\t\tal/ri {\n\t\t\t\t\t\t\t\t\t\t\t\t\tSPADirection = Both\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tResetEventsDescriptor\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tResetEventsDescriptor\n\t\t\t\t}\n\t\t\t},\n\t\t\tSignals {\n\t\t\t\tcg/rt\n\t\t\t},\n\t\t\tDigitMap = dialplan00 {\n\t\t\t\t(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg78a09,<<"MEGACO/3 [125.125.125.111]:55555\nTransaction = 10001 {\n\tContext = - {\n\t\tModify = 11111111/00000000/00000000 {\n\t\t\tEvents = 2223 {\n\t\t\t\tal/on {\n\t\t\t\t\tstrict=state\n\t\t\t\t},\n\t\t\t\tal/on {\n\t\t\t\t\tStream = 7899,\n\t\t\t\t\tstrict=state,\n\t\t\t\t\tKeepActive,\n\t\t\t\t\tDigitMap = dialplan00,\n\t\t\t\t\tRegulatedNotify {\n\t\t\t\t\t\tEmbed {\n\t\t\t\t\t\t\tSignals {\n\t\t\t\t\t\t\t\tcg/rt {\n\t\t\t\t\t\t\t\t\tStream = 7869,\n\t\t\t\t\t\t\t\t\tSignalType = Brief,\n\t\t\t\t\t\t\t\t\tDuration = 17809,\n\t\t\t\t\t\t\t\t\tNotifyCompletion = {\n\t\t\t\t\t\t\t\t\t\tTimeOut,\n\t\t\t\t\t\t\t\t\t\tOtherReason\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tKeepActive,\n\t\t\t\t\t\t\t\t\tSPADirection = External,\n\t\t\t\t\t\t\t\t\tSPARequestID = 7879,\n\t\t\t\t\t\t\t\t\tIntersignal = 7889\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tEvents = 7859 {\n\t\t\t\t\t\t\t\tal/of {\n\t\t\t\t\t\t\t\t\tStream = 7849,\n\t\t\t\t\t\t\t\t\tKeepActive,\n\t\t\t\t\t\t\t\t\tDigitMap = dialplan00,\n\t\t\t\t\t\t\t\t\tRegulatedNotify {\n\t\t\t\t\t\t\t\t\t\tEmbed {\n\t\t\t\t\t\t\t\t\t\t\tSignals {\n\t\t\t\t\t\t\t\t\t\t\t\tcg/rt {\n\t\t\t\t\t\t\t\t\t\t\t\t\tStream = 7819,\n\t\t\t\t\t\t\t\t\t\t\t\t\tSignalType = TimeOut,\n\t\t\t\t\t\t\t\t\t\t\t\t\tDuration = 7898,\n\t\t\t\t\t\t\t\t\t\t\t\t\tNotifyCompletion = {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tTimeOut,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tIntByEvent,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tOtherReason\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\tSPADirection = Both,\n\t\t\t\t\t\t\t\t\t\t\t\t\tSPARequestID = 7829,\n\t\t\t\t\t\t\t\t\t\t\t\t\tIntersignal = 7839\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tResetEventsDescriptor\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tResetEventsDescriptor\n\t\t\t\t}\n\t\t\t},\n\t\t\tSignals {\n\t\t\t\tcg/rt\n\t\t\t},\n\t\t\tDigitMap = dialplan00 {\n\t\t\t\t(0s| 00s|[1-7]xlxx|8lxxxxxxx|#xxxxxxx|*xx|9l1xxxxxxxxxx|9l011x.s)\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg79a01,<<"MEGACO/3 [125.125.125.111]:55555\nReply = 7931 {\n\tContext = 7921 {\n\t\tAuditValue = [\n\t\t\t11111111/00000000/00000000,\n\t\t\t11111111/00000000/11111111,\n\t\t\t11111111/11111111/00000000\n\t\t] {\n\t\t\tError = 502 { } ,\n\t\t\tEvents = 7911 {\n\t\t\t\tal/of\n\t\t\t},\n\t\t\tMedia,\n\t\t\tDigitMap,\n\t\t\tStatistics,\n\t\t\tPackages\n\t\t}\n\t}\n}">>},
+ {msg80a01,<<"MEGACO/3 [124.124.124.222]:55555\nReply = 8000/1 {\n\tContext = 80 {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg80a02,<<"MEGACO/3 [125.125.125.111]:55555\nReply = 8000/1000 {\n\tContext = 80 {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg80a03,<<"MEGACO/3 [125.124.123.122]:55555\nReply = 8000/65535 {\n\tContext = 80 {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg80b01,<<"MEGACO/3 [124.124.124.222]:55555\nReply = 8989/1/END {\n\tContext = 80 {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg80b02,<<"MEGACO/3 [125.125.125.111]:55555\nReply = 8989/1000/END {\n\tContext = 80 {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg80b03,<<"MEGACO/3 [125.124.123.122]:55555\nReply = 8989/65535/END {\n\tContext = 80 {\n\t\tServiceChange = root {\n\t\t\tServices {\n\t\t\t\tServiceChangeAddress = 55555,\n\t\t\t\tProfile = resgw/1\n\t\t\t}\n\t\t}\n\t}\n}">>},
+ {msg81a01,<<"MEGACO/3 [124.124.124.222]:55555\nSegment = 8101/1">>},
+ {msg81a02,<<"MEGACO/3 [125.125.125.111]:55555\nSegment = 8101/1000">>},
+ {msg81a03,<<"MEGACO/3 [125.124.123.122]:55555\nSegment = 8101/65535">>},
+ {msg81b01,<<"MEGACO/3 [124.124.124.222]:55555\nSegment = 8102/1/END">>},
+ {msg81b02,<<"MEGACO/3 [125.125.125.111]:55555\nSegment = 8102/1000/END">>},
+ {msg81b03,<<"MEGACO/3 [125.124.123.122]:55555\nSegment = 8102/65535/END">>}]}.
diff --git a/lib/megaco/examples/simple/Makefile b/lib/megaco/examples/simple/Makefile
new file mode 100644
index 0000000000..f91d1d886f
--- /dev/null
+++ b/lib/megaco/examples/simple/Makefile
@@ -0,0 +1,153 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2001-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%
+
+include $(ERL_TOP)/make/target.mk
+
+ifeq ($(TYPE),debug)
+ERL_COMPILE_FLAGS += -Ddebug -W
+endif
+
+EBIN = .
+MEGACO_INCLUDEDIR = ../../include
+
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../../vsn.mk
+VSN=$(MEGACO_VSN)
+
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/megaco-$(VSN)
+
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+include modules.mk
+
+MODULES = $(MG_MODULES) $(MGC_MODULES) $(COMMON_MODULES)
+
+ERL_FILES = $(MODULES:%=%.erl)
+
+TARGET_FILES = \
+ $(ERL_FILES:%.erl=$(EBIN)/%.$(EMULATOR))
+
+MEGACO_ROOT_DIR = $(shell (cd .. ; dirname `pwd`))
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ifeq ($(WARN_UNUSED_WARS),true)
+ERL_COMPILE_FLAGS += +warn_unused_vars
+endif
+
+ERL_COMPILE_FLAGS += \
+ -pa $(ERL_TOP)/lib/megaco/ebin \
+ -I../../include
+
+ifneq ($(MGC_HOST),)
+MG_START_ARGS = "{mgc_host, $(MGC_HOST)}"
+endif
+
+ifneq ($(MG_INLINE_TRACE),true)
+MG_MEGACO_FILTER = -s megaco_filter
+MG_START_ARGS += "{trace,false}"
+else
+MG_START_ARGS += "{trace,true}"
+endif
+
+ifneq ($(MG_DEBUG),)
+MG_START_ARGS += "{debug,true}"
+else
+MG_START_ARGS += "{debug,false}"
+endif
+
+
+ifneq ($(MGC_INLINE_TRACE),true)
+MGC_MEGACO_FILTER = -s megaco_filter
+MGC_START_ARGS += "{trace,false}"
+else
+MGC_START_ARGS += "{trace,true}"
+endif
+
+ifneq ($(MGC_DEBUG),)
+MGC_START_ARGS += "{debug,true}"
+else
+MGC_START_ARGS += "{debug,false}"
+endif
+
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+opt: $(TARGET_FILES)
+
+debug:
+ @${MAKE} TYPE=debug opt
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f errs core *~
+
+docs:
+
+info:
+ @echo "MEGACO_ROOT_DIR = $(MEGACO_ROOT_DIR)"
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+
+mg: opt
+ erl -noshell -pa $(MEGACO_ROOT_DIR)/ebin \
+ $(MG_MEGACO_FILTER) \
+ -s megaco \
+ -s megaco_simple_mg start_batch $(MG_START_ARGS)
+
+mgc: opt
+ erl -noshell -pa $(MEGACO_ROOT_DIR)/ebin \
+ $(MGC_MEGACO_FILTER) \
+ -s megaco \
+ -s megaco_simple_mgc start_batch $(MGC_START_ARGS)
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/examples
+ $(INSTALL_DIR) $(RELSYSDIR)/examples/simple
+ $(INSTALL_DATA) $(ERL_FILES) $(TARGET_FILES) $(RELSYSDIR)/examples/simple
+
+
+release_docs_spec:
+
+
+# ----------------------------------------------------
+# Include dependencies
+# ----------------------------------------------------
+
diff --git a/lib/megaco/examples/simple/megaco_simple_mg.erl b/lib/megaco/examples/simple/megaco_simple_mg.erl
new file mode 100644
index 0000000000..95efaf5df3
--- /dev/null
+++ b/lib/megaco/examples/simple/megaco_simple_mg.erl
@@ -0,0 +1,437 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-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: Simple example of an MG
+%%
+%% Example usage:
+%%
+%% cd megaco/examples/simple
+%% erl -pa ../../../megaco/ebin -s megaco_filter -s megaco
+%% megaco_simple_mg:start().
+%%----------------------------------------------------------------------
+
+-module(megaco_simple_mg).
+
+-behaviour(megaco_user).
+
+-export([
+ start_batch/0, start_batch/1, init_batch/4,
+ start/0, start/3,
+ start/4, %% ????????????????????????
+ stop/0, stop/1,
+ start_tcp_text/2, start_tcp_binary/2,
+ start_udp_text/2, start_udp_binary/2
+ ]).
+
+-export([
+ handle_connect/2,
+ handle_disconnect/3,
+ handle_syntax_error/3,
+ handle_message_error/3,
+ handle_trans_request/3,
+ handle_trans_long_request/3,
+ handle_trans_reply/4,
+ handle_trans_ack/4,
+ handle_unexpected_trans/3,
+ handle_trans_request_abort/4
+ ]).
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v1.hrl").
+
+
+
+%%----------------------------------------------------------------------
+%% To be used at command line: erl -s ?MODULE start_batch
+%%----------------------------------------------------------------------
+
+start_batch() ->
+ start_batch([]).
+
+start_batch(Args0) when is_list(Args0) ->
+ {ok, LocalHost} = inet:gethostname(),
+ Defs = [{mgc_host, LocalHost}, {trace,false}, {debug, false}],
+ Args = parse_args(Args0, Defs),
+ MgcHost = get_arg(mgc_host, Args),
+ Trace = get_arg(trace, Args),
+ Debug = get_arg(debug, Args),
+ Pid = spawn(?MODULE, init_batch, [self(), MgcHost, Trace, Debug]),
+ receive
+ {init_batch, Pid, Res} ->
+ io:format("~p(~p): ~p~n", [?MODULE, ?LINE, Res]),
+ Res
+ end.
+
+parse_args([], Acc) ->
+ Acc;
+parse_args([Arg|Args], Acc) when is_atom(Arg) ->
+ case string:tokens(atom_to_list(Arg),"{},") of
+ ["mgc_host", Host] when is_list(Host) ->
+ parse_args(Args, parse_args(mgc_host, Host, Acc));
+ ["trace",Trace] ->
+ parse_args(Args, parse_args(trace, list_to_atom(Trace), Acc));
+ ["debug",Debug] ->
+ parse_args(Args, parse_args(debug, list_to_atom(Debug), Acc));
+ _Invalid ->
+ parse_args(Args, Acc)
+ end.
+
+parse_args(Key, Val, Args) ->
+ Entry = {Key, Val},
+ case lists:keyreplace(Key, 1, Args, {Key, Val}) of
+ Args ->
+ [Entry|Args];
+ Args2 ->
+ Args2
+ end.
+
+get_arg(Key, Args) ->
+ {value, {Key, Val}} = lists:keysearch(Key, 1, Args),
+ Val.
+
+init_batch(ReplyTo, MgcHost, Trace, Debug) ->
+ register(?MODULE, self()),
+ Res = start(MgcHost, Trace, Debug),
+ ReplyTo ! {init_batch, self(), Res},
+ receive
+ after infinity -> Res
+ end.
+
+
+%%----------------------------------------------------------------------
+%% Starting the MG
+%%----------------------------------------------------------------------
+
+%% -----------------------------------------------------------------------
+
+init_inline_trace(true) ->
+ megaco:enable_trace(max, io);
+init_inline_trace(_) ->
+ ok.
+
+%% -----------------------------------------------------------------------
+
+
+start() ->
+ {ok, LocalHost} = inet:gethostname(),
+ start(LocalHost, false, false).
+
+%% Used when calling from the erlang shell:
+start(MgcHost, Trace, Debug)
+ when is_atom(MgcHost) andalso is_atom(Trace) andalso is_atom(Debug) ->
+ start(atom_to_list(MgcHost), Trace, Debug);
+
+start(MgcHost, Trace, Debug)
+ when is_list(MgcHost) andalso is_atom(Trace) andalso is_atom(Debug) ->
+ put(debug, Debug),
+ d("start -> entry with"
+ "~n MgcHost: ~s"
+ "~n Trace: ~p", [MgcHost, Trace]),
+ init_inline_trace(Trace),
+ Starters = [fun start_tcp_text/2,
+ fun start_tcp_binary/2,
+ fun start_udp_text/2,
+ fun start_udp_binary/2],
+ [Fun(MgcHost, []) || Fun <- Starters].
+
+start_tcp_text(MgcHost, Default) ->
+ d("start_tcp_text -> entry with"
+ "~n MgcHost: ~p", [MgcHost]),
+ Config = [{encoding_mod, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {send_mod, megaco_tcp} | Default],
+ Mid = {deviceName, "gateway_tt"},
+ {Mid, start(MgcHost, ?megaco_ip_port_text, Mid, Config)}.
+
+start_tcp_binary(MgcHost, Default) ->
+ d("start_tcp_binary -> entry with"
+ "~n MgcHost: ~p", [MgcHost]),
+ Config = [{encoding_mod, megaco_binary_encoder},
+ {encoding_config, []},
+ {send_mod, megaco_tcp} | Default],
+ Mid = {deviceName, "gateway_tb"},
+ {Mid, start(MgcHost, ?megaco_ip_port_binary, Mid, Config)}.
+
+start_udp_text(MgcHost, Default) ->
+ d("start_udp_text -> entry with"
+ "~n MgcHost: ~p", [MgcHost]),
+ Config = [{encoding_mod, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {send_mod, megaco_udp} | Default],
+ Mid = {deviceName, "gateway_ut"},
+ {Mid, start(MgcHost, ?megaco_ip_port_text, Mid, Config)}.
+
+start_udp_binary(MgcHost, Default) ->
+ d("start_udp_binary -> entry with"
+ "~n MgcHost: ~p", [MgcHost]),
+ Config = [{encoding_mod, megaco_binary_encoder},
+ {encoding_config, []},
+ {send_mod, megaco_udp} | Default],
+ Mid = {deviceName, "gateway_ub"},
+ {Mid, start(MgcHost, ?megaco_ip_port_binary, Mid, Config)}.
+
+start(MgcHost, MgcPort, Mid, Config) ->
+ case megaco:start_user(Mid, [{user_mod, ?MODULE} | Config]) of
+ ok ->
+ case start_transport(MgcHost, MgcPort, Mid) of
+ {ok, ConnHandle} ->
+ service_change(ConnHandle);
+ {error, Reason} ->
+ {error, Reason}
+ end;
+ {error, Reason} ->
+ {error, {start_user, Reason}}
+ end.
+
+start_transport(MgcHost, MgcPort, Mid) ->
+ RecHandle = megaco:user_info(Mid, receive_handle),
+ case RecHandle#megaco_receive_handle.send_mod of
+ megaco_tcp -> start_tcp(MgcHost, MgcPort, RecHandle);
+ megaco_udp -> start_udp(MgcHost, MgcPort, RecHandle);
+ SendMod -> {error, {bad_send_mod, SendMod}}
+ end.
+
+start_tcp(MgcHost, MgcPort, RecHandle) ->
+ d("start_tcp -> start transport"),
+ case megaco_tcp:start_transport() of
+ {ok, Pid} ->
+ d("start_tcp -> transport started: ~p", [Pid]),
+ Options = [{host, MgcHost},
+ {port, MgcPort},
+ {receive_handle, RecHandle}],
+ case megaco_tcp:connect(Pid, Options) of
+ {ok, SendHandle, ControlPid} ->
+ d("start_tcp -> connected: ~p", [ControlPid]),
+ MgcMid = preliminary_mid,
+ megaco:connect(RecHandle, MgcMid, SendHandle, ControlPid);
+ {error, Reason} ->
+ d("start_tcp -> connection failed: ~p", [Reason]),
+ {error, {megaco_tcp_connect, Reason}}
+ end;
+ {error, Reason} ->
+ d("start_tcp -> failed starting transport: ~p", [Reason]),
+ {error, {megaco_tcp_start_transport, Reason}}
+ end.
+
+start_udp(MgcHost, MgcPort, RecHandle) ->
+ d("start_udp -> start transport"),
+ case megaco_udp:start_transport() of
+ {ok, SupPid} ->
+ d("start_udp -> transport started: ~p", [SupPid]),
+ Options = [{port, 0}, {receive_handle, RecHandle}],
+ case megaco_udp:open(SupPid, Options) of
+ {ok, Handle, ControlPid} ->
+ d("start_udp -> port opened: ~p", [ControlPid]),
+ %% Socket = megaco_udp:socket(Handle),
+ %% MgPort = inet:port(Socket), BUGBUG BUGBUG
+ MgcMid = preliminary_mid,
+ SendHandle = megaco_udp:create_send_handle(Handle,
+ MgcHost, % BUGBUG BUGBUG
+ MgcPort),
+ megaco:connect(RecHandle, MgcMid, SendHandle, ControlPid);
+ {error, Reason} ->
+ d("start_udp -> failed open port: ~p", [Reason]),
+ {error, {megaco_udp_open, Reason}}
+ end;
+ {error, Reason} ->
+ d("start_udp -> failed starting transport: ~p", [Reason]),
+ {error, {megaco_udp_start_transport, Reason}}
+ end.
+
+service_change(ConnHandle) ->
+ service_change(ConnHandle, restart, ?megaco_cold_boot).
+
+service_change(ConnHandle, Method, Reason) ->
+ SCP = #'ServiceChangeParm'{serviceChangeMethod = Method,
+ serviceChangeReason = [Reason]},
+ TermId = [?megaco_root_termination_id],
+ SCR = #'ServiceChangeRequest'{terminationID = TermId,
+ serviceChangeParms = SCP},
+ CR = #'CommandRequest'{command = {serviceChangeReq, SCR}},
+ AR = #'ActionRequest'{contextId = ?megaco_null_context_id,
+ commandRequests = [CR]},
+ megaco:call(ConnHandle, [AR], []).
+
+%%----------------------------------------------------------------------
+%% Stopping the MG
+%%----------------------------------------------------------------------
+
+stop() ->
+ [{Mid, stop(Mid)} || Mid <- megaco:system_info(users)].
+
+stop(Mid) ->
+ Reason = stopped_by_user,
+ Disco = fun(CH) ->
+ Pid = megaco:conn_info(CH, control_pid),
+ megaco:disconnect(CH, Reason),
+ megaco:cancel(CH, Reason),
+ exit(Pid, Reason)
+ end,
+ lists:map(Disco, megaco:user_info(Mid, connections)),
+ megaco:stop_user(Mid).
+
+%%----------------------------------------------------------------------
+%% Invoked when a new connection is established
+%%----------------------------------------------------------------------
+
+handle_connect(ConnHandle, ProtocolVersion) ->
+ d("handle_connect -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p", [ConnHandle, ProtocolVersion]),
+ ok.
+
+%%----------------------------------------------------------------------
+%% Invoked when a connection is teared down
+%%----------------------------------------------------------------------
+
+handle_disconnect(ConnHandle, ProtocolVersion, Reason) ->
+ d("handle_disconnect -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n Reason: ~p", [ConnHandle, ProtocolVersion, Reason]),
+ megaco:cancel(ConnHandle, Reason), % Cancel the outstanding messages
+ d("handle_disconnect -> done", []),
+ ok.
+
+%%----------------------------------------------------------------------
+%% Invoked when a received message had syntax errors
+%%----------------------------------------------------------------------
+
+handle_syntax_error(ReceiveHandle, ProtocolVersion, ErrorDescriptor) ->
+ d("handle_syntax_error -> entry with"
+ "~n ReceiveHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n ErrorDescriptor: ~p",
+ [ReceiveHandle, ProtocolVersion, ErrorDescriptor]),
+ reply.
+
+%%----------------------------------------------------------------------
+%% Invoked when a received message contained no transactions
+%%----------------------------------------------------------------------
+
+handle_message_error(ConnHandle, ProtocolVersion, ErrorDescriptor) ->
+ d("handle_message_error -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n ErrorDescriptor: ~p",
+ [ConnHandle, ProtocolVersion, ErrorDescriptor]),
+ no_reply.
+
+%%----------------------------------------------------------------------
+%% Invoked for each transaction request
+%%----------------------------------------------------------------------
+
+handle_trans_request(ConnHandle, ProtocolVersion, ActionRequests) ->
+ d("handle_trans_request -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n ActionRequests: ~p",
+ [ConnHandle, ProtocolVersion, ActionRequests]),
+ ED = #'ErrorDescriptor'{errorCode = ?megaco_not_implemented,
+ errorText = "Transaction requests not handled"},
+ {discard_ack, ED}.
+
+%%----------------------------------------------------------------------
+%% Optionally invoked for a time consuming transaction request
+%%----------------------------------------------------------------------
+
+handle_trans_long_request(ConnHandle, ProtocolVersion, ReqData) ->
+ d("handle_trans_long_request -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n ReqData: ~p", [ConnHandle, ProtocolVersion, ReqData]),
+ ED = #'ErrorDescriptor'{errorCode = ?megaco_not_implemented,
+ errorText = "Long transaction requests not handled"},
+ {discard_ack, ED}.
+
+%%----------------------------------------------------------------------
+%% Optionally invoked for a transaction reply
+%%----------------------------------------------------------------------
+
+handle_trans_reply(ConnHandle, ProtocolVersion, ActualReply, ReplyData) ->
+ d("handle_trans_reply -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n ActualReply: ~p"
+ "~n ReplyData: ~p",
+ [ConnHandle, ProtocolVersion, ActualReply, ReplyData]),
+ ok.
+
+%%----------------------------------------------------------------------
+%% Optionally invoked for a transaction acknowledgement
+%%----------------------------------------------------------------------
+
+handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData) ->
+ d("handle_trans_ack -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n AckStatus: ~p"
+ "~n AckData: ~p",
+ [ConnHandle, ProtocolVersion, AckStatus, AckData]),
+ ok.
+
+
+%%----------------------------------------------------------------------
+%% Invoked when an unexpected message has been received
+%%----------------------------------------------------------------------
+
+handle_unexpected_trans(ConnHandle, ProtocolVersion, Trans) ->
+ d("handle_unexpected_trans -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n AckStatus: ~p"
+ "~n AckData: ~p",
+ [ConnHandle, ProtocolVersion, Trans]),
+ ok.
+
+
+%%----------------------------------------------------------------------
+%% Invoked when an unexpected message has been received
+%%----------------------------------------------------------------------
+
+handle_trans_request_abort(ConnHandle, ProtocolVersion, TransId, Pid) ->
+ d("handle_trans_request_abort -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n TransId: ~p"
+ "~n Pid: ~p",
+ [ConnHandle, ProtocolVersion, TransId, Pid]),
+ ok.
+
+
+%%----------------------------------------------------------------------
+%% DEBUGGING
+%%----------------------------------------------------------------------
+
+d(F) ->
+ d(F, []).
+
+d(F,A) ->
+ d(get(debug),F,A).
+
+d(true,F,A) ->
+ io:format("SIMPLE_MG: " ++ F ++ "~n", A);
+d(_, _F, _A) ->
+ ok.
+
+
+
+
diff --git a/lib/megaco/examples/simple/megaco_simple_mgc.erl b/lib/megaco/examples/simple/megaco_simple_mgc.erl
new file mode 100644
index 0000000000..04493b983f
--- /dev/null
+++ b/lib/megaco/examples/simple/megaco_simple_mgc.erl
@@ -0,0 +1,455 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2001-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: Simple example of an MGC
+%%
+%% Example usage:
+%%
+%% cd megaco/examples/simple
+%% erl -pa ../../../megaco/ebin -s megaco_filter -s megaco
+%% megaco_simple_mgc:start().
+%%----------------------------------------------------------------------
+
+-module(megaco_simple_mgc).
+
+-behaviour(megaco_user).
+
+-export([
+ start_batch/0, start_batch/1, init_batch/3,
+ start/0, start/2,
+ start/4,
+ stop/0, stop/1
+ ]).
+
+-export([
+ handle_connect/2,
+ handle_disconnect/3,
+ handle_syntax_error/3,
+ handle_message_error/3,
+ handle_trans_request/3,
+ handle_trans_long_request/3,
+ handle_trans_reply/4,
+ handle_trans_ack/4,
+ handle_unexpected_trans/3,
+ handle_trans_request_abort/4
+ ]).
+
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v1.hrl").
+
+
+%%----------------------------------------------------------------------
+%% Starting the MGC
+%%----------------------------------------------------------------------
+
+start() ->
+ start(false, false).
+
+start(Trace, Debug) ->
+ start({deviceName, "controller"}, [], Trace, Debug).
+
+start(Mid, Config, Trace, Debug) ->
+ put(debug, Debug),
+ d("start -> entry with"
+ "~n Mid: ~p"
+ "~n Config: ~p"
+ "~n Trace: ~p", [Mid, Config, Trace]),
+ init_inline_trace(Trace),
+ case megaco:start_user(Mid, [{user_mod, ?MODULE} | Config]) of
+ ok ->
+ d("start -> user started"),
+ case catch do_start(Mid) of
+ {'EXIT', Reason} ->
+ d("start -> exited: ~n~p",[Reason]),
+ {error, Reason};
+ Other ->
+ d("start -> Other: ~n~p",[Other]),
+ Other
+ end;
+ {error, Reason} ->
+ d("start -> user start failed: ~n~p", [Reason]),
+ {error, {start_user, Reason}}
+ end.
+
+
+%% -----------------------------------------------------------------------
+
+init_inline_trace(true) ->
+ megaco:enable_trace(max, io);
+init_inline_trace(_) ->
+ ok.
+
+%% -----------------------------------------------------------------------
+
+do_start(Mid) ->
+ d("do_start -> entry"),
+ RecHandle = megaco:user_info(Mid, receive_handle),
+ d("do_start -> RecHandle: ~n~p",[RecHandle]),
+
+ TextMod = megaco_pretty_text_encoder,
+ TextTcp = RecHandle#megaco_receive_handle{encoding_mod = TextMod,
+ encoding_config = [],
+ send_mod = megaco_tcp},
+ d("do_start -> TextTcp: ~n~p",[TextTcp]),
+ TextUdp = TextTcp#megaco_receive_handle{send_mod = megaco_udp},
+ d("do_start -> TextUdp: ~n~p",[TextUdp]),
+
+ BinMod = megaco_binary_encoder,
+ BinTcp = RecHandle#megaco_receive_handle{encoding_mod = BinMod,
+ encoding_config = [],
+ send_mod = megaco_tcp},
+ d("do_start -> BinTcp: ~n~p",[BinTcp]),
+ BinUdp = BinTcp#megaco_receive_handle{send_mod = megaco_udp},
+ d("do_start -> BinUdp: ~n~p",[BinUdp]),
+
+ ListenTo = [{?megaco_ip_port_text, TextTcp},
+ {?megaco_ip_port_text, TextUdp},
+ {?megaco_ip_port_binary, BinTcp},
+ {?megaco_ip_port_binary, BinUdp}
+ ],
+
+ d("do_start -> start transports"),
+ Transports =
+ [{start_transport(Port, RH), Port, RH} || {Port, RH} <- ListenTo],
+ d("do_start -> Transports: ~n~p",[Transports]),
+
+ {ok, Transports}.
+
+start_transport(MgcPort, RecHandle) ->
+ case RecHandle#megaco_receive_handle.send_mod of
+ megaco_tcp -> start_tcp(MgcPort, RecHandle);
+ megaco_udp -> start_udp(MgcPort, RecHandle);
+ SendMod -> {error, {bad_send_mod, SendMod}}
+ end.
+
+start_udp(MgcPort, RecHandle) ->
+ d("start_udp -> entry with"
+ "~n MgcPort: ~p"
+ "~n RecHandle: ~p", [MgcPort, RecHandle]),
+ case megaco_udp:start_transport() of
+ {ok, SupPid} ->
+ Options = [{port, MgcPort}, {receive_handle, RecHandle}],
+ case megaco_udp:open(SupPid, Options) of
+ {ok, _SendHandle, _ControlPid} ->
+ ok;
+ {error, Reason} ->
+ {error, {megaco_udp_open, Reason}}
+ end;
+ {error, Reason} ->
+ {error, {megaco_udp_start_transport, Reason}}
+ end.
+
+start_tcp(MgcPort, RecHandle) ->
+ d("start_tcp -> entry with"
+ "~n MgcPort: ~p"
+ "~n RecHandle: ~p", [MgcPort, RecHandle]),
+ case megaco_tcp:start_transport() of
+ {ok, SupPid} ->
+ d("start_tcp -> transport started: "
+ "~n SupPid: ~p", [SupPid]),
+ Options = [{port, MgcPort}, {receive_handle, RecHandle}],
+ case megaco_tcp:listen(SupPid, Options) of
+ ok ->
+ d("start_tcp -> listen ok"),
+ ok;
+ {error, Reason} ->
+ d("start_tcp -> listen failed: "
+ "~n Reason: ~p", [Reason]),
+ {error, {megaco_tcp_listen, Reason}}
+ end;
+ {error, Reason} ->
+ d("start_tcp -> transport start failed: "
+ "~n Reason: ~p", [Reason]),
+ {error, {megaco_tcp_start_transport, Reason}}
+ end.
+
+%%----------------------------------------------------------------------
+%% Stopping the MGC
+%%----------------------------------------------------------------------
+
+stop() ->
+ [{Mid, stop(Mid)} || Mid <- megaco:system_info(users)].
+
+stop(Mid) ->
+ d("stop -> entry with~n Mid: ~p", [Mid]),
+ Disco = fun(CH) ->
+ d("stop -> CH: ~p", [CH]),
+ Reason = stopped_by_user,
+ Pid = megaco:conn_info(CH, control_pid),
+ SendMod = megaco:conn_info(CH, send_mod),
+ SendHandle = megaco:conn_info(CH, send_handle),
+
+ d("stop -> disconnect", []),
+ megaco:disconnect(CH, Reason),
+ d("stop -> cancel", []),
+ megaco:cancel(CH, Reason),
+ d("stop -> close transport"
+ "~n SendMod: ~p"
+ "~n SendHandle: ~p", [SendMod, SendHandle]),
+ case SendMod of
+ megaco_tcp -> megaco_tcp:close(SendHandle);
+ megaco_udp -> megaco_udp:close(SendHandle);
+ SendMod -> exit(Pid, Reason)
+ end
+ end,
+ Conns = megaco:user_info(Mid, connections),
+ d("stop -> Conns: ~p", [Conns]),
+ Disconns = lists:map(Disco, Conns),
+ d("stop -> Disconns: ~p", [Disconns]),
+ megaco:stop_user(Mid),
+ case whereis(?MODULE) of
+ undefined ->
+ ignore;
+ Pid ->
+ d("stop -> Pid: ~p", [Pid]),
+ unlink(Pid),
+ exit(Pid, shutdown)
+ end,
+ ok.
+
+%%----------------------------------------------------------------------
+%% Invoked when a new connection is established
+%%----------------------------------------------------------------------
+
+handle_connect(ConnHandle, ProtocolVersion) ->
+ d("handle_connect -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "", [ConnHandle, ProtocolVersion]),
+ ok.
+
+%%----------------------------------------------------------------------
+%% Invoked when a connection is teared down
+%%----------------------------------------------------------------------
+
+handle_disconnect(ConnHandle, ProtocolVersion, Reason) ->
+ d("handle_disconnect -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n Reason: ~p"
+ "", [ConnHandle, ProtocolVersion, Reason]),
+ megaco:cancel(ConnHandle, Reason), % Cancel the outstanding messages
+ ok.
+
+%%----------------------------------------------------------------------
+%% Invoked when a received message had syntax errors
+%%----------------------------------------------------------------------
+
+handle_syntax_error(ReceiveHandle, ProtocolVersion, ErrorDescriptor) ->
+ d("handle_syntax_error -> entry with"
+ "~n ReceiveHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n ErrorDescriptor: ~p"
+ "", [ReceiveHandle, ProtocolVersion, ErrorDescriptor]),
+ reply.
+
+%%----------------------------------------------------------------------
+%% Invoked when a received message contained no transactions
+%%----------------------------------------------------------------------
+
+handle_message_error(ConnHandle, ProtocolVersion, ErrorDescriptor) ->
+ d("handle_message_error -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n ErrorDescriptor: ~p"
+ "", [ConnHandle, ProtocolVersion, ErrorDescriptor]),
+ no_reply.
+
+%%----------------------------------------------------------------------
+%% Invoked for each transaction request
+%%----------------------------------------------------------------------
+
+handle_trans_request(ConnHandle, ProtocolVersion, ActionRequests) ->
+ d("handle_trans_request -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n ActionRequests: ~p"
+ "", [ConnHandle, ProtocolVersion, ActionRequests]),
+ ED = #'ErrorDescriptor'{errorCode = ?megaco_not_implemented,
+ errorText = "Only single service change on null context handled"},
+ case ActionRequests of
+ [AR] ->
+ ContextId = AR#'ActionRequest'.contextId,
+ case AR#'ActionRequest'.commandRequests of
+ [CR] when ContextId =:= ?megaco_null_context_id ->
+ case CR#'CommandRequest'.command of
+ {serviceChangeReq, Req} ->
+ Rep = service_change(ConnHandle, ProtocolVersion, Req),
+ {discard_ack,
+ [#'ActionReply'{contextId = ContextId,
+ commandReply = [{serviceChangeReply, Rep}]}]};
+ _ ->
+ {discard_ack, ED}
+ end;
+ _ ->
+ {discard_ack, ED}
+ end;
+ _ ->
+ {discard_ack, ED}
+ end.
+
+service_change(ConnHandle, _ProtocolVersion, SCR) ->
+ SCP = SCR#'ServiceChangeRequest'.serviceChangeParms,
+ #'ServiceChangeParm'{serviceChangeAddress = Address,
+ serviceChangeProfile = Profile} = SCP,
+ TermId = SCR#'ServiceChangeRequest'.terminationID,
+ if
+ TermId == [?megaco_root_termination_id] ->
+ MyMid = ConnHandle#megaco_conn_handle.local_mid,
+ Res = {serviceChangeResParms,
+ #'ServiceChangeResParm'{serviceChangeMgcId = MyMid,
+ serviceChangeAddress = Address,
+ serviceChangeProfile = Profile}},
+ #'ServiceChangeReply'{terminationID = TermId,
+ serviceChangeResult = Res};
+ true ->
+ Res = {errorDescriptor,
+ #'ErrorDescriptor'{errorCode = ?megaco_not_implemented,
+ errorText = "Only handled for root"}},
+
+ #'ServiceChangeReply'{terminationID = TermId,
+ serviceChangeResult = Res}
+ end.
+
+%%----------------------------------------------------------------------
+%% Optionally invoked for a time consuming transaction request
+%%----------------------------------------------------------------------
+
+handle_trans_long_request(_ConnHandle, _ProtocolVersion, _ReqData) ->
+ ED = #'ErrorDescriptor'{errorCode = ?megaco_not_implemented,
+ errorText = "Long transaction requests not handled"},
+ {discard_ack, ED}.
+
+%%----------------------------------------------------------------------
+%% Optionally invoked for a transaction reply
+%%----------------------------------------------------------------------
+
+handle_trans_reply(ConnHandle, ProtocolVersion, ActualReply, ReplyData) ->
+ d("handle_trans_eply -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n ActualReply: ~p"
+ "~n ReplyData: ~p"
+ "", [ConnHandle, ProtocolVersion, ActualReply, ReplyData]),
+ ok.
+
+%%----------------------------------------------------------------------
+%% Optionally invoked for a transaction acknowledgement
+%%----------------------------------------------------------------------
+
+handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData) ->
+ d("handle_trans_ack -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n ckStatus: ~p"
+ "~n AckData: ~p"
+ "", [ConnHandle, ProtocolVersion, AckStatus, AckData]),
+ ok.
+
+%%----------------------------------------------------------------------
+%% Invoked when an unexpected message has been received
+%%----------------------------------------------------------------------
+
+handle_unexpected_trans(ConnHandle, ProtocolVersion, Trans) ->
+ d("handle_unexpected_trans -> entry with"
+ "~n ConnHandle: ~p"
+ "~n ProtocolVersion: ~p"
+ "~n Trans: ~p"
+ "", [ConnHandle, ProtocolVersion, Trans]),
+ ok.
+
+
+%%----------------------------------------------------------------------
+%% Invoked when an unexpected message has been received
+%%----------------------------------------------------------------------
+
+handle_trans_request_abort(_ConnHandle, _ProtocolVersion, _TransId, _Pid) ->
+ ok.
+
+%%----------------------------------------------------------------------
+%% To be used at command line: erl -s ?MODULE start_batch
+%%----------------------------------------------------------------------
+
+start_batch() ->
+ start_batch([false]).
+
+start_batch(Args0) ->
+ Defs = [{trace,false}, {debug, false}],
+ Args = parse_args(Args0, Defs),
+ Trace = get_arg(trace, Args),
+ Debug = get_arg(debug, Args),
+ Pid = spawn(?MODULE, init_batch, [self(), Trace, Debug]),
+ receive
+ {init_batch, Pid, Res} ->
+ io:format("~p(~p): ~p~n", [?MODULE, ?LINE, Res]),
+ Res
+ end.
+
+init_batch(ReplyTo, Trace, Debug) ->
+ register(?MODULE, self()),
+ Res = start(Trace, Debug),
+ ReplyTo ! {init_batch, self(), Res},
+ receive
+ after infinity -> Res
+ end.
+
+
+parse_args([], Acc) ->
+ Acc;
+parse_args([Arg|Args], Acc) when is_atom(Arg) ->
+ case string:tokens(atom_to_list(Arg),"{},") of
+ ["trace",Trace] ->
+ parse_args(Args, parse_args(trace, list_to_atom(Trace), Acc));
+ ["debug",Debug] ->
+ parse_args(Args, parse_args(debug, list_to_atom(Debug), Acc));
+ _Invalid ->
+ parse_args(Args, Acc)
+ end.
+
+parse_args(Key, Val, Args) ->
+ Entry = {Key, Val},
+ case lists:keyreplace(Key, 1, Args, {Key, Val}) of
+ Args ->
+ [Entry|Args];
+ Args2 ->
+ Args2
+ end.
+
+get_arg(Key, Args) ->
+ {value, {Key, Val}} = lists:keysearch(Key, 1, Args),
+ Val.
+
+
+%%----------------------------------------------------------------------
+%% DEBUGGING
+%%----------------------------------------------------------------------
+
+d(F) ->
+ d(F, []).
+
+d(F,A) ->
+ d(get(debug),F,A).
+
+d(true,F,A) ->
+ io:format("SIMPLE_MGC: " ++ F ++ "~n", A);
+d(_, _F, _A) ->
+ ok.
+
diff --git a/lib/megaco/examples/simple/modules.mk b/lib/megaco/examples/simple/modules.mk
new file mode 100644
index 0000000000..bcba5666a1
--- /dev/null
+++ b/lib/megaco/examples/simple/modules.mk
@@ -0,0 +1,27 @@
+#-*-makefile-*- ; force emacs to enter makefile-mode
+
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2001-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%
+
+MG_MODULES = \
+ megaco_simple_mg
+
+MGC_MODULES = \
+ megaco_simple_mgc
+
+COMMON_MODULES =
+