megaco_test_generator.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,523 行 · 第 1/4 页

ERL
1,523
字号
    end;do_megaco({listen, Opts0},	  #megaco{recv_handle = RH, port = Port, transport_sup = Pid} = State)   when RH#megaco_receive_handle.send_mod == megaco_udp ->    p("listen(udp) - open"),    Opts = [{port, Port}, {receive_handle, RH}|Opts0],    case megaco_udp:open(Pid, Opts) of	{ok, _SH, _CtrlPid} ->	    State;	Else ->	    megaco_error({listen, Opts0}, {failed_starting_udp_open, Else})    end;do_megaco({connect, Host, Opts0}, 	  #megaco{transport_sup = Sup,		  recv_handle   = RH, 		  port          = Port} = State) ->    #megaco_receive_handle{send_mod = TM} = RH,    p("connect ~w ~p", [TM,Host]),    PrelMid = preliminary_mid,    case TM of	megaco_tcp ->	    Opts = [{host, Host}, {port, Port}, {receive_handle, RH}|Opts0],	    case (catch megaco_tcp:connect(Sup, Opts)) of		{ok, SH, ControlPid} ->		    d("tcp connected: ~p, ~p", [SH, ControlPid]),		    megaco_connector_start(RH, PrelMid, SH, ControlPid),		    State#megaco{send_handle = SH,				 ctrl_pid    = ControlPid};		Error ->		    megaco_error({connect, tcp, Host, Opts0}, Error)	    end;	megaco_udp ->	    Opts = [{port, 0}, {receive_handle, RH}|Opts0],            d("udp open", []),	    case (catch megaco_udp:open(Sup, Opts)) of		{ok, Handle, ControlPid} ->		    d("udp opened: ~p, ~p", [Handle, ControlPid]),		    SH = megaco_udp:create_send_handle(Handle, Host, Port),		    megaco_connector_start(RH, PrelMid, SH, ControlPid),		    State#megaco{send_handle = SH,				 ctrl_pid    = ControlPid};		Error ->		    megaco_error({connect, udp, Host, Opts0}, Error)	    end;	megaco_test_generic_transport ->	    Opts = [{host, Host}, {port, Port}, {receive_handle, RH}|Opts0],	    case (catch megaco_test_generic_transport:connect(Sup, Opts)) of		{ok, SH, ControlPid} ->		    d("generic connected: ~p, ~p", [SH, ControlPid]),		    megaco_connector_start(RH, PrelMid, SH, ControlPid),		    State#megaco{send_handle = SH,				 ctrl_pid    = ControlPid};		Error ->		    megaco_error({connect, generic, Host, Opts0}, Error)	    end    end;do_megaco(megaco_connect, State) ->    p("megaco_connect"),    receive	{megaco_connect_result, {ok, CH}} ->	    p("megaco connect succeeded: ~p", [CH]),	    State#megaco{conn_handle = CH};	{megaco_connect_result, Error} ->	    p("megaco connect failed: ~p", [Error]),	    #megaco{result = Res} = State,	    State#megaco{result = [Error|Res]}    end;do_megaco({megaco_user_info, Tag}, #megaco{mid = Mid, result = Res} = State)   when Mid /= undefined ->    p("megaco_user_info: ~w", [Tag]),    Val = (catch megaco:user_info(Mid, Tag)),    d("megaco_user_info: ~p", [Val]),    State#megaco{result = [Val|Res]};do_megaco({megaco_update_user_info, Tag, Val}, #megaco{mid = Mid} = State)   when Mid /= undefined ->    p("megaco_update_user_info: ~w -> ~p", [Tag, Val]),    ok = megaco:update_user_info(Mid, Tag, Val),    State;do_megaco({megaco_conn_info, Tag}, 	  #megaco{conn_handle = CH, result = Res} = State)   when CH /= undefined ->    p("megaco_conn_info: ~w", [Tag]),    Val = (catch megaco:conn_info(CH, Tag)),    d("megaco_conn_info: ~p", [Val]),    State#megaco{result = [Val|Res]};do_megaco({megaco_update_conn_info, Tag, Val}, 	  #megaco{conn_handle = CH} = State)   when CH /= undefined ->    p("megaco_update_conn_info: ~w -> ~p", [Tag, Val]),    ok = megaco:update_conn_info(CH, Tag, Val),    State;do_megaco({megaco_system_info, Tag}, #megaco{result = Res} = State) ->    p("megaco_system_info: ~w", [Tag]),    Val = (catch megaco:system_info(Tag)),    d("megaco_system_info: ~p", [Val]),    State#megaco{result = [Val|Res]};%% This is either a MG or a MGC which is only connected to one MGdo_megaco({megaco_call, ARs, Opts}, #megaco{conn_handle = CH} = State)  when CH /= undefined ->    p("megaco_call"),    {_PV, UserReply} = megaco:call(CH, ARs, Opts),    d("megaco_cast -> UserReply: ~n~p", [UserReply]),    State;do_megaco({megaco_call, RemoteMid, ARs, Opts}, #megaco{mid = Mid} = State) ->    p("megaco_call: ~p", [RemoteMid]),    %% First we have to find the CH for this Mid    Conns = megaco:user_info(Mid, connections),    {value, {_, CH}} = 	lists:keysearch(RemoteMid, #megaco_conn_handle.remote_mid, Conns),    {_PV, UserReply} = megaco:call(CH, ARs, Opts),    d("megaco_call -> UserReply: ~n~p", [UserReply]),    State;%% This is either a MG or a MGC which is only connected to one MGdo_megaco({megaco_cast, ARs, Opts}, #megaco{conn_handle = CH} = State)  when CH /= undefined ->    p("megaco_cast"),    case megaco:cast(CH, ARs, Opts) of	ok -> 	    State;	Error ->	    d("failed sending (cast) message: ~n~p", [Error]), 	    #megaco{result = Acc} = State,	    {error, State#megaco{result = [Error|Acc]}}    end;do_megaco({megaco_cast, RemoteMid, ARs, Opts}, #megaco{mid = Mid} = State) ->    p("megaco_cast: ~p", [RemoteMid]),    %% First we have to find the CH for this Mid    Conns = megaco:user_info(Mid, connections),    {value, {_, CH}} = 	lists:keysearch(RemoteMid, #megaco_conn_handle.remote_mid, Conns),    case megaco:cast(CH, ARs, Opts) of	ok ->	    State;	Error ->	    d("failed sending (cast) message: ~n~p", [Error]), 	    #megaco{result = Acc} = State,	    {error, State#megaco{result = [Error|Acc]}}    end;%% Nothing shall happen for atleast Timeout timedo_megaco({megaco_callback, nocall, Timeout}, State) ->    p("megaco_callback [~w]", [nocall]),    receive	{handle_megaco_callback, Type, Msg, Pid} ->	    d("received unexpected megaco callback: ~n~p", [Msg]),	    #megaco{result = Res} = State,	    Err = {unexpected_callback, Type, Msg, Pid},	    {error, State#megaco{result = [Err|Res]}}    after Timeout ->	    State    end;do_megaco({megaco_callback, Tag, Verify}, State) when is_function(Verify) ->    p("megaco_callback [~w]", [Tag]),    receive	{handle_megaco_callback, Type, Msg, Pid} ->	    d("received megaco callback: ~n~p", [Msg]),	    case Verify(Msg) of		{VRes, Res, Reply} ->		    d("megaco_callback [~w] ~w",[Tag, VRes]),		    handle_megaco_callback_reply(Pid, Type, Reply),		    validate(VRes, Tag, Res, State);		{VRes, Delay, Res, Reply} ->		    d("megaco_callback [~w] ~w, ~w",[Tag,Delay,VRes]),		    handle_megaco_callback_reply(Pid, Type, Delay, Reply),		    validate(VRes, Tag, Res, State)	    end    end;do_megaco({megaco_callback, Tag, {VMod, VFunc, VArgs}}, State)   when is_atom(VMod) and is_atom(VFunc) and is_list(VArgs) ->    p("megaco_callback [~w]", [Tag]),    receive	{handle_megaco_callback, Type, Msg, Pid} ->	    d("received megaco callback: ~n~p"	      "~n   VMod:  ~w"	      "~n   VFunc: ~w"	      "~n   VArgs: ~p", [Msg, VMod, VFunc, VArgs]),	    case apply(VMod, VFunc, [Msg|VArgs]) of		{VRes, Res, Reply} ->		    d("megaco_callback [~w] ~w",[Tag, VRes]),		    handle_megaco_callback_reply(Pid, Type, Reply),		    validate(VRes, Tag, Res, State);		{VRes, Delay, Res, Reply} ->		    d("megaco_callback [~w] ~w, ~w",[Tag,Delay,VRes]),		    handle_megaco_callback_reply(Pid, Type, Delay, Reply),		    validate(VRes, Tag, Res, State)	    end    end;do_megaco({megaco_callback, Tag, Verify, Timeout}, State)   when is_function(Verify) and (is_integer(Timeout) and (Timeout > 0)) ->    p("megaco_callback [~w]", [Tag]),    receive	{handle_megaco_callback, Type, Msg, Pid} ->	    d("received megaco callback: ~n~p", [Msg]),	    case Verify(Msg) of		{VRes, Res, Reply} ->		    d("megaco_callback [~w] ~w",[Tag,VRes]),		    handle_megaco_callback_reply(Pid, Type, Reply),		    validate(VRes, Tag, Res, State);		{VRes, Delay, Res, Reply} ->		    d("megaco_callback [~w] ~w, ~w",[Tag,Delay,VRes]),		    handle_megaco_callback_reply(Pid, Type, Delay, Reply),		    validate(VRes, Tag, Res, State)	    end    after Timeout ->	    #megaco{result = Res} = State,	    Err = {callback_timeout, Tag, Timeout},	    {error, State#megaco{result = [Err|Res]}}    end;do_megaco({megaco_callback, Verifiers}, State) ->    p("megaco_callback"),    (catch megaco_callback_verify(Verifiers, State));do_megaco({megaco_cancel, Reason}, #megaco{conn_handle = CH} = State) ->    p("megaco_cancel [~w]", [Reason]),    case megaco:cancel(CH, Reason) of	ok ->	    State;	Error ->	    d("failed cancel: ~n~p", [Error]), 	    #megaco{result = Acc} = State,	    {error, State#megaco{result = [Error|Acc]}}    end;do_megaco({trigger, Trigger}, State) when is_function(Trigger) ->    p("trigger"),    Trigger(),    State;do_megaco({sleep, To}, State) ->    p("sleep ~p", [To]),    sleep(To),    State;do_megaco(Instr, _State) ->    megaco_error(Instr, invalid_instruction).%% This is used when a number of callback's is expected, but where%% the specific order is unknown.megaco_callback_verify([], State) ->    d("megaco_callback_verify -> done"),    State;megaco_callback_verify(Verifiers0, State0) ->    d("megaco_callback_verify -> entry when"      "~n   length(Verifiers0): ~w", [length(Verifiers0)]),    receive	{handle_megaco_callback, Type, Msg, Pid} ->	    d("received megaco callback: ~w~n~p", [Type,Msg]),	    case megaco_callback_verify(Verifiers0, Type, Msg, Pid, State0) of		{ok, Verifiers, State} ->		    megaco_callback_verify(Verifiers, State);		Error ->		    Error	    end    end.    megaco_callback_verify(Verifiers0, Type, Msg, Pid, State0) ->    d("megaco_callback_verify -> entry"),    Tag = element(1,Msg),    d("megaco_callback_verify -> Tag: ~w",[Tag]),    case lists:keysearch(Tag, 1, Verifiers0) of	{value, {Tag, N, Verify}} when (N > 0) and is_function(Verify) ->	    d("megaco_callback_verify -> N: ~w",[N]),	    case Verify(Msg) of		{VRes, Res, Reply} ->		    d("megaco_callback_verify -> VRes: ~w",[VRes]),		    handle_megaco_callback_reply(Pid, Type, Reply),		    case validate(VRes, Tag, Res, State0) of			{error, _} = EState ->			    d("megaco_callback_verify -> (1) error"),			    throw(EState);			State when N > 1 ->			    d("megaco_callback_verify -> (1) validated"),			    Rec = {Tag, N-1, Verify},			    Verifiers = 				lists:keyreplace(Tag, 1, Verifiers0, Rec),			    {ok, Verifiers, State};			State ->			    d("megaco_callback_verify -> (2) validated"),			    Verifiers = lists:keydelete(Tag, 1, Verifiers0),			    {ok, Verifiers, State}		    end;		{VRes, Delay, Res, Reply} ->		    d("megaco_callback_verify -> Delay: ~w, VRes: ~w",		      [Delay,VRes]),		    handle_megaco_callback_reply(Pid, Type, Delay, Reply),		    case validate(VRes, Tag, Res, State0) of			{error, _} = EState ->			    d("megaco_callback_verify -> (2) error"),			    throw(EState);			State when N > 1 ->			    d("megaco_callback_verify -> (3) validated"),			    Rec = {Tag, N-1, Verify},			    Verifiers = 				lists:keyreplace(Tag, 1, Verifiers0, Rec),			    {ok, Verifiers, State};			State ->			    d("megaco_callback_verify -> (4) validated"),			    Verifiers = lists:keydelete(Tag, 1, Verifiers0),			    {ok, Verifiers, State}		    end	    end;	false ->	    d("megaco_callback_verify -> no such tag ~w~n~p", 	      [Tag, Verifiers0]),	    #megaco{result = Res} = State0,	    State = State0#megaco{result = [{Type, error, Msg}|Res]},	    throw({error, State})    end.validate(ok, handle_connect = Tag, CH, #megaco{result = Acc} = S) ->    S#megaco{conn_handle = CH, result = [{Tag, ok, CH}|Acc]};validate(ok, Tag, Res, #megaco{result = Acc} = S) ->    S#megaco{result = [{Tag, ok, Res}|Acc]};validate(error, Tag, Res, #megaco{result = Acc} = S) ->    {error, S#megaco{result = [{Tag, error, Res}|Acc]}}.megaco_error(Instr, Error) ->    throw({error, {Instr, Error}}).megaco_connector_start(RH, PrelMid, SH, ControlPid) ->    spawn_link(?MODULE, megaco_connect, [RH, PrelMid, SH, ControlPid, self()]).megaco_connect(RH, PrelMid, SH, ControlPid, Parent) ->    Result = megaco:connect(RH, PrelMid, SH, ControlPid),    Parent ! {megaco_connect_result, Result},    exit(normal).megaco_cleanup(#megaco{mid = Mid}) ->    Close = fun(CH) -> do_megaco_cleanup(CH) end,    Conns = megaco:user_info(Mid, connections),    lists:foreach(Close, Conns).do_megaco_cleanup(CH) ->    case (catch do_megaco_cleanup2(CH)) of	ok ->	    ok;	{'EXIT', {no_such_connection, _}} ->	    ok;	{'EXIT', Reason} ->	    exit(Reason)    end.do_megaco_cleanup2(CH) ->    d("do_megaco_cleanup2 -> entry with"      "~n   CH: ~p", [CH]),    Reason     = {stopped_by_user,self()},    Pid        = megaco:conn_info(CH, control_pid),    SendMod    = megaco:conn_info(CH, send_mod),    SendHandle = megaco:conn_info(CH, send_handle),    d("do_megaco_cleanup2 -> disconnect"),    megaco:disconnect(CH, Reason),    d("do_megaco_cleanup2 -> disconnected, now cancel"),    megaco:cancel(CH, Reason),    d("do_megaco_cleanup2 -> canceled, now close"),    case SendMod of	megaco_tcp -> megaco_tcp:close(SendHandle);	megaco_udp -> megaco_udp:close(SendHandle);	SendMod    -> exit(Pid, Reason)    end,    ok.parse_megaco([], RevInstrs) ->    {ok, lists:reverse(RevInstrs)};

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?