diff options
Diffstat (limited to 'lib/megaco/examples')
-rw-r--r-- | lib/megaco/examples/meas/Makefile | 132 | ||||
-rw-r--r-- | lib/megaco/examples/meas/meas.sh.skel | 41 | ||||
-rw-r--r-- | lib/megaco/examples/meas/megaco_codec_meas.erl | 655 | ||||
-rw-r--r-- | lib/megaco/examples/meas/megaco_codec_mstone1.erl | 408 | ||||
-rw-r--r-- | lib/megaco/examples/meas/megaco_codec_mstone2.erl | 400 | ||||
-rw-r--r-- | lib/megaco/examples/meas/megaco_codec_mstone_lib.erl | 534 | ||||
-rw-r--r-- | lib/megaco/examples/meas/megaco_codec_transform.erl | 305 | ||||
-rw-r--r-- | lib/megaco/examples/meas/modules.mk | 35 | ||||
-rw-r--r-- | lib/megaco/examples/meas/mstone1.sh.skel | 239 | ||||
-rw-r--r-- | lib/megaco/examples/meas/time_test.msgs | 149 | ||||
-rw-r--r-- | lib/megaco/examples/simple/Makefile | 153 | ||||
-rw-r--r-- | lib/megaco/examples/simple/megaco_simple_mg.erl | 437 | ||||
-rw-r--r-- | lib/megaco/examples/simple/megaco_simple_mgc.erl | 455 | ||||
-rw-r--r-- | lib/megaco/examples/simple/modules.mk | 27 |
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 = + |