aboutsummaryrefslogtreecommitdiffstats
path: root/lib/megaco/test/megaco_segment_test.erl
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/megaco/test/megaco_segment_test.erl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/megaco/test/megaco_segment_test.erl')
-rw-r--r--lib/megaco/test/megaco_segment_test.erl7819
1 files changed, 7819 insertions, 0 deletions
diff --git a/lib/megaco/test/megaco_segment_test.erl b/lib/megaco/test/megaco_segment_test.erl
new file mode 100644
index 0000000000..ef07ee54b1
--- /dev/null
+++ b/lib/megaco/test/megaco_segment_test.erl
@@ -0,0 +1,7819 @@
+%%
+%% %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: Test the segment package introduced in v3 of the megaco std.
+%%----------------------------------------------------------------------
+-module(megaco_segment_test).
+
+-export([t/0, t/1]).
+-export([init_per_testcase/2, fin_per_testcase/2]).
+-export([all/1,
+
+ send/1,
+ send_segmented_msg_plain1/1,
+ send_segmented_msg_plain2/1,
+ send_segmented_msg_plain3/1,
+ send_segmented_msg_plain4/1,
+ send_segmented_msg_ooo1/1,
+ send_segmented_msg_missing_seg_reply1/1,
+ send_segmented_msg_missing_seg_reply2/1,
+
+ recv/1,
+ recv_segmented_msg_plain/1,
+ recv_segmented_msg_ooo_seg/1,
+ recv_segmented_msg_missing_seg1/1,
+ recv_segmented_msg_missing_seg2/1,
+
+ tickets/1
+
+ ]).
+
+-include("megaco_test_lib.hrl").
+-include_lib("megaco/include/megaco.hrl").
+-include_lib("megaco/include/megaco_message_v3.hrl").
+
+-define(TEST_VERBOSITY, debug).
+
+-define(VERSION, 3).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+t() -> megaco_test_lib:t(?MODULE).
+t(Case) -> megaco_test_lib:t({?MODULE, Case}).
+
+
+%% Test server callbacks
+init_per_testcase(Case, Config) ->
+ process_flag(trap_exit, true),
+ megaco_test_lib:init_per_testcase(Case, Config).
+
+fin_per_testcase(Case, Config) ->
+ process_flag(trap_exit, false),
+ megaco_test_lib:fin_per_testcase(Case, Config).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+all(suite) ->
+ [
+ send,
+ recv
+
+ %% Tickets last
+ %% tickets
+ ].
+
+send(suite) ->
+ [
+ send_segmented_msg_plain1,
+ send_segmented_msg_plain2,
+ send_segmented_msg_plain3,
+ send_segmented_msg_plain4,
+ send_segmented_msg_ooo1,
+ send_segmented_msg_missing_seg_reply1,
+ send_segmented_msg_missing_seg_reply2
+ ].
+
+recv(suite) ->
+ [
+ recv_segmented_msg_plain,
+ recv_segmented_msg_ooo_seg,
+ recv_segmented_msg_missing_seg1,
+ recv_segmented_msg_missing_seg2
+ ].
+
+tickets(suite) ->
+ [
+ ].
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% %%%
+%%% Segmented reply send test cases %%%
+%%% %%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+send_segmented_msg_plain1(suite) ->
+ [];
+send_segmented_msg_plain1(doc) ->
+ "First plain test that it is possible to send segmented messages. "
+ "Send window = infinity. ";
+send_segmented_msg_plain1(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, ssmp1),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ d("[MGC] start the simulator "),
+ {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode),
+
+ d("[MGC] create the event sequence"),
+ MgcEvSeq = ssmp1_mgc_event_sequence(text, tcp),
+
+ i("wait some time before starting the MGC simulation"),
+ sleep(1000),
+
+ d("[MGC] start the simulation"),
+ {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq),
+
+ i("wait some time before starting the MG simulator"),
+ sleep(1000),
+
+ d("[MG] start the simulator (generator)"),
+ {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode),
+
+ d("[MG] create the event sequence"),
+ MgEvSeq = ssmp1_mg_event_sequence(text, tcp),
+
+ i("wait some time before starting the MG simulation"),
+ sleep(1000),
+
+ d("[MG] start the simulation"),
+ {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq),
+
+ d("await the generator reply(s)"),
+ await_completion([MgcId, MgId]),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop generator"),
+ megaco_test_tcp_generator:stop(Mgc),
+
+ %% Tell Mg to stop
+ i("[MG] stop generator"),
+ megaco_test_megaco_generator:stop(Mg),
+
+ i("done", []),
+ ok.
+
+
+
+%%
+%% MGC generator stuff
+%%
+
+ssmp1_mgc_event_sequence(text, tcp) ->
+ DecodeFun = ssmp1_mgc_decode_msg_fun(megaco_pretty_text_encoder, []),
+ EncodeFun = ssmp1_mgc_encode_msg_fun(megaco_pretty_text_encoder, []),
+ Mid = {deviceName,"mgc"},
+ ScrVerifyFun = ssmp1_mgc_verify_service_change_req_msg_fun(),
+ ServiceChangeRep = ssmp1_mgc_service_change_reply_msg(Mid, 1),
+ TermId1 =
+ #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ CtxId1 = 1,
+ TermId2 =
+ #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ CtxId2 = 2,
+ TransId = 2,
+ NotifyReq = ssmp1_mgc_notify_request_msg(Mid, TransId,
+ TermId1, CtxId1,
+ TermId2, CtxId2),
+ NrVerifyFun1 =
+ ssmp1_mgc_verify_notify_reply_segment_msg_fun(1, false, TransId,
+ TermId1, CtxId1),
+ NrVerifyFun2 =
+ ssmp1_mgc_verify_notify_reply_segment_msg_fun(2, true, TransId,
+ TermId2, CtxId2),
+ SegmentRep1 = ssmp1_mgc_segment_reply_msg(Mid, TransId, 1, false),
+ SegmentRep2 = ssmp1_mgc_segment_reply_msg(Mid, TransId, 2, true),
+ TransAck = ssmp1_mgc_trans_ack_msg(Mid, TransId),
+ EvSeq = [{debug, true},
+ {decode, DecodeFun},
+ {encode, EncodeFun},
+ {listen, 2944},
+ {expect_accept, any},
+ {expect_receive, "service-change-request", {ScrVerifyFun, 5000}},
+ {send, "service-change-reply", ServiceChangeRep},
+ {expect_nothing, timer:seconds(1)},
+ {send, "notify request", NotifyReq},
+ {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 2000}},
+ {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}},
+ {send, "segment reply 1", SegmentRep1},
+ {sleep, 100},
+ {send, "segment reply 2", SegmentRep2},
+ {sleep, 100}, % {expect_nothing, 500},
+ {send, "transaction-ack", TransAck},
+ {expect_closed, timer:seconds(5)},
+ disconnect
+ ],
+ EvSeq.
+
+ssmp1_mgc_encode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:encode_message(Conf, M)
+ end.
+
+ssmp1_mgc_decode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:decode_message(Conf, M)
+ end.
+
+ssmp1_mgc_verify_service_change_req_msg_fun() ->
+ fun(Msg) ->
+ (catch ssmp1_mgc_verify_service_change_req(Msg))
+ end.
+
+ssmp1_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) ->
+ io:format("ssmp1_mgc_verify_service_change_req -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ Body =
+ case Mess of
+ #'Message'{version = 1,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = _TransId,
+ actions = [ActionReq]} ->
+ ActionReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ CR =
+ case AR of
+ #'ActionRequest'{contextId = _Cid,
+ commandRequests = [CmdReq]} ->
+ CmdReq;
+ _ ->
+ throw({error, {invalid_action, AR}})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}})
+ end,
+ {Tid, Parms} =
+ case Cmd of
+ {serviceChangeReq,
+ #'ServiceChangeRequest'{terminationID = [TermID],
+ serviceChangeParms = ServChParms}} ->
+ {TermID, ServChParms};
+ _ ->
+ throw({error, {invalid_command, Cmd}})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ throw({error, {invalid_terminationID, Tid}})
+ end,
+ case Parms of
+ %% Version 1 'ServiceChangeParm'
+ {'ServiceChangeParm',
+ restart, % serviceChangeMethod
+ asn1_NOVALUE, % serviceChangeAddress
+ ?VERSION, % serviceChangeVersion,
+ {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile
+ [[$9,$0,$1|_]], % serviceChangeReason
+ asn1_NOVALUE, % serviceChangeDelay
+ asn1_NOVALUE, % serviceChangeMgcId
+ asn1_NOVALUE, % timeStamp
+ asn1_NOVALUE % nonStandardData
+ } ->
+ {ok, M};
+ _ ->
+ {error, {invalid_serviceChangeParms, Parms}}
+ end.
+
+ssmp1_mgc_verify_notify_reply_segment_msg_fun(SN, Last,
+ TransId, TermId, Cid) ->
+ fun(Msg) ->
+ (catch ssmp1_mgc_verify_notify_reply_segment(Msg,
+ SN, Last,
+ TransId, TermId, Cid))
+ end.
+
+ssmp1_mgc_verify_notify_reply_segment(#'MegacoMessage'{mess = Mess} = M,
+ SN, Last, TransId, TermId, Cid) ->
+ io:format("ssmp1_mgc_verify_notify_reply_segment -> entry with"
+ "~n M: ~p"
+ "~n SN: ~p"
+ "~n Last: ~p"
+ "~n TransId: ~p"
+ "~n TermId: ~p"
+ "~n Cid: ~p"
+ "~n", [M, SN, Last, TransId, TermId, Cid]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionReply, TransReply} ->
+ TransReply;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ TRes =
+ case TR of
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = TransRes,
+ segmentNumber = SN,
+ segmentationComplete = asn1_NOVALUE} when (Last == false) ->
+ TransRes;
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = TransRes,
+ segmentNumber = SN,
+ segmentationComplete = 'NULL'} when (Last == true) ->
+ TransRes;
+ _ ->
+ throw({error, {invalid_transactionReply, TR}})
+ end,
+ AR =
+ case TRes of
+ {actionReplies, [ActionReply]} ->
+ ActionReply;
+ {actionReplies, ActionReplies} ->
+ throw({error, {invalid_actionReplies, ActionReplies}});
+ _ ->
+ throw({error, {invalid_transactionResult, TRes}})
+ end,
+ CR =
+ case AR of
+ #'ActionReply'{contextId = Cid,
+ commandReply = [CommandReply]} ->
+ CommandReply;
+ #'ActionReply'{contextId = Cid,
+ commandReply = CommandReplies} ->
+ throw({error, {invalid_commandReplies, CommandReplies}});
+ _ ->
+ throw({error, {invalid_actionReply, AR}})
+ end,
+ NR =
+ case CR of
+ {notifyReply, NotifyReply} ->
+ NotifyReply;
+ _ ->
+ throw({error, {invalid_commandReply, CR}})
+ end,
+ case NR of
+ #'NotifyReply'{terminationID = [TermId],
+ errorDescriptor = asn1_NOVALUE} ->
+ {ok, M};
+ _ ->
+ {error, {invalid_NotifyReply, NR}}
+ end;
+ssmp1_mgc_verify_notify_reply_segment(Crap,
+ _SN, _Last, _TransId, _TermId, _Cid) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+
+ssmp1_mgc_service_change_reply_msg(Mid, Cid) ->
+ SCRP = cre_serviceChangeResParm(Mid),
+ SCRes = cre_serviceChangeResult(SCRP),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReply([Root], SCRes),
+ CR = cre_cmdReply(SCR),
+ AR = cre_actionReply(Cid, [CR]),
+ TRes = cre_transResult([AR]),
+ TR = {'TransactionReply', 1, asn1_NOVALUE, TRes},
+ Trans = cre_transaction(TR),
+ Mess = cre_message(1, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmp1_mgc_notify_request_msg(Mid, TransId, TermId1, Cid1, TermId2, Cid2) ->
+ AR1 = ssmp1_mgc_notify_request_ar(1, TermId1, Cid1),
+ AR2 = ssmp1_mgc_notify_request_ar(2, TermId2, Cid2),
+ TR = cre_transReq(TransId, [AR1, AR2]),
+ Trans = cre_transaction(TR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmp1_mgc_notify_request_ar(Rid, Tid, Cid) ->
+ TT = cre_timeNotation(integer_to_list(19990720+Rid),
+ integer_to_list(22000000+Rid)),
+ Ev = cre_obsEvent("al/of", TT),
+ EvsDesc = cre_obsEvsDesc(Rid, [Ev]),
+ NR = cre_notifyReq([Tid], EvsDesc),
+ CMD = cre_command(NR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+ssmp1_mgc_segment_reply_msg(Mid, TransId, SN, Last) ->
+ SR = ssmp1_mgc_segment_reply(TransId, SN, Last),
+ Trans = cre_transaction(SR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmp1_mgc_segment_reply(TransId, SN, true) ->
+ cre_segReply(TransId, SN, 'NULL');
+ssmp1_mgc_segment_reply(TransId, SN, false) ->
+ cre_segReply(TransId, SN, asn1_NOVALUE).
+
+ssmp1_mgc_trans_ack_msg(Mid, TransId) ->
+ TA = cre_transAck(TransId),
+ Trans = cre_transaction([TA]),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+
+%%
+%% MG generator stuff
+%%
+ssmp1_mg_event_sequence(text, tcp) ->
+ Mid = {deviceName,"mg"},
+ RI = [
+ {port, 2944},
+ {encoding_module, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {transport_module, megaco_tcp}
+ ],
+ ConnectVerify = ssmp1_mg_verify_handle_connect_fun(),
+ ServiceChangeReq = ssmp1_mg_service_change_request_ar(Mid, 1),
+ ServiceChangeReplyVerify = ssmp1_mg_verify_service_change_reply_fun(),
+ Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ NotifyReqVerify = ssmp1_mg_verify_notify_request_fun(Tid1, Tid2),
+ AckVerify = ssmp1_mg_verify_ack_fun(),
+ EvSeq = [
+ {debug, true},
+ {megaco_trace, disable},
+ %% {megaco_trace, max},
+ megaco_start,
+ {megaco_start_user, Mid, RI, []},
+ start_transport,
+ {megaco_system_info, users},
+ {megaco_system_info, connections},
+ connect,
+ {megaco_callback, handle_connect, ConnectVerify},
+ megaco_connect,
+ {megaco_cast, [ServiceChangeReq], []},
+ {megaco_callback, handle_connect, ConnectVerify},
+ {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify},
+ {megaco_update_conn_info, protocol_version, ?VERSION},
+ {megaco_update_conn_info, segment_send, infinity},
+ {megaco_update_conn_info, max_pdu_size, 128},
+ {sleep, 1000},
+ {megaco_callback, handle_trans_request, NotifyReqVerify},
+ {megaco_callback, handle_trans_ack, AckVerify, 5000},
+ megaco_stop_user,
+ megaco_stop,
+ {sleep, 1000}
+ ],
+ EvSeq.
+
+
+ssmp1_mg_verify_handle_connect_fun() ->
+ fun(Ev) -> ssmp1_mg_verify_handle_connect(Ev) end.
+
+ssmp1_mg_verify_handle_connect({handle_connect, CH, 1}) ->
+ io:format("ssmp1_mg_verify_handle_connect -> ok"
+ "~n CH: ~p~n", [CH]),
+ {ok, CH, ok};
+ssmp1_mg_verify_handle_connect(Else) ->
+ io:format("ssmp1_mg_verify_handle_connect -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, ok}.
+
+
+ssmp1_mg_verify_service_change_reply_fun() ->
+ fun(Rep) -> ssmp1_mg_verify_scr(Rep) end.
+
+ssmp1_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) ->
+ (catch ssmp1_mg_do_verify_scr(AR));
+ssmp1_mg_verify_scr(Crap) ->
+ io:format("ssmp1_mg_verify_scr -> error: "
+ "~n Crap: ~p"
+ "~n", [Crap]),
+ {error, Crap, ok}.
+
+ssmp1_mg_do_verify_scr(AR) ->
+ io:format("ssmp1_mg_do_verify_scr -> ok: "
+ "~n AR: ~p~n", [AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ SCR =
+ case CR of
+ {serviceChangeReply, ServChRep} ->
+ ServChRep;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ {Tid, SCRes} =
+ case SCR of
+ #'ServiceChangeReply'{terminationID = [TermID],
+ serviceChangeResult = Res} ->
+ {TermID, Res};
+ _ ->
+ Reason3 = {invalid_service_change_reply, SCR},
+ throw({error, Reason3, ok})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ Reason4 = {invalid_termination_id, Tid},
+ throw({error, Reason4, ok})
+ end,
+ SCRParm =
+ case SCRes of
+ {serviceChangeResParms, ServChResParms} ->
+ ServChResParms;
+ _ ->
+ Reason5 = {invalid_serviceChangeResult, SCRes},
+ throw({error, Reason5, ok})
+ end,
+ case SCRParm of
+ #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} ->
+ {ok, AR, ok};
+ _ ->
+ Reason6 = {invalid_service_change_result, SCRParm},
+ {error, Reason6, ok}
+ end.
+
+ssmp1_mg_verify_notify_request_fun(Tid1, Tid2) ->
+ fun(Req) ->
+ ssmp1_mg_verify_notify_request(Req, Tid1, Tid2)
+ end.
+
+ssmp1_mg_verify_notify_request(
+ {handle_trans_request, _CH, ?VERSION, [AR1, AR2]}, Tid1, Tid2) ->
+ (catch ssmp1_mg_do_verify_notify_request(Tid1, Tid2, AR1, AR2));
+ssmp1_mg_verify_notify_request(
+ {handle_trans_request, _CH, ?VERSION, ARs}, _Tid1, _Tid2) ->
+ {error, {invalid_action_requests, ARs}, ok};
+ssmp1_mg_verify_notify_request(
+ {handle_trans_request, CH, V, ARs}, _Tid1, _Tid2) ->
+ {error, {invalid_trans_request, {CH, V, ARs}}, ok};
+ssmp1_mg_verify_notify_request(Crap, _Tid1, _Tid2) ->
+ io:format("ssmp1_mg_verify_notify_request -> unknown request"
+ "~n Tid1: ~p"
+ "~n Tid2: ~p"
+ "~n Crap: ~p"
+ "~n", [_Tid1, _Tid2, Crap]),
+ {error, {unexpected_event, Crap}, ok}.
+
+ssmp1_mg_do_verify_notify_request(Tid1, Tid2, AR1, AR2) ->
+ io:format("ssmp1_mg_do_verify_notify_request -> ok"
+ "~n Tid1: ~p"
+ "~n Tid2: ~p"
+ "~n AR1: ~p"
+ "~n AR2: ~p"
+ "~n", [Tid1, Tid2, AR1, AR2]),
+ ActionReply1 = ssmp1_mg_do_verify_notify_request(Tid1, AR1),
+ ActionReply2 = ssmp1_mg_do_verify_notify_request(Tid2, AR2),
+ Reply = {{handle_ack, ssmp1}, [ActionReply1, ActionReply2]},
+ {ok, [AR1, AR2], Reply}.
+
+ssmp1_mg_do_verify_notify_request(Tid, AR) ->
+ io:format("ssmp1_mg_do_verify_notify_request -> ok"
+ "~n Tid: ~p"
+ "~n AR: ~p"
+ "~n", [Tid, AR]),
+ {Cid, CR} =
+ case AR of
+ #'ActionRequest'{contextId = CtxId,
+ commandRequests = [CmdReq]} ->
+ {CtxId, CmdReq};
+ _ ->
+ Reason1 = {invalid_actionRequest, AR},
+ throw({error, Reason1, ok})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}, ok})
+ end,
+ OED =
+ case Cmd of
+ {notifyReq,
+ #'NotifyRequest'{terminationID = [Tid],
+ observedEventsDescriptor = ObsEvDesc,
+ errorDescriptor = asn1_NOVALUE}} ->
+ ObsEvDesc;
+ _ ->
+ throw({error, {invalid_command, Cmd}, ok})
+ end,
+ OE =
+ case OED of
+ #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} ->
+ ObsEv;
+ #'ObservedEventsDescriptor'{observedEventLst = ObsEvLst} ->
+ throw({error, {invalid_observedEventLst, ObsEvLst}, ok});
+ _ ->
+ throw({error, {invalid_ObservedEventsDescriptor, OED}, ok})
+ end,
+ case OE of
+ #'ObservedEvent'{eventName = "al/of"} ->
+ ssmp1_mg_notify_reply_ar(Cid, Tid);
+ _ ->
+ throw({error, {invalid_ObservedEvent, OE}, ok})
+ end.
+
+
+ssmp1_mg_verify_ack_fun() ->
+ fun(Event) -> ssmp1_mg_verify_ack(Event) end.
+
+ssmp1_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, ssmp1}) ->
+ io:format("ssmp1_mg_verify_ack -> ok"
+ "~n CH: ~p"
+ "~n", [CH]),
+ {ok, CH, ok};
+ssmp1_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, CrapAckData}) ->
+ io:format("ssmp1_mg_verify_ack -> error"
+ "~n CrapAckData: ~p"
+ "~n CH: ~p"
+ "~n", [CrapAckData, CH]),
+ {error, {unknown_ack_data, CrapAckData, CH}, ok};
+ssmp1_mg_verify_ack({handle_trans_ack, CH, ?VERSION,
+ BadAckStatus, BadAckData}) ->
+ io:format("ssmp1_mg_verify_ack -> error"
+ "~n BadAckStatus: ~p"
+ "~n BadAckData: ~p"
+ "~n CH: ~p"
+ "~n", [BadAckStatus, BadAckData, CH]),
+ {error, {unknown_ack_status, BadAckStatus, BadAckData, CH}, ok};
+ssmp1_mg_verify_ack(BadEvent) ->
+ {error, {unknown_event, BadEvent}, ok}.
+
+
+ssmp1_mg_service_change_request_ar(_Mid, Cid) ->
+ Prof = cre_serviceChangeProf("resgw", 1),
+ SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReq([Root], SCP),
+ CMD = cre_command(SCR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+ssmp1_mg_notify_reply_ar(Cid, Tid) ->
+ NR = cre_notifyReply([Tid]),
+ CR = cre_cmdReply(NR),
+ cre_actionReply(Cid, [CR]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+send_segmented_msg_plain2(suite) ->
+ [];
+send_segmented_msg_plain2(doc) ->
+ "Second plain test that it is possible to send segmented messages. "
+ "Send window = infinity. ";
+send_segmented_msg_plain2(Config) when is_list(Config) ->
+ %% <CONDITIONAL-SKIP>
+ Skippable = [{unix, [linux]}],
+ Condition = fun() -> ?OS_BASED_SKIP(Skippable) end,
+ ?NON_PC_TC_MAYBE_SKIP(Config, Condition),
+ %% </CONDITIONAL-SKIP>
+
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, ssmp2),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ d("[MGC] start the simulator "),
+ {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode),
+
+ d("[MGC] create the event sequence"),
+ MgcEvSeq = ssmp2_mgc_event_sequence(text, tcp),
+
+ i("wait some time before starting the MGC simulation"),
+ sleep(1000),
+
+ d("[MGC] start the simulation"),
+ {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq),
+
+ i("wait some time before starting the MG simulator"),
+ sleep(1000),
+
+ d("[MG] start the simulator (generator)"),
+ {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode),
+
+ d("[MG] create the event sequence"),
+ MgEvSeq = ssmp2_mg_event_sequence(text, tcp),
+
+ i("wait some time before starting the MG simulation"),
+ sleep(1000),
+
+ d("[MG] start the simulation"),
+ {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq),
+
+ d("await the generator reply(s)"),
+ await_completion([MgcId, MgId]),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop generator"),
+ megaco_test_tcp_generator:stop(Mgc),
+
+ %% Tell Mg to stop
+ i("[MG] stop generator"),
+ megaco_test_megaco_generator:stop(Mg),
+
+ i("done", []),
+ ok.
+
+
+
+%%
+%% MGC generator stuff
+%%
+
+ssmp2_mgc_event_sequence(text, tcp) ->
+ DecodeFun = ssmp2_mgc_decode_msg_fun(megaco_pretty_text_encoder, []),
+ EncodeFun = ssmp2_mgc_encode_msg_fun(megaco_pretty_text_encoder, []),
+ Mid = {deviceName,"mgc"},
+ ScrVerifyFun = ssmp2_mgc_verify_service_change_req_msg_fun(),
+ ServiceChangeRep = ssmp2_mgc_service_change_reply_msg(Mid, 1),
+ TermId1 =
+ #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ CtxId1 = 1,
+ TermId2 =
+ #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ CtxId2 = 2,
+ TransId = 2,
+ NotifyReq = ssmp2_mgc_notify_request_msg(Mid, TransId,
+ TermId1, CtxId1,
+ TermId2, CtxId2),
+ NrVerifyFun1 =
+ ssmp2_mgc_verify_notify_reply_segment_msg_fun(1, false, TransId,
+ TermId1, CtxId1),
+ NrVerifyFun2 =
+ ssmp2_mgc_verify_notify_reply_segment_msg_fun(2, true, TransId,
+ TermId2, CtxId2),
+ SegmentRep1 = ssmp2_mgc_segment_reply_msg(Mid, TransId, 1, false),
+ SegmentRep2 = ssmp2_mgc_segment_reply_msg(Mid, TransId, 2, true),
+ TransAck = ssmp2_mgc_trans_ack_msg(Mid, TransId),
+ EvSeq = [{debug, true},
+ {decode, DecodeFun},
+ {encode, EncodeFun},
+ {listen, 2944},
+ {expect_accept, any},
+ {expect_receive, "service-change-request", {ScrVerifyFun, 5000}},
+ {send, "service-change-reply", ServiceChangeRep},
+ {expect_nothing, timer:seconds(1)},
+ {send, "notify request", NotifyReq},
+ {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 2000}},
+ {send, "segment reply 1", SegmentRep1},
+ {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}},
+ {send, "segment reply 2", SegmentRep2},
+ {sleep, 100}, % {expect_nothing, 500},
+ {send, "transaction-ack", TransAck},
+ {expect_closed, timer:seconds(5)},
+ disconnect
+ ],
+ EvSeq.
+
+ssmp2_mgc_encode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:encode_message(Conf, M)
+ end.
+
+ssmp2_mgc_decode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:decode_message(Conf, M)
+ end.
+
+ssmp2_mgc_verify_service_change_req_msg_fun() ->
+ fun(Msg) ->
+ (catch ssmp2_mgc_verify_service_change_req(Msg))
+ end.
+
+ssmp2_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) ->
+ io:format("ssmp2_mgc_verify_service_change_req -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ Body =
+ case Mess of
+ #'Message'{version = 1,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = _TransId,
+ actions = [ActionReq]} ->
+ ActionReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ CR =
+ case AR of
+ #'ActionRequest'{contextId = _Cid,
+ commandRequests = [CmdReq]} ->
+ CmdReq;
+ _ ->
+ throw({error, {invalid_action, AR}})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}})
+ end,
+ {Tid, Parms} =
+ case Cmd of
+ {serviceChangeReq,
+ #'ServiceChangeRequest'{terminationID = [TermID],
+ serviceChangeParms = ServChParms}} ->
+ {TermID, ServChParms};
+ _ ->
+ throw({error, {invalid_command, Cmd}})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ throw({error, {invalid_terminationID, Tid}})
+ end,
+ case Parms of
+ %% Version 1 'ServiceChangeParm'
+ {'ServiceChangeParm',
+ restart, % serviceChangeMethod
+ asn1_NOVALUE, % serviceChangeAddress
+ ?VERSION, % serviceChangeVersion,
+ {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile
+ [[$9,$0,$1|_]], % serviceChangeReason
+ asn1_NOVALUE, % serviceChangeDelay
+ asn1_NOVALUE, % serviceChangeMgcId
+ asn1_NOVALUE, % timeStamp
+ asn1_NOVALUE % nonStandardData
+ } ->
+ {ok, M};
+ _ ->
+ {error, {invalid_serviceChangeParms, Parms}}
+ end.
+
+ssmp2_mgc_verify_notify_reply_segment_msg_fun(SN, Last,
+ TransId, TermId, Cid) ->
+ fun(Msg) ->
+ (catch ssmp2_mgc_verify_notify_reply_segment(Msg,
+ SN, Last,
+ TransId, TermId, Cid))
+ end.
+
+ssmp2_mgc_verify_notify_reply_segment(#'MegacoMessage'{mess = Mess} = M,
+ SN, Last, TransId, TermId, Cid) ->
+ io:format("ssmp2_mgc_verify_notify_reply_segment -> entry with"
+ "~n M: ~p"
+ "~n SN: ~p"
+ "~n Last: ~p"
+ "~n TransId: ~p"
+ "~n TermId: ~p"
+ "~n Cid: ~p"
+ "~n", [M, SN, Last, TransId, TermId, Cid]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionReply, TransReply} ->
+ TransReply;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ TRes =
+ case TR of
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = TransRes,
+ segmentNumber = SN,
+ segmentationComplete = asn1_NOVALUE} when (Last == false) ->
+ TransRes;
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = TransRes,
+ segmentNumber = SN,
+ segmentationComplete = 'NULL'} when (Last == true) ->
+ TransRes;
+ _ ->
+ throw({error, {invalid_transactionReply, TR}})
+ end,
+ AR =
+ case TRes of
+ {actionReplies, [ActionReply]} ->
+ ActionReply;
+ {actionReplies, ActionReplies} ->
+ throw({error, {invalid_actionReplies, ActionReplies}});
+ _ ->
+ throw({error, {invalid_transactionResult, TRes}})
+ end,
+ CR =
+ case AR of
+ #'ActionReply'{contextId = Cid,
+ commandReply = [CommandReply]} ->
+ CommandReply;
+ #'ActionReply'{contextId = Cid,
+ commandReply = CommandReplies} ->
+ throw({error, {invalid_commandReplies, CommandReplies}});
+ _ ->
+ throw({error, {invalid_actionReply, AR}})
+ end,
+ NR =
+ case CR of
+ {notifyReply, NotifyReply} ->
+ NotifyReply;
+ _ ->
+ throw({error, {invalid_commandReply, CR}})
+ end,
+ case NR of
+ #'NotifyReply'{terminationID = [TermId],
+ errorDescriptor = asn1_NOVALUE} ->
+ {ok, M};
+ _ ->
+ {error, {invalid_NotifyReply, NR}}
+ end;
+ssmp2_mgc_verify_notify_reply_segment(Crap,
+ _SN, _Last, _TransId, _TermId, _Cid) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+
+ssmp2_mgc_service_change_reply_msg(Mid, Cid) ->
+ SCRP = cre_serviceChangeResParm(Mid),
+ SCRes = cre_serviceChangeResult(SCRP),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReply([Root], SCRes),
+ CR = cre_cmdReply(SCR),
+ AR = cre_actionReply(Cid, [CR]),
+ TRes = cre_transResult([AR]),
+ TR = {'TransactionReply', 1, asn1_NOVALUE, TRes},
+ Trans = cre_transaction(TR),
+ Mess = cre_message(1, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmp2_mgc_notify_request_msg(Mid, TransId, TermId1, Cid1, TermId2, Cid2) ->
+ AR1 = ssmp2_mgc_notify_request_ar(1, TermId1, Cid1),
+ AR2 = ssmp2_mgc_notify_request_ar(2, TermId2, Cid2),
+ TR = cre_transReq(TransId, [AR1, AR2]),
+ Trans = cre_transaction(TR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmp2_mgc_notify_request_ar(Rid, Tid, Cid) ->
+ TT = cre_timeNotation(integer_to_list(19990720+Rid),
+ integer_to_list(22000000+Rid)),
+ Ev = cre_obsEvent("al/of", TT),
+ EvsDesc = cre_obsEvsDesc(Rid, [Ev]),
+ NR = cre_notifyReq([Tid], EvsDesc),
+ CMD = cre_command(NR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+ssmp2_mgc_segment_reply_msg(Mid, TransId, SN, Last) ->
+ SR = ssmp2_mgc_segment_reply(TransId, SN, Last),
+ Trans = cre_transaction(SR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmp2_mgc_segment_reply(TransId, SN, true) ->
+ cre_segReply(TransId, SN, 'NULL');
+ssmp2_mgc_segment_reply(TransId, SN, false) ->
+ cre_segReply(TransId, SN, asn1_NOVALUE).
+
+ssmp2_mgc_trans_ack_msg(Mid, TransId) ->
+ TA = cre_transAck(TransId),
+ Trans = cre_transaction([TA]),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+
+%%
+%% MG generator stuff
+%%
+ssmp2_mg_event_sequence(text, tcp) ->
+ Mid = {deviceName,"mg"},
+ RI = [
+ {port, 2944},
+ {encoding_module, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {transport_module, megaco_tcp}
+ ],
+ ConnectVerify = ssmp2_mg_verify_handle_connect_fun(),
+ ServiceChangeReq = ssmp2_mg_service_change_request_ar(Mid, 1),
+ ServiceChangeReplyVerify = ssmp2_mg_verify_service_change_reply_fun(),
+ Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ NotifyReqVerify = ssmp2_mg_verify_notify_request_fun(Tid1, Tid2),
+ AckVerify = ssmp2_mg_verify_ack_fun(),
+ EvSeq = [
+ {debug, true},
+ {megaco_trace, disable},
+ %% {megaco_trace, max},
+ megaco_start,
+ {megaco_start_user, Mid, RI, []},
+ start_transport,
+ {megaco_system_info, users},
+ {megaco_system_info, connections},
+ connect,
+ {megaco_callback, handle_connect, ConnectVerify},
+ megaco_connect,
+ {megaco_cast, [ServiceChangeReq], []},
+ {megaco_callback, handle_connect, ConnectVerify},
+ {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify},
+ {megaco_update_conn_info, protocol_version, ?VERSION},
+ {megaco_update_conn_info, segment_send, infinity},
+ {megaco_update_conn_info, max_pdu_size, 128},
+ {sleep, 1000},
+ {megaco_callback, handle_trans_request, NotifyReqVerify},
+ {megaco_callback, handle_trans_ack, AckVerify, 5000},
+ megaco_stop_user,
+ megaco_stop,
+ {sleep, 1000}
+ ],
+ EvSeq.
+
+
+ssmp2_mg_verify_handle_connect_fun() ->
+ fun(Ev) -> ssmp2_mg_verify_handle_connect(Ev) end.
+
+ssmp2_mg_verify_handle_connect({handle_connect, CH, 1}) ->
+ io:format("ssmp2_mg_verify_handle_connect -> ok"
+ "~n CH: ~p~n", [CH]),
+ {ok, CH, ok};
+ssmp2_mg_verify_handle_connect(Else) ->
+ io:format("ssmp2_mg_verify_handle_connect -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, ok}.
+
+
+ssmp2_mg_verify_service_change_reply_fun() ->
+ fun(Rep) -> ssmp2_mg_verify_scr(Rep) end.
+
+ssmp2_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) ->
+ (catch ssmp2_mg_do_verify_scr(AR));
+ssmp2_mg_verify_scr(Crap) ->
+ io:format("ssmp2_mg_verify_scr -> error: "
+ "~n Crap: ~p"
+ "~n", [Crap]),
+ {error, Crap, ok}.
+
+ssmp2_mg_do_verify_scr(AR) ->
+ io:format("ssmp2_mg_do_verify_scr -> ok: "
+ "~n AR: ~p~n", [AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ SCR =
+ case CR of
+ {serviceChangeReply, ServChRep} ->
+ ServChRep;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ {Tid, SCRes} =
+ case SCR of
+ #'ServiceChangeReply'{terminationID = [TermID],
+ serviceChangeResult = Res} ->
+ {TermID, Res};
+ _ ->
+ Reason3 = {invalid_service_change_reply, SCR},
+ throw({error, Reason3, ok})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ Reason4 = {invalid_termination_id, Tid},
+ throw({error, Reason4, ok})
+ end,
+ SCRParm =
+ case SCRes of
+ {serviceChangeResParms, ServChResParms} ->
+ ServChResParms;
+ _ ->
+ Reason5 = {invalid_serviceChangeResult, SCRes},
+ throw({error, Reason5, ok})
+ end,
+ case SCRParm of
+ #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} ->
+ {ok, AR, ok};
+ _ ->
+ Reason6 = {invalid_service_change_result, SCRParm},
+ {error, Reason6, ok}
+ end.
+
+ssmp2_mg_verify_notify_request_fun(Tid1, Tid2) ->
+ fun(Req) -> ssmp2_mg_verify_notify_request(Req, Tid1, Tid2) end.
+
+ssmp2_mg_verify_notify_request(
+ {handle_trans_request, _CH, ?VERSION, [AR1, AR2]}, Tid1, Tid2) ->
+ (catch ssmp2_mg_do_verify_notify_request(Tid1, Tid2, AR1, AR2));
+ssmp2_mg_verify_notify_request(
+ {handle_trans_request, _CH, ?VERSION, ARs}, _Tid1, _Tid2) ->
+ {error, {invalid_action_requests, ARs}, ok};
+ssmp2_mg_verify_notify_request(
+ {handle_trans_request, CH, V, ARs}, _Tid1, _Tid2) ->
+ {error, {invalid_trans_request, {CH, V, ARs}}, ok};
+ssmp2_mg_verify_notify_request(Crap, _Tid1, _Tid2) ->
+ io:format("ssmp2_mg_verify_notify_request -> unknown request"
+ "~n Tid1: ~p"
+ "~n Tid2: ~p"
+ "~n Crap: ~p"
+ "~n", [_Tid1, _Tid2, Crap]),
+ {error, {unexpected_event, Crap}, ok}.
+
+ssmp2_mg_do_verify_notify_request(Tid1, Tid2, AR1, AR2) ->
+ io:format("ssmp2_mg_do_verify_notify_request -> ok"
+ "~n Tid1: ~p"
+ "~n Tid2: ~p"
+ "~n AR1: ~p"
+ "~n AR2: ~p"
+ "~n", [Tid1, Tid2, AR1, AR2]),
+ ActionReply1 = ssmp2_mg_do_verify_notify_request(Tid1, AR1),
+ ActionReply2 = ssmp2_mg_do_verify_notify_request(Tid2, AR2),
+ Reply = {{handle_ack, ssmp2}, [ActionReply1, ActionReply2]},
+ {ok, [AR1, AR2], Reply}.
+
+ssmp2_mg_do_verify_notify_request(Tid, AR) ->
+ io:format("ssmp2_mg_do_verify_notify_request -> ok"
+ "~n Tid: ~p"
+ "~n AR: ~p"
+ "~n", [Tid, AR]),
+ {Cid, CR} =
+ case AR of
+ #'ActionRequest'{contextId = CtxId,
+ commandRequests = [CmdReq]} ->
+ {CtxId, CmdReq};
+ _ ->
+ Reason1 = {invalid_actionRequest, AR},
+ throw({error, Reason1, ok})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}, ok})
+ end,
+ OED =
+ case Cmd of
+ {notifyReq,
+ #'NotifyRequest'{terminationID = [Tid],
+ observedEventsDescriptor = ObsEvDesc,
+ errorDescriptor = asn1_NOVALUE}} ->
+ ObsEvDesc;
+ _ ->
+ throw({error, {invalid_command, Cmd}, ok})
+ end,
+ OE =
+ case OED of
+ #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} ->
+ ObsEv;
+ #'ObservedEventsDescriptor'{observedEventLst = ObsEvLst} ->
+ throw({error, {invalid_observedEventLst, ObsEvLst}, ok});
+ _ ->
+ throw({error, {invalid_ObservedEventsDescriptor, OED}, ok})
+ end,
+ case OE of
+ #'ObservedEvent'{eventName = "al/of"} ->
+ ssmp2_mg_notify_reply_ar(Cid, Tid);
+ _ ->
+ throw({error, {invalid_ObservedEvent, OE}, ok})
+ end.
+
+
+ssmp2_mg_verify_ack_fun() ->
+ fun(Event) -> ssmp2_mg_verify_ack(Event) end.
+
+ssmp2_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, ssmp2}) ->
+ io:format("ssmp2_mg_verify_ack -> ok"
+ "~n CH: ~p"
+ "~n", [CH]),
+ {ok, CH, ok};
+ssmp2_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, CrapAckData}) ->
+ {error, {unknown_ack_data, CrapAckData, CH}, ok};
+ssmp2_mg_verify_ack({handle_trans_ack, CH, ?VERSION,
+ BadAckStatus, BadAckData}) ->
+ {error, {unknown_ack_status, BadAckStatus, BadAckData, CH}, ok};
+ssmp2_mg_verify_ack(BadEvent) ->
+ {error, {unknown_event, BadEvent}, ok}.
+
+
+ssmp2_mg_service_change_request_ar(_Mid, Cid) ->
+ Prof = cre_serviceChangeProf("resgw", 1),
+ SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReq([Root], SCP),
+ CMD = cre_command(SCR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+ssmp2_mg_notify_reply_ar(Cid, Tid) ->
+ NR = cre_notifyReply([Tid]),
+ CR = cre_cmdReply(NR),
+ cre_actionReply(Cid, [CR]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+send_segmented_msg_plain3(suite) ->
+ [];
+send_segmented_msg_plain3(doc) ->
+ "Third plain test that it is possible to send segmented messages. "
+ "Send window = 1. ";
+send_segmented_msg_plain3(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, ssmp3),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ d("[MGC] start the simulator "),
+ {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode),
+
+ d("[MGC] create the event sequence"),
+ MgcEvSeq = ssmp3_mgc_event_sequence(text, tcp),
+
+ i("wait some time before starting the MGC simulation"),
+ sleep(1000),
+
+ d("[MGC] start the simulation"),
+ {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq),
+
+ i("wait some time before starting the MG simulator"),
+ sleep(1000),
+
+ d("[MG] start the simulator (generator)"),
+ {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode),
+
+ d("[MG] create the event sequence"),
+ MgEvSeq = ssmp3_mg_event_sequence(text, tcp),
+
+ i("wait some time before starting the MG simulation"),
+ sleep(1000),
+
+ d("[MG] start the simulation"),
+ {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq),
+
+ d("await the generator reply(s)"),
+ await_completion([MgcId, MgId]),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop generator"),
+ megaco_test_tcp_generator:stop(Mgc),
+
+ %% Tell Mg to stop
+ i("[MG] stop generator"),
+ megaco_test_megaco_generator:stop(Mg),
+
+ i("done", []),
+ ok.
+
+
+
+%%
+%% MGC generator stuff
+%%
+
+ssmp3_mgc_event_sequence(text, tcp) ->
+ DecodeFun = ssmp3_mgc_decode_msg_fun(megaco_pretty_text_encoder, []),
+ EncodeFun = ssmp3_mgc_encode_msg_fun(megaco_pretty_text_encoder, []),
+ Mid = {deviceName,"mgc"},
+ ScrVerifyFun = ssmp3_mgc_verify_service_change_req_msg_fun(),
+ ServiceChangeRep = ssmp3_mgc_service_change_reply_msg(Mid, 1),
+ TermId1 =
+ #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ CtxId1 = 1,
+ TermId2 =
+ #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ CtxId2 = 2,
+ TermId3 =
+ #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ CtxId3 = 3,
+ TermId4 =
+ #megaco_term_id{id = ["00000000","00000000","00000004"]},
+ CtxId4 = 4,
+ TermId5 =
+ #megaco_term_id{id = ["00000000","00000000","00000005"]},
+ CtxId5 = 5,
+ TermId6 =
+ #megaco_term_id{id = ["00000000","00000000","00000006"]},
+ CtxId6 = 6,
+ TermId7 =
+ #megaco_term_id{id = ["00000000","00000000","00000007"]},
+ CtxId7 = 7,
+ TermId8 =
+ #megaco_term_id{id = ["00000000","00000000","00000008"]},
+ CtxId8 = 8,
+ TransId = 2,
+ TermIDs = [TermId1, TermId2, TermId3, TermId4,
+ TermId5, TermId6, TermId7, TermId8],
+ CIDs = [CtxId1, CtxId2, CtxId3, CtxId4,
+ CtxId5, CtxId6, CtxId7, CtxId8],
+ NotifyReq = ssmp3_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs),
+ NrVerifyFun1 =
+ ssmp3_mgc_verify_notify_reply_segment_msg_fun(1, false, TransId,
+ TermId1, CtxId1),
+ NrVerifyFun2 =
+ ssmp3_mgc_verify_notify_reply_segment_msg_fun(2, false, TransId,
+ TermId2, CtxId2),
+ NrVerifyFun3 =
+ ssmp3_mgc_verify_notify_reply_segment_msg_fun(3, false, TransId,
+ TermId3, CtxId3),
+ NrVerifyFun4 =
+ ssmp3_mgc_verify_notify_reply_segment_msg_fun(4, false, TransId,
+ TermId4, CtxId4),
+ NrVerifyFun5 =
+ ssmp3_mgc_verify_notify_reply_segment_msg_fun(5, false, TransId,
+ TermId5, CtxId5),
+ NrVerifyFun6 =
+ ssmp3_mgc_verify_notify_reply_segment_msg_fun(6, false, TransId,
+ TermId6, CtxId6),
+ NrVerifyFun7 =
+ ssmp3_mgc_verify_notify_reply_segment_msg_fun(7, false, TransId,
+ TermId7, CtxId7),
+ NrVerifyFun8 =
+ ssmp3_mgc_verify_notify_reply_segment_msg_fun(8, true, TransId,
+ TermId8, CtxId8),
+ SegmentRep1 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 1, false),
+ SegmentRep2 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 2, false),
+ SegmentRep3 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 3, false),
+ SegmentRep4 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 4, false),
+ SegmentRep5 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 5, false),
+ SegmentRep6 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 6, false),
+ SegmentRep7 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 7, false),
+ SegmentRep8 = ssmp3_mgc_segment_reply_msg(Mid, TransId, 8, true),
+ TransAck = ssmp3_mgc_trans_ack_msg(Mid, TransId),
+ EvSeq = [{debug, true},
+ {decode, DecodeFun},
+ {encode, EncodeFun},
+ {listen, 2944},
+ {expect_accept, any},
+ {expect_receive, "service-change-request", {ScrVerifyFun, 5000}},
+ {send, "service-change-reply", ServiceChangeRep},
+ {expect_nothing, 1000},
+ {send, "notify request", NotifyReq},
+ {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 1000}},
+ {expect_nothing, 200},
+ {send, "segment reply 1", SegmentRep1},
+
+ {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}},
+ {expect_nothing, 200},
+ {send, "segment reply 2", SegmentRep2},
+
+ {expect_receive, "notify reply: segment 3", {NrVerifyFun3, 1000}},
+ {expect_nothing, 200},
+ {send, "segment reply 3", SegmentRep3},
+
+ {expect_receive, "notify reply: segment 4", {NrVerifyFun4, 1000}},
+ {expect_nothing, 200},
+ {send, "segment reply 4", SegmentRep4},
+
+ {expect_receive, "notify reply: segment 5", {NrVerifyFun5, 1000}},
+ {expect_nothing, 200},
+ {send, "segment reply 5", SegmentRep5},
+
+ {expect_receive, "notify reply: segment 6", {NrVerifyFun6, 1000}},
+ {expect_nothing, 200},
+ {send, "segment reply 6", SegmentRep6},
+
+ {expect_receive, "notify reply: segment 7", {NrVerifyFun7, 1000}},
+ {expect_nothing, 200},
+ {send, "segment reply 7", SegmentRep7},
+
+ {expect_receive, "notify reply: segment 8", {NrVerifyFun8, 1000}},
+ {expect_nothing, 200},
+ {send, "segment reply 8", SegmentRep8},
+
+ {expect_nothing, 200},
+ {send, "transaction-ack", TransAck},
+ {expect_closed, 5000},
+ disconnect
+ ],
+ EvSeq.
+
+ssmp3_mgc_encode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:encode_message(Conf, M)
+ end.
+
+ssmp3_mgc_decode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:decode_message(Conf, M)
+ end.
+
+ssmp3_mgc_verify_service_change_req_msg_fun() ->
+ fun(Msg) ->
+ (catch ssmp3_mgc_verify_service_change_req(Msg))
+ end.
+
+ssmp3_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) ->
+ io:format("ssmp3_mgc_verify_service_change_req -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ Body =
+ case Mess of
+ #'Message'{version = 1,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = _TransId,
+ actions = [ActionReq]} ->
+ ActionReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ CR =
+ case AR of
+ #'ActionRequest'{contextId = _Cid,
+ commandRequests = [CmdReq]} ->
+ CmdReq;
+ _ ->
+ throw({error, {invalid_action, AR}})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}})
+ end,
+ {Tid, Parms} =
+ case Cmd of
+ {serviceChangeReq,
+ #'ServiceChangeRequest'{terminationID = [TermID],
+ serviceChangeParms = ServChParms}} ->
+ {TermID, ServChParms};
+ _ ->
+ throw({error, {invalid_command, Cmd}})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ throw({error, {invalid_terminationID, Tid}})
+ end,
+ case Parms of
+ %% Version 1 'ServiceChangeParm'
+ {'ServiceChangeParm',
+ restart, % serviceChangeMethod
+ asn1_NOVALUE, % serviceChangeAddress
+ ?VERSION, % serviceChangeVersion,
+ {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile
+ [[$9,$0,$1|_]], % serviceChangeReason
+ asn1_NOVALUE, % serviceChangeDelay
+ asn1_NOVALUE, % serviceChangeMgcId
+ asn1_NOVALUE, % timeStamp
+ asn1_NOVALUE % nonStandardData
+ } ->
+ {ok, M};
+ _ ->
+ {error, {invalid_serviceChangeParms, Parms}}
+ end.
+
+ssmp3_mgc_verify_notify_reply_segment_msg_fun(SN, Last,
+ TransId, TermId, Cid) ->
+ fun(Msg) ->
+ (catch ssmp3_mgc_verify_notify_reply_segment(Msg,
+ SN, Last,
+ TransId, TermId, Cid))
+ end.
+
+ssmp3_mgc_verify_notify_reply_segment(#'MegacoMessage'{mess = Mess} = M,
+ SN, Last, TransId, TermId, Cid) ->
+ io:format("ssmp3_mgc_verify_notify_reply_segment -> entry with"
+ "~n M: ~p"
+ "~n SN: ~p"
+ "~n Last: ~p"
+ "~n TransId: ~p"
+ "~n TermId: ~p"
+ "~n Cid: ~p"
+ "~n", [M, SN, Last, TransId, TermId, Cid]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionReply, TransReply} ->
+ TransReply;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ TRes =
+ case TR of
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = TransRes,
+ segmentNumber = SN,
+ segmentationComplete = asn1_NOVALUE} when (Last == false) ->
+ TransRes;
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = TransRes,
+ segmentNumber = SN,
+ segmentationComplete = 'NULL'} when (Last == true) ->
+ TransRes;
+ _ ->
+ throw({error, {invalid_transactionReply, TR}})
+ end,
+ AR =
+ case TRes of
+ {actionReplies, [ActionReply]} ->
+ ActionReply;
+ {actionReplies, ActionReplies} ->
+ throw({error, {invalid_actionReplies, ActionReplies}});
+ _ ->
+ throw({error, {invalid_transactionResult, TRes}})
+ end,
+ CR =
+ case AR of
+ #'ActionReply'{contextId = Cid,
+ commandReply = [CommandReply]} ->
+ CommandReply;
+ #'ActionReply'{contextId = Cid,
+ commandReply = CommandReplies} ->
+ throw({error, {invalid_commandReplies, CommandReplies}});
+ _ ->
+ throw({error, {invalid_actionReply, AR}})
+ end,
+ NR =
+ case CR of
+ {notifyReply, NotifyReply} ->
+ NotifyReply;
+ _ ->
+ throw({error, {invalid_commandReply, CR}})
+ end,
+ case NR of
+ #'NotifyReply'{terminationID = [TermId],
+ errorDescriptor = asn1_NOVALUE} ->
+ {ok, M};
+ _ ->
+ {error, {invalid_NotifyReply, NR}}
+ end;
+ssmp3_mgc_verify_notify_reply_segment(Crap,
+ _SN, _Last, _TransId, _TermId, _Cid) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+
+ssmp3_mgc_service_change_reply_msg(Mid, Cid) ->
+ SCRP = cre_serviceChangeResParm(Mid),
+ SCRes = cre_serviceChangeResult(SCRP),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReply([Root], SCRes),
+ CR = cre_cmdReply(SCR),
+ AR = cre_actionReply(Cid, [CR]),
+ TRes = cre_transResult([AR]),
+ TR = {'TransactionReply', 1, asn1_NOVALUE, TRes},
+ Trans = cre_transaction(TR),
+ Mess = cre_message(1, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmp3_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs) ->
+ ARs = ssmp3_mgc_notify_request_ars(TermIDs, CIDs),
+ TR = cre_transReq(TransId, ARs),
+ Trans = cre_transaction(TR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmp3_mgc_notify_request_ars(TermIDs, CIDs) ->
+ ssmp3_mgc_notify_request_ars(TermIDs, CIDs, []).
+
+ssmp3_mgc_notify_request_ars([], [], Acc) ->
+ lists:reverse(Acc);
+ssmp3_mgc_notify_request_ars([TermID|TermIDs], [CID|CIDs], Acc) ->
+ AR = ssmp3_mgc_notify_request_ar(100+CID, TermID, CID),
+ ssmp3_mgc_notify_request_ars(TermIDs, CIDs, [AR|Acc]).
+
+ssmp3_mgc_notify_request_ar(Rid, Tid, Cid) ->
+ TT = cre_timeNotation(integer_to_list(19990720+Rid),
+ integer_to_list(22000000+Rid)),
+ Ev = cre_obsEvent("al/of", TT),
+ EvsDesc = cre_obsEvsDesc(Rid, [Ev]),
+ NR = cre_notifyReq([Tid], EvsDesc),
+ CMD = cre_command(NR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+ssmp3_mgc_segment_reply_msg(Mid, TransId, SN, Last) ->
+ SR = ssmp3_mgc_segment_reply(TransId, SN, Last),
+ Trans = cre_transaction(SR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmp3_mgc_segment_reply(TransId, SN, true) ->
+ cre_segReply(TransId, SN, 'NULL');
+ssmp3_mgc_segment_reply(TransId, SN, false) ->
+ cre_segReply(TransId, SN, asn1_NOVALUE).
+
+ssmp3_mgc_trans_ack_msg(Mid, TransId) ->
+ TA = cre_transAck(TransId),
+ Trans = cre_transaction([TA]),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+
+%%
+%% MG generator stuff
+%%
+ssmp3_mg_event_sequence(text, tcp) ->
+ Mid = {deviceName,"mg"},
+ RI = [
+ {port, 2944},
+ {encoding_module, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {transport_module, megaco_tcp}
+ ],
+ ConnectVerify = ssmp3_mg_verify_handle_connect_fun(),
+ ServiceChangeReq = ssmp3_mg_service_change_request_ar(Mid, 1),
+ ServiceChangeReplyVerify = ssmp3_mg_verify_service_change_reply_fun(),
+ Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ Tid4 = #megaco_term_id{id = ["00000000","00000000","00000004"]},
+ Tid5 = #megaco_term_id{id = ["00000000","00000000","00000005"]},
+ Tid6 = #megaco_term_id{id = ["00000000","00000000","00000006"]},
+ Tid7 = #megaco_term_id{id = ["00000000","00000000","00000007"]},
+ Tid8 = #megaco_term_id{id = ["00000000","00000000","00000008"]},
+ Tids = [Tid1, Tid2, Tid3, Tid4, Tid5, Tid6, Tid7, Tid8],
+ NotifyReqVerify = ssmp3_mg_verify_notify_request_fun(Tids),
+ AckVerify = ssmp3_mg_verify_ack_fun(),
+ EvSeq = [
+ {debug, true},
+ {megaco_trace, disable},
+ %% {megaco_trace, max},
+ megaco_start,
+ {megaco_start_user, Mid, RI, []},
+ start_transport,
+ {megaco_system_info, users},
+ {megaco_system_info, connections},
+ connect,
+ {megaco_callback, handle_connect, ConnectVerify},
+ megaco_connect,
+ {megaco_cast, [ServiceChangeReq], []},
+ {megaco_callback, handle_connect, ConnectVerify},
+ {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify},
+ {megaco_update_conn_info, protocol_version, ?VERSION},
+ {megaco_update_conn_info, segment_send, 1},
+ {megaco_update_conn_info, max_pdu_size, 128},
+ {sleep, 500},
+ {megaco_callback, handle_trans_request, NotifyReqVerify},
+ {megaco_callback, handle_trans_ack, AckVerify, 5000},
+ megaco_stop_user,
+ megaco_stop,
+ {sleep, 1000}
+ ],
+ EvSeq.
+
+
+ssmp3_mg_verify_handle_connect_fun() ->
+ fun(Ev) -> ssmp3_mg_verify_handle_connect(Ev) end.
+
+ssmp3_mg_verify_handle_connect({handle_connect, CH, 1}) ->
+ io:format("ssmp3_mg_verify_handle_connect -> ok"
+ "~n CH: ~p~n", [CH]),
+ {ok, CH, ok};
+ssmp3_mg_verify_handle_connect(Else) ->
+ io:format("ssmp3_mg_verify_handle_connect -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, ok}.
+
+
+ssmp3_mg_verify_service_change_reply_fun() ->
+ fun(Rep) -> ssmp3_mg_verify_scr(Rep) end.
+
+ssmp3_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) ->
+ (catch ssmp3_mg_do_verify_scr(AR));
+ssmp3_mg_verify_scr(Crap) ->
+ io:format("ssmp3_mg_verify_scr -> error: "
+ "~n Crap: ~p"
+ "~n", [Crap]),
+ {error, Crap, ok}.
+
+ssmp3_mg_do_verify_scr(AR) ->
+ io:format("ssmp3_mg_do_verify_scr -> ok: "
+ "~n AR: ~p~n", [AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ SCR =
+ case CR of
+ {serviceChangeReply, ServChRep} ->
+ ServChRep;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ {Tid, SCRes} =
+ case SCR of
+ #'ServiceChangeReply'{terminationID = [TermID],
+ serviceChangeResult = Res} ->
+ {TermID, Res};
+ _ ->
+ Reason3 = {invalid_service_change_reply, SCR},
+ throw({error, Reason3, ok})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ Reason4 = {invalid_termination_id, Tid},
+ throw({error, Reason4, ok})
+ end,
+ SCRParm =
+ case SCRes of
+ {serviceChangeResParms, ServChResParms} ->
+ ServChResParms;
+ _ ->
+ Reason5 = {invalid_serviceChangeResult, SCRes},
+ throw({error, Reason5, ok})
+ end,
+ case SCRParm of
+ #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} ->
+ {ok, AR, ok};
+ _ ->
+ Reason6 = {invalid_service_change_result, SCRParm},
+ {error, Reason6, ok}
+ end.
+
+ssmp3_mg_verify_notify_request_fun(Tids) ->
+ fun(Req) -> ssmp3_mg_verify_notify_request(Req, Tids) end.
+
+ssmp3_mg_verify_notify_request(
+ {handle_trans_request, _CH, ?VERSION, ARs}, Tids)
+ when length(ARs) == length(Tids) ->
+ (catch ssmp3_mg_do_verify_notify_request(Tids, ARs));
+ssmp3_mg_verify_notify_request(
+ {handle_trans_request, _CH, ?VERSION, ARs}, _Tids) ->
+ {error, {invalid_action_requests, ARs}, ok};
+ssmp3_mg_verify_notify_request(
+ {handle_trans_request, CH, V, ARs}, _Tids) ->
+ {error, {invalid_trans_request, {CH, V, ARs}}, ok};
+ssmp3_mg_verify_notify_request(Crap, _Tids) ->
+ io:format("ssmp3_mg_verify_notify_request -> unknown request"
+ "~n Crap: ~p"
+ "~n Tids: ~p"
+ "~n", [Crap, _Tids]),
+ {error, {unexpected_event, Crap}, ok}.
+
+ssmp3_mg_do_verify_notify_request(Tids, ARs) ->
+ io:format("ssmp3_mg_do_verify_notify_request -> ok"
+ "~n Tids: ~p"
+ "~n ARs: ~p"
+ "~n", [Tids, ARs]),
+ ActionReplies = ssmp3_mg_do_verify_notify_request_ars(Tids, ARs),
+ io:format("ssmp3_mg_do_verify_notify_request -> ok"
+ "~n ActionReplies: ~p"
+ "~n", [ActionReplies]),
+ Reply = {{handle_ack, ssmp3}, ActionReplies},
+ {ok, ARs, Reply}.
+
+ssmp3_mg_do_verify_notify_request_ars(Tids, ARs) ->
+ ssmp3_mg_do_verify_notify_request_ars(Tids, ARs, []).
+
+ssmp3_mg_do_verify_notify_request_ars([], [], Acc) ->
+ lists:reverse(Acc);
+ssmp3_mg_do_verify_notify_request_ars([Tid|Tids], [AR|ARs], Acc) ->
+ ActionReply = ssmp3_mg_do_verify_notify_request_ar(Tid, AR),
+ ssmp3_mg_do_verify_notify_request_ars(Tids, ARs, [ActionReply|Acc]).
+
+ssmp3_mg_do_verify_notify_request_ar(Tid, AR) ->
+ io:format("ssmp3_mg_do_verify_notify_request_ar -> ok"
+ "~n Tid: ~p"
+ "~n AR: ~p"
+ "~n", [Tid, AR]),
+ {Cid, CR} =
+ case AR of
+ #'ActionRequest'{contextId = CtxId,
+ commandRequests = [CmdReq]} ->
+ {CtxId, CmdReq};
+ _ ->
+ Reason1 = {invalid_actionRequest, AR},
+ throw({error, Reason1, ok})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}, ok})
+ end,
+ OED =
+ case Cmd of
+ {notifyReq,
+ #'NotifyRequest'{terminationID = [Tid],
+ observedEventsDescriptor = ObsEvDesc,
+ errorDescriptor = asn1_NOVALUE}} ->
+ ObsEvDesc;
+ _ ->
+ throw({error, {invalid_command, Cmd}, ok})
+ end,
+ OE =
+ case OED of
+ #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} ->
+ ObsEv;
+ #'ObservedEventsDescriptor'{observedEventLst = ObsEvLst} ->
+ throw({error, {invalid_observedEventLst, ObsEvLst}, ok});
+ _ ->
+ throw({error, {invalid_ObservedEventsDescriptor, OED}, ok})
+ end,
+ case OE of
+ #'ObservedEvent'{eventName = "al/of"} ->
+ ssmp3_mg_notify_reply_ar(Cid, Tid);
+ _ ->
+ throw({error, {invalid_ObservedEvent, OE}, ok})
+ end.
+
+
+ssmp3_mg_verify_ack_fun() ->
+ fun(Event) -> ssmp3_mg_verify_ack(Event) end.
+
+ssmp3_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, ssmp3}) ->
+ io:format("ssmp3_mg_verify_ack -> ok"
+ "~n CH: ~p"
+ "~n", [CH]),
+ {ok, CH, ok};
+ssmp3_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, CrapAckData}) ->
+ {error, {unknown_ack_data, CrapAckData, CH}, ok};
+ssmp3_mg_verify_ack({handle_trans_ack, CH, ?VERSION,
+ BadAckStatus, BadAckData}) ->
+ {error, {unknown_ack_status, BadAckStatus, BadAckData, CH}, ok};
+ssmp3_mg_verify_ack(BadEvent) ->
+ {error, {unknown_event, BadEvent}, ok}.
+
+
+ssmp3_mg_service_change_request_ar(_Mid, Cid) ->
+ Prof = cre_serviceChangeProf("resgw", 1),
+ SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReq([Root], SCP),
+ CMD = cre_command(SCR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+ssmp3_mg_notify_reply_ar(Cid, Tid) ->
+ NR = cre_notifyReply([Tid]),
+ CR = cre_cmdReply(NR),
+ cre_actionReply(Cid, [CR]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+send_segmented_msg_plain4(suite) ->
+ [];
+send_segmented_msg_plain4(doc) ->
+ "Forth plain test that it is possible to send segmented messages. "
+ "Send window = 3. ";
+send_segmented_msg_plain4(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, ssmp4),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ d("[MGC] start the simulator "),
+ {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode),
+
+ d("[MGC] create the event sequence"),
+ MgcEvSeq = ssmp4_mgc_event_sequence(text, tcp),
+
+ i("wait some time before starting the MGC simulation"),
+ sleep(1000),
+
+ d("[MGC] start the simulation"),
+ {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq),
+
+ i("wait some time before starting the MG simulator"),
+ sleep(1000),
+
+ d("[MG] start the simulator (generator)"),
+ {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode),
+
+ d("[MG] create the event sequence"),
+ MgEvSeq = ssmp4_mg_event_sequence(text, tcp),
+
+ i("wait some time before starting the MG simulation"),
+ sleep(1000),
+
+ d("[MG] start the simulation"),
+ {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq),
+
+ d("await the generator reply(s)"),
+ await_completion([MgcId, MgId]),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop generator"),
+ megaco_test_tcp_generator:stop(Mgc),
+
+ %% Tell Mg to stop
+ i("[MG] stop generator"),
+ megaco_test_megaco_generator:stop(Mg),
+
+ i("done", []),
+ ok.
+
+
+
+%%
+%% MGC generator stuff
+%%
+
+ssmp4_mgc_event_sequence(text, tcp) ->
+ DecodeFun = ssmp4_mgc_decode_msg_fun(megaco_pretty_text_encoder, []),
+ EncodeFun = ssmp4_mgc_encode_msg_fun(megaco_pretty_text_encoder, []),
+ Mid = {deviceName,"mgc"},
+ ScrVerifyFun = ssmp4_mgc_verify_service_change_req_msg_fun(),
+ ServiceChangeRep = ssmp4_mgc_service_change_reply_msg(Mid, 1),
+ TermId1 =
+ #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ CtxId1 = 1,
+ TermId2 =
+ #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ CtxId2 = 2,
+ TermId3 =
+ #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ CtxId3 = 3,
+ TermId4 =
+ #megaco_term_id{id = ["00000000","00000000","00000004"]},
+ CtxId4 = 4,
+ TermId5 =
+ #megaco_term_id{id = ["00000000","00000000","00000005"]},
+ CtxId5 = 5,
+ TermId6 =
+ #megaco_term_id{id = ["00000000","00000000","00000006"]},
+ CtxId6 = 6,
+ TermId7 =
+ #megaco_term_id{id = ["00000000","00000000","00000007"]},
+ CtxId7 = 7,
+ TermId8 =
+ #megaco_term_id{id = ["00000000","00000000","00000008"]},
+ CtxId8 = 8,
+ TransId = 2,
+ TermIDs = [TermId1, TermId2, TermId3, TermId4,
+ TermId5, TermId6, TermId7, TermId8],
+ CIDs = [CtxId1, CtxId2, CtxId3, CtxId4,
+ CtxId5, CtxId6, CtxId7, CtxId8],
+ NotifyReq = ssmp4_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs),
+ NrVerifyFun1 =
+ ssmp4_mgc_verify_notify_reply_segment_msg_fun(1, false, TransId,
+ TermId1, CtxId1),
+ NrVerifyFun2 =
+ ssmp4_mgc_verify_notify_reply_segment_msg_fun(2, false, TransId,
+ TermId2, CtxId2),
+ NrVerifyFun3 =
+ ssmp4_mgc_verify_notify_reply_segment_msg_fun(3, false, TransId,
+ TermId3, CtxId3),
+ NrVerifyFun4 =
+ ssmp4_mgc_verify_notify_reply_segment_msg_fun(4, false, TransId,
+ TermId4, CtxId4),
+ NrVerifyFun5 =
+ ssmp4_mgc_verify_notify_reply_segment_msg_fun(5, false, TransId,
+ TermId5, CtxId5),
+ NrVerifyFun6 =
+ ssmp4_mgc_verify_notify_reply_segment_msg_fun(6, false, TransId,
+ TermId6, CtxId6),
+ NrVerifyFun7 =
+ ssmp4_mgc_verify_notify_reply_segment_msg_fun(7, false, TransId,
+ TermId7, CtxId7),
+ NrVerifyFun8 =
+ ssmp4_mgc_verify_notify_reply_segment_msg_fun(8, true, TransId,
+ TermId8, CtxId8),
+ SegmentRep1 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 1, false),
+ SegmentRep2 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 2, false),
+ SegmentRep3 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 3, false),
+ SegmentRep4 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 4, false),
+ SegmentRep5 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 5, false),
+ SegmentRep6 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 6, false),
+ SegmentRep7 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 7, false),
+ SegmentRep8 = ssmp4_mgc_segment_reply_msg(Mid, TransId, 8, true),
+ TransAck = ssmp4_mgc_trans_ack_msg(Mid, TransId),
+ EvSeq = [{debug, true},
+ {decode, DecodeFun},
+ {encode, EncodeFun},
+ {listen, 2944},
+ {expect_accept, any},
+ {expect_receive, "service-change-request", {ScrVerifyFun, 5000}},
+ {send, "service-change-reply", ServiceChangeRep},
+ {expect_nothing, 1000},
+ {send, "notify request", NotifyReq},
+ {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 1000}},
+ {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}},
+ {expect_receive, "notify reply: segment 3", {NrVerifyFun3, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 1", SegmentRep1},
+ {expect_receive, "notify reply: segment 4", {NrVerifyFun4, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 2", SegmentRep2},
+ {expect_receive, "notify reply: segment 5", {NrVerifyFun5, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 3", SegmentRep3},
+ {expect_receive, "notify reply: segment 6", {NrVerifyFun6, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 4", SegmentRep4},
+ {expect_receive, "notify reply: segment 7", {NrVerifyFun7, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 5", SegmentRep5},
+ {expect_receive, "notify reply: segment 8", {NrVerifyFun8, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 6", SegmentRep6},
+ {expect_nothing, 1000},
+ {send, "segment reply 7", SegmentRep7},
+ {expect_nothing, 1000},
+ {send, "segment reply 8", SegmentRep8},
+ {expect_nothing, 1000},
+ {send, "transaction-ack", TransAck},
+ {expect_closed, 5000},
+ disconnect
+ ],
+ EvSeq.
+
+ssmp4_mgc_encode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:encode_message(Conf, M)
+ end.
+
+ssmp4_mgc_decode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:decode_message(Conf, M)
+ end.
+
+ssmp4_mgc_verify_service_change_req_msg_fun() ->
+ fun(Msg) ->
+ (catch ssmp4_mgc_verify_service_change_req(Msg))
+ end.
+
+ssmp4_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) ->
+ io:format("ssmp4_mgc_verify_service_change_req -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ Body =
+ case Mess of
+ #'Message'{version = 1,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = _TransId,
+ actions = [ActionReq]} ->
+ ActionReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ CR =
+ case AR of
+ #'ActionRequest'{contextId = _Cid,
+ commandRequests = [CmdReq]} ->
+ CmdReq;
+ _ ->
+ throw({error, {invalid_action, AR}})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}})
+ end,
+ {Tid, Parms} =
+ case Cmd of
+ {serviceChangeReq,
+ #'ServiceChangeRequest'{terminationID = [TermID],
+ serviceChangeParms = ServChParms}} ->
+ {TermID, ServChParms};
+ _ ->
+ throw({error, {invalid_command, Cmd}})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ throw({error, {invalid_terminationID, Tid}})
+ end,
+ case Parms of
+ %% Version 1 'ServiceChangeParm'
+ {'ServiceChangeParm',
+ restart, % serviceChangeMethod
+ asn1_NOVALUE, % serviceChangeAddress
+ ?VERSION, % serviceChangeVersion,
+ {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile
+ [[$9,$0,$1|_]], % serviceChangeReason
+ asn1_NOVALUE, % serviceChangeDelay
+ asn1_NOVALUE, % serviceChangeMgcId
+ asn1_NOVALUE, % timeStamp
+ asn1_NOVALUE % nonStandardData
+ } ->
+ {ok, M};
+ _ ->
+ {error, {invalid_serviceChangeParms, Parms}}
+ end.
+
+ssmp4_mgc_verify_notify_reply_segment_msg_fun(SN, Last,
+ TransId, TermId, Cid) ->
+ fun(Msg) ->
+ (catch ssmp4_mgc_verify_notify_reply_segment(Msg,
+ SN, Last,
+ TransId, TermId, Cid))
+ end.
+
+ssmp4_mgc_verify_notify_reply_segment(#'MegacoMessage'{mess = Mess} = M,
+ SN, Last, TransId, TermId, Cid) ->
+ io:format("ssmp4_mgc_verify_notify_reply_segment -> entry with"
+ "~n M: ~p"
+ "~n SN: ~p"
+ "~n Last: ~p"
+ "~n TransId: ~p"
+ "~n TermId: ~p"
+ "~n Cid: ~p"
+ "~n", [M, SN, Last, TransId, TermId, Cid]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionReply, TransReply} ->
+ TransReply;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ TRes =
+ case TR of
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = TransRes,
+ segmentNumber = SN,
+ segmentationComplete = asn1_NOVALUE} when (Last == false) ->
+ TransRes;
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = TransRes,
+ segmentNumber = SN,
+ segmentationComplete = 'NULL'} when (Last == true) ->
+ TransRes;
+ _ ->
+ throw({error, {invalid_transactionReply, TR}})
+ end,
+ AR =
+ case TRes of
+ {actionReplies, [ActionReply]} ->
+ ActionReply;
+ {actionReplies, ActionReplies} ->
+ throw({error, {invalid_actionReplies, ActionReplies}});
+ _ ->
+ throw({error, {invalid_transactionResult, TRes}})
+ end,
+ CR =
+ case AR of
+ #'ActionReply'{contextId = Cid,
+ commandReply = [CommandReply]} ->
+ CommandReply;
+ #'ActionReply'{contextId = Cid,
+ commandReply = CommandReplies} ->
+ throw({error, {invalid_commandReplies, CommandReplies}});
+ _ ->
+ throw({error, {invalid_actionReply, AR}})
+ end,
+ NR =
+ case CR of
+ {notifyReply, NotifyReply} ->
+ NotifyReply;
+ _ ->
+ throw({error, {invalid_commandReply, CR}})
+ end,
+ case NR of
+ #'NotifyReply'{terminationID = [TermId],
+ errorDescriptor = asn1_NOVALUE} ->
+ {ok, M};
+ _ ->
+ {error, {invalid_NotifyReply, NR}}
+ end;
+ssmp4_mgc_verify_notify_reply_segment(Crap,
+ _SN, _Last, _TransId, _TermId, _Cid) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+
+ssmp4_mgc_service_change_reply_msg(Mid, Cid) ->
+ SCRP = cre_serviceChangeResParm(Mid),
+ SCRes = cre_serviceChangeResult(SCRP),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReply([Root], SCRes),
+ CR = cre_cmdReply(SCR),
+ AR = cre_actionReply(Cid, [CR]),
+ TRes = cre_transResult([AR]),
+ TR = {'TransactionReply', 1, asn1_NOVALUE, TRes},
+ Trans = cre_transaction(TR),
+ Mess = cre_message(1, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmp4_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs) ->
+ ARs = ssmp4_mgc_notify_request_ars(TermIDs, CIDs),
+ TR = cre_transReq(TransId, ARs),
+ Trans = cre_transaction(TR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmp4_mgc_notify_request_ars(TermIDs, CIDs) ->
+ ssmp4_mgc_notify_request_ars(TermIDs, CIDs, []).
+
+ssmp4_mgc_notify_request_ars([], [], Acc) ->
+ lists:reverse(Acc);
+ssmp4_mgc_notify_request_ars([TermID|TermIDs], [CID|CIDs], Acc) ->
+ AR = ssmp4_mgc_notify_request_ar(100+CID, TermID, CID),
+ ssmp4_mgc_notify_request_ars(TermIDs, CIDs, [AR|Acc]).
+
+ssmp4_mgc_notify_request_ar(Rid, Tid, Cid) ->
+ TT = cre_timeNotation(integer_to_list(19990720+Rid),
+ integer_to_list(22000000+Rid)),
+ Ev = cre_obsEvent("al/of", TT),
+ EvsDesc = cre_obsEvsDesc(Rid, [Ev]),
+ NR = cre_notifyReq([Tid], EvsDesc),
+ CMD = cre_command(NR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+ssmp4_mgc_segment_reply_msg(Mid, TransId, SN, Last) ->
+ SR = ssmp4_mgc_segment_reply(TransId, SN, Last),
+ Trans = cre_transaction(SR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmp4_mgc_segment_reply(TransId, SN, true) ->
+ cre_segReply(TransId, SN, 'NULL');
+ssmp4_mgc_segment_reply(TransId, SN, false) ->
+ cre_segReply(TransId, SN, asn1_NOVALUE).
+
+ssmp4_mgc_trans_ack_msg(Mid, TransId) ->
+ TA = cre_transAck(TransId),
+ Trans = cre_transaction([TA]),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+
+%%
+%% MG generator stuff
+%%
+ssmp4_mg_event_sequence(text, tcp) ->
+ Mid = {deviceName,"mg"},
+ RI = [
+ {port, 2944},
+ {encoding_module, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {transport_module, megaco_tcp}
+ ],
+ ConnectVerify = ssmp4_mg_verify_handle_connect_fun(),
+ ServiceChangeReq = ssmp4_mg_service_change_request_ar(Mid, 1),
+ ServiceChangeReplyVerify = ssmp4_mg_verify_service_change_reply_fun(),
+ Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ Tid4 = #megaco_term_id{id = ["00000000","00000000","00000004"]},
+ Tid5 = #megaco_term_id{id = ["00000000","00000000","00000005"]},
+ Tid6 = #megaco_term_id{id = ["00000000","00000000","00000006"]},
+ Tid7 = #megaco_term_id{id = ["00000000","00000000","00000007"]},
+ Tid8 = #megaco_term_id{id = ["00000000","00000000","00000008"]},
+ Tids = [Tid1, Tid2, Tid3, Tid4, Tid5, Tid6, Tid7, Tid8],
+ NotifyReqVerify = ssmp4_mg_verify_notify_request_fun(Tids),
+ AckVerify = ssmp4_mg_verify_ack_fun(),
+ EvSeq = [
+ {debug, true},
+ {megaco_trace, disable},
+ %% {megaco_trace, max},
+ megaco_start,
+ {megaco_start_user, Mid, RI, []},
+ start_transport,
+ {megaco_system_info, users},
+ {megaco_system_info, connections},
+ connect,
+ {megaco_callback, handle_connect, ConnectVerify},
+ megaco_connect,
+ {megaco_cast, [ServiceChangeReq], []},
+ {megaco_callback, handle_connect, ConnectVerify},
+ {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify},
+ {megaco_update_conn_info, protocol_version, ?VERSION},
+ {megaco_update_conn_info, segment_send, 3},
+ {megaco_update_conn_info, max_pdu_size, 128},
+ {sleep, 1000},
+ {megaco_callback, handle_trans_request, NotifyReqVerify},
+ {megaco_callback, handle_trans_ack, AckVerify, 15000},
+ megaco_stop_user,
+ megaco_stop,
+ {sleep, 1000}
+ ],
+ EvSeq.
+
+
+ssmp4_mg_verify_handle_connect_fun() ->
+ fun(Ev) -> ssmp4_mg_verify_handle_connect(Ev) end.
+
+ssmp4_mg_verify_handle_connect({handle_connect, CH, 1}) ->
+ io:format("ssmp4_mg_verify_handle_connect -> ok"
+ "~n CH: ~p~n", [CH]),
+ {ok, CH, ok};
+ssmp4_mg_verify_handle_connect(Else) ->
+ io:format("ssmp4_mg_verify_handle_connect -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, ok}.
+
+
+ssmp4_mg_verify_service_change_reply_fun() ->
+ fun(Rep) -> ssmp4_mg_verify_scr(Rep) end.
+
+ssmp4_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) ->
+ (catch ssmp4_mg_do_verify_scr(AR));
+ssmp4_mg_verify_scr(Crap) ->
+ io:format("ssmp4_mg_verify_scr -> error: "
+ "~n Crap: ~p"
+ "~n", [Crap]),
+ {error, Crap, ok}.
+
+ssmp4_mg_do_verify_scr(AR) ->
+ io:format("ssmp4_mg_do_verify_scr -> ok: "
+ "~n AR: ~p~n", [AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ SCR =
+ case CR of
+ {serviceChangeReply, ServChRep} ->
+ ServChRep;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ {Tid, SCRes} =
+ case SCR of
+ #'ServiceChangeReply'{terminationID = [TermID],
+ serviceChangeResult = Res} ->
+ {TermID, Res};
+ _ ->
+ Reason3 = {invalid_service_change_reply, SCR},
+ throw({error, Reason3, ok})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ Reason4 = {invalid_termination_id, Tid},
+ throw({error, Reason4, ok})
+ end,
+ SCRParm =
+ case SCRes of
+ {serviceChangeResParms, ServChResParms} ->
+ ServChResParms;
+ _ ->
+ Reason5 = {invalid_serviceChangeResult, SCRes},
+ throw({error, Reason5, ok})
+ end,
+ case SCRParm of
+ #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} ->
+ {ok, AR, ok};
+ _ ->
+ Reason6 = {invalid_service_change_result, SCRParm},
+ {error, Reason6, ok}
+ end.
+
+ssmp4_mg_verify_notify_request_fun(Tids) ->
+ fun(Req) -> ssmp4_mg_verify_notify_request(Req, Tids) end.
+
+ssmp4_mg_verify_notify_request(
+ {handle_trans_request, _CH, ?VERSION, ARs}, Tids)
+ when length(ARs) == length(Tids) ->
+ (catch ssmp4_mg_do_verify_notify_request(Tids, ARs));
+ssmp4_mg_verify_notify_request(
+ {handle_trans_request, _CH, ?VERSION, ARs}, _Tids) ->
+ {error, {invalid_action_requests, ARs}, ok};
+ssmp4_mg_verify_notify_request(
+ {handle_trans_request, CH, V, ARs}, _Tids) ->
+ {error, {invalid_trans_request, {CH, V, ARs}}, ok};
+ssmp4_mg_verify_notify_request(Crap, _Tids) ->
+ io:format("ssmp4_mg_verify_notify_request -> unknown request"
+ "~n Crap: ~p"
+ "~n Tids: ~p"
+ "~n", [Crap, _Tids]),
+ {error, {unexpected_event, Crap}, ok}.
+
+ssmp4_mg_do_verify_notify_request(Tids, ARs) ->
+ io:format("ssmp4_mg_do_verify_notify_request -> ok"
+ "~n Tids: ~p"
+ "~n ARs: ~p"
+ "~n", [Tids, ARs]),
+ ActionReplies = ssmp4_mg_do_verify_notify_request_ars(Tids, ARs),
+ io:format("ssmp4_mg_do_verify_notify_request -> ok"
+ "~n ActionReplies: ~p"
+ "~n", [ActionReplies]),
+ Reply = {{handle_ack, ssmp4}, ActionReplies},
+ {ok, ARs, Reply}.
+
+ssmp4_mg_do_verify_notify_request_ars(Tids, ARs) ->
+ ssmp4_mg_do_verify_notify_request_ars(Tids, ARs, []).
+
+ssmp4_mg_do_verify_notify_request_ars([], [], Acc) ->
+ lists:reverse(Acc);
+ssmp4_mg_do_verify_notify_request_ars([Tid|Tids], [AR|ARs], Acc) ->
+ ActionReply = ssmp4_mg_do_verify_notify_request_ar(Tid, AR),
+ ssmp4_mg_do_verify_notify_request_ars(Tids, ARs, [ActionReply|Acc]).
+
+ssmp4_mg_do_verify_notify_request_ar(Tid, AR) ->
+ io:format("ssmp4_mg_do_verify_notify_request_ar -> ok"
+ "~n Tid: ~p"
+ "~n AR: ~p"
+ "~n", [Tid, AR]),
+ {Cid, CR} =
+ case AR of
+ #'ActionRequest'{contextId = CtxId,
+ commandRequests = [CmdReq]} ->
+ {CtxId, CmdReq};
+ _ ->
+ Reason1 = {invalid_actionRequest, AR},
+ throw({error, Reason1, ok})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}, ok})
+ end,
+ OED =
+ case Cmd of
+ {notifyReq,
+ #'NotifyRequest'{terminationID = [Tid],
+ observedEventsDescriptor = ObsEvDesc,
+ errorDescriptor = asn1_NOVALUE}} ->
+ ObsEvDesc;
+ _ ->
+ throw({error, {invalid_command, Cmd}, ok})
+ end,
+ OE =
+ case OED of
+ #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} ->
+ ObsEv;
+ #'ObservedEventsDescriptor'{observedEventLst = ObsEvLst} ->
+ throw({error, {invalid_observedEventLst, ObsEvLst}, ok});
+ _ ->
+ throw({error, {invalid_ObservedEventsDescriptor, OED}, ok})
+ end,
+ case OE of
+ #'ObservedEvent'{eventName = "al/of"} ->
+ ssmp4_mg_notify_reply_ar(Cid, Tid);
+ _ ->
+ throw({error, {invalid_ObservedEvent, OE}, ok})
+ end.
+
+
+ssmp4_mg_verify_ack_fun() ->
+ fun(Event) -> ssmp4_mg_verify_ack(Event) end.
+
+ssmp4_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, ssmp4}) ->
+ io:format("ssmp4_mg_verify_ack -> ok"
+ "~n CH: ~p"
+ "~n", [CH]),
+ {ok, CH, ok};
+ssmp4_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, CrapAckData}) ->
+ {error, {unknown_ack_data, CrapAckData, CH}, ok};
+ssmp4_mg_verify_ack({handle_trans_ack, CH, ?VERSION,
+ BadAckStatus, BadAckData}) ->
+ {error, {unknown_ack_status, BadAckStatus, BadAckData, CH}, ok};
+ssmp4_mg_verify_ack(BadEvent) ->
+ {error, {unknown_event, BadEvent}, ok}.
+
+
+ssmp4_mg_service_change_request_ar(_Mid, Cid) ->
+ Prof = cre_serviceChangeProf("resgw", 1),
+ SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReq([Root], SCP),
+ CMD = cre_command(SCR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+ssmp4_mg_notify_reply_ar(Cid, Tid) ->
+ NR = cre_notifyReply([Tid]),
+ CR = cre_cmdReply(NR),
+ cre_actionReply(Cid, [CR]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+send_segmented_msg_ooo1(suite) ->
+ [];
+send_segmented_msg_ooo1(doc) ->
+ "First segment out of order test. "
+ "Tests that it is possible to send segmented messages, when the "
+ "segment reply is sent out-of-order. "
+ "Send window = 3. ";
+send_segmented_msg_ooo1(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, ssmo1),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ d("[MGC] start the simulator "),
+ {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode),
+
+ d("[MGC] create the event sequence"),
+ MgcEvSeq = ssmo1_mgc_event_sequence(text, tcp),
+
+ i("wait some time before starting the MGC simulation"),
+ sleep(1000),
+
+ d("[MGC] start the simulation"),
+ {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq),
+
+ i("wait some time before starting the MG simulator"),
+ sleep(1000),
+
+ d("[MG] start the simulator (generator)"),
+ {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode),
+
+ d("[MG] create the event sequence"),
+ MgEvSeq = ssmo1_mg_event_sequence(text, tcp),
+
+ i("wait some time before starting the MG simulation"),
+ sleep(1000),
+
+ d("[MG] start the simulation"),
+ {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq),
+
+ d("await the generator reply(s)"),
+ await_completion([MgcId, MgId]),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop generator"),
+ megaco_test_tcp_generator:stop(Mgc),
+
+ %% Tell Mg to stop
+ i("[MG] stop generator"),
+ megaco_test_megaco_generator:stop(Mg),
+
+ i("done", []),
+ ok.
+
+
+
+%%
+%% MGC generator stuff
+%%
+
+ssmo1_mgc_event_sequence(text, tcp) ->
+ DecodeFun = ssmo1_mgc_decode_msg_fun(megaco_pretty_text_encoder, []),
+ EncodeFun = ssmo1_mgc_encode_msg_fun(megaco_pretty_text_encoder, []),
+ Mid = {deviceName,"mgc"},
+ ScrVerifyFun = ssmo1_mgc_verify_service_change_req_msg_fun(),
+ ServiceChangeRep = ssmo1_mgc_service_change_reply_msg(Mid, 1),
+ TermId1 =
+ #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ CtxId1 = 1,
+ TermId2 =
+ #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ CtxId2 = 2,
+ TermId3 =
+ #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ CtxId3 = 3,
+ TermId4 =
+ #megaco_term_id{id = ["00000000","00000000","00000004"]},
+ CtxId4 = 4,
+ TermId5 =
+ #megaco_term_id{id = ["00000000","00000000","00000005"]},
+ CtxId5 = 5,
+ TermId6 =
+ #megaco_term_id{id = ["00000000","00000000","00000006"]},
+ CtxId6 = 6,
+ TermId7 =
+ #megaco_term_id{id = ["00000000","00000000","00000007"]},
+ CtxId7 = 7,
+ TermId8 =
+ #megaco_term_id{id = ["00000000","00000000","00000008"]},
+ CtxId8 = 8,
+ TransId = 2,
+ TermIDs = [TermId1, TermId2, TermId3, TermId4,
+ TermId5, TermId6, TermId7, TermId8],
+ CIDs = [CtxId1, CtxId2, CtxId3, CtxId4,
+ CtxId5, CtxId6, CtxId7, CtxId8],
+ NotifyReq = ssmo1_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs),
+ NrVerifyFun1 =
+ ssmo1_mgc_verify_notify_reply_segment_msg_fun(1, false, TransId,
+ TermId1, CtxId1),
+ NrVerifyFun2 =
+ ssmo1_mgc_verify_notify_reply_segment_msg_fun(2, false, TransId,
+ TermId2, CtxId2),
+ NrVerifyFun3 =
+ ssmo1_mgc_verify_notify_reply_segment_msg_fun(3, false, TransId,
+ TermId3, CtxId3),
+ NrVerifyFun4 =
+ ssmo1_mgc_verify_notify_reply_segment_msg_fun(4, false, TransId,
+ TermId4, CtxId4),
+ NrVerifyFun5 =
+ ssmo1_mgc_verify_notify_reply_segment_msg_fun(5, false, TransId,
+ TermId5, CtxId5),
+ NrVerifyFun6 =
+ ssmo1_mgc_verify_notify_reply_segment_msg_fun(6, false, TransId,
+ TermId6, CtxId6),
+ NrVerifyFun7 =
+ ssmo1_mgc_verify_notify_reply_segment_msg_fun(7, false, TransId,
+ TermId7, CtxId7),
+ NrVerifyFun8 =
+ ssmo1_mgc_verify_notify_reply_segment_msg_fun(8, true, TransId,
+ TermId8, CtxId8),
+ SegmentRep1 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 1, false),
+ SegmentRep2 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 2, false),
+ SegmentRep3 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 3, false),
+ SegmentRep4 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 4, false),
+ SegmentRep5 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 5, false),
+ SegmentRep6 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 6, false),
+ SegmentRep7 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 7, false),
+ SegmentRep8 = ssmo1_mgc_segment_reply_msg(Mid, TransId, 8, true),
+ TransAck = ssmo1_mgc_trans_ack_msg(Mid, TransId),
+ EvSeq = [{debug, true},
+ {decode, DecodeFun},
+ {encode, EncodeFun},
+ {listen, 2944},
+ {expect_accept, any},
+ {expect_receive, "service-change-request", {ScrVerifyFun, 5000}},
+ {send, "service-change-reply", ServiceChangeRep},
+ {expect_nothing, 1000},
+ {send, "notify request", NotifyReq},
+ {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 1000}},
+ {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}},
+ {expect_receive, "notify reply: segment 3", {NrVerifyFun3, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 2 [1]", SegmentRep2},
+ {expect_receive, "notify reply: segment 4", {NrVerifyFun4, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 1 [2]", SegmentRep1},
+ {expect_receive, "notify reply: segment 5", {NrVerifyFun5, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 3 [3]", SegmentRep3},
+ {expect_receive, "notify reply: segment 6", {NrVerifyFun6, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 5 [4]", SegmentRep5},
+ {expect_receive, "notify reply: segment 7", {NrVerifyFun7, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 4 [5]", SegmentRep4},
+ {expect_receive, "notify reply: segment 8", {NrVerifyFun8, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 6", SegmentRep6},
+ {expect_nothing, 1000},
+ {send, "segment reply 7", SegmentRep7},
+ {expect_nothing, 1000},
+ {send, "segment reply 8", SegmentRep8},
+ {expect_nothing, 1000},
+ {send, "transaction-ack", TransAck},
+ {expect_closed, 5000},
+ disconnect
+ ],
+ EvSeq.
+
+ssmo1_mgc_encode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:encode_message(Conf, M)
+ end.
+
+ssmo1_mgc_decode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:decode_message(Conf, M)
+ end.
+
+ssmo1_mgc_verify_service_change_req_msg_fun() ->
+ fun(Msg) ->
+ (catch ssmo1_mgc_verify_service_change_req(Msg))
+ end.
+
+ssmo1_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) ->
+ io:format("ssmo1_mgc_verify_service_change_req -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ Body =
+ case Mess of
+ #'Message'{version = 1,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = _TransId,
+ actions = [ActionReq]} ->
+ ActionReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ CR =
+ case AR of
+ #'ActionRequest'{contextId = _Cid,
+ commandRequests = [CmdReq]} ->
+ CmdReq;
+ _ ->
+ throw({error, {invalid_action, AR}})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}})
+ end,
+ {Tid, Parms} =
+ case Cmd of
+ {serviceChangeReq,
+ #'ServiceChangeRequest'{terminationID = [TermID],
+ serviceChangeParms = ServChParms}} ->
+ {TermID, ServChParms};
+ _ ->
+ throw({error, {invalid_command, Cmd}})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ throw({error, {invalid_terminationID, Tid}})
+ end,
+ case Parms of
+ %% Version 1 'ServiceChangeParm'
+ {'ServiceChangeParm',
+ restart, % serviceChangeMethod
+ asn1_NOVALUE, % serviceChangeAddress
+ ?VERSION, % serviceChangeVersion,
+ {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile
+ [[$9,$0,$1|_]], % serviceChangeReason
+ asn1_NOVALUE, % serviceChangeDelay
+ asn1_NOVALUE, % serviceChangeMgcId
+ asn1_NOVALUE, % timeStamp
+ asn1_NOVALUE % nonStandardData
+ } ->
+ {ok, M};
+ _ ->
+ {error, {invalid_serviceChangeParms, Parms}}
+ end.
+
+ssmo1_mgc_verify_notify_reply_segment_msg_fun(SN, Last,
+ TransId, TermId, Cid) ->
+ fun(Msg) ->
+ (catch ssmo1_mgc_verify_notify_reply_segment(Msg,
+ SN, Last,
+ TransId, TermId, Cid))
+ end.
+
+ssmo1_mgc_verify_notify_reply_segment(#'MegacoMessage'{mess = Mess} = M,
+ SN, Last, TransId, TermId, Cid) ->
+ io:format("ssmo1_mgc_verify_notify_reply_segment -> entry with"
+ "~n M: ~p"
+ "~n SN: ~p"
+ "~n Last: ~p"
+ "~n TransId: ~p"
+ "~n TermId: ~p"
+ "~n Cid: ~p"
+ "~n", [M, SN, Last, TransId, TermId, Cid]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionReply, TransReply} ->
+ TransReply;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ TRes =
+ case TR of
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = TransRes,
+ segmentNumber = SN,
+ segmentationComplete = asn1_NOVALUE} when (Last == false) ->
+ TransRes;
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = TransRes,
+ segmentNumber = SN,
+ segmentationComplete = 'NULL'} when (Last == true) ->
+ TransRes;
+ _ ->
+ throw({error, {invalid_transactionReply, TR}})
+ end,
+ AR =
+ case TRes of
+ {actionReplies, [ActionReply]} ->
+ ActionReply;
+ {actionReplies, ActionReplies} ->
+ throw({error, {invalid_actionReplies, ActionReplies}});
+ _ ->
+ throw({error, {invalid_transactionResult, TRes}})
+ end,
+ CR =
+ case AR of
+ #'ActionReply'{contextId = Cid,
+ commandReply = [CommandReply]} ->
+ CommandReply;
+ #'ActionReply'{contextId = Cid,
+ commandReply = CommandReplies} ->
+ throw({error, {invalid_commandReplies, CommandReplies}});
+ _ ->
+ throw({error, {invalid_actionReply, AR}})
+ end,
+ NR =
+ case CR of
+ {notifyReply, NotifyReply} ->
+ NotifyReply;
+ _ ->
+ throw({error, {invalid_commandReply, CR}})
+ end,
+ case NR of
+ #'NotifyReply'{terminationID = [TermId],
+ errorDescriptor = asn1_NOVALUE} ->
+ {ok, M};
+ _ ->
+ {error, {invalid_NotifyReply, NR}}
+ end;
+ssmo1_mgc_verify_notify_reply_segment(Crap,
+ _SN, _Last, _TransId, _TermId, _Cid) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+
+ssmo1_mgc_service_change_reply_msg(Mid, Cid) ->
+ SCRP = cre_serviceChangeResParm(Mid),
+ SCRes = cre_serviceChangeResult(SCRP),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReply([Root], SCRes),
+ CR = cre_cmdReply(SCR),
+ AR = cre_actionReply(Cid, [CR]),
+ TRes = cre_transResult([AR]),
+ TR = {'TransactionReply', 1, asn1_NOVALUE, TRes},
+ Trans = cre_transaction(TR),
+ Mess = cre_message(1, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmo1_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs) ->
+ ARs = ssmo1_mgc_notify_request_ars(TermIDs, CIDs),
+ TR = cre_transReq(TransId, ARs),
+ Trans = cre_transaction(TR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmo1_mgc_notify_request_ars(TermIDs, CIDs) ->
+ ssmo1_mgc_notify_request_ars(TermIDs, CIDs, []).
+
+ssmo1_mgc_notify_request_ars([], [], Acc) ->
+ lists:reverse(Acc);
+ssmo1_mgc_notify_request_ars([TermID|TermIDs], [CID|CIDs], Acc) ->
+ AR = ssmo1_mgc_notify_request_ar(100+CID, TermID, CID),
+ ssmo1_mgc_notify_request_ars(TermIDs, CIDs, [AR|Acc]).
+
+ssmo1_mgc_notify_request_ar(Rid, Tid, Cid) ->
+ TT = cre_timeNotation(integer_to_list(19990720+Rid),
+ integer_to_list(22000000+Rid)),
+ Ev = cre_obsEvent("al/of", TT),
+ EvsDesc = cre_obsEvsDesc(Rid, [Ev]),
+ NR = cre_notifyReq([Tid], EvsDesc),
+ CMD = cre_command(NR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+ssmo1_mgc_segment_reply_msg(Mid, TransId, SN, Last) ->
+ SR = ssmo1_mgc_segment_reply(TransId, SN, Last),
+ Trans = cre_transaction(SR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmo1_mgc_segment_reply(TransId, SN, true) ->
+ cre_segReply(TransId, SN, 'NULL');
+ssmo1_mgc_segment_reply(TransId, SN, false) ->
+ cre_segReply(TransId, SN, asn1_NOVALUE).
+
+ssmo1_mgc_trans_ack_msg(Mid, TransId) ->
+ TA = cre_transAck(TransId),
+ Trans = cre_transaction([TA]),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+
+%%
+%% MG generator stuff
+%%
+ssmo1_mg_event_sequence(text, tcp) ->
+ Mid = {deviceName,"mg"},
+ RI = [
+ {port, 2944},
+ {encoding_module, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {transport_module, megaco_tcp}
+ ],
+ ConnectVerify = ssmo1_mg_verify_handle_connect_fun(),
+ ServiceChangeReq = ssmo1_mg_service_change_request_ar(Mid, 1),
+ ServiceChangeReplyVerify = ssmo1_mg_verify_service_change_reply_fun(),
+ Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ Tid4 = #megaco_term_id{id = ["00000000","00000000","00000004"]},
+ Tid5 = #megaco_term_id{id = ["00000000","00000000","00000005"]},
+ Tid6 = #megaco_term_id{id = ["00000000","00000000","00000006"]},
+ Tid7 = #megaco_term_id{id = ["00000000","00000000","00000007"]},
+ Tid8 = #megaco_term_id{id = ["00000000","00000000","00000008"]},
+ Tids = [Tid1, Tid2, Tid3, Tid4, Tid5, Tid6, Tid7, Tid8],
+ NotifyReqVerify = ssmo1_mg_verify_notify_request_fun(Tids),
+ AckVerify = ssmo1_mg_verify_ack_fun(),
+ EvSeq = [
+ {debug, true},
+ {megaco_trace, disable},
+ %% {megaco_trace, max},
+ megaco_start,
+ {megaco_start_user, Mid, RI, []},
+ start_transport,
+ {megaco_system_info, users},
+ {megaco_system_info, connections},
+ connect,
+ {megaco_callback, handle_connect, ConnectVerify},
+ megaco_connect,
+ {megaco_cast, [ServiceChangeReq], []},
+ {megaco_callback, handle_connect, ConnectVerify},
+ {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify},
+ {megaco_update_conn_info, protocol_version, ?VERSION},
+ {megaco_update_conn_info, segment_send, 3},
+ {megaco_update_conn_info, max_pdu_size, 128},
+ {sleep, 1000},
+ {megaco_callback, handle_trans_request, NotifyReqVerify},
+ {megaco_callback, handle_trans_ack, AckVerify, 15000},
+ megaco_stop_user,
+ megaco_stop,
+ {sleep, 1000}
+ ],
+ EvSeq.
+
+
+ssmo1_mg_verify_handle_connect_fun() ->
+ fun(Ev) -> ssmo1_mg_verify_handle_connect(Ev) end.
+
+ssmo1_mg_verify_handle_connect({handle_connect, CH, 1}) ->
+ io:format("ssmo1_mg_verify_handle_connect -> ok"
+ "~n CH: ~p~n", [CH]),
+ {ok, CH, ok};
+ssmo1_mg_verify_handle_connect(Else) ->
+ io:format("ssmo1_mg_verify_handle_connect -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, ok}.
+
+
+ssmo1_mg_verify_service_change_reply_fun() ->
+ fun(Rep) -> ssmo1_mg_verify_scr(Rep) end.
+
+ssmo1_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) ->
+ (catch ssmo1_mg_do_verify_scr(AR));
+ssmo1_mg_verify_scr(Crap) ->
+ io:format("ssmo1_mg_verify_scr -> error: "
+ "~n Crap: ~p"
+ "~n", [Crap]),
+ {error, Crap, ok}.
+
+ssmo1_mg_do_verify_scr(AR) ->
+ io:format("ssmo1_mg_do_verify_scr -> ok: "
+ "~n AR: ~p~n", [AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ SCR =
+ case CR of
+ {serviceChangeReply, ServChRep} ->
+ ServChRep;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ {Tid, SCRes} =
+ case SCR of
+ #'ServiceChangeReply'{terminationID = [TermID],
+ serviceChangeResult = Res} ->
+ {TermID, Res};
+ _ ->
+ Reason3 = {invalid_service_change_reply, SCR},
+ throw({error, Reason3, ok})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ Reason4 = {invalid_termination_id, Tid},
+ throw({error, Reason4, ok})
+ end,
+ SCRParm =
+ case SCRes of
+ {serviceChangeResParms, ServChResParms} ->
+ ServChResParms;
+ _ ->
+ Reason5 = {invalid_serviceChangeResult, SCRes},
+ throw({error, Reason5, ok})
+ end,
+ case SCRParm of
+ #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} ->
+ {ok, AR, ok};
+ _ ->
+ Reason6 = {invalid_service_change_result, SCRParm},
+ {error, Reason6, ok}
+ end.
+
+ssmo1_mg_verify_notify_request_fun(Tids) ->
+ fun(Req) -> ssmo1_mg_verify_notify_request(Req, Tids) end.
+
+ssmo1_mg_verify_notify_request(
+ {handle_trans_request, _CH, ?VERSION, ARs}, Tids)
+ when length(ARs) == length(Tids) ->
+ (catch ssmo1_mg_do_verify_notify_request(Tids, ARs));
+ssmo1_mg_verify_notify_request(
+ {handle_trans_request, _CH, ?VERSION, ARs}, _Tids) ->
+ {error, {invalid_action_requests, ARs}, ok};
+ssmo1_mg_verify_notify_request(
+ {handle_trans_request, CH, V, ARs}, _Tids) ->
+ {error, {invalid_trans_request, {CH, V, ARs}}, ok};
+ssmo1_mg_verify_notify_request(Crap, _Tids) ->
+ io:format("ssmo1_mg_verify_notify_request -> unknown request"
+ "~n Crap: ~p"
+ "~n Tids: ~p"
+ "~n", [Crap, _Tids]),
+ {error, {unexpected_event, Crap}, ok}.
+
+ssmo1_mg_do_verify_notify_request(Tids, ARs) ->
+ io:format("ssmo1_mg_do_verify_notify_request -> ok"
+ "~n Tids: ~p"
+ "~n ARs: ~p"
+ "~n", [Tids, ARs]),
+ ActionReplies = ssmo1_mg_do_verify_notify_request_ars(Tids, ARs),
+ io:format("ssmo1_mg_do_verify_notify_request -> ok"
+ "~n ActionReplies: ~p"
+ "~n", [ActionReplies]),
+ Reply = {{handle_ack, ssmp4}, ActionReplies},
+ {ok, ARs, Reply}.
+
+ssmo1_mg_do_verify_notify_request_ars(Tids, ARs) ->
+ ssmo1_mg_do_verify_notify_request_ars(Tids, ARs, []).
+
+ssmo1_mg_do_verify_notify_request_ars([], [], Acc) ->
+ lists:reverse(Acc);
+ssmo1_mg_do_verify_notify_request_ars([Tid|Tids], [AR|ARs], Acc) ->
+ ActionReply = ssmo1_mg_do_verify_notify_request_ar(Tid, AR),
+ ssmo1_mg_do_verify_notify_request_ars(Tids, ARs, [ActionReply|Acc]).
+
+ssmo1_mg_do_verify_notify_request_ar(Tid, AR) ->
+ io:format("ssmo1_mg_do_verify_notify_request_ar -> ok"
+ "~n Tid: ~p"
+ "~n AR: ~p"
+ "~n", [Tid, AR]),
+ {Cid, CR} =
+ case AR of
+ #'ActionRequest'{contextId = CtxId,
+ commandRequests = [CmdReq]} ->
+ {CtxId, CmdReq};
+ _ ->
+ Reason1 = {invalid_actionRequest, AR},
+ throw({error, Reason1, ok})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}, ok})
+ end,
+ OED =
+ case Cmd of
+ {notifyReq,
+ #'NotifyRequest'{terminationID = [Tid],
+ observedEventsDescriptor = ObsEvDesc,
+ errorDescriptor = asn1_NOVALUE}} ->
+ ObsEvDesc;
+ _ ->
+ throw({error, {invalid_command, Cmd}, ok})
+ end,
+ OE =
+ case OED of
+ #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} ->
+ ObsEv;
+ #'ObservedEventsDescriptor'{observedEventLst = ObsEvLst} ->
+ throw({error, {invalid_observedEventLst, ObsEvLst}, ok});
+ _ ->
+ throw({error, {invalid_ObservedEventsDescriptor, OED}, ok})
+ end,
+ case OE of
+ #'ObservedEvent'{eventName = "al/of"} ->
+ ssmo1_mg_notify_reply_ar(Cid, Tid);
+ _ ->
+ throw({error, {invalid_ObservedEvent, OE}, ok})
+ end.
+
+
+ssmo1_mg_verify_ack_fun() ->
+ fun(Event) -> ssmo1_mg_verify_ack(Event) end.
+
+ssmo1_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, ssmp4}) ->
+ io:format("ssmo1_mg_verify_ack -> ok"
+ "~n CH: ~p"
+ "~n", [CH]),
+ {ok, CH, ok};
+ssmo1_mg_verify_ack({handle_trans_ack, CH, ?VERSION, ok, CrapAckData}) ->
+ {error, {unknown_ack_data, CrapAckData, CH}, ok};
+ssmo1_mg_verify_ack({handle_trans_ack, CH, ?VERSION,
+ BadAckStatus, BadAckData}) ->
+ {error, {unknown_ack_status, BadAckStatus, BadAckData, CH}, ok};
+ssmo1_mg_verify_ack(BadEvent) ->
+ {error, {unknown_event, BadEvent}, ok}.
+
+
+ssmo1_mg_service_change_request_ar(_Mid, Cid) ->
+ Prof = cre_serviceChangeProf("resgw", 1),
+ SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReq([Root], SCP),
+ CMD = cre_command(SCR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+ssmo1_mg_notify_reply_ar(Cid, Tid) ->
+ NR = cre_notifyReply([Tid]),
+ CR = cre_cmdReply(NR),
+ cre_actionReply(Cid, [CR]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+send_segmented_msg_missing_seg_reply1(suite) ->
+ [];
+send_segmented_msg_missing_seg_reply1(doc) ->
+ "First missing segment test. "
+ "Tests that the callbacks and error messages are delivered "
+ "when a segment reply goes missing. Ack expected. "
+ "Send window = 3. ";
+send_segmented_msg_missing_seg_reply1(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, ssmmsr1),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ d("[MGC] start the simulator "),
+ {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode),
+
+ d("[MGC] create the event sequence"),
+ MgcEvSeq = ssmmsr1_mgc_event_sequence(text, tcp),
+
+ i("wait some time before starting the MGC simulation"),
+ sleep(1000),
+
+ d("[MGC] start the simulation"),
+ {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq),
+
+ i("wait some time before starting the MG simulator"),
+ sleep(1000),
+
+ d("[MG] start the simulator (generator)"),
+ {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode),
+
+ d("[MG] create the event sequence"),
+ MgEvSeq = ssmmsr1_mg_event_sequence(text, tcp),
+
+ i("wait some time before starting the MG simulation"),
+ sleep(1000),
+
+ d("[MG] start the simulation"),
+ {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq),
+
+ %% Await MGC ready for segments
+ d("await MGC trigger event"),
+ MgcPid =
+ receive
+ {ready_for_segments, mgc, Pid1} ->
+ d("received MGC trigger event"),
+ Pid1
+ after 5000 ->
+ d("timeout waiting for MGC trigger event: ~p",
+ [megaco_test_lib:flush()]),
+ ?ERROR(timeout_MGC_trigger_event)
+ end,
+
+ %% Await MG ready for segments
+ d("await MG trigger event"),
+ MgPid =
+ receive
+ {ready_for_segments, mg, Pid2} ->
+ d("received MG trigger event"),
+ Pid2
+ after 5000 ->
+ d("timeout waiting for MG trigger event: ~p",
+ [megaco_test_lib:flush()]),
+ ?ERROR(timeout_MG_trigger_event)
+ end,
+
+ %% Instruct the MG to continue
+ d("send continue to MG"),
+ MgPid ! {continue_with_segments, self()},
+
+ sleep(500),
+
+ %% Instruct the MGC to continue
+ d("send continue to MGC"),
+ MgcPid ! {continue_with_segments, self()},
+
+ d("await the generator reply(s)"),
+ await_completion([MgcId, MgId]),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop generator"),
+ megaco_test_tcp_generator:stop(Mgc),
+
+ %% Tell Mg to stop
+ i("[MG] stop generator"),
+ megaco_test_megaco_generator:stop(Mg),
+
+ i("done", []),
+ ok.
+
+
+
+%%
+%% MGC generator stuff
+%%
+
+ssmmsr1_mgc_event_sequence(text, tcp) ->
+ DecodeFun = ssmmsr1_mgc_decode_msg_fun(megaco_pretty_text_encoder, []),
+ EncodeFun = ssmmsr1_mgc_encode_msg_fun(megaco_pretty_text_encoder, []),
+ Mid = {deviceName,"mgc"},
+ ScrVerifyFun = ssmmsr1_mgc_verify_service_change_req_msg_fun(),
+ ServiceChangeRep = ssmmsr1_mgc_service_change_reply_msg(Mid, 1),
+ TermId1 =
+ #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ CtxId1 = 1,
+ TermId2 =
+ #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ CtxId2 = 2,
+ TermId3 =
+ #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ CtxId3 = 3,
+ TermId4 =
+ #megaco_term_id{id = ["00000000","00000000","00000004"]},
+ CtxId4 = 4,
+ TermId5 =
+ #megaco_term_id{id = ["00000000","00000000","00000005"]},
+ CtxId5 = 5,
+ TermId6 =
+ #megaco_term_id{id = ["00000000","00000000","00000006"]},
+ CtxId6 = 6,
+ TermId7 =
+ #megaco_term_id{id = ["00000000","00000000","00000007"]},
+ CtxId7 = 7,
+ TermId8 =
+ #megaco_term_id{id = ["00000000","00000000","00000008"]},
+ CtxId8 = 8,
+ TransId = 2,
+ TermIDs = [TermId1, TermId2, TermId3, TermId4,
+ TermId5, TermId6, TermId7, TermId8],
+ CIDs = [CtxId1, CtxId2, CtxId3, CtxId4,
+ CtxId5, CtxId6, CtxId7, CtxId8],
+ NotifyReq = ssmmsr1_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs),
+ NrVerifyFun1 =
+ ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(1, false, TransId,
+ TermId1, CtxId1),
+ NrVerifyFun2 =
+ ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(2, false, TransId,
+ TermId2, CtxId2),
+ NrVerifyFun3 =
+ ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(3, false, TransId,
+ TermId3, CtxId3),
+ NrVerifyFun4 =
+ ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(4, false, TransId,
+ TermId4, CtxId4),
+ NrVerifyFun5 =
+ ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(5, false, TransId,
+ TermId5, CtxId5),
+ NrVerifyFun6 =
+ ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(6, false, TransId,
+ TermId6, CtxId6),
+ NrVerifyFun7 =
+ ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(7, false, TransId,
+ TermId7, CtxId7),
+ NrVerifyFun8 =
+ ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(8, true, TransId,
+ TermId8, CtxId8),
+ SegmentRep1 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 1, false),
+ SegmentRep2 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 2, false),
+ %% SegmentRep3 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 3, false),
+ SegmentRep4 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 4, false),
+ SegmentRep5 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 5, false),
+ SegmentRep6 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 6, false),
+ SegmentRep7 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 7, false),
+ SegmentRep8 = ssmmsr1_mgc_segment_reply_msg(Mid, TransId, 8, true),
+ TransAck = ssmmsr1_mgc_trans_ack_msg(Mid, TransId),
+ ReadyForSegments = ssmmsr1_mgc_ready_for_segments_fun(),
+ EvSeq = [{debug, true},
+ {decode, DecodeFun},
+ {encode, EncodeFun},
+ {listen, 2944},
+ {expect_accept, any},
+ {expect_receive, "service-change-request", {ScrVerifyFun, 5000}},
+ {send, "service-change-reply", ServiceChangeRep},
+ %% {expect_nothing, 1000},
+ {trigger, "segment send sync trigger", ReadyForSegments},
+ {send, "notify request", NotifyReq},
+ {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 1000}},
+ {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}},
+ {expect_receive, "notify reply: segment 3", {NrVerifyFun3, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 1 [1]", SegmentRep1},
+ {expect_receive, "notify reply: segment 4", {NrVerifyFun4, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 2 [2]", SegmentRep2},
+ {expect_receive, "notify reply: segment 5", {NrVerifyFun5, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 4 [3]", SegmentRep4},
+ {expect_receive, "notify reply: segment 6", {NrVerifyFun6, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 5 [4]", SegmentRep5},
+ {expect_receive, "notify reply: segment 7", {NrVerifyFun7, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 6 [5]", SegmentRep6},
+ {expect_receive, "notify reply: segment 8", {NrVerifyFun8, 1000}},
+ {expect_nothing, 1000},
+ {send, "segment reply 7 [6]", SegmentRep7},
+ {expect_nothing, 1000},
+ {send, "segment reply 8 [7]", SegmentRep8},
+ {expect_nothing, 1000},
+ {send, "transaction-ack", TransAck},
+ {expect_closed, 5000},
+ disconnect
+ ],
+ EvSeq.
+
+ssmmsr1_mgc_ready_for_segments_fun() ->
+ TC = self(),
+ fun() ->
+ io:format("ssmmsr1_mgc_ready_for_segments_fun -> entry~n", []),
+ TC ! {ready_for_segments, mgc, self()},
+ receive
+ {continue_with_segments, TC} ->
+ io:format("ssmmsr1_mgc_ready_for_segments_fun -> "
+ "received continue~n", []),
+ ok
+ end
+ end.
+
+ssmmsr1_mgc_encode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:encode_message(Conf, M)
+ end.
+
+ssmmsr1_mgc_decode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:decode_message(Conf, M)
+ end.
+
+ssmmsr1_mgc_verify_service_change_req_msg_fun() ->
+ fun(Msg) ->
+ (catch ssmmsr1_mgc_verify_service_change_req(Msg))
+ end.
+
+ssmmsr1_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) ->
+ io:format("ssmmsr1_mgc_verify_service_change_req -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ Body =
+ case Mess of
+ #'Message'{version = 1,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = _TransId,
+ actions = [ActionReq]} ->
+ ActionReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ CR =
+ case AR of
+ #'ActionRequest'{contextId = _Cid,
+ commandRequests = [CmdReq]} ->
+ CmdReq;
+ _ ->
+ throw({error, {invalid_action, AR}})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}})
+ end,
+ {Tid, Parms} =
+ case Cmd of
+ {serviceChangeReq,
+ #'ServiceChangeRequest'{terminationID = [TermID],
+ serviceChangeParms = ServChParms}} ->
+ {TermID, ServChParms};
+ _ ->
+ throw({error, {invalid_command, Cmd}})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ throw({error, {invalid_terminationID, Tid}})
+ end,
+ case Parms of
+ %% Version 1 'ServiceChangeParm'
+ {'ServiceChangeParm',
+ restart, % serviceChangeMethod
+ asn1_NOVALUE, % serviceChangeAddress
+ ?VERSION, % serviceChangeVersion,
+ {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile
+ [[$9,$0,$1|_]], % serviceChangeReason
+ asn1_NOVALUE, % serviceChangeDelay
+ asn1_NOVALUE, % serviceChangeMgcId
+ asn1_NOVALUE, % timeStamp
+ asn1_NOVALUE % nonStandardData
+ } ->
+ {ok, M};
+ _ ->
+ {error, {invalid_serviceChangeParms, Parms}}
+ end.
+
+ssmmsr1_mgc_verify_notify_reply_segment_msg_fun(SN, Last,
+ TransId, TermId, Cid) ->
+ fun(Msg) ->
+ (catch ssmmsr1_mgc_verify_notify_reply_segment(Msg,
+ SN, Last,
+ TransId, TermId, Cid))
+ end.
+
+ssmmsr1_mgc_verify_notify_reply_segment(#'MegacoMessage'{mess = Mess} = M,
+ SN, Last, TransId, TermId, Cid) ->
+ io:format("ssmmsr1_mgc_verify_notify_reply_segment -> entry with"
+ "~n M: ~p"
+ "~n SN: ~p"
+ "~n Last: ~p"
+ "~n TransId: ~p"
+ "~n TermId: ~p"
+ "~n Cid: ~p"
+ "~n", [M, SN, Last, TransId, TermId, Cid]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionReply, TransReply} ->
+ TransReply;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ TRes =
+ case TR of
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = TransRes,
+ segmentNumber = SN,
+ segmentationComplete = asn1_NOVALUE} when (Last == false) ->
+ TransRes;
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = TransRes,
+ segmentNumber = SN,
+ segmentationComplete = 'NULL'} when (Last == true) ->
+ TransRes;
+ _ ->
+ throw({error, {invalid_transactionReply, TR}})
+ end,
+ AR =
+ case TRes of
+ {actionReplies, [ActionReply]} ->
+ ActionReply;
+ {actionReplies, ActionReplies} ->
+ throw({error, {invalid_actionReplies, ActionReplies}});
+ _ ->
+ throw({error, {invalid_transactionResult, TRes}})
+ end,
+ CR =
+ case AR of
+ #'ActionReply'{contextId = Cid,
+ commandReply = [CommandReply]} ->
+ CommandReply;
+ #'ActionReply'{contextId = Cid,
+ commandReply = CommandReplies} ->
+ throw({error, {invalid_commandReplies, CommandReplies}});
+ _ ->
+ throw({error, {invalid_actionReply, AR}})
+ end,
+ NR =
+ case CR of
+ {notifyReply, NotifyReply} ->
+ NotifyReply;
+ _ ->
+ throw({error, {invalid_commandReply, CR}})
+ end,
+ case NR of
+ #'NotifyReply'{terminationID = [TermId],
+ errorDescriptor = asn1_NOVALUE} ->
+ {ok, M};
+ _ ->
+ {error, {invalid_NotifyReply, NR}}
+ end;
+ssmmsr1_mgc_verify_notify_reply_segment(Crap,
+ _SN, _Last, _TransId, _TermId, _Cid) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+
+ssmmsr1_mgc_service_change_reply_msg(Mid, Cid) ->
+ SCRP = cre_serviceChangeResParm(Mid),
+ SCRes = cre_serviceChangeResult(SCRP),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReply([Root], SCRes),
+ CR = cre_cmdReply(SCR),
+ AR = cre_actionReply(Cid, [CR]),
+ TRes = cre_transResult([AR]),
+ TR = {'TransactionReply', 1, asn1_NOVALUE, TRes},
+ Trans = cre_transaction(TR),
+ Mess = cre_message(1, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmmsr1_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs) ->
+ ARs = ssmmsr1_mgc_notify_request_ars(TermIDs, CIDs),
+ TR = cre_transReq(TransId, ARs),
+ Trans = cre_transaction(TR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmmsr1_mgc_notify_request_ars(TermIDs, CIDs) ->
+ ssmmsr1_mgc_notify_request_ars(TermIDs, CIDs, []).
+
+ssmmsr1_mgc_notify_request_ars([], [], Acc) ->
+ lists:reverse(Acc);
+ssmmsr1_mgc_notify_request_ars([TermID|TermIDs], [CID|CIDs], Acc) ->
+ AR = ssmmsr1_mgc_notify_request_ar(100+CID, TermID, CID),
+ ssmmsr1_mgc_notify_request_ars(TermIDs, CIDs, [AR|Acc]).
+
+ssmmsr1_mgc_notify_request_ar(Rid, Tid, Cid) ->
+ TT = cre_timeNotation(integer_to_list(19990720+Rid),
+ integer_to_list(22000000+Rid)),
+ Ev = cre_obsEvent("al/of", TT),
+ EvsDesc = cre_obsEvsDesc(Rid, [Ev]),
+ NR = cre_notifyReq([Tid], EvsDesc),
+ CMD = cre_command(NR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+ssmmsr1_mgc_segment_reply_msg(Mid, TransId, SN, Last) ->
+ SR = ssmmsr1_mgc_segment_reply(TransId, SN, Last),
+ Trans = cre_transaction(SR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmmsr1_mgc_segment_reply(TransId, SN, true) ->
+ cre_segReply(TransId, SN, 'NULL');
+ssmmsr1_mgc_segment_reply(TransId, SN, false) ->
+ cre_segReply(TransId, SN, asn1_NOVALUE).
+
+ssmmsr1_mgc_trans_ack_msg(Mid, TransId) ->
+ TA = cre_transAck(TransId),
+ Trans = cre_transaction([TA]),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+
+%%
+%% MG generator stuff
+%%
+ssmmsr1_mg_event_sequence(text, tcp) ->
+ Mid = {deviceName,"mg"},
+ RI = [
+ {port, 2944},
+ {encoding_module, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {transport_module, megaco_tcp}
+ ],
+ ConnectVerify = ssmmsr1_mg_verify_handle_connect_fun(),
+ ServiceChangeReq = ssmmsr1_mg_service_change_request_ar(Mid, 1),
+ ServiceChangeReplyVerify = ssmmsr1_mg_verify_service_change_reply_fun(),
+ Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ Tid4 = #megaco_term_id{id = ["00000000","00000000","00000004"]},
+ Tid5 = #megaco_term_id{id = ["00000000","00000000","00000005"]},
+ Tid6 = #megaco_term_id{id = ["00000000","00000000","00000006"]},
+ Tid7 = #megaco_term_id{id = ["00000000","00000000","00000007"]},
+ Tid8 = #megaco_term_id{id = ["00000000","00000000","00000008"]},
+ Tids = [Tid1, Tid2, Tid3, Tid4, Tid5, Tid6, Tid7, Tid8],
+ NotifyReqVerify = ssmmsr1_mg_verify_notify_request_fun(Tids),
+ AckVerify = ssmmsr1_mg_verify_ack_fun(),
+ ReadyForSegments = ssmmsr1_mg_ready_for_segments_fun(),
+ EvSeq = [
+ {debug, true},
+ {megaco_trace, disable},
+ %% {megaco_trace, max},
+ megaco_start,
+ {megaco_start_user, Mid, RI, []},
+ start_transport,
+ {megaco_system_info, users},
+ {megaco_system_info, connections},
+ connect,
+ {megaco_callback, handle_connect, ConnectVerify},
+ megaco_connect,
+ {megaco_cast, [ServiceChangeReq], []},
+ {megaco_callback, handle_connect, ConnectVerify},
+ {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify},
+ {megaco_update_conn_info, protocol_version, ?VERSION},
+ {megaco_update_conn_info, reply_timer, 20000},
+ {megaco_update_conn_info, segment_send, 3},
+ {megaco_update_conn_info, max_pdu_size, 128},
+ %% {sleep, 1000},
+ {trigger, ReadyForSegments},
+ {megaco_callback, handle_trans_request, NotifyReqVerify},
+ {megaco_callback, handle_trans_ack, AckVerify, 15000},
+ megaco_stop_user,
+ megaco_stop,
+ {sleep, 1000}
+ ],
+ EvSeq.
+
+
+ssmmsr1_mg_ready_for_segments_fun() ->
+ TC = self(),
+ fun() ->
+ io:format("ssmmsr1_mg_ready_for_segments_fun -> entry~n", []),
+ TC ! {ready_for_segments, mg, self()},
+ receive
+ {continue_with_segments, TC} ->
+ io:format("ssmmsr1_mg_ready_for_segments_fun -> "
+ "received continue~n", []),
+ ok
+ end
+ end.
+
+ssmmsr1_mg_verify_handle_connect_fun() ->
+ fun(Ev) -> ssmmsr1_mg_verify_handle_connect(Ev) end.
+
+ssmmsr1_mg_verify_handle_connect({handle_connect, CH, 1}) ->
+ io:format("ssmmsr1_mg_verify_handle_connect -> ok"
+ "~n CH: ~p~n", [CH]),
+ {ok, CH, ok};
+ssmmsr1_mg_verify_handle_connect(Else) ->
+ io:format("ssmmsr1_mg_verify_handle_connect -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, ok}.
+
+
+ssmmsr1_mg_verify_service_change_reply_fun() ->
+ fun(Rep) -> ssmmsr1_mg_verify_scr(Rep) end.
+
+ssmmsr1_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) ->
+ (catch ssmmsr1_mg_do_verify_scr(AR));
+ssmmsr1_mg_verify_scr(Crap) ->
+ io:format("ssmmsr1_mg_verify_scr -> error: "
+ "~n Crap: ~p"
+ "~n", [Crap]),
+ {error, Crap, ok}.
+
+ssmmsr1_mg_do_verify_scr(AR) ->
+ io:format("ssmmsr1_mg_do_verify_scr -> ok: "
+ "~n AR: ~p~n", [AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ SCR =
+ case CR of
+ {serviceChangeReply, ServChRep} ->
+ ServChRep;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ {Tid, SCRes} =
+ case SCR of
+ #'ServiceChangeReply'{terminationID = [TermID],
+ serviceChangeResult = Res} ->
+ {TermID, Res};
+ _ ->
+ Reason3 = {invalid_service_change_reply, SCR},
+ throw({error, Reason3, ok})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ Reason4 = {invalid_termination_id, Tid},
+ throw({error, Reason4, ok})
+ end,
+ SCRParm =
+ case SCRes of
+ {serviceChangeResParms, ServChResParms} ->
+ ServChResParms;
+ _ ->
+ Reason5 = {invalid_serviceChangeResult, SCRes},
+ throw({error, Reason5, ok})
+ end,
+ case SCRParm of
+ #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} ->
+ {ok, AR, ok};
+ _ ->
+ Reason6 = {invalid_service_change_result, SCRParm},
+ {error, Reason6, ok}
+ end.
+
+ssmmsr1_mg_verify_notify_request_fun(Tids) ->
+ fun(Req) -> ssmmsr1_mg_verify_notify_request(Req, Tids) end.
+
+ssmmsr1_mg_verify_notify_request(
+ {handle_trans_request, _CH, ?VERSION, ARs}, Tids)
+ when length(ARs) == length(Tids) ->
+ (catch ssmmsr1_mg_do_verify_notify_request(Tids, ARs));
+ssmmsr1_mg_verify_notify_request(
+ {handle_trans_request, _CH, ?VERSION, ARs}, _Tids) ->
+ {error, {invalid_action_requests, ARs}, ok};
+ssmmsr1_mg_verify_notify_request(
+ {handle_trans_request, CH, V, ARs}, _Tids) ->
+ {error, {invalid_trans_request, {CH, V, ARs}}, ok};
+ssmmsr1_mg_verify_notify_request(Crap, _Tids) ->
+ io:format("ssmmsr1_mg_verify_notify_request -> unknown request"
+ "~n Crap: ~p"
+ "~n Tids: ~p"
+ "~n", [Crap, _Tids]),
+ {error, {unexpected_event, Crap}, ok}.
+
+ssmmsr1_mg_do_verify_notify_request(Tids, ARs) ->
+ io:format("ssmmsr1_mg_do_verify_notify_request -> ok"
+ "~n Tids: ~p"
+ "~n ARs: ~p"
+ "~n", [Tids, ARs]),
+ ActionReplies = ssmmsr1_mg_do_verify_notify_request_ars(Tids, ARs),
+ io:format("ssmmsr1_mg_do_verify_notify_request -> ok"
+ "~n ActionReplies: ~p"
+ "~n", [ActionReplies]),
+ Reply = {{handle_ack, ssmmsr1}, ActionReplies},
+ {ok, ARs, Reply}.
+
+ssmmsr1_mg_do_verify_notify_request_ars(Tids, ARs) ->
+ ssmmsr1_mg_do_verify_notify_request_ars(Tids, ARs, []).
+
+ssmmsr1_mg_do_verify_notify_request_ars([], [], Acc) ->
+ lists:reverse(Acc);
+ssmmsr1_mg_do_verify_notify_request_ars([Tid|Tids], [AR|ARs], Acc) ->
+ ActionReply = ssmmsr1_mg_do_verify_notify_request_ar(Tid, AR),
+ ssmmsr1_mg_do_verify_notify_request_ars(Tids, ARs, [ActionReply|Acc]).
+
+ssmmsr1_mg_do_verify_notify_request_ar(Tid, AR) ->
+ io:format("ssmmsr1_mg_do_verify_notify_request_ar -> ok"
+ "~n Tid: ~p"
+ "~n AR: ~p"
+ "~n", [Tid, AR]),
+ {Cid, CR} =
+ case AR of
+ #'ActionRequest'{contextId = CtxId,
+ commandRequests = [CmdReq]} ->
+ {CtxId, CmdReq};
+ _ ->
+ Reason1 = {invalid_actionRequest, AR},
+ throw({error, Reason1, ok})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}, ok})
+ end,
+ OED =
+ case Cmd of
+ {notifyReq,
+ #'NotifyRequest'{terminationID = [Tid],
+ observedEventsDescriptor = ObsEvDesc,
+ errorDescriptor = asn1_NOVALUE}} ->
+ ObsEvDesc;
+ _ ->
+ throw({error, {invalid_command, Cmd}, ok})
+ end,
+ OE =
+ case OED of
+ #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} ->
+ ObsEv;
+ #'ObservedEventsDescriptor'{observedEventLst = ObsEvLst} ->
+ throw({error, {invalid_observedEventLst, ObsEvLst}, ok});
+ _ ->
+ throw({error, {invalid_ObservedEventsDescriptor, OED}, ok})
+ end,
+ case OE of
+ #'ObservedEvent'{eventName = "al/of"} ->
+ ssmmsr1_mg_notify_reply_ar(Cid, Tid);
+ _ ->
+ throw({error, {invalid_ObservedEvent, OE}, ok})
+ end.
+
+
+ssmmsr1_mg_verify_ack_fun() ->
+ fun(Event) -> ssmmsr1_mg_verify_ack(Event) end.
+
+ssmmsr1_mg_verify_ack({handle_trans_ack, CH, ?VERSION, AckStatus, ssmmsr1}) ->
+ io:format("ssmmsr1_mg_verify_ack -> "
+ "~n AckStatus: ~p"
+ "~n CH: ~p"
+ "~n", [AckStatus, CH]),
+ case AckStatus of
+ {error, Reason} ->
+ case Reason of
+ {segment_failure, SegInfo} when is_list(SegInfo) ->
+ case lists:keysearch(segments_not_acked, 1, SegInfo) of
+ {value, {segments_not_acked, [3]}} ->
+ {ok, CH, ok};
+ {value, {segments_not_acked, SNs}} ->
+ X = {unexpected_not_acked_segments, SNs},
+ {error, X, ok};
+ false ->
+ X = {unexpected_seg_info, SegInfo},
+ {error, X, ok}
+ end;
+ _ ->
+ X = {unexpected_reason, Reason},
+ {error, X, ok}
+ end;
+ _ ->
+ X = {unexpected_ack_status, AckStatus},
+ {error, X, ok}
+ end;
+ssmmsr1_mg_verify_ack({handle_trans_ack, CH, ?VERSION,
+ BadAckStatus, BadAckData}) ->
+ {error, {unknown_ack_status, BadAckStatus, BadAckData, CH}, ok};
+ssmmsr1_mg_verify_ack(BadEvent) ->
+ {error, {unknown_event, BadEvent}, ok}.
+
+
+ssmmsr1_mg_service_change_request_ar(_Mid, Cid) ->
+ Prof = cre_serviceChangeProf("resgw", 1),
+ SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReq([Root], SCP),
+ CMD = cre_command(SCR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+ssmmsr1_mg_notify_reply_ar(Cid, Tid) ->
+ NR = cre_notifyReply([Tid]),
+ CR = cre_cmdReply(NR),
+ cre_actionReply(Cid, [CR]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+send_segmented_msg_missing_seg_reply2(suite) ->
+ [];
+send_segmented_msg_missing_seg_reply2(doc) ->
+ "First missing segment test. "
+ "Tests that the callbacks and error messages are delivered "
+ "when a segment reply goes missing. Ack expected. "
+ "Send window = 1. ";
+send_segmented_msg_missing_seg_reply2(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, ssmmsr2),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ d("[MGC] start the simulator "),
+ {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode),
+
+ d("[MGC] create the event sequence"),
+ MgcEvSeq = ssmmsr2_mgc_event_sequence(text, tcp),
+
+ i("wait some time before starting the MGC simulation"),
+ sleep(1000),
+
+ d("[MGC] start the simulation"),
+ {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq),
+
+ i("wait some time before starting the MG simulator"),
+ sleep(1000),
+
+ d("[MG] start the simulator (generator)"),
+ {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode),
+
+ d("[MG] create the event sequence"),
+ MgEvSeq = ssmmsr2_mg_event_sequence(text, tcp),
+
+ i("wait some time before starting the MG simulation"),
+ sleep(1000),
+
+ d("[MG] start the simulation"),
+ {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq),
+
+ %% Await MGC ready for segments
+ d("await MGC trigger event"),
+ MgcPid =
+ receive
+ {ready_for_segments, mgc, Pid1} ->
+ d("received MGC trigger event"),
+ Pid1
+ after 5000 ->
+ d("timeout waiting for MGC trigger event: ~p",
+ [megaco_test_lib:flush()]),
+ ?ERROR(timeout_MGC_trigger_event)
+ end,
+
+ %% Await MG ready for segments
+ d("await MG trigger event"),
+ MgPid =
+ receive
+ {ready_for_segments, mg, Pid2} ->
+ d("received MG trigger event"),
+ Pid2
+ after 5000 ->
+ d("timeout waiting for MG trigger event: ~p",
+ [megaco_test_lib:flush()]),
+ ?ERROR(timeout_MG_trigger_event)
+ end,
+
+ %% Instruct the MG to continue
+ d("send continue to MG"),
+ MgPid ! {continue_with_segments, self()},
+
+ sleep(500),
+
+ %% Instruct the MGC to continue
+ d("send continue to MGC"),
+ MgcPid ! {continue_with_segments, self()},
+
+ d("await the generator reply(s)"),
+ await_completion([MgcId, MgId]),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop generator"),
+ megaco_test_tcp_generator:stop(Mgc),
+
+ %% Tell Mg to stop
+ i("[MG] stop generator"),
+ megaco_test_megaco_generator:stop(Mg),
+
+ i("done", []),
+ ok.
+
+
+
+%%
+%% MGC generator stuff
+%%
+
+ssmmsr2_mgc_event_sequence(text, tcp) ->
+ DecodeFun = ssmmsr2_mgc_decode_msg_fun(megaco_pretty_text_encoder, []),
+ EncodeFun = ssmmsr2_mgc_encode_msg_fun(megaco_pretty_text_encoder, []),
+ Mid = {deviceName,"mgc"},
+ ScrVerifyFun = ssmmsr2_mgc_verify_service_change_req_msg_fun(),
+ ServiceChangeRep = ssmmsr2_mgc_service_change_reply_msg(Mid, 1),
+ TermId1 =
+ #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ CtxId1 = 1,
+ TermId2 =
+ #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ CtxId2 = 2,
+ TermId3 =
+ #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ CtxId3 = 3,
+ TermId4 =
+ #megaco_term_id{id = ["00000000","00000000","00000004"]},
+ CtxId4 = 4,
+ TermId5 =
+ #megaco_term_id{id = ["00000000","00000000","00000005"]},
+ CtxId5 = 5,
+ TermId6 =
+ #megaco_term_id{id = ["00000000","00000000","00000006"]},
+ CtxId6 = 6,
+ TermId7 =
+ #megaco_term_id{id = ["00000000","00000000","00000007"]},
+ CtxId7 = 7,
+ TermId8 =
+ #megaco_term_id{id = ["00000000","00000000","00000008"]},
+ CtxId8 = 8,
+ TransId = 2,
+ TermIDs = [TermId1, TermId2, TermId3, TermId4,
+ TermId5, TermId6, TermId7, TermId8],
+ CIDs = [CtxId1, CtxId2, CtxId3, CtxId4,
+ CtxId5, CtxId6, CtxId7, CtxId8],
+ NotifyReq = ssmmsr2_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs),
+ NrVerifyFun1 =
+ ssmmsr2_mgc_verify_notify_reply_segment_msg_fun(1, false, TransId,
+ TermId1, CtxId1),
+ NrVerifyFun2 =
+ ssmmsr2_mgc_verify_notify_reply_segment_msg_fun(2, false, TransId,
+ TermId2, CtxId2),
+ SegmentRep1 = ssmmsr2_mgc_segment_reply_msg(Mid, TransId, 1, false),
+ ReadyForSegments = ssmmsr2_mgc_ready_for_segments_fun(),
+ EvSeq = [{debug, true},
+ {decode, DecodeFun},
+ {encode, EncodeFun},
+ {listen, 2944},
+ {expect_accept, any},
+ {expect_receive, "service-change-request", {ScrVerifyFun, 5000}},
+ {send, "service-change-reply", ServiceChangeRep},
+ %% {expect_nothing, 1000},
+ {trigger, "segment send sync trigger", ReadyForSegments},
+ {send, "notify request", NotifyReq},
+ {expect_receive, "notify reply: segment 1", {NrVerifyFun1, 1000}},
+ {send, "segment reply 1", SegmentRep1},
+ {expect_receive, "notify reply: segment 2", {NrVerifyFun2, 1000}},
+ {expect_closed, 20000},
+ disconnect
+ ],
+ EvSeq.
+
+ssmmsr2_mgc_ready_for_segments_fun() ->
+ TC = self(),
+ fun() ->
+ io:format("ssmmsr2_mgc_ready_for_segments_fun -> entry~n", []),
+ TC ! {ready_for_segments, mgc, self()},
+ receive
+ {continue_with_segments, TC} ->
+ io:format("ssmmsr2_mgc_ready_for_segments_fun -> "
+ "received continue~n", []),
+ ok
+ end
+ end.
+
+ssmmsr2_mgc_encode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:encode_message(Conf, M)
+ end.
+
+ssmmsr2_mgc_decode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:decode_message(Conf, M)
+ end.
+
+ssmmsr2_mgc_verify_service_change_req_msg_fun() ->
+ fun(Msg) ->
+ (catch ssmmsr2_mgc_verify_service_change_req(Msg))
+ end.
+
+ssmmsr2_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) ->
+ io:format("ssmmsr2_mgc_verify_service_change_req -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ Body =
+ case Mess of
+ #'Message'{version = 1,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = _TransId,
+ actions = [ActionReq]} ->
+ ActionReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ CR =
+ case AR of
+ #'ActionRequest'{contextId = _Cid,
+ commandRequests = [CmdReq]} ->
+ CmdReq;
+ _ ->
+ throw({error, {invalid_action, AR}})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}})
+ end,
+ {Tid, Parms} =
+ case Cmd of
+ {serviceChangeReq,
+ #'ServiceChangeRequest'{terminationID = [TermID],
+ serviceChangeParms = ServChParms}} ->
+ {TermID, ServChParms};
+ _ ->
+ throw({error, {invalid_command, Cmd}})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ throw({error, {invalid_terminationID, Tid}})
+ end,
+ case Parms of
+ %% Version 1 'ServiceChangeParm'
+ {'ServiceChangeParm',
+ restart, % serviceChangeMethod
+ asn1_NOVALUE, % serviceChangeAddress
+ ?VERSION, % serviceChangeVersion,
+ {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile
+ [[$9,$0,$1|_]], % serviceChangeReason
+ asn1_NOVALUE, % serviceChangeDelay
+ asn1_NOVALUE, % serviceChangeMgcId
+ asn1_NOVALUE, % timeStamp
+ asn1_NOVALUE % nonStandardData
+ } ->
+ {ok, M};
+ _ ->
+ {error, {invalid_serviceChangeParms, Parms}}
+ end.
+
+ssmmsr2_mgc_verify_notify_reply_segment_msg_fun(SN, Last,
+ TransId, TermId, Cid) ->
+ fun(Msg) ->
+ (catch ssmmsr2_mgc_verify_notify_reply_segment(Msg,
+ SN, Last,
+ TransId, TermId, Cid))
+ end.
+
+ssmmsr2_mgc_verify_notify_reply_segment(#'MegacoMessage'{mess = Mess} = M,
+ SN, Last, TransId, TermId, Cid) ->
+ io:format("ssmmsr2_mgc_verify_notify_reply_segment -> entry with"
+ "~n M: ~p"
+ "~n SN: ~p"
+ "~n Last: ~p"
+ "~n TransId: ~p"
+ "~n TermId: ~p"
+ "~n Cid: ~p"
+ "~n", [M, SN, Last, TransId, TermId, Cid]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionReply, TransReply} ->
+ TransReply;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ TRes =
+ case TR of
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = TransRes,
+ segmentNumber = SN,
+ segmentationComplete = asn1_NOVALUE} when (Last == false) ->
+ TransRes;
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = TransRes,
+ segmentNumber = SN,
+ segmentationComplete = 'NULL'} when (Last == true) ->
+ TransRes;
+ _ ->
+ throw({error, {invalid_transactionReply, TR}})
+ end,
+ AR =
+ case TRes of
+ {actionReplies, [ActionReply]} ->
+ ActionReply;
+ {actionReplies, ActionReplies} ->
+ throw({error, {invalid_actionReplies, ActionReplies}});
+ _ ->
+ throw({error, {invalid_transactionResult, TRes}})
+ end,
+ CR =
+ case AR of
+ #'ActionReply'{contextId = Cid,
+ commandReply = [CommandReply]} ->
+ CommandReply;
+ #'ActionReply'{contextId = Cid,
+ commandReply = CommandReplies} ->
+ throw({error, {invalid_commandReplies, CommandReplies}});
+ _ ->
+ throw({error, {invalid_actionReply, AR}})
+ end,
+ NR =
+ case CR of
+ {notifyReply, NotifyReply} ->
+ NotifyReply;
+ _ ->
+ throw({error, {invalid_commandReply, CR}})
+ end,
+ case NR of
+ #'NotifyReply'{terminationID = [TermId],
+ errorDescriptor = asn1_NOVALUE} ->
+ {ok, M};
+ _ ->
+ {error, {invalid_NotifyReply, NR}}
+ end;
+ssmmsr2_mgc_verify_notify_reply_segment(Crap,
+ _SN, _Last, _TransId, _TermId, _Cid) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+
+ssmmsr2_mgc_service_change_reply_msg(Mid, Cid) ->
+ SCRP = cre_serviceChangeResParm(Mid),
+ SCRes = cre_serviceChangeResult(SCRP),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReply([Root], SCRes),
+ CR = cre_cmdReply(SCR),
+ AR = cre_actionReply(Cid, [CR]),
+ TRes = cre_transResult([AR]),
+ TR = {'TransactionReply', 1, asn1_NOVALUE, TRes},
+ Trans = cre_transaction(TR),
+ Mess = cre_message(1, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmmsr2_mgc_notify_request_msg(Mid, TransId, TermIDs, CIDs) ->
+ ARs = ssmmsr2_mgc_notify_request_ars(TermIDs, CIDs),
+ TR = cre_transReq(TransId, ARs),
+ Trans = cre_transaction(TR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmmsr2_mgc_notify_request_ars(TermIDs, CIDs) ->
+ ssmmsr2_mgc_notify_request_ars(TermIDs, CIDs, []).
+
+ssmmsr2_mgc_notify_request_ars([], [], Acc) ->
+ lists:reverse(Acc);
+ssmmsr2_mgc_notify_request_ars([TermID|TermIDs], [CID|CIDs], Acc) ->
+ AR = ssmmsr2_mgc_notify_request_ar(100+CID, TermID, CID),
+ ssmmsr2_mgc_notify_request_ars(TermIDs, CIDs, [AR|Acc]).
+
+ssmmsr2_mgc_notify_request_ar(Rid, Tid, Cid) ->
+ TT = cre_timeNotation(integer_to_list(19990720+Rid),
+ integer_to_list(22000000+Rid)),
+ Ev = cre_obsEvent("al/of", TT),
+ EvsDesc = cre_obsEvsDesc(Rid, [Ev]),
+ NR = cre_notifyReq([Tid], EvsDesc),
+ CMD = cre_command(NR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+ssmmsr2_mgc_segment_reply_msg(Mid, TransId, SN, Last) ->
+ SR = ssmmsr2_mgc_segment_reply(TransId, SN, Last),
+ Trans = cre_transaction(SR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+ssmmsr2_mgc_segment_reply(TransId, SN, true) ->
+ cre_segReply(TransId, SN, 'NULL');
+ssmmsr2_mgc_segment_reply(TransId, SN, false) ->
+ cre_segReply(TransId, SN, asn1_NOVALUE).
+
+%% ssmmsr2_mgc_trans_ack_msg(Mid, TransId) ->
+%% TA = cre_transAck(TransId),
+%% Trans = cre_transaction([TA]),
+%% Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+%% cre_megacoMessage(Mess).
+
+
+%%
+%% MG generator stuff
+%%
+ssmmsr2_mg_event_sequence(text, tcp) ->
+ Mid = {deviceName,"mg"},
+ RI = [
+ {port, 2944},
+ {encoding_module, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {transport_module, megaco_tcp}
+ ],
+ ConnectVerify = ssmmsr2_mg_verify_handle_connect_fun(),
+ ServiceChangeReq = ssmmsr2_mg_service_change_request_ar(Mid, 1),
+ ServiceChangeReplyVerify = ssmmsr2_mg_verify_service_change_reply_fun(),
+ Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ Tid4 = #megaco_term_id{id = ["00000000","00000000","00000004"]},
+ Tid5 = #megaco_term_id{id = ["00000000","00000000","00000005"]},
+ Tid6 = #megaco_term_id{id = ["00000000","00000000","00000006"]},
+ Tid7 = #megaco_term_id{id = ["00000000","00000000","00000007"]},
+ Tid8 = #megaco_term_id{id = ["00000000","00000000","00000008"]},
+ Tids = [Tid1, Tid2, Tid3, Tid4, Tid5, Tid6, Tid7, Tid8],
+ NotifyReqVerify = ssmmsr2_mg_verify_notify_request_fun(Tids),
+ AckVerify = ssmmsr2_mg_verify_ack_fun(),
+ ReadyForSegments = ssmmsr2_mg_ready_for_segments_fun(),
+ EvSeq = [
+ {debug, true},
+ {megaco_trace, disable},
+ %% {megaco_trace, max},
+ megaco_start,
+ {megaco_start_user, Mid, RI, []},
+ start_transport,
+ {megaco_system_info, users},
+ {megaco_system_info, connections},
+ connect,
+ {megaco_callback, handle_connect, ConnectVerify},
+ megaco_connect,
+ {megaco_cast, [ServiceChangeReq], []},
+ {megaco_callback, handle_connect, ConnectVerify},
+ {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify},
+ {megaco_update_conn_info, protocol_version, ?VERSION},
+ {megaco_update_conn_info, reply_timer, 12000},
+ {megaco_update_conn_info, segment_send, 1},
+ {megaco_update_conn_info, max_pdu_size, 128},
+ %% {sleep, 1000},
+ {trigger, ReadyForSegments},
+ {megaco_callback, handle_trans_request, NotifyReqVerify},
+ {megaco_callback, handle_trans_ack, AckVerify, 15000},
+ megaco_stop_user,
+ megaco_stop,
+ {sleep, 1000}
+ ],
+ EvSeq.
+
+
+ssmmsr2_mg_ready_for_segments_fun() ->
+ TC = self(),
+ fun() ->
+ io:format("ssmmsr2_mg_ready_for_segments_fun -> entry~n", []),
+ TC ! {ready_for_segments, mg, self()},
+ receive
+ {continue_with_segments, TC} ->
+ io:format("ssmmsr2_mg_ready_for_segments_fun -> "
+ "received continue~n", []),
+ ok
+ end
+ end.
+
+ssmmsr2_mg_verify_handle_connect_fun() ->
+ fun(Ev) -> ssmmsr2_mg_verify_handle_connect(Ev) end.
+
+ssmmsr2_mg_verify_handle_connect({handle_connect, CH, 1}) ->
+ io:format("ssmmsr2_mg_verify_handle_connect -> ok"
+ "~n CH: ~p~n", [CH]),
+ {ok, CH, ok};
+ssmmsr2_mg_verify_handle_connect(Else) ->
+ io:format("ssmmsr2_mg_verify_handle_connect -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, ok}.
+
+
+ssmmsr2_mg_verify_service_change_reply_fun() ->
+ fun(Rep) -> ssmmsr2_mg_verify_scr(Rep) end.
+
+ssmmsr2_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) ->
+ (catch ssmmsr2_mg_do_verify_scr(AR));
+ssmmsr2_mg_verify_scr(Crap) ->
+ io:format("ssmmsr2_mg_verify_scr -> error: "
+ "~n Crap: ~p"
+ "~n", [Crap]),
+ {error, Crap, ok}.
+
+ssmmsr2_mg_do_verify_scr(AR) ->
+ io:format("ssmmsr2_mg_do_verify_scr -> ok: "
+ "~n AR: ~p~n", [AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ SCR =
+ case CR of
+ {serviceChangeReply, ServChRep} ->
+ ServChRep;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ {Tid, SCRes} =
+ case SCR of
+ #'ServiceChangeReply'{terminationID = [TermID],
+ serviceChangeResult = Res} ->
+ {TermID, Res};
+ _ ->
+ Reason3 = {invalid_service_change_reply, SCR},
+ throw({error, Reason3, ok})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ Reason4 = {invalid_termination_id, Tid},
+ throw({error, Reason4, ok})
+ end,
+ SCRParm =
+ case SCRes of
+ {serviceChangeResParms, ServChResParms} ->
+ ServChResParms;
+ _ ->
+ Reason5 = {invalid_serviceChangeResult, SCRes},
+ throw({error, Reason5, ok})
+ end,
+ case SCRParm of
+ #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} ->
+ {ok, AR, ok};
+ _ ->
+ Reason6 = {invalid_service_change_result, SCRParm},
+ {error, Reason6, ok}
+ end.
+
+ssmmsr2_mg_verify_notify_request_fun(Tids) ->
+ fun(Req) -> ssmmsr2_mg_verify_notify_request(Req, Tids) end.
+
+ssmmsr2_mg_verify_notify_request(
+ {handle_trans_request, _CH, ?VERSION, ARs}, Tids)
+ when length(ARs) == length(Tids) ->
+ (catch ssmmsr2_mg_do_verify_notify_request(Tids, ARs));
+ssmmsr2_mg_verify_notify_request(
+ {handle_trans_request, _CH, ?VERSION, ARs}, _Tids) ->
+ {error, {invalid_action_requests, ARs}, ok};
+ssmmsr2_mg_verify_notify_request(
+ {handle_trans_request, CH, V, ARs}, _Tids) ->
+ {error, {invalid_trans_request, {CH, V, ARs}}, ok};
+ssmmsr2_mg_verify_notify_request(Crap, _Tids) ->
+ io:format("ssmmsr2_mg_verify_notify_request -> unknown request"
+ "~n Crap: ~p"
+ "~n Tids: ~p"
+ "~n", [Crap, _Tids]),
+ {error, {unexpected_event, Crap}, ok}.
+
+ssmmsr2_mg_do_verify_notify_request(Tids, ARs) ->
+ io:format("ssmmsr2_mg_do_verify_notify_request -> ok"
+ "~n Tids: ~p"
+ "~n ARs: ~p"
+ "~n", [Tids, ARs]),
+ ActionReplies = ssmmsr2_mg_do_verify_notify_request_ars(Tids, ARs),
+ io:format("ssmmsr2_mg_do_verify_notify_request -> ok"
+ "~n ActionReplies: ~p"
+ "~n", [ActionReplies]),
+ Reply = {{handle_ack, ssmmsr2}, ActionReplies},
+ {ok, ARs, Reply}.
+
+ssmmsr2_mg_do_verify_notify_request_ars(Tids, ARs) ->
+ ssmmsr2_mg_do_verify_notify_request_ars(Tids, ARs, []).
+
+ssmmsr2_mg_do_verify_notify_request_ars([], [], Acc) ->
+ lists:reverse(Acc);
+ssmmsr2_mg_do_verify_notify_request_ars([Tid|Tids], [AR|ARs], Acc) ->
+ ActionReply = ssmmsr2_mg_do_verify_notify_request_ar(Tid, AR),
+ ssmmsr2_mg_do_verify_notify_request_ars(Tids, ARs, [ActionReply|Acc]).
+
+ssmmsr2_mg_do_verify_notify_request_ar(Tid, AR) ->
+ io:format("ssmmsr2_mg_do_verify_notify_request_ar -> ok"
+ "~n Tid: ~p"
+ "~n AR: ~p"
+ "~n", [Tid, AR]),
+ {Cid, CR} =
+ case AR of
+ #'ActionRequest'{contextId = CtxId,
+ commandRequests = [CmdReq]} ->
+ {CtxId, CmdReq};
+ _ ->
+ Reason1 = {invalid_actionRequest, AR},
+ throw({error, Reason1, ok})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}, ok})
+ end,
+ OED =
+ case Cmd of
+ {notifyReq,
+ #'NotifyRequest'{terminationID = [Tid],
+ observedEventsDescriptor = ObsEvDesc,
+ errorDescriptor = asn1_NOVALUE}} ->
+ ObsEvDesc;
+ _ ->
+ throw({error, {invalid_command, Cmd}, ok})
+ end,
+ OE =
+ case OED of
+ #'ObservedEventsDescriptor'{observedEventLst = [ObsEv]} ->
+ ObsEv;
+ #'ObservedEventsDescriptor'{observedEventLst = ObsEvLst} ->
+ throw({error, {invalid_observedEventLst, ObsEvLst}, ok});
+ _ ->
+ throw({error, {invalid_ObservedEventsDescriptor, OED}, ok})
+ end,
+ case OE of
+ #'ObservedEvent'{eventName = "al/of"} ->
+ ssmmsr2_mg_notify_reply_ar(Cid, Tid);
+ _ ->
+ throw({error, {invalid_ObservedEvent, OE}, ok})
+ end.
+
+
+ssmmsr2_mg_verify_ack_fun() ->
+ fun(Event) -> (catch ssmmsr2_mg_verify_ack(Event)) end.
+
+ssmmsr2_mg_verify_ack({handle_trans_ack, CH, ?VERSION, AckStatus, ssmmsr2}) ->
+ io:format("ssmmsr2_mg_verify_ack -> "
+ "~n AckStatus: ~p"
+ "~n CH: ~p"
+ "~n", [AckStatus, CH]),
+ case AckStatus of
+ {error, Reason} ->
+ case Reason of
+ {segment_failure, SegInfo} when is_list(SegInfo) ->
+ io:format("ssmmsr2_mg_verify_ack -> verify not acked"
+ "~n", []),
+ case lists:keysearch(segments_not_acked, 1, SegInfo) of
+ {value, {segments_not_acked, [2]}} ->
+ ok;
+ {value, {segments_not_acked, SNs}} ->
+ X = {unexpected_not_acked_segments, SNs},
+ throw({error, X, ok});
+ false ->
+ X = {unexpected_seg_info, SegInfo},
+ throw({error, X, ok})
+ end,
+ io:format("ssmmsr2_mg_verify_ack -> verify not sent"
+ "~n", []),
+ case lists:keysearch(segments_not_sent, 1, SegInfo) of
+ {value, {segments_not_sent, NotSent}} ->
+ case [3,4,5,6,7,8] -- NotSent of
+ [] ->
+ {ok, CH, ok};
+ _ ->
+ Y = {unexpected_not_sent_segments,
+ NotSent},
+ throw({error, Y, ok})
+ end;
+ false ->
+ Y = {unexpected_seg_info, SegInfo},
+ throw({error, Y, ok})
+ end;
+ _ ->
+ X = {unexpected_reason, Reason},
+ {error, X, ok}
+ end;
+ _ ->
+ X = {unexpected_ack_status, AckStatus},
+ {error, X, ok}
+ end;
+ssmmsr2_mg_verify_ack({handle_trans_ack, CH, ?VERSION,
+ BadAckStatus, BadAckData}) ->
+ {error, {unknown_ack_status, BadAckStatus, BadAckData, CH}, ok};
+ssmmsr2_mg_verify_ack(BadEvent) ->
+ {error, {unknown_event, BadEvent}, ok}.
+
+
+ssmmsr2_mg_service_change_request_ar(_Mid, Cid) ->
+ Prof = cre_serviceChangeProf("resgw", 1),
+ SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReq([Root], SCP),
+ CMD = cre_command(SCR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+ssmmsr2_mg_notify_reply_ar(Cid, Tid) ->
+ NR = cre_notifyReply([Tid]),
+ CR = cre_cmdReply(NR),
+ cre_actionReply(Cid, [CR]).
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%% %%%
+%%% Segmented reply received test cases %%%
+%%% %%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+recv_segmented_msg_plain(suite) ->
+ [];
+recv_segmented_msg_plain(doc) ->
+ "Received segmented megaco message [plain]";
+recv_segmented_msg_plain(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, rsmp),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ d("[MGC] start the simulator "),
+ {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode),
+
+ d("[MGC] create the event sequence"),
+ MgcEvSeq = rsmp_mgc_event_sequence(text, tcp),
+
+ i("wait some time before starting the MGC simulation"),
+ sleep(1000),
+
+ d("[MGC] start the simulation"),
+ {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq),
+
+ i("wait some time before starting the MG simulator"),
+ sleep(1000),
+
+ d("[MG] start the simulator (generator)"),
+ {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode),
+
+ d("[MG] create the event sequence"),
+ MgEvSeq = rsmp_mg_event_sequence(text, tcp),
+
+ i("wait some time before starting the MG simulation"),
+ sleep(1000),
+
+ d("[MG] start the simulation"),
+ {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq),
+
+ d("await the generator reply(s)"),
+ await_completion([MgcId, MgId]),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop generator"),
+ megaco_test_tcp_generator:stop(Mgc),
+
+ %% Tell Mg to stop
+ i("[MG] stop generator"),
+ megaco_test_megaco_generator:stop(Mg),
+
+ i("done", []),
+ ok.
+
+
+%%
+%% MGC generator stuff
+%%
+
+rsmp_mgc_event_sequence(text, tcp) ->
+ DecodeFun = rsmp_mgc_decode_msg_fun(megaco_pretty_text_encoder, []),
+ EncodeFun = rsmp_mgc_encode_msg_fun(megaco_pretty_text_encoder, []),
+ Mid = {deviceName,"mgc"},
+ ScrVerifyFun = rsmp_mgc_verify_service_change_req_msg_fun(),
+ ServiceChangeRep = rsmp_mgc_service_change_reply_msg(Mid, 1),
+ TermId1 =
+ #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ TermId2 =
+ #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ TermId3 =
+ #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ TermIds = [TermId1, TermId2, TermId3],
+ TransId = 2,
+ ReqId = 1,
+ CtxId = 1,
+ NrVerifyFun =
+ rsmp_mgc_verify_notify_req_msg_fun(TermIds, TransId, ReqId, CtxId),
+ NotifyRep1 = rsmp_mgc_notify_reply_msg(1, Mid, TransId, CtxId, TermId1),
+ NotifyRep2 = rsmp_mgc_notify_reply_msg(2, Mid, TransId, CtxId, TermId2),
+ NotifyRep3 = rsmp_mgc_notify_reply_msg(3, Mid, TransId, CtxId, TermId3),
+ SrVerifyFun1 = rsmp_mgc_verify_segment_reply_msg_fun(1, TransId),
+ SrVerifyFun2 = rsmp_mgc_verify_segment_reply_msg_fun(2, TransId),
+ SrVerifyFun3 = rsmp_mgc_verify_segment_reply_msg_fun(3, TransId),
+ AckVerifyFun = rsmp_mgc_verify_trans_ack_msg_fun(TransId),
+ EvSeq = [{debug, false},
+ {decode, DecodeFun},
+ {encode, EncodeFun},
+ {listen, 2944},
+ {expect_accept, any},
+ {expect_receive, "service-change-request", {ScrVerifyFun, 5000}},
+ {sleep, 500},
+
+ {send, "service-change-reply", ServiceChangeRep},
+ {expect_receive, "notify-request(1)", {NrVerifyFun, 4000}},
+ {sleep, 500},
+
+ {send, "notify reply - segment 1", NotifyRep1},
+ {expect_receive, "segment reply 1", {SrVerifyFun1, 2000}},
+ {sleep, 500},
+
+ {send, "notify reply - segment 2", NotifyRep2},
+ {expect_receive, "segment reply 2", {SrVerifyFun2, 2000}},
+ {sleep, 500},
+
+ {send, "notify reply - segment 3 (last)", NotifyRep3},
+ {expect_receive, "segment reply 3 (last)", {SrVerifyFun3, 2000}},
+ {expect_receive, "ack", {AckVerifyFun, 4000}},
+ {sleep, 1000},
+ disconnect
+ ],
+ EvSeq.
+
+rsmp_mgc_encode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:encode_message(Conf, M)
+ end.
+
+rsmp_mgc_decode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:decode_message(Conf, M)
+ end.
+
+rsmp_mgc_verify_service_change_req_msg_fun() ->
+ fun(Msg) ->
+ (catch rsmp_mgc_verify_service_change_req(Msg))
+ end.
+
+rsmp_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) ->
+ io:format("rsmp_mgc_verify_service_change_req -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ Body =
+ case Mess of
+ #'Message'{version = 1,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = _TransId,
+ actions = [ActionReq]} ->
+ ActionReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ CR =
+ case AR of
+ #'ActionRequest'{contextId = _Cid,
+ commandRequests = [CmdReq]} ->
+ CmdReq;
+ _ ->
+ throw({error, {invalid_action, AR}})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}})
+ end,
+ {Tid, Parms} =
+ case Cmd of
+ {serviceChangeReq,
+ #'ServiceChangeRequest'{terminationID = [TermID],
+ serviceChangeParms = ServChParms}} ->
+ {TermID, ServChParms};
+ _ ->
+ throw({error, {invalid_command, Cmd}})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ throw({error, {invalid_terminationID, Tid}})
+ end,
+ case Parms of
+ %% Version 1 'ServiceChangeParm'
+ {'ServiceChangeParm',
+ restart, % serviceChangeMethod
+ asn1_NOVALUE, % serviceChangeAddress
+ ?VERSION, % serviceChangeVersion,
+ {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile
+ [[$9,$0,$1|_]], % serviceChangeReason
+ asn1_NOVALUE, % serviceChangeDelay
+ asn1_NOVALUE, % serviceChangeMgcId
+ asn1_NOVALUE, % timeStamp
+ asn1_NOVALUE % nonStandardData
+ } ->
+ {ok, M};
+ _ ->
+ {error, {invalid_serviceChangeParms, Parms}}
+ end.
+
+rsmp_mgc_verify_notify_req_msg_fun(TermIds, TransId, Rid, Cid) ->
+ fun(Msg) ->
+ (catch rsmp_mgc_verify_notify_req(Msg,
+ TermIds, TransId, Rid, Cid))
+ end.
+
+rsmp_mgc_verify_notify_req(#'MegacoMessage'{mess = Mess} = M,
+ TermIds, TransId, Rid, Cid) ->
+ io:format("rsmp_mgc_verify_notify_req -> entry with"
+ "~n M: ~p"
+ "~n TermIds: ~p"
+ "~n TransId: ~p"
+ "~n Rid: ~p"
+ "~n Cid: ~p"
+ "~n", [M, TermIds, TransId, Rid, Cid]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = TransId,
+ actions = [ActReq]} ->
+ ActReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ Cmds =
+ case AR of
+ #'ActionRequest'{contextId = Cid,
+ commandRequests = Commands} ->
+ Commands;
+ _ ->
+ throw({error, {invalid_actions, AR}})
+ end,
+ ok = rsmp_mgc_verify_notify_req_cmds(TermIds, Cmds),
+ {ok, M};
+rsmp_mgc_verify_notify_req(Crap, _TermId, _TransId, _Rid, _Cid) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+rsmp_mgc_verify_notify_req_cmds([], []) ->
+ ok;
+rsmp_mgc_verify_notify_req_cmds([TermId|TermIds], [Cmd|Cmds]) ->
+ rsmp_mgc_verify_notify_req_cmd(TermId, Cmd),
+ rsmp_mgc_verify_notify_req_cmds(TermIds, Cmds);
+rsmp_mgc_verify_notify_req_cmds(TermIds, Cmds) ->
+ throw({error, {invalid_commands, TermIds, Cmds}}).
+
+rsmp_mgc_verify_notify_req_cmd(TermId, #'CommandRequest'{command = Cmd}) ->
+ io:format("rsmp_mgc_verify_notify_req_cmd -> entry with"
+ "~n TermId: ~p"
+ "~n Cmd: ~p"
+ "~n", [TermId, Cmd]),
+ NR =
+ case Cmd of
+ {notifyReq, NotifReq} ->
+ NotifReq;
+ _ ->
+ throw({error, {invalid_command}})
+ end,
+ OED =
+ case NR of
+ #'NotifyRequest'{terminationID = [TermId],
+ observedEventsDescriptor = ObsEvsDesc,
+ errorDescriptor = asn1_NOVALUE} ->
+ ObsEvsDesc;
+ _ ->
+ throw({error, {invalid_notifyReq, NR}})
+ end,
+ OE =
+ case OED of
+ #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} ->
+ ObsEvLst;
+ _ ->
+ throw({error, {invalid_observedEventsDescriptor, OED}})
+ end,
+ case OE of
+ #'ObservedEvent'{eventName = "al/of"} ->
+ ok;
+ _ ->
+ throw({error, {invalid_observedEventLst, OE}})
+ end;
+rsmp_mgc_verify_notify_req_cmd(_, BadCmdReq) ->
+ io:format("rsmp_mgc_verify_notify_req_cmd -> invalid"
+ "~n BadCmdReq: ~p"
+ "~n", [BadCmdReq]),
+ throw({error, {invalid_CommandRequest, BadCmdReq}}).
+
+rsmp_mgc_verify_segment_reply_msg_fun(SN, TransId) ->
+ fun(Msg) ->
+ (catch rsmp_mgc_verify_segment_reply(Msg, SN, TransId))
+ end.
+
+rsmp_mgc_verify_segment_reply(#'MegacoMessage'{mess = Mess} = M,
+ SN, TransId) ->
+ io:format("rsmp_mgc_verify_segment_reply -> entry with"
+ "~n SN: ~p"
+ "~n TransId: ~p"
+ "~n M: ~p"
+ "~n", [SN, TransId, M]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ SR =
+ case Trans of
+ {segmentReply, SegmentReply} ->
+ SegmentReply;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ case SR of
+ #'SegmentReply'{transactionId = TransId,
+ segmentNumber = SN,
+ segmentationComplete = 'NULL'} when SN == 3 ->
+ {ok, M};
+ #'SegmentReply'{transactionId = TransId,
+ segmentNumber = SN,
+ segmentationComplete = asn1_NOVALUE} ->
+ {ok, M};
+ _ ->
+ throw({error, {invalid_segmentReply, SR}})
+ end;
+rsmp_mgc_verify_segment_reply(Crap, SN, TransId) ->
+ io:format("rsmp_mgc_verify_segment_reply -> invalid: "
+ "~n SN: ~p"
+ "~n TransId: ~p"
+ "~n Crap: ~p"
+ "~n", [SN, TransId, Crap]),
+ {error, {invalid_MegacoMessage, Crap, SN, TransId}}.
+
+rsmp_mgc_verify_trans_ack_msg_fun(TransId) ->
+ fun(Msg) ->
+ (catch rsmp_mgc_verify_trans_ack(Msg, TransId))
+ end.
+
+rsmp_mgc_verify_trans_ack(#'MegacoMessage'{mess = Mess} = M, TransId) ->
+ io:format("rsmp_mgc_verify_trans_ack -> entry with"
+ "~n TransId: ~p"
+ "~n M: ~p"
+ "~n", [TransId, M]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TA =
+ case Trans of
+ {transactionResponseAck, [TransAck]} ->
+ TransAck;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ case TA of
+ #'TransactionAck'{firstAck = TransId,
+ lastAck = asn1_NOVALUE} ->
+ {ok, M};
+ _ ->
+ throw({error, {invalid_transactionResponseAck, TA}})
+ end;
+rsmp_mgc_verify_trans_ack(Crap, _TransId) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+rsmp_mgc_service_change_reply_msg(Mid, Cid) ->
+ SCRP = cre_serviceChangeResParm(Mid),
+ SCRes = cre_serviceChangeResult(SCRP),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReply([Root], SCRes),
+ CR = cre_cmdReply(SCR),
+ AR = cre_actionReply(Cid, [CR]),
+ TRes = cre_transResult([AR]),
+ TR = {'TransactionReply', 1, asn1_NOVALUE, TRes},
+ Trans = cre_transaction(TR),
+ Mess = cre_message(1, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+rsmp_mgc_notify_reply_ar(Cid, TermId) ->
+ NR = cre_notifyReply([TermId]),
+ CR = cre_cmdReply(NR),
+ cre_actionReply(Cid, [CR]).
+
+rsmp_mgc_notify_reply_msg(SN, Mid, TransId, Cid, TermId) ->
+ AR = rsmp_mgc_notify_reply_ar(Cid, TermId),
+ TRes = cre_transResult([AR]),
+ TR =
+ if
+ SN == 3 ->
+ cre_transReply(TransId, TRes, SN, 'NULL');
+ true ->
+ cre_transReply(TransId, TRes, SN)
+ end,
+ Trans = cre_transaction(TR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+
+%%
+%% MG generator stuff
+%%
+rsmp_mg_event_sequence(text, tcp) ->
+ Mid = {deviceName,"mg"},
+ RI = [
+ {port, 2944},
+ {encoding_module, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {transport_module, megaco_tcp}
+ ],
+ ServiceChangeReq = rsmp_mg_service_change_request_ar(Mid, 1),
+ ConnectVerify = rsmp_mg_verify_handle_connect_fun(),
+ ServiceChangeReplyVerify = rsmp_mg_verify_service_change_reply_fun(),
+ Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ Tids = [Tid1, Tid2, Tid3],
+ NotifyReq = rsmp_mg_notify_request_ar(1, Tids, 1),
+ NotifyReplyVerify1 = rsmp_mg_verify_notify_reply_fun(1, Tid1),
+ NotifyReplyVerify2 = rsmp_mg_verify_notify_reply_fun(2, Tid2),
+ NotifyReplyVerify3 = rsmp_mg_verify_notify_reply_fun(3, Tid3),
+ EvSeq = [
+ {debug, true},
+ %% {megaco_trace, disable},
+ {megaco_trace, max},
+ megaco_start,
+ {megaco_start_user, Mid, RI, []},
+ start_transport,
+ {megaco_system_info, users},
+ {megaco_system_info, connections},
+ connect,
+ {megaco_callback, handle_connect, ConnectVerify},
+ megaco_connect,
+ {megaco_cast, [ServiceChangeReq], []},
+ {megaco_callback, handle_connect, ConnectVerify},
+ {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify},
+ {megaco_update_user_info, protocol_version, ?VERSION},
+ {megaco_update_conn_info, protocol_version, ?VERSION},
+ {sleep, 1000},
+ {megaco_cast, [NotifyReq], []},
+ {megaco_callback, handle_trans_reply, NotifyReplyVerify1},
+ {megaco_callback, handle_trans_reply, NotifyReplyVerify2},
+ {megaco_callback, handle_trans_reply, NotifyReplyVerify3},
+ {sleep, 1000},
+ megaco_stop_user,
+ megaco_stop,
+ {sleep, 1000}
+ ],
+ EvSeq.
+
+
+rsmp_mg_verify_handle_connect_fun() ->
+ fun(Ev) -> rsmp_mg_verify_handle_connect(Ev) end.
+
+rsmp_mg_verify_handle_connect({handle_connect, CH, 1}) ->
+ io:format("rsmp_mg_verify_handle_connect -> ok"
+ "~n CH: ~p~n", [CH]),
+ {ok, CH, ok};
+rsmp_mg_verify_handle_connect(Else) ->
+ io:format("rsmp_mg_verify_handle_connect -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, ok}.
+
+
+rsmp_mg_verify_service_change_reply_fun() ->
+ fun(Rep) -> rsmp_mg_verify_scr(Rep) end.
+
+rsmp_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) ->
+ (catch rsmp_mg_do_verify_scr(AR));
+rsmp_mg_verify_scr(Crap) ->
+ io:format("rsmp_mg_verify_scr -> error: "
+ "~n Crap: ~p"
+ "~n", [Crap]),
+ {error, Crap, ok}.
+
+rsmp_mg_do_verify_scr(AR) ->
+ io:format("rsmp_mg_do_verify_scr -> ok: "
+ "~n AR: ~p~n", [AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ SCR =
+ case CR of
+ {serviceChangeReply, ServChRep} ->
+ ServChRep;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ {Tid, SCRes} =
+ case SCR of
+ #'ServiceChangeReply'{terminationID = [TermID],
+ serviceChangeResult = Res} ->
+ {TermID, Res};
+ _ ->
+ Reason3 = {invalid_service_change_reply, SCR},
+ throw({error, Reason3, ok})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ Reason4 = {invalid_termination_id, Tid},
+ throw({error, Reason4, ok})
+ end,
+ SCRParm =
+ case SCRes of
+ {serviceChangeResParms, ServChResParms} ->
+ ServChResParms;
+ _ ->
+ Reason5 = {invalid_serviceChangeResult, SCRes},
+ throw({error, Reason5, ok})
+ end,
+ case SCRParm of
+ #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} ->
+ {ok, AR, ok};
+ _ ->
+ Reason6 = {invalid_service_change_result, SCRParm},
+ {error, Reason6, ok}
+ end.
+
+rsmp_mg_verify_notify_reply_fun(SN, Tid) ->
+ fun(Rep) -> rsmp_mg_verify_notify_reply(Rep, SN, Tid) end.
+
+rsmp_mg_verify_notify_reply(
+ {handle_trans_reply, _CH, ?VERSION, {ok, {SN, Last, [AR]}}, _}, SN, Tid)
+ when ((SN =:= 3) andalso (Last =:= true)) orelse
+ ((SN =/= 3) andalso (Last =:= false)) ->
+ (catch rsmp_mg_do_verify_notify_reply(Tid, AR));
+rsmp_mg_verify_notify_reply(
+ {handle_trans_reply, _CH, Version, {ok, {SN1, Last, ARs}}, _}, SN2, Tid) ->
+ io:format("rsmp_mg_verify_notify_reply -> unknown reply"
+ "~n Version: ~p"
+ "~n SN1: ~p"
+ "~n Last: ~p"
+ "~n ARs: ~p"
+ "~n SN2: ~p"
+ "~n Tid: ~p"
+ "~n", [Version, SN1, Last, ARs, SN2, Tid]),
+ Crap = {unexpected_segment_data, [SN1, Last, ARs, SN2, Tid]},
+ {error, Crap, ok};
+rsmp_mg_verify_notify_reply(Crap, SN, Tid) ->
+ io:format("rsmp_mg_verify_notify_reply -> unknown reply"
+ "~n SN: ~p"
+ "~n Tid: ~p"
+ "~n Crap: ~p"
+ "~n", [SN, Tid, Crap]),
+ {error, Crap, ok}.
+
+rsmp_mg_do_verify_notify_reply(Tid, AR) ->
+ io:format("rsmp_mg_do_verify_notify_reply -> ok"
+ "~n Tid: ~p"
+ "~n AR: ~p"
+ "~n", [Tid, AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ NR =
+ case CR of
+ {notifyReply, NotifyReply} ->
+ NotifyReply;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ case NR of
+ #'NotifyReply'{terminationID = [Tid],
+ errorDescriptor = asn1_NOVALUE} ->
+ {ok, AR, ok};
+ _ ->
+ Reason3 = {invalid_NotifyReply, NR},
+ {error, Reason3, ok}
+ end.
+
+
+rsmp_mg_service_change_request_ar(_Mid, Cid) ->
+ Prof = cre_serviceChangeProf("resgw", 1),
+ SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReq([Root], SCP),
+ CMD = cre_command(SCR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+rsmp_mg_notify_request_ar(Rid, Tids, Cid) ->
+ rsmp_mg_notify_request_ar(Rid, Tids, Cid, []).
+
+rsmp_mg_notify_request_ar(_Rid, [], Cid, Cmds) ->
+ cre_actionReq(Cid, lists:reverse(Cmds));
+rsmp_mg_notify_request_ar(Rid, [Tid|Tids], Cid, Cmds) ->
+ TT = cre_timeNotation("19990729", "22000000"),
+ Ev = cre_obsEvent("al/of", TT),
+ EvsDesc = cre_obsEvsDesc(Rid, [Ev]),
+ NR = cre_notifyReq([Tid], EvsDesc),
+ CMD = cre_command(NR),
+ CR = cre_cmdReq(CMD),
+ rsmp_mg_notify_request_ar(Rid, Tids, Cid, [CR|Cmds]).
+
+%% rsmp_internalError(Text) ->
+%% Code = ?megaco_internal_gateway_error,
+%% cre_errorDesc(Code, Text).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+recv_segmented_msg_ooo_seg(suite) ->
+ [];
+recv_segmented_msg_ooo_seg(doc) ->
+ "Received segmented megaco message [out-of-order segments]";
+recv_segmented_msg_ooo_seg(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, rsmos),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ d("[MGC] start the simulator "),
+ {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode),
+
+ d("[MGC] create the event sequence"),
+ MgcEvSeq = rsmos_mgc_event_sequence(text, tcp),
+
+ i("wait some time before starting the MGC simulation"),
+ sleep(1000),
+
+ d("[MGC] start the simulation"),
+ {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq),
+
+ i("wait some time before starting the MG simulator"),
+ sleep(1000),
+
+ d("[MG] start the simulator (generator)"),
+ {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode),
+
+ d("[MG] create the event sequence"),
+ MgEvSeq = rsmos_mg_event_sequence(text, tcp),
+
+ i("wait some time before starting the MG simulation"),
+ sleep(1000),
+
+ d("[MG] start the simulation"),
+ {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq),
+
+ d("await the generator reply(s)"),
+ await_completion([MgcId, MgId]),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop generator"),
+ megaco_test_tcp_generator:stop(Mgc),
+
+ %% Tell Mg to stop
+ i("[MG] stop generator"),
+ megaco_test_megaco_generator:stop(Mg),
+
+ i("done", []),
+ ok.
+
+
+%%
+%% MGC generator stuff
+%%
+
+rsmos_mgc_event_sequence(text, tcp) ->
+ DecodeFun = rsmos_mgc_decode_msg_fun(megaco_pretty_text_encoder, []),
+ EncodeFun = rsmos_mgc_encode_msg_fun(megaco_pretty_text_encoder, []),
+ Mid = {deviceName,"mgc"},
+ ScrVerifyFun = rsmos_mgc_verify_service_change_req_msg_fun(),
+ ServiceChangeRep = rsmos_mgc_service_change_reply_msg(Mid, 1),
+ TermId1 =
+ #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ TermId2 =
+ #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ TermId3 =
+ #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ TermIds = [TermId1, TermId2, TermId3],
+ TransId = 2,
+ ReqId = 1,
+ CtxId = 1,
+ NrVerifyFun =
+ rsmos_mgc_verify_notify_req_msg_fun(TermIds, TransId, ReqId, CtxId),
+ NotifyRep1 = rsmos_mgc_notify_reply_msg(1, Mid, TransId, CtxId, TermId1),
+ NotifyRep2 = rsmos_mgc_notify_reply_msg(2, Mid, TransId, CtxId, TermId2),
+ NotifyRep3 = rsmos_mgc_notify_reply_msg(3, Mid, TransId, CtxId, TermId3),
+ SrVerifyFun1 = rsmos_mgc_verify_segment_reply_msg_fun(1, TransId),
+ SrVerifyFun2 = rsmos_mgc_verify_segment_reply_msg_fun(2, TransId),
+ SrVerifyFun3 = rsmos_mgc_verify_segment_reply_msg_fun(3, TransId),
+ AckVerifyFun = rsmos_mgc_verify_trans_ack_msg_fun(TransId),
+ EvSeq = [{debug, false},
+ {decode, DecodeFun},
+ {encode, EncodeFun},
+ {listen, 2944},
+ {expect_accept, any},
+ {expect_receive, "service-change-request", {ScrVerifyFun, 5000}},
+ {send, "service-change-reply", ServiceChangeRep},
+ {expect_receive, "notify-request", {NrVerifyFun, 4000}},
+ {send, "notify reply - segment 3", NotifyRep3},
+ {expect_receive, "segment reply 3", {SrVerifyFun3, 2000}},
+ {sleep, 1000},
+ {send, "notify reply - segment 2", NotifyRep2},
+ {expect_receive, "segment reply 2", {SrVerifyFun2, 2000}},
+ {sleep, 1000},
+ {send, "notify reply - segment 1 (last)", NotifyRep1},
+ {expect_receive, "segment reply 1 (last)", {SrVerifyFun1, 2000}},
+ {expect_receive, "ack", {AckVerifyFun, 4000}},
+ {expect_nothing, 10000},
+ disconnect
+ ],
+ EvSeq.
+
+rsmos_mgc_encode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:encode_message(Conf, M)
+ end.
+
+rsmos_mgc_decode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:decode_message(Conf, M)
+ end.
+
+rsmos_mgc_verify_service_change_req_msg_fun() ->
+ fun(Msg) ->
+ (catch rsmos_mgc_verify_service_change_req(Msg))
+ end.
+
+rsmos_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) ->
+ io:format("rsmos_mgc_verify_service_change_req -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ Body =
+ case Mess of
+ #'Message'{version = 1,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = _TransId,
+ actions = [ActionReq]} ->
+ ActionReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ CR =
+ case AR of
+ #'ActionRequest'{contextId = _Cid,
+ commandRequests = [CmdReq]} ->
+ CmdReq;
+ _ ->
+ throw({error, {invalid_action, AR}})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}})
+ end,
+ {Tid, Parms} =
+ case Cmd of
+ {serviceChangeReq,
+ #'ServiceChangeRequest'{terminationID = [TermID],
+ serviceChangeParms = ServChParms}} ->
+ {TermID, ServChParms};
+ _ ->
+ throw({error, {invalid_command, Cmd}})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ throw({error, {invalid_terminationID, Tid}})
+ end,
+ case Parms of
+ %% Version 1 'ServiceChangeParm'
+ {'ServiceChangeParm',
+ restart, % serviceChangeMethod
+ asn1_NOVALUE, % serviceChangeAddress
+ ?VERSION, % serviceChangeVersion,
+ {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile
+ [[$9,$0,$1|_]], % serviceChangeReason
+ asn1_NOVALUE, % serviceChangeDelay
+ asn1_NOVALUE, % serviceChangeMgcId
+ asn1_NOVALUE, % timeStamp
+ asn1_NOVALUE % nonStandardData
+ } ->
+ {ok, M};
+ _ ->
+ {error, {invalid_serviceChangeParms, Parms}}
+ end.
+
+rsmos_mgc_verify_notify_req_msg_fun(TermIds, TransId, Rid, Cid) ->
+ fun(Msg) ->
+ (catch rsmos_mgc_verify_notify_req(Msg,
+ TermIds, TransId, Rid, Cid))
+ end.
+
+rsmos_mgc_verify_notify_req(#'MegacoMessage'{mess = Mess} = M,
+ TermIds, TransId, Rid, Cid) ->
+ io:format("rsmos_mgc_verify_notify_req -> entry with"
+ "~n M: ~p"
+ "~n TermIds: ~p"
+ "~n TransId: ~p"
+ "~n Rid: ~p"
+ "~n Cid: ~p"
+ "~n", [M, TermIds, TransId, Rid, Cid]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = TransId,
+ actions = [ActReq]} ->
+ ActReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ Cmds =
+ case AR of
+ #'ActionRequest'{contextId = Cid,
+ commandRequests = Commands} ->
+ Commands;
+ _ ->
+ throw({error, {invalid_actions, AR}})
+ end,
+ ok = rsmos_mgc_verify_notify_req_cmds(TermIds, Cmds),
+ {ok, M};
+rsmos_mgc_verify_notify_req(Crap, _TermId, _TransId, _Rid, _Cid) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+rsmos_mgc_verify_notify_req_cmds([], []) ->
+ ok;
+rsmos_mgc_verify_notify_req_cmds([TermId|TermIds], [Cmd|Cmds]) ->
+ rsmos_mgc_verify_notify_req_cmd(TermId, Cmd),
+ rsmos_mgc_verify_notify_req_cmds(TermIds, Cmds);
+rsmos_mgc_verify_notify_req_cmds(TermIds, Cmds) ->
+ throw({error, {invalid_commands, TermIds, Cmds}}).
+
+rsmos_mgc_verify_notify_req_cmd(TermId, #'CommandRequest'{command = Cmd}) ->
+ io:format("rsmos_mgc_verify_notify_req_cmd -> entry with"
+ "~n TermId: ~p"
+ "~n Cmd: ~p"
+ "~n", [TermId, Cmd]),
+ NR =
+ case Cmd of
+ {notifyReq, NotifReq} ->
+ NotifReq;
+ _ ->
+ throw({error, {invalid_command}})
+ end,
+ OED =
+ case NR of
+ #'NotifyRequest'{terminationID = [TermId],
+ observedEventsDescriptor = ObsEvsDesc,
+ errorDescriptor = asn1_NOVALUE} ->
+ ObsEvsDesc;
+ _ ->
+ throw({error, {invalid_notifyReq, NR}})
+ end,
+ OE =
+ case OED of
+ #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} ->
+ ObsEvLst;
+ _ ->
+ throw({error, {invalid_observedEventsDescriptor, OED}})
+ end,
+ case OE of
+ #'ObservedEvent'{eventName = "al/of"} ->
+ ok;
+ _ ->
+ throw({error, {invalid_observedEventLst, OE}})
+ end;
+rsmos_mgc_verify_notify_req_cmd(_, BadCmdReq) ->
+ io:format("rsmos_mgc_verify_notify_req_cmd -> invalid"
+ "~n BadCmdReq: ~p"
+ "~n", [BadCmdReq]),
+ throw({error, {invalid_CommandRequest, BadCmdReq}}).
+
+rsmos_mgc_verify_segment_reply_msg_fun(SN, TransId) ->
+ fun(Msg) ->
+ (catch rsmos_mgc_verify_segment_reply(Msg, SN, TransId))
+ end.
+
+rsmos_mgc_verify_segment_reply(#'MegacoMessage'{mess = Mess} = M,
+ SN, TransId) ->
+ io:format("rsmos_mgc_verify_segment_reply -> entry with"
+ "~n SN: ~p"
+ "~n TransId: ~p"
+ "~n M: ~p"
+ "~n", [SN, TransId, M]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ SR =
+ case Trans of
+ {segmentReply, SegmentReply} ->
+ SegmentReply;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ case SR of
+ #'SegmentReply'{transactionId = TransId,
+ segmentNumber = SN,
+ segmentationComplete = 'NULL'} when SN == 3 ->
+ {ok, M};
+ #'SegmentReply'{transactionId = TransId,
+ segmentNumber = SN,
+ segmentationComplete = asn1_NOVALUE} ->
+ {ok, M};
+ _ ->
+ throw({error, {invalid_segmentReply, SR}})
+ end;
+rsmos_mgc_verify_segment_reply(Crap, SN, TransId) ->
+ io:format("rsmos_mgc_verify_segment_reply -> invalid: "
+ "~n SN: ~p"
+ "~n TransId: ~p"
+ "~n Crap: ~p"
+ "~n", [SN, TransId, Crap]),
+ {error, {invalid_MegacoMessage, Crap, SN, TransId}}.
+
+rsmos_mgc_verify_trans_ack_msg_fun(TransId) ->
+ fun(Msg) ->
+ (catch rsmos_mgc_verify_trans_ack(Msg, TransId))
+ end.
+
+rsmos_mgc_verify_trans_ack(#'MegacoMessage'{mess = Mess} = M, TransId) ->
+ io:format("rsmos_mgc_verify_trans_ack -> entry with"
+ "~n TransId: ~p"
+ "~n M: ~p"
+ "~n", [TransId, M]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TA =
+ case Trans of
+ {transactionResponseAck, [TransAck]} ->
+ TransAck;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ case TA of
+ #'TransactionAck'{firstAck = TransId,
+ lastAck = asn1_NOVALUE} ->
+ {ok, M};
+ _ ->
+ throw({error, {invalid_transactionResponseAck, TA}})
+ end;
+rsmos_mgc_verify_trans_ack(Crap, _TransId) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+rsmos_mgc_service_change_reply_msg(Mid, Cid) ->
+ SCRP = cre_serviceChangeResParm(Mid),
+ SCRes = cre_serviceChangeResult(SCRP),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReply([Root], SCRes),
+ CR = cre_cmdReply(SCR),
+ AR = cre_actionReply(Cid, [CR]),
+ TRes = cre_transResult([AR]),
+ TR = {'TransactionReply', 1, asn1_NOVALUE, TRes},
+ Trans = cre_transaction(TR),
+ Mess = cre_message(1, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+rsmos_mgc_notify_reply_ar(Cid, TermId) ->
+ NR = cre_notifyReply([TermId]),
+ CR = cre_cmdReply(NR),
+ cre_actionReply(Cid, [CR]).
+
+rsmos_mgc_notify_reply_msg(SN, Mid, TransId, Cid, TermId) ->
+ AR = rsmos_mgc_notify_reply_ar(Cid, TermId),
+ TRes = cre_transResult([AR]),
+ TR =
+ if
+ SN == 3 ->
+ cre_transReply(TransId, TRes, SN, 'NULL');
+ true ->
+ cre_transReply(TransId, TRes, SN)
+ end,
+ Trans = cre_transaction(TR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+
+%%
+%% MG generator stuff
+%%
+rsmos_mg_event_sequence(text, tcp) ->
+ Mid = {deviceName,"mg"},
+ RI = [
+ {port, 2944},
+ {encoding_module, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {transport_module, megaco_tcp}
+ ],
+ ServiceChangeReq = rsmos_mg_service_change_request_ar(Mid, 1),
+ ConnectVerify = rsmos_mg_verify_handle_connect_fun(),
+ ServiceChangeReplyVerify = rsmos_mg_verify_service_change_reply_fun(),
+ Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ Tids = [Tid1, Tid2, Tid3],
+ NotifyReq = rsmos_mg_notify_request_ar(1, Tids, 1),
+ NotifyReplyVerify1 = rsmos_mg_verify_notify_reply_fun(1, Tid1),
+ NotifyReplyVerify2 = rsmos_mg_verify_notify_reply_fun(2, Tid2),
+ NotifyReplyVerify3 = rsmos_mg_verify_notify_reply_fun(3, Tid3),
+ DiscoVerify = rsmos_mg_verify_handle_disco_fun(),
+ EvSeq = [
+ {debug, true},
+ %% {megaco_trace, disable},
+ {megaco_trace, max},
+ megaco_start,
+ {megaco_start_user, Mid, RI, []},
+ start_transport,
+ {megaco_system_info, users},
+ {megaco_system_info, connections},
+ {megaco_update_user_info, segment_recv_timer, 3000},
+ connect,
+ {megaco_callback, handle_connect, ConnectVerify},
+ megaco_connect,
+ {megaco_cast, [ServiceChangeReq], []},
+ {megaco_callback, handle_connect, ConnectVerify},
+ {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify},
+ {megaco_update_conn_info, protocol_version, ?VERSION},
+ {sleep, 1000},
+ {megaco_cast, [NotifyReq], []},
+ {megaco_callback, handle_trans_reply, NotifyReplyVerify3},
+ {megaco_callback, handle_trans_reply, NotifyReplyVerify2},
+ {megaco_callback, handle_trans_reply, NotifyReplyVerify1},
+ {megaco_callback, handle_disconnect, DiscoVerify},
+ megaco_stop_user,
+ megaco_stop
+ ],
+ EvSeq.
+
+
+rsmos_mg_verify_handle_connect_fun() ->
+ fun(Ev) -> rsmos_mg_verify_handle_connect(Ev) end.
+
+rsmos_mg_verify_handle_connect({handle_connect, CH, 1}) ->
+ io:format("rsmos_mg_verify_handle_connect -> ok"
+ "~n CH: ~p~n", [CH]),
+ {ok, CH, ok};
+rsmos_mg_verify_handle_connect(Else) ->
+ io:format("rsmos_mg_verify_handle_connect -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, ok}.
+
+
+rsmos_mg_verify_service_change_reply_fun() ->
+ fun(Rep) -> rsmos_mg_verify_scr(Rep) end.
+
+rsmos_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) ->
+ (catch rsmos_mg_do_verify_scr(AR));
+rsmos_mg_verify_scr(Crap) ->
+ io:format("rsmos_mg_verify_scr -> error: "
+ "~n Crap: ~p"
+ "~n", [Crap]),
+ {error, Crap, ok}.
+
+rsmos_mg_do_verify_scr(AR) ->
+ io:format("rsmos_mg_do_verify_scr -> ok: "
+ "~n AR: ~p~n", [AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ SCR =
+ case CR of
+ {serviceChangeReply, ServChRep} ->
+ ServChRep;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ {Tid, SCRes} =
+ case SCR of
+ #'ServiceChangeReply'{terminationID = [TermID],
+ serviceChangeResult = Res} ->
+ {TermID, Res};
+ _ ->
+ Reason3 = {invalid_service_change_reply, SCR},
+ throw({error, Reason3, ok})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ Reason4 = {invalid_termination_id, Tid},
+ throw({error, Reason4, ok})
+ end,
+ SCRParm =
+ case SCRes of
+ {serviceChangeResParms, ServChResParms} ->
+ ServChResParms;
+ _ ->
+ Reason5 = {invalid_serviceChangeResult, SCRes},
+ throw({error, Reason5, ok})
+ end,
+ case SCRParm of
+ #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} ->
+ {ok, AR, ok};
+ _ ->
+ Reason6 = {invalid_service_change_result, SCRParm},
+ {error, Reason6, ok}
+ end.
+
+rsmos_mg_verify_notify_reply_fun(SN, Tid) ->
+ fun(Rep) -> rsmos_mg_verify_notify_reply(Rep, SN, Tid) end.
+
+rsmos_mg_verify_notify_reply(
+ {handle_trans_reply, _CH, ?VERSION, {ok, {SN, Last, [AR]}}, _}, SN, Tid)
+ when ((SN == 1) and (Last == true)) or
+ ((SN =/= 1) and (Last == false)) ->
+ (catch rsmos_mg_do_verify_notify_reply(Tid, AR));
+rsmos_mg_verify_notify_reply(Crap, SN, Tid) ->
+ io:format("rsmos_mg_verify_notify_reply -> unknown reply"
+ "~n SN: ~p"
+ "~n Tid: ~p"
+ "~n Crap: ~p"
+ "~n", [SN, Tid, Crap]),
+ {error, Crap, ok}.
+
+rsmos_mg_do_verify_notify_reply(Tid, AR) ->
+ io:format("rsmos_mg_do_verify_notify_reply -> ok"
+ "~n Tid: ~p"
+ "~n AR: ~p"
+ "~n", [Tid, AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ NR =
+ case CR of
+ {notifyReply, NotifyReply} ->
+ NotifyReply;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ case NR of
+ #'NotifyReply'{terminationID = [Tid],
+ errorDescriptor = asn1_NOVALUE} ->
+ {ok, AR, ok};
+ _ ->
+ Reason3 = {invalid_NotifyReply, NR},
+ {error, Reason3, ok}
+ end.
+
+rsmos_mg_verify_handle_disco_fun() ->
+ fun(Ev) -> rsmos_mg_verify_handle_disconnect(Ev) end.
+
+rsmos_mg_verify_handle_disconnect({handle_disconnect, _CH, ?VERSION, R}) ->
+ io:format("rsmos_mg_verify_handle_disconnect -> ok"
+ "~n R: ~p"
+ "~n", [R]),
+ case R of
+ {no_controlling_process,shutdown} ->
+ {ok, R, ok};
+ _ ->
+ {error, {unexpected_reason, R}, ok}
+ end;
+rsmos_mg_verify_handle_disconnect(Crap) ->
+ io:format("rsmos_mg_verify_handle_disconnect -> invalid: "
+ "~n Crap: ~p"
+ "~n", [Crap]),
+ {error, Crap, ok}.
+
+
+rsmos_mg_service_change_request_ar(_Mid, Cid) ->
+ Prof = cre_serviceChangeProf("resgw", 1),
+ SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReq([Root], SCP),
+ CMD = cre_command(SCR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+rsmos_mg_notify_request_ar(Rid, Tids, Cid) ->
+ rsmos_mg_notify_request_ar(Rid, Tids, Cid, []).
+
+rsmos_mg_notify_request_ar(_Rid, [], Cid, Cmds) ->
+ cre_actionReq(Cid, lists:reverse(Cmds));
+rsmos_mg_notify_request_ar(Rid, [Tid|Tids], Cid, Cmds) ->
+ TT = cre_timeNotation("19990729", "22000000"),
+ Ev = cre_obsEvent("al/of", TT),
+ EvsDesc = cre_obsEvsDesc(Rid, [Ev]),
+ NR = cre_notifyReq([Tid], EvsDesc),
+ CMD = cre_command(NR),
+ CR = cre_cmdReq(CMD),
+ rsmos_mg_notify_request_ar(Rid, Tids, Cid, [CR|Cmds]).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+recv_segmented_msg_missing_seg1(suite) ->
+ [];
+recv_segmented_msg_missing_seg1(doc) ->
+ "Received segmented megaco message with one segment missing "
+ "using plain integer recv segment timer";
+recv_segmented_msg_missing_seg1(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, rsmms1),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ d("[MGC] start the simulator "),
+ {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode),
+
+ d("[MGC] create the event sequence"),
+ MgcEvSeq = rsmms1_mgc_event_sequence(text, tcp),
+
+ i("wait some time before starting the MGC simulation"),
+ sleep(1000),
+
+ d("[MGC] start the simulation"),
+ {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq),
+
+ i("wait some time before starting the MG simulator"),
+ sleep(1000),
+
+ d("[MG] start the simulator (generator)"),
+ {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode),
+
+ d("[MG] create the event sequence"),
+ MgEvSeq = rsmms1_mg_event_sequence(text, tcp),
+
+ i("wait some time before starting the MG simulation"),
+ sleep(1000),
+
+ d("[MG] start the simulation"),
+ {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq),
+
+ d("await the generator reply(s)"),
+ await_completion([MgcId, MgId]),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop generator"),
+ megaco_test_tcp_generator:stop(Mgc),
+
+ %% Tell Mg to stop
+ i("[MG] stop generator"),
+ megaco_test_megaco_generator:stop(Mg),
+
+ i("done", []),
+ ok.
+
+
+%%
+%% MGC generator stuff
+%%
+
+rsmms1_mgc_event_sequence(text, tcp) ->
+ DecodeFun = rsmms1_mgc_decode_msg_fun(megaco_pretty_text_encoder, []),
+ EncodeFun = rsmms1_mgc_encode_msg_fun(megaco_pretty_text_encoder, []),
+ Mid = {deviceName,"mgc"},
+ ScrVerifyFun = rsmms1_mgc_verify_service_change_req_msg_fun(),
+ ServiceChangeRep = rsmms1_mgc_service_change_reply_msg(Mid, 1),
+ TermId1 =
+ #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ TermId2 =
+ #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ TermId3 =
+ #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ TermIds = [TermId1, TermId2, TermId3],
+ TransId = 2,
+ ReqId = 1,
+ CtxId = 1,
+ NrVerifyFun =
+ rsmms1_mgc_verify_notify_req_msg_fun(TermIds, TransId, ReqId, CtxId),
+ NotifyRep1 =
+ rsmms1_mgc_notify_reply_msg(1, Mid, TransId, CtxId, TermId1),
+ NotifyRep3 =
+ rsmms1_mgc_notify_reply_msg(3, Mid, TransId, CtxId, TermId3),
+ SrVerifyFun1 = rsmms1_mgc_verify_segment_reply_msg_fun(1, TransId),
+ SrVerifyFun3 = rsmms1_mgc_verify_segment_reply_msg_fun(3, TransId),
+ MissingSegVerifyFun = rsmms1_mgc_verify_missing_segment_fun("2"),
+ EvSeq = [{debug, false},
+ {decode, DecodeFun},
+ {encode, EncodeFun},
+ {listen, 2944},
+ {expect_accept, any},
+ {expect_receive, "service-change-request", {ScrVerifyFun, 5000}},
+ {send, "service-change-reply", ServiceChangeRep},
+ {expect_receive, "notify-request", {NrVerifyFun, 4000}},
+ {sleep, 1000},
+ {send, "notify reply - segment 1", NotifyRep1},
+ {expect_receive, "segment reply 1", {SrVerifyFun1, 2000}},
+ {sleep, 1000},
+ {send, "notify reply - segment 3", NotifyRep3},
+ {expect_receive, "segment reply 3", {SrVerifyFun3, 2000}},
+ {expect_receive, "missing segment error", {MissingSegVerifyFun, 4000}},
+ {expect_nothing, 10000},
+ disconnect
+ ],
+ EvSeq.
+
+rsmms1_mgc_encode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:encode_message(Conf, M)
+ end.
+
+rsmms1_mgc_decode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:decode_message(Conf, M)
+ end.
+
+rsmms1_mgc_verify_service_change_req_msg_fun() ->
+ fun(Msg) ->
+ (catch rsmms1_mgc_verify_service_change_req(Msg))
+ end.
+
+rsmms1_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) ->
+ io:format("rsmms1_mgc_verify_service_change_req -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ Body =
+ case Mess of
+ #'Message'{version = 1,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = _TransId,
+ actions = [ActionReq]} ->
+ ActionReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ CR =
+ case AR of
+ #'ActionRequest'{contextId = _Cid,
+ commandRequests = [CmdReq]} ->
+ CmdReq;
+ _ ->
+ throw({error, {invalid_action, AR}})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}})
+ end,
+ {Tid, Parms} =
+ case Cmd of
+ {serviceChangeReq,
+ #'ServiceChangeRequest'{terminationID = [TermID],
+ serviceChangeParms = ServChParms}} ->
+ {TermID, ServChParms};
+ _ ->
+ throw({error, {invalid_command, Cmd}})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ throw({error, {invalid_terminationID, Tid}})
+ end,
+ case Parms of
+ %% Version 1 'ServiceChangeParm'
+ {'ServiceChangeParm',
+ restart, % serviceChangeMethod
+ asn1_NOVALUE, % serviceChangeAddress
+ ?VERSION, % serviceChangeVersion,
+ {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile
+ [[$9,$0,$1|_]], % serviceChangeReason
+ asn1_NOVALUE, % serviceChangeDelay
+ asn1_NOVALUE, % serviceChangeMgcId
+ asn1_NOVALUE, % timeStamp
+ asn1_NOVALUE % nonStandardData
+ } ->
+ {ok, M};
+ _ ->
+ {error, {invalid_serviceChangeParms, Parms}}
+ end.
+
+rsmms1_mgc_verify_notify_req_msg_fun(TermIds, TransId, Rid, Cid) ->
+ fun(Msg) ->
+ (catch rsmms1_mgc_verify_notify_req(Msg,
+ TermIds, TransId, Rid, Cid))
+ end.
+
+rsmms1_mgc_verify_notify_req(#'MegacoMessage'{mess = Mess} = M,
+ TermIds, TransId, Rid, Cid) ->
+ io:format("rsmms1_mgc_verify_notify_req -> entry with"
+ "~n M: ~p"
+ "~n TermIds: ~p"
+ "~n TransId: ~p"
+ "~n Rid: ~p"
+ "~n Cid: ~p"
+ "~n", [M, TermIds, TransId, Rid, Cid]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = TransId,
+ actions = [ActReq]} ->
+ ActReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ Cmds =
+ case AR of
+ #'ActionRequest'{contextId = Cid,
+ commandRequests = Commands} ->
+ Commands;
+ _ ->
+ throw({error, {invalid_actions, AR}})
+ end,
+ ok = rsmms1_mgc_verify_notify_req_cmds(TermIds, Cmds),
+ {ok, M};
+rsmms1_mgc_verify_notify_req(Crap, _TermId, _TransId, _Rid, _Cid) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+rsmms1_mgc_verify_notify_req_cmds([], []) ->
+ ok;
+rsmms1_mgc_verify_notify_req_cmds([TermId|TermIds], [Cmd|Cmds]) ->
+ rsmms1_mgc_verify_notify_req_cmd(TermId, Cmd),
+ rsmms1_mgc_verify_notify_req_cmds(TermIds, Cmds);
+rsmms1_mgc_verify_notify_req_cmds(TermIds, Cmds) ->
+ throw({error, {invalid_commands, TermIds, Cmds}}).
+
+rsmms1_mgc_verify_notify_req_cmd(TermId, #'CommandRequest'{command = Cmd}) ->
+ io:format("rsmms1_mgc_verify_notify_req_cmd -> entry with"
+ "~n TermId: ~p"
+ "~n Cmd: ~p"
+ "~n", [TermId, Cmd]),
+ NR =
+ case Cmd of
+ {notifyReq, NotifReq} ->
+ NotifReq;
+ _ ->
+ throw({error, {invalid_command}})
+ end,
+ OED =
+ case NR of
+ #'NotifyRequest'{terminationID = [TermId],
+ observedEventsDescriptor = ObsEvsDesc,
+ errorDescriptor = asn1_NOVALUE} ->
+ ObsEvsDesc;
+ _ ->
+ throw({error, {invalid_notifyReq, NR}})
+ end,
+ OE =
+ case OED of
+ #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} ->
+ ObsEvLst;
+ _ ->
+ throw({error, {invalid_observedEventsDescriptor, OED}})
+ end,
+ case OE of
+ #'ObservedEvent'{eventName = "al/of"} ->
+ ok;
+ _ ->
+ throw({error, {invalid_observedEventLst, OE}})
+ end;
+rsmms1_mgc_verify_notify_req_cmd(_, BadCmdReq) ->
+ io:format("rsmms1_mgc_verify_notify_req_cmd -> invalid"
+ "~n BadCmdReq: ~p"
+ "~n", [BadCmdReq]),
+ throw({error, {invalid_CommandRequest, BadCmdReq}}).
+
+rsmms1_mgc_verify_segment_reply_msg_fun(SN, TransId) ->
+ fun(Msg) ->
+ (catch rsmms1_mgc_verify_segment_reply(Msg, SN, TransId))
+ end.
+
+rsmms1_mgc_verify_segment_reply(#'MegacoMessage'{mess = Mess} = M,
+ SN, TransId) ->
+ io:format("rsmms1_mgc_verify_segment_reply -> entry with"
+ "~n SN: ~p"
+ "~n TransId: ~p"
+ "~n M: ~p"
+ "~n", [SN, TransId, M]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ SR =
+ case Trans of
+ {segmentReply, SegmentReply} ->
+ SegmentReply;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ case SR of
+ #'SegmentReply'{transactionId = TransId,
+ segmentNumber = SN,
+ segmentationComplete = 'NULL'} when SN == 3 ->
+ {ok, M};
+ #'SegmentReply'{transactionId = TransId,
+ segmentNumber = SN,
+ segmentationComplete = asn1_NOVALUE} ->
+ {ok, M};
+ _ ->
+ throw({error, {invalid_segmentReply, SR}})
+ end;
+rsmms1_mgc_verify_segment_reply(Crap, SN, TransId) ->
+ io:format("rsmms1_mgc_verify_segment_reply -> invalid: "
+ "~n SN: ~p"
+ "~n TransId: ~p"
+ "~n Crap: ~p"
+ "~n", [SN, TransId, Crap]),
+ {error, {invalid_MegacoMessage, Crap, SN, TransId}}.
+
+
+rsmms1_mgc_verify_missing_segment_fun(SN) ->
+ fun(Msg) -> (catch rsmms1_mgc_verify_missing_segment(Msg, SN)) end.
+
+rsmms1_mgc_verify_missing_segment(#'MegacoMessage'{mess = Mess} = M, Text) ->
+ io:format("rsmms1_mgc_verify_missing_segment -> entry with"
+ "~n Text: ~p"
+ "~n M: ~p"
+ "~n", [Text, M]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ case Body of
+ {messageError,
+ #'ErrorDescriptor'{errorCode = ?megaco_segments_not_received,
+ errorText = Text}} ->
+ {ok, M};
+ _ ->
+ throw({error, {invalid_messageError, Body}})
+ end;
+rsmms1_mgc_verify_missing_segment(Crap, _SN) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+rsmms1_mgc_service_change_reply_msg(Mid, Cid) ->
+ SCRP = cre_serviceChangeResParm(Mid),
+ SCRes = cre_serviceChangeResult(SCRP),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReply([Root], SCRes),
+ CR = cre_cmdReply(SCR),
+ AR = cre_actionReply(Cid, [CR]),
+ TRes = cre_transResult([AR]),
+ TR = {'TransactionReply', 1, asn1_NOVALUE, TRes},
+ Trans = cre_transaction(TR),
+ Mess = cre_message(1, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+rsmms1_mgc_notify_reply_ar(Cid, TermId) ->
+ NR = cre_notifyReply([TermId]),
+ CR = cre_cmdReply(NR),
+ cre_actionReply(Cid, [CR]).
+
+rsmms1_mgc_notify_reply_msg(SN, Mid, TransId, Cid, TermId) ->
+ AR = rsmms1_mgc_notify_reply_ar(Cid, TermId),
+ TRes = cre_transResult([AR]),
+ TR =
+ if
+ SN == 3 ->
+ cre_transReply(TransId, TRes, SN, 'NULL');
+ true ->
+ cre_transReply(TransId, TRes, SN)
+ end,
+ Trans = cre_transaction(TR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+
+%%
+%% MG generator stuff
+%%
+rsmms1_mg_event_sequence(text, tcp) ->
+ Mid = {deviceName,"mg"},
+ RI = [
+ {port, 2944},
+ {encoding_module, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {transport_module, megaco_tcp}
+ ],
+ ServiceChangeReq = rsmms1_mg_service_change_request_ar(Mid, 1),
+ ConnectVerify = rsmms1_mg_verify_handle_connect_fun(),
+ ServiceChangeReplyVerify = rsmms1_mg_verify_service_change_reply_fun(),
+ Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ Tids = [Tid1, Tid2, Tid3],
+ NotifyReq = rsmms1_mg_notify_request_ar(1, Tids, 1),
+ NotifyReplyVerify1 = rsmms1_mg_verify_notify_reply_fun(1, Tid1),
+ NotifyReplyVerify3 = rsmms1_mg_verify_notify_reply_fun(3, Tid3),
+ SegTimeoutVerify = rsmms1_mg_verify_segment_timeout_fun(2),
+ DiscoVerify = rsmms1_mg_verify_handle_disco_fun(),
+ EvSeq = [
+ {debug, true},
+ {megaco_trace, disable},
+ %% {megaco_trace, max},
+ megaco_start,
+ {megaco_start_user, Mid, RI, []},
+ start_transport,
+ {megaco_system_info, users},
+ {megaco_system_info, connections},
+ {megaco_update_user_info, segment_recv_timer, 3000},
+ connect,
+ {megaco_callback, handle_connect, ConnectVerify},
+ megaco_connect,
+ {megaco_cast, [ServiceChangeReq], []},
+ {megaco_callback, handle_connect, ConnectVerify},
+ {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify},
+ {megaco_update_conn_info, protocol_version, ?VERSION},
+ {sleep, 1000},
+ {megaco_cast, [NotifyReq], []},
+ {megaco_callback, handle_trans_reply, NotifyReplyVerify1},
+ {megaco_callback, handle_trans_reply, NotifyReplyVerify3},
+ {megaco_callback, handle_trans_reply, SegTimeoutVerify},
+ {megaco_callback, handle_disconnect, DiscoVerify},
+ megaco_stop_user,
+ megaco_stop
+ ],
+ EvSeq.
+
+
+rsmms1_mg_verify_handle_connect_fun() ->
+ fun(Ev) -> rsmms1_mg_verify_handle_connect(Ev) end.
+
+rsmms1_mg_verify_handle_connect({handle_connect, CH, 1}) ->
+ io:format("rsmms1_mg_verify_handle_connect -> ok"
+ "~n CH: ~p~n", [CH]),
+ {ok, CH, ok};
+rsmms1_mg_verify_handle_connect(Else) ->
+ io:format("rsmms1_mg_verify_handle_connect -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, ok}.
+
+
+rsmms1_mg_verify_service_change_reply_fun() ->
+ fun(Rep) -> rsmms1_mg_verify_scr(Rep) end.
+
+rsmms1_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) ->
+ (catch rsmms1_mg_do_verify_scr(AR));
+rsmms1_mg_verify_scr(Crap) ->
+ io:format("rsmms1_mg_verify_scr -> error: "
+ "~n Crap: ~p"
+ "~n", [Crap]),
+ {error, Crap, ok}.
+
+rsmms1_mg_do_verify_scr(AR) ->
+ io:format("rsmms1_mg_do_verify_scr -> ok: "
+ "~n AR: ~p~n", [AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ SCR =
+ case CR of
+ {serviceChangeReply, ServChRep} ->
+ ServChRep;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ {Tid, SCRes} =
+ case SCR of
+ #'ServiceChangeReply'{terminationID = [TermID],
+ serviceChangeResult = Res} ->
+ {TermID, Res};
+ _ ->
+ Reason3 = {invalid_service_change_reply, SCR},
+ throw({error, Reason3, ok})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ Reason4 = {invalid_termination_id, Tid},
+ throw({error, Reason4, ok})
+ end,
+ SCRParm =
+ case SCRes of
+ {serviceChangeResParms, ServChResParms} ->
+ ServChResParms;
+ _ ->
+ Reason5 = {invalid_serviceChangeResult, SCRes},
+ throw({error, Reason5, ok})
+ end,
+ case SCRParm of
+ #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} ->
+ {ok, AR, ok};
+ _ ->
+ Reason6 = {invalid_service_change_result, SCRParm},
+ {error, Reason6, ok}
+ end.
+
+rsmms1_mg_verify_notify_reply_fun(SN, Tid) ->
+ fun(Rep) -> rsmms1_mg_verify_notify_reply(Rep, SN, Tid) end.
+
+rsmms1_mg_verify_notify_reply(
+ {handle_trans_reply, _CH, ?VERSION, {ok, {SN, Last, [AR]}}, _}, SN, Tid)
+ when (Last == false) ->
+ (catch rsmms1_mg_do_verify_notify_reply(Tid, AR));
+rsmms1_mg_verify_notify_reply(Crap, SN, Tid) ->
+ io:format("rsmms1_mg_verify_notify_reply -> unknown reply"
+ "~n SN: ~p"
+ "~n Tid: ~p"
+ "~n Crap: ~p"
+ "~n", [SN, Tid, Crap]),
+ {error, Crap, ok}.
+
+rsmms1_mg_do_verify_notify_reply(Tid, AR) ->
+ io:format("rsmms1_mg_do_verify_notify_reply -> ok"
+ "~n Tid: ~p"
+ "~n AR: ~p"
+ "~n", [Tid, AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ NR =
+ case CR of
+ {notifyReply, NotifyReply} ->
+ NotifyReply;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ case NR of
+ #'NotifyReply'{terminationID = [Tid],
+ errorDescriptor = asn1_NOVALUE} ->
+ {ok, AR, ok};
+ _ ->
+ Reason3 = {invalid_NotifyReply, NR},
+ {error, Reason3, ok}
+ end.
+
+rsmms1_mg_verify_segment_timeout_fun(SN) ->
+ fun(Rep) -> rsmms1_mg_verify_segment_timeout(Rep, SN) end.
+
+rsmms1_mg_verify_segment_timeout(
+ {handle_trans_reply, _CH, ?VERSION, {error, Reason}, _}, SN) ->
+ case Reason of
+ {segment_timeout, [SN]} ->
+ {ok, Reason, ok};
+ _ ->
+ {error, {invalid_reason, Reason}, ok}
+ end;
+rsmms1_mg_verify_segment_timeout(Crap, SN) ->
+ io:format("rsmms1_mg_verify_segment_timeout -> unknown reply"
+ "~n SN: ~p"
+ "~n Crap: ~p"
+ "~n", [SN, Crap]),
+ {error, Crap, ok}.
+
+rsmms1_mg_verify_handle_disco_fun() ->
+ fun(Ev) -> rsmms1_mg_verify_handle_disconnect(Ev) end.
+
+rsmms1_mg_verify_handle_disconnect({handle_disconnect, _CH, ?VERSION, R}) ->
+ io:format("rsmms1_mg_verify_handle_disconnect -> ok"
+ "~n R: ~p"
+ "~n", [R]),
+ case R of
+ {no_controlling_process,shutdown} ->
+ {ok, R, ok};
+ _ ->
+ {error, {unexpected_reason, R}, ok}
+ end;
+rsmms1_mg_verify_handle_disconnect(Crap) ->
+ io:format("rsmms1_mg_verify_handle_disconnect -> invalid: "
+ "~n Crap: ~p"
+ "~n", [Crap]),
+ {error, Crap, ok}.
+
+
+rsmms1_mg_service_change_request_ar(_Mid, Cid) ->
+ Prof = cre_serviceChangeProf("resgw", 1),
+ SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReq([Root], SCP),
+ CMD = cre_command(SCR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+rsmms1_mg_notify_request_ar(Rid, Tids, Cid) ->
+ rsmms1_mg_notify_request_ar(Rid, Tids, Cid, []).
+
+rsmms1_mg_notify_request_ar(_Rid, [], Cid, Cmds) ->
+ cre_actionReq(Cid, lists:reverse(Cmds));
+rsmms1_mg_notify_request_ar(Rid, [Tid|Tids], Cid, Cmds) ->
+ TT = cre_timeNotation("19990729", "22000000"),
+ Ev = cre_obsEvent("al/of", TT),
+ EvsDesc = cre_obsEvsDesc(Rid, [Ev]),
+ NR = cre_notifyReq([Tid], EvsDesc),
+ CMD = cre_command(NR),
+ CR = cre_cmdReq(CMD),
+ rsmms1_mg_notify_request_ar(Rid, Tids, Cid, [CR|Cmds]).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+recv_segmented_msg_missing_seg2(suite) ->
+ [];
+recv_segmented_msg_missing_seg2(doc) ->
+ "Received segmented megaco message with one segment missing "
+ "using incremental recv segment timer";
+recv_segmented_msg_missing_seg2(Config) when is_list(Config) ->
+ put(verbosity, ?TEST_VERBOSITY),
+ put(sname, "TEST"),
+ put(tc, rsmms2),
+ i("starting"),
+
+ MgcNode = make_node_name(mgc),
+ MgNode = make_node_name(mg),
+ d("start nodes: "
+ "~n MgcNode: ~p"
+ "~n MgNode: ~p",
+ [MgcNode, MgNode]),
+ ok = megaco_test_lib:start_nodes([MgcNode, MgNode], ?FILE, ?LINE),
+
+ d("[MGC] start the simulator "),
+ {ok, Mgc} = megaco_test_tcp_generator:start_link("MGC", MgcNode),
+
+ d("[MGC] create the event sequence"),
+ MgcEvSeq = rsmms2_mgc_event_sequence(text, tcp),
+
+ i("wait some time before starting the MGC simulation"),
+ sleep(1000),
+
+ d("[MGC] start the simulation"),
+ {ok, MgcId} = megaco_test_tcp_generator:exec(Mgc, MgcEvSeq),
+
+ i("wait some time before starting the MG simulator"),
+ sleep(1000),
+
+ d("[MG] start the simulator (generator)"),
+ {ok, Mg} = megaco_test_megaco_generator:start_link("MG", MgNode),
+
+ d("[MG] create the event sequence"),
+ MgEvSeq = rsmms2_mg_event_sequence(text, tcp),
+
+ i("wait some time before starting the MG simulation"),
+ sleep(1000),
+
+ d("[MG] start the simulation"),
+ {ok, MgId} = megaco_test_megaco_generator:exec(Mg, MgEvSeq),
+
+ d("await the generator reply(s)"),
+ await_completion([MgcId, MgId]),
+
+ %% Tell Mgc to stop
+ i("[MGC] stop generator"),
+ megaco_test_tcp_generator:stop(Mgc),
+
+ %% Tell Mg to stop
+ i("[MG] stop generator"),
+ megaco_test_megaco_generator:stop(Mg),
+
+ i("done", []),
+ ok.
+
+
+%%
+%% MGC generator stuff
+%%
+
+rsmms2_mgc_event_sequence(text, tcp) ->
+ DecodeFun = rsmms2_mgc_decode_msg_fun(megaco_pretty_text_encoder, []),
+ EncodeFun = rsmms2_mgc_encode_msg_fun(megaco_pretty_text_encoder, []),
+ Mid = {deviceName,"mgc"},
+ ScrVerifyFun = rsmms2_mgc_verify_service_change_req_msg_fun(),
+ ServiceChangeRep = rsmms2_mgc_service_change_reply_msg(Mid, 1),
+ TermId1 =
+ #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ TermId2 =
+ #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ TermId3 =
+ #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ TermIds = [TermId1, TermId2, TermId3],
+ TransId = 2,
+ ReqId = 1,
+ CtxId = 1,
+ NrVerifyFun =
+ rsmms2_mgc_verify_notify_req_msg_fun(TermIds, TransId, ReqId, CtxId),
+ NotifyRep1 =
+ rsmms2_mgc_notify_reply_msg(1, Mid, TransId, CtxId, TermId1),
+ NotifyRep3 =
+ rsmms2_mgc_notify_reply_msg(3, Mid, TransId, CtxId, TermId3),
+ SrVerifyFun1 = rsmms2_mgc_verify_segment_reply_msg_fun(1, TransId),
+ SrVerifyFun3 = rsmms2_mgc_verify_segment_reply_msg_fun(3, TransId),
+ MissingSegVerifyFun = rsmms2_mgc_verify_missing_segment_fun("2"),
+ EvSeq = [{debug, false},
+ {decode, DecodeFun},
+ {encode, EncodeFun},
+ {listen, 2944},
+ {expect_accept, any},
+ {expect_receive, "service-change-request", {ScrVerifyFun, 5000}},
+ {send, "service-change-reply", ServiceChangeRep},
+ {expect_receive, "notify-request", {NrVerifyFun, 4000}},
+ {sleep, 1000},
+ {send, "notify reply - segment 1", NotifyRep1},
+ {expect_receive, "segment reply 1", {SrVerifyFun1, 2000}},
+ {sleep, 1000},
+ {send, "notify reply - segment 3", NotifyRep3},
+ {expect_receive, "segment reply 3", {SrVerifyFun3, 2000}},
+ {expect_receive, "missing segment error", {MissingSegVerifyFun, 4000}},
+ {expect_nothing, 10000},
+ disconnect
+ ],
+ EvSeq.
+
+rsmms2_mgc_encode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:encode_message(Conf, M)
+ end.
+
+rsmms2_mgc_decode_msg_fun(Mod, Conf) ->
+ fun(M) ->
+ Mod:decode_message(Conf, M)
+ end.
+
+rsmms2_mgc_verify_service_change_req_msg_fun() ->
+ fun(Msg) ->
+ (catch rsmms2_mgc_verify_service_change_req(Msg))
+ end.
+
+rsmms2_mgc_verify_service_change_req(#'MegacoMessage'{mess = Mess} = M) ->
+ io:format("rsmms2_mgc_verify_service_change_req -> entry with"
+ "~n M: ~p"
+ "~n", [M]),
+ Body =
+ case Mess of
+ #'Message'{version = 1,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = _TransId,
+ actions = [ActionReq]} ->
+ ActionReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ CR =
+ case AR of
+ #'ActionRequest'{contextId = _Cid,
+ commandRequests = [CmdReq]} ->
+ CmdReq;
+ _ ->
+ throw({error, {invalid_action, AR}})
+ end,
+ Cmd =
+ case CR of
+ #'CommandRequest'{command = Command} ->
+ Command;
+ _ ->
+ throw({error, {invalid_commandRequest, CR}})
+ end,
+ {Tid, Parms} =
+ case Cmd of
+ {serviceChangeReq,
+ #'ServiceChangeRequest'{terminationID = [TermID],
+ serviceChangeParms = ServChParms}} ->
+ {TermID, ServChParms};
+ _ ->
+ throw({error, {invalid_command, Cmd}})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ throw({error, {invalid_terminationID, Tid}})
+ end,
+ case Parms of
+ %% Version 1 'ServiceChangeParm'
+ {'ServiceChangeParm',
+ restart, % serviceChangeMethod
+ asn1_NOVALUE, % serviceChangeAddress
+ ?VERSION, % serviceChangeVersion,
+ {'ServiceChangeProfile',"resgw",1}, % serviceChangeProfile
+ [[$9,$0,$1|_]], % serviceChangeReason
+ asn1_NOVALUE, % serviceChangeDelay
+ asn1_NOVALUE, % serviceChangeMgcId
+ asn1_NOVALUE, % timeStamp
+ asn1_NOVALUE % nonStandardData
+ } ->
+ {ok, M};
+ _ ->
+ {error, {invalid_serviceChangeParms, Parms}}
+ end.
+
+rsmms2_mgc_verify_notify_req_msg_fun(TermIds, TransId, Rid, Cid) ->
+ fun(Msg) ->
+ (catch rsmms2_mgc_verify_notify_req(Msg,
+ TermIds, TransId, Rid, Cid))
+ end.
+
+rsmms2_mgc_verify_notify_req(#'MegacoMessage'{mess = Mess} = M,
+ TermIds, TransId, Rid, Cid) ->
+ io:format("rsmms2_mgc_verify_notify_req -> entry with"
+ "~n M: ~p"
+ "~n TermIds: ~p"
+ "~n TransId: ~p"
+ "~n Rid: ~p"
+ "~n Cid: ~p"
+ "~n", [M, TermIds, TransId, Rid, Cid]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ TR =
+ case Trans of
+ {transactionRequest, TransRequest} ->
+ TransRequest;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ AR =
+ case TR of
+ #'TransactionRequest'{transactionId = TransId,
+ actions = [ActReq]} ->
+ ActReq;
+ _ ->
+ throw({error, {invalid_transactionRequest, TR}})
+ end,
+ Cmds =
+ case AR of
+ #'ActionRequest'{contextId = Cid,
+ commandRequests = Commands} ->
+ Commands;
+ _ ->
+ throw({error, {invalid_actions, AR}})
+ end,
+ ok = rsmms2_mgc_verify_notify_req_cmds(TermIds, Cmds),
+ {ok, M};
+rsmms2_mgc_verify_notify_req(Crap, _TermId, _TransId, _Rid, _Cid) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+rsmms2_mgc_verify_notify_req_cmds([], []) ->
+ ok;
+rsmms2_mgc_verify_notify_req_cmds([TermId|TermIds], [Cmd|Cmds]) ->
+ rsmms2_mgc_verify_notify_req_cmd(TermId, Cmd),
+ rsmms2_mgc_verify_notify_req_cmds(TermIds, Cmds);
+rsmms2_mgc_verify_notify_req_cmds(TermIds, Cmds) ->
+ throw({error, {invalid_commands, TermIds, Cmds}}).
+
+rsmms2_mgc_verify_notify_req_cmd(TermId, #'CommandRequest'{command = Cmd}) ->
+ io:format("rsmms2_mgc_verify_notify_req_cmd -> entry with"
+ "~n TermId: ~p"
+ "~n Cmd: ~p"
+ "~n", [TermId, Cmd]),
+ NR =
+ case Cmd of
+ {notifyReq, NotifReq} ->
+ NotifReq;
+ _ ->
+ throw({error, {invalid_command}})
+ end,
+ OED =
+ case NR of
+ #'NotifyRequest'{terminationID = [TermId],
+ observedEventsDescriptor = ObsEvsDesc,
+ errorDescriptor = asn1_NOVALUE} ->
+ ObsEvsDesc;
+ _ ->
+ throw({error, {invalid_notifyReq, NR}})
+ end,
+ OE =
+ case OED of
+ #'ObservedEventsDescriptor'{observedEventLst = [ObsEvLst]} ->
+ ObsEvLst;
+ _ ->
+ throw({error, {invalid_observedEventsDescriptor, OED}})
+ end,
+ case OE of
+ #'ObservedEvent'{eventName = "al/of"} ->
+ ok;
+ _ ->
+ throw({error, {invalid_observedEventLst, OE}})
+ end;
+rsmms2_mgc_verify_notify_req_cmd(_, BadCmdReq) ->
+ io:format("rsmms2_mgc_verify_notify_req_cmd -> invalid"
+ "~n BadCmdReq: ~p"
+ "~n", [BadCmdReq]),
+ throw({error, {invalid_CommandRequest, BadCmdReq}}).
+
+rsmms2_mgc_verify_segment_reply_msg_fun(SN, TransId) ->
+ fun(Msg) ->
+ (catch rsmms2_mgc_verify_segment_reply(Msg, SN, TransId))
+ end.
+
+rsmms2_mgc_verify_segment_reply(#'MegacoMessage'{mess = Mess} = M,
+ SN, TransId) ->
+ io:format("rsmms2_mgc_verify_segment_reply -> entry with"
+ "~n SN: ~p"
+ "~n TransId: ~p"
+ "~n M: ~p"
+ "~n", [SN, TransId, M]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _MgMid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ Trans =
+ case Body of
+ {transactions, [Transactions]} ->
+ Transactions;
+ _ ->
+ throw({error, {invalid_messageBody, Body}})
+ end,
+ SR =
+ case Trans of
+ {segmentReply, SegmentReply} ->
+ SegmentReply;
+ _ ->
+ throw({error, {invalid_transactions, Trans}})
+ end,
+ case SR of
+ #'SegmentReply'{transactionId = TransId,
+ segmentNumber = SN,
+ segmentationComplete = 'NULL'} when SN == 3 ->
+ {ok, M};
+ #'SegmentReply'{transactionId = TransId,
+ segmentNumber = SN,
+ segmentationComplete = asn1_NOVALUE} ->
+ {ok, M};
+ _ ->
+ throw({error, {invalid_segmentReply, SR}})
+ end;
+rsmms2_mgc_verify_segment_reply(Crap, SN, TransId) ->
+ io:format("rsmms2_mgc_verify_segment_reply -> invalid: "
+ "~n SN: ~p"
+ "~n TransId: ~p"
+ "~n Crap: ~p"
+ "~n", [SN, TransId, Crap]),
+ {error, {invalid_MegacoMessage, Crap, SN, TransId}}.
+
+
+rsmms2_mgc_verify_missing_segment_fun(SN) ->
+ fun(Msg) -> (catch rsmms2_mgc_verify_missing_segment(Msg, SN)) end.
+
+rsmms2_mgc_verify_missing_segment(#'MegacoMessage'{mess = Mess} = M, Text) ->
+ io:format("rsmms2_mgc_verify_missing_segment -> entry with"
+ "~n Text: ~p"
+ "~n M: ~p"
+ "~n", [Text, M]),
+ Body =
+ case Mess of
+ #'Message'{version = ?VERSION,
+ mId = _Mid,
+ messageBody = MsgBody} ->
+ MsgBody;
+ _ ->
+ throw({error, {invalid_Message, Mess}})
+ end,
+ case Body of
+ {messageError,
+ #'ErrorDescriptor'{errorCode = ?megaco_segments_not_received,
+ errorText = Text}} ->
+ {ok, M};
+ _ ->
+ throw({error, {invalid_messageError, Body}})
+ end;
+rsmms2_mgc_verify_missing_segment(Crap, _SN) ->
+ {error, {invalid_MegacoMessage, Crap}}.
+
+rsmms2_mgc_service_change_reply_msg(Mid, Cid) ->
+ SCRP = cre_serviceChangeResParm(Mid),
+ SCRes = cre_serviceChangeResult(SCRP),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReply([Root], SCRes),
+ CR = cre_cmdReply(SCR),
+ AR = cre_actionReply(Cid, [CR]),
+ TRes = cre_transResult([AR]),
+ TR = {'TransactionReply', 1, asn1_NOVALUE, TRes},
+ Trans = cre_transaction(TR),
+ Mess = cre_message(1, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+rsmms2_mgc_notify_reply_ar(Cid, TermId) ->
+ NR = cre_notifyReply([TermId]),
+ CR = cre_cmdReply(NR),
+ cre_actionReply(Cid, [CR]).
+
+rsmms2_mgc_notify_reply_msg(SN, Mid, TransId, Cid, TermId) ->
+ AR = rsmms2_mgc_notify_reply_ar(Cid, TermId),
+ TRes = cre_transResult([AR]),
+ TR =
+ if
+ SN == 3 ->
+ cre_transReply(TransId, TRes, SN, 'NULL');
+ true ->
+ cre_transReply(TransId, TRes, SN)
+ end,
+ Trans = cre_transaction(TR),
+ Mess = cre_message(?VERSION, Mid, cre_transactions([Trans])),
+ cre_megacoMessage(Mess).
+
+
+%%
+%% MG generator stuff
+%%
+rsmms2_mg_event_sequence(text, tcp) ->
+ Mid = {deviceName,"mg"},
+ RI = [
+ {port, 2944},
+ {encoding_module, megaco_pretty_text_encoder},
+ {encoding_config, []},
+ {transport_module, megaco_tcp}
+ ],
+ SegRecvTmr = #megaco_incr_timer{wait_for = 1000,
+ factor = 1,
+ incr = 0,
+ max_retries = 2
+ },
+ ServiceChangeReq = rsmms2_mg_service_change_request_ar(Mid, 1),
+ ConnectVerify = rsmms2_mg_verify_handle_connect_fun(),
+ ServiceChangeReplyVerify = rsmms2_mg_verify_service_change_reply_fun(),
+ Tid1 = #megaco_term_id{id = ["00000000","00000000","00000001"]},
+ Tid2 = #megaco_term_id{id = ["00000000","00000000","00000002"]},
+ Tid3 = #megaco_term_id{id = ["00000000","00000000","00000003"]},
+ Tids = [Tid1, Tid2, Tid3],
+ NotifyReq = rsmms2_mg_notify_request_ar(1, Tids, 1),
+ NotifyReplyVerify1 = rsmms2_mg_verify_notify_reply_fun(1, Tid1),
+ NotifyReplyVerify3 = rsmms2_mg_verify_notify_reply_fun(3, Tid3),
+ SegTimeoutVerify = rsmms2_mg_verify_segment_timeout_fun(2),
+ DiscoVerify = rsmms2_mg_verify_handle_disco_fun(),
+ EvSeq = [
+ {debug, true},
+ {megaco_trace, disable},
+ %% {megaco_trace, max},
+ megaco_start,
+ {megaco_start_user, Mid, RI, []},
+ start_transport,
+ {megaco_system_info, users},
+ {megaco_system_info, connections},
+ {megaco_update_user_info, segment_recv_timer, SegRecvTmr},
+ connect,
+ {megaco_callback, handle_connect, ConnectVerify},
+ megaco_connect,
+ {megaco_cast, [ServiceChangeReq], []},
+ {megaco_callback, handle_connect, ConnectVerify},
+ {megaco_callback, handle_trans_reply, ServiceChangeReplyVerify},
+ {megaco_update_conn_info, protocol_version, ?VERSION},
+ {sleep, 1000},
+ {megaco_cast, [NotifyReq], []},
+ {megaco_callback, handle_trans_reply, NotifyReplyVerify1},
+ {megaco_callback, handle_trans_reply, NotifyReplyVerify3},
+ {megaco_callback, handle_trans_reply, SegTimeoutVerify},
+ {megaco_callback, handle_disconnect, DiscoVerify},
+ megaco_stop_user,
+ megaco_stop
+ ],
+ EvSeq.
+
+
+rsmms2_mg_verify_handle_connect_fun() ->
+ fun(Ev) -> rsmms2_mg_verify_handle_connect(Ev) end.
+
+rsmms2_mg_verify_handle_connect({handle_connect, CH, 1}) ->
+ io:format("rsmms2_mg_verify_handle_connect -> ok"
+ "~n CH: ~p~n", [CH]),
+ {ok, CH, ok};
+rsmms2_mg_verify_handle_connect(Else) ->
+ io:format("rsmms2_mg_verify_handle_connect -> unknown"
+ "~n Else: ~p~n", [Else]),
+ {error, Else, ok}.
+
+
+rsmms2_mg_verify_service_change_reply_fun() ->
+ fun(Rep) -> rsmms2_mg_verify_scr(Rep) end.
+
+rsmms2_mg_verify_scr({handle_trans_reply, _CH, 1, {ok, [AR]}, _}) ->
+ (catch rsmms2_mg_do_verify_scr(AR));
+rsmms2_mg_verify_scr(Crap) ->
+ io:format("rsmms2_mg_verify_scr -> error: "
+ "~n Crap: ~p"
+ "~n", [Crap]),
+ {error, Crap, ok}.
+
+rsmms2_mg_do_verify_scr(AR) ->
+ io:format("rsmms2_mg_do_verify_scr -> ok: "
+ "~n AR: ~p~n", [AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ SCR =
+ case CR of
+ {serviceChangeReply, ServChRep} ->
+ ServChRep;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ {Tid, SCRes} =
+ case SCR of
+ #'ServiceChangeReply'{terminationID = [TermID],
+ serviceChangeResult = Res} ->
+ {TermID, Res};
+ _ ->
+ Reason3 = {invalid_service_change_reply, SCR},
+ throw({error, Reason3, ok})
+ end,
+ case Tid of
+ #megaco_term_id{contains_wildcards = false, id = ["root"]} ->
+ ok;
+ _ ->
+ Reason4 = {invalid_termination_id, Tid},
+ throw({error, Reason4, ok})
+ end,
+ SCRParm =
+ case SCRes of
+ {serviceChangeResParms, ServChResParms} ->
+ ServChResParms;
+ _ ->
+ Reason5 = {invalid_serviceChangeResult, SCRes},
+ throw({error, Reason5, ok})
+ end,
+ case SCRParm of
+ #'ServiceChangeResParm'{serviceChangeMgcId = _RemoteMid} ->
+ {ok, AR, ok};
+ _ ->
+ Reason6 = {invalid_service_change_result, SCRParm},
+ {error, Reason6, ok}
+ end.
+
+rsmms2_mg_verify_notify_reply_fun(SN, Tid) ->
+ fun(Rep) -> rsmms2_mg_verify_notify_reply(Rep, SN, Tid) end.
+
+rsmms2_mg_verify_notify_reply(
+ {handle_trans_reply, _CH, ?VERSION, {ok, {SN, Last, [AR]}}, _}, SN, Tid)
+ when (Last == false) ->
+ (catch rsmms2_mg_do_verify_notify_reply(Tid, AR));
+rsmms2_mg_verify_notify_reply(Crap, SN, Tid) ->
+ io:format("rsmms2_mg_verify_notify_reply -> unknown reply"
+ "~n SN: ~p"
+ "~n Tid: ~p"
+ "~n Crap: ~p"
+ "~n", [SN, Tid, Crap]),
+ {error, Crap, ok}.
+
+rsmms2_mg_do_verify_notify_reply(Tid, AR) ->
+ io:format("rsmms2_mg_do_verify_notify_reply -> ok"
+ "~n Tid: ~p"
+ "~n AR: ~p"
+ "~n", [Tid, AR]),
+ CR =
+ case AR of
+ #'ActionReply'{commandReply = [CmdRep]} ->
+ CmdRep;
+ _ ->
+ Reason1 = {invalid_action_reply, AR},
+ throw({error, Reason1, ok})
+ end,
+ NR =
+ case CR of
+ {notifyReply, NotifyReply} ->
+ NotifyReply;
+ _ ->
+ Reason2 = {invalid_command_reply, CR},
+ throw({error, Reason2, ok})
+ end,
+ case NR of
+ #'NotifyReply'{terminationID = [Tid],
+ errorDescriptor = asn1_NOVALUE} ->
+ {ok, AR, ok};
+ _ ->
+ Reason3 = {invalid_NotifyReply, NR},
+ {error, Reason3, ok}
+ end.
+
+rsmms2_mg_verify_segment_timeout_fun(SN) ->
+ fun(Rep) -> rsmms2_mg_verify_segment_timeout(Rep, SN) end.
+
+rsmms2_mg_verify_segment_timeout(
+ {handle_trans_reply, _CH, ?VERSION, {error, Reason}, _}, SN) ->
+ case Reason of
+ {segment_timeout, [SN]} ->
+ {ok, Reason, ok};
+ _ ->
+ {error, {invalid_reason, Reason}, ok}
+ end;
+rsmms2_mg_verify_segment_timeout(Crap, SN) ->
+ io:format("rsmms2_mg_verify_segment_timeout -> unknown reply"
+ "~n SN: ~p"
+ "~n Crap: ~p"
+ "~n", [SN, Crap]),
+ {error, Crap, ok}.
+
+rsmms2_mg_verify_handle_disco_fun() ->
+ fun(Ev) -> rsmms2_mg_verify_handle_disconnect(Ev) end.
+
+rsmms2_mg_verify_handle_disconnect({handle_disconnect, _CH, ?VERSION, R}) ->
+ io:format("rsmms2_mg_verify_handle_disconnect -> ok"
+ "~n R: ~p"
+ "~n", [R]),
+ case R of
+ {no_controlling_process,shutdown} ->
+ {ok, R, ok};
+ _ ->
+ {error, {unexpected_reason, R}, ok}
+ end;
+rsmms2_mg_verify_handle_disconnect(Crap) ->
+ io:format("rsmms2_mg_verify_handle_disconnect -> invalid: "
+ "~n Crap: ~p"
+ "~n", [Crap]),
+ {error, Crap, ok}.
+
+
+rsmms2_mg_service_change_request_ar(_Mid, Cid) ->
+ Prof = cre_serviceChangeProf("resgw", 1),
+ SCP = cre_serviceChangeParm(restart, ["901 mg col boot"], Prof),
+ Root = #megaco_term_id{id = ["root"]},
+ SCR = cre_serviceChangeReq([Root], SCP),
+ CMD = cre_command(SCR),
+ CR = cre_cmdReq(CMD),
+ cre_actionReq(Cid, [CR]).
+
+rsmms2_mg_notify_request_ar(Rid, Tids, Cid) ->
+ rsmms2_mg_notify_request_ar(Rid, Tids, Cid, []).
+
+rsmms2_mg_notify_request_ar(_Rid, [], Cid, Cmds) ->
+ cre_actionReq(Cid, lists:reverse(Cmds));
+rsmms2_mg_notify_request_ar(Rid, [Tid|Tids], Cid, Cmds) ->
+ TT = cre_timeNotation("19990729", "22000000"),
+ Ev = cre_obsEvent("al/of", TT),
+ EvsDesc = cre_obsEvsDesc(Rid, [Ev]),
+ NR = cre_notifyReq([Tid], EvsDesc),
+ CMD = cre_command(NR),
+ CR = cre_cmdReq(CMD),
+ rsmms2_mg_notify_request_ar(Rid, Tids, Cid, [CR|Cmds]).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Common message creation functions
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% cre_errorDesc(Code, Text) when is_list(Text) ->
+%% #'ErrorDescriptor'{errorCode = Code, errorText = Text};
+%% cre_errorDesc(Code, Text0) ->
+%% Text = lists:flatten(io_lib:format("~w",[Text0])),
+%% #'ErrorDescriptor'{errorCode = Code, errorText = Text}.
+
+cre_segReply(TransId, SN, SC) ->
+ megaco_test_msg_v3_lib:cre_SegmentReply(TransId, SN, SC).
+
+cre_serviceChangeParm(M,R,P) ->
+ %% Version 1 'ServiceChangeParm'
+ {'ServiceChangeParm',
+ M, % serviceChangeMethod,
+ asn1_NOVALUE, % serviceChangeAddress
+ ?VERSION, % serviceChangeVersion
+ P, % serviceChangeProfile
+ R, % serviceChangeReason
+ asn1_NOVALUE, % serviceChangeDelay
+ asn1_NOVALUE, % serviceChangeMgcId
+ asn1_NOVALUE, % timeStamp
+ asn1_NOVALUE % nonStandardData
+ }.
+
+cre_serviceChangeReq(Tid, Parms) ->
+ #'ServiceChangeRequest'{terminationID = Tid,
+ serviceChangeParms = Parms}.
+
+cre_timeNotation(D,T) ->
+ #'TimeNotation'{date = D, time = T}.
+
+cre_obsEvent(Name, Not) ->
+ #'ObservedEvent'{eventName = Name,
+ timeNotation = Not}.
+%% cre_obsEvent(Name, Not, Par) ->
+%% #'ObservedEvent'{eventName = Name,
+%% timeNotation = Not,
+%% eventParList = Par}.
+
+cre_obsEvsDesc(Id, EvList) ->
+ #'ObservedEventsDescriptor'{requestId = Id,
+ observedEventLst = EvList}.
+
+cre_notifyReq(Tid, EvsDesc) ->
+ #'NotifyRequest'{terminationID = Tid,
+ observedEventsDescriptor = EvsDesc}.
+
+cre_command(R) when is_record(R, 'NotifyRequest') ->
+ {notifyReq, R};
+cre_command(R) when is_record(R, 'ServiceChangeRequest') ->
+ {serviceChangeReq, R}.
+
+cre_cmdReq(Cmd) ->
+ #'CommandRequest'{command = Cmd}.
+
+cre_actionReq(CtxId, CmdReqs) when is_list(CmdReqs) ->
+ #'ActionRequest'{contextId = CtxId,
+ commandRequests = CmdReqs}.
+
+cre_transReq(TransId, ARs) when is_list(ARs) ->
+ #'TransactionRequest'{transactionId = TransId,
+ actions = ARs}.
+
+%% --
+
+cre_serviceChangeResParm(Mid) ->
+ cre_serviceChangeResParm(Mid, ?VERSION).
+
+cre_serviceChangeResParm(Mid, V) ->
+ #'ServiceChangeResParm'{serviceChangeMgcId = Mid,
+ serviceChangeVersion = V}.
+
+cre_serviceChangeResult(SCRP) when is_record(SCRP, 'ServiceChangeResParm') ->
+ {serviceChangeResParms, SCRP};
+cre_serviceChangeResult(ED) when is_record(ED, 'ErrorDescriptor') ->
+ {errorDescriptor, ED}.
+
+cre_serviceChangeReply(Tid, Res) ->
+ #'ServiceChangeReply'{terminationID = Tid,
+ serviceChangeResult = Res}.
+
+cre_cmdReply(R) when is_record(R, 'NotifyReply') ->
+ {notifyReply, R};
+cre_cmdReply(R) when is_record(R, 'ServiceChangeReply') ->
+ {serviceChangeReply, R}.
+
+cre_notifyReply(Tid) ->
+ #'NotifyReply'{terminationID = Tid}.
+
+cre_actionReply(CtxId, CmdRep) ->
+ #'ActionReply'{contextId = CtxId,
+ commandReply = CmdRep}.
+
+cre_transResult(ED) when is_record(ED, 'ErrorDescriptor') ->
+ {transactionError, ED};
+cre_transResult([AR|_] = ARs) when is_record(AR, 'ActionReply') ->
+ {actionReplies, ARs}.
+
+%% cre_transReply(TransId, Res) ->
+%% #'TransactionReply'{transactionId = TransId,
+%% transactionResult = Res}.
+
+cre_transReply(TransId, Res, SN) ->
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = Res,
+ segmentNumber = SN}.
+
+cre_transReply(TransId, Res, SN, SC) ->
+ #'TransactionReply'{transactionId = TransId,
+ transactionResult = Res,
+ segmentNumber = SN,
+ segmentationComplete = SC}.
+
+cre_transAck(TransId) ->
+ megaco_test_msg_v3_lib:cre_TransactionAck(TransId).
+
+
+%% --
+
+cre_serviceChangeProf(Name, Ver) when is_list(Name) andalso is_integer(Ver) ->
+ #'ServiceChangeProfile'{profileName = Name,
+ version = Ver}.
+
+cre_transaction(Trans) when is_record(Trans, 'TransactionRequest') ->
+ {transactionRequest, Trans};
+cre_transaction(Trans) when is_record(Trans, 'TransactionPending') ->
+ {transactionPending, Trans};
+cre_transaction(Trans)
+ when is_record(Trans, 'TransactionReply') or
+ (is_tuple(Trans) and (element(1, Trans) == 'TransactionReply')) ->
+ {transactionReply, Trans};
+cre_transaction(Trans) when is_list(Trans) ->
+ {transactionResponseAck, Trans};
+cre_transaction(SR) when is_record(SR, 'SegmentReply') ->
+ {segmentReply, SR}.
+
+cre_transactions(Trans) when is_list(Trans) ->
+ {transactions, Trans}.
+
+cre_message(Version, Mid, Body) ->
+ #'Message'{version = Version,
+ mId = Mid,
+ messageBody = Body}.
+
+cre_megacoMessage(Mess) ->
+ #'MegacoMessage'{mess = Mess}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Transform a short timer to a long one.
+%% The purpose of this is to trick the stack
+%% to keep re-sending the request, even after
+%% having received the first pending (which
+%% indicates that the other side _IS_
+%% working on the request).
+-ifdef(MEGACO_TEST_CODE).
+
+init_request_timer({short, Ref}) ->
+ {long, Ref};
+init_request_timer(O) ->
+ O.
+
+-endif.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+await_completion(Ids) ->
+ case megaco_test_generator_lib:await_completion(Ids) of
+ {ok, Reply} ->
+ d("OK => Reply: ~n~p", [Reply]),
+ ok;
+ {error, {OK, ERROR}} ->
+ d("ERROR => "
+ "~n OK: ~p"
+ "~n ERROR: ~p", [OK, ERROR]),
+ ?ERROR({failed, ERROR});
+ {error, Reply} ->
+ d("ERROR => "
+ "~n Reply: ~p", [Reply]),
+ ?ERROR({failed, Reply})
+ end.
+
+%% await_completion(Ids, Timeout) ->
+%% case megaco_test_generator_lib:await_completion(Ids, Timeout) of
+%% {ok, Reply} ->
+%% d("OK => Reply: ~n~p", [Reply]),
+%% ok;
+%% {error, {OK, ERROR}} ->
+%% d("ERROR => "
+%% "~n OK: ~p"
+%% "~n ERROR: ~p", [OK, ERROR]),
+%% ?ERROR({failed, ERROR});
+%% {error, Reply} ->
+%% d("ERROR => Reply: ~n~p", [Reply]),
+%% ?ERROR({failed, Reply})
+%% end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% tim() ->
+%% {A,B,C} = erlang:now(),
+%% A*1000000000+B*1000+(C div 1000).
+
+
+make_node_name(Name) ->
+ case string:tokens(atom_to_list(node()), [$@]) of
+ [_,Host] ->
+ list_to_atom(lists:concat([atom_to_list(Name) ++ "@" ++ Host]));
+ _ ->
+ exit("Test node must be started with '-sname'")
+ end.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+sleep(X) -> receive after X -> ok end.
+
+%% error_msg(F,A) -> error_logger:error_msg(F ++ "~n",A).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+i(F) ->
+ i(F, []).
+
+i(F, A) ->
+ print(info, get(verbosity), now(), get(tc), "INF", F, A).
+
+
+d(F) ->
+ d(F, []).
+
+d(F, A) ->
+ print(debug, get(verbosity), now(), get(tc), "DBG", F, A).
+
+
+printable(_, debug) -> true;
+printable(info, info) -> true;
+printable(_,_) -> false.
+
+print(Severity, Verbosity, Ts, Tc, P, F, A) ->
+ print(printable(Severity,Verbosity), Ts, Tc, P, F, A).
+
+print(true, Ts, Tc, P, F, A) ->
+ io:format("*** [~s] ~s ~p ~s:~w ***"
+ "~n " ++ F ++ "~n",
+ [format_timestamp(Ts), P, self(), get(sname), Tc | A]);
+print(_, _, _, _, _, _) ->
+ ok.
+
+format_timestamp(Now) -> megaco:format_timestamp(Now).
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% random_init() ->
+%% {A,B,C} = now(),
+%% random:seed(A,B,C).
+
+%% random() ->
+%% 10 * random:uniform(50).
+
+%% apply_load_timer() ->
+%% erlang:send_after(random(), self(), apply_load_timeout).
+
+
+