📄 megaco_test_generic_transport.erl
字号:
%% ``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 via the world wide web 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.%%%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 2007, Ericsson Utvecklings%% AB. All Rights Reserved.''%%%% $Id$%%%%----------------------------------------------------------------------%% Purpose: Generic megaco transport simulator module%%-----------------------------------------------------------------------module(megaco_test_generic_transport).-behaviour(gen_server).-behaviour(megaco_transport).-export([ start_transport/0, connect/2, start/1, stop/0, incomming_message/2 ]).%% gen_server callbacks-export([ init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3 ]).%% megaco_transport callbacks-export([ send_message/2, resend_message/2 ]).-record(state, {parent, controller, receive_handle}).-include_lib("megaco/include/megaco.hrl").%% -include("megaco_test_lib.hrl").-define(SERVER, ?MODULE).%%-------------------------------------------------------------------%% API%%-------------------------------------------------------------------start(RH) -> {ok, Pid} = start_transport(), {ok, SendHandle, _} = connect(Pid, [{receive_handle, RH}]), {ok, SendHandle}.start_transport() -> %% GS_ARGS = [{debug,[trace]}], GS_ARGS = [], {ok, Pid} = gen_server:start_link({local, ?SERVER}, ?MODULE, [self()], GS_ARGS), unlink(Pid), {ok, Pid}.connect(Sup, Opts) -> call({connect, Sup, Opts}).stop() -> call(stop).%%----------------------------------------------------------------------%% Megaco transport callback%%----------------------------------------------------------------------send_message(SendHandle, Bin) -> call({transport, {send_message, SendHandle, Bin}}).resend_message(SendHandle, Bin) -> call({transport, {resend_message, SendHandle, Bin}}).incomming_message(Pid, Msg) -> cast(Pid, {incomming_message, Msg}).%%%-------------------------------------------------------------------%%% Callback functions from gen_server%%%-------------------------------------------------------------------%%--------------------------------------------------------------------%% Func: init/1%% Returns: {ok, State} |%% {ok, State, Timeout} |%% ignore |%% {stop, Reason}%%--------------------------------------------------------------------init([Parent]) -> {ok, #state{parent = Parent}}.%%--------------------------------------------------------------------%% Func: handle_call/3%% Returns: {reply, Reply, State} |%% {reply, Reply, State, Timeout} |%% {noreply, State} |%% {noreply, State, Timeout} |%% {stop, Reason, Reply, State} | (terminate/2 is called)%% {stop, Reason, State} (terminate/2 is called)%%--------------------------------------------------------------------handle_call({connect, _Sup, Opts}, _From, State) -> d("handle_call(connect) -> entry with" "~n Opts: ~p", [Opts]), {value, {_, ReceiveHandle}} = lists:keysearch(receive_handle, 1, Opts), {value, {_, Controller}} = lists:keysearch(port, 1, Opts), SendHandle = self(), ControlPid = self(), Reply = {ok, SendHandle, ControlPid}, {reply, Reply, State#state{controller = Controller, receive_handle = ReceiveHandle}};handle_call(stop, _From, State) -> d("handle_call(stop) -> entry"), Reply = ok, Reason = normal, {stop, Reason, Reply, State};handle_call({transport, Event}, _From, #state{controller = Pid, receive_handle = RH} = State) -> d("handle_call(transport) -> entry with" "~n Event: ~p", [Event]), Reply = handle_transport(Pid, RH, Event), {reply, Reply, State};handle_call(Req, From, State) -> d("handle_call -> entry with" "~n Req: ~p", [Req]), Reply = {error, {unknown_request, Req}}, Reason = {received_unexpected_request, Req, From}, {stop, Reason, Reply, State}.%%--------------------------------------------------------------------%% Func: handle_cast/2%% Returns: {noreply, State} |%% {noreply, State, Timeout} |%% {stop, Reason, State} (terminate/2 is called)%%--------------------------------------------------------------------handle_cast({incomming_message, Msg}, #state{receive_handle = RH} = State) -> d("handle_cast(incomming_message) -> entry with" "~n Msg: ~p", [Msg]), handle_incomming_message(Msg, RH), {noreply, State};handle_cast(Msg, State) -> d("handle_cast -> entry with" "~n Msg: ~p", [Msg]), Reason = {received_unexpected_message, Msg}, {stop, Reason, State}.%%--------------------------------------------------------------------%% Func: handle_info/2%% Returns: {noreply, State} |%% {noreply, State, Timeout} |%% {stop, Reason, State} (terminate/2 is called)%%--------------------------------------------------------------------handle_info(Info, State) -> d("handle_info -> entry with" "~n Info: ~p", [Info]), Reason = {received_unexpected_info, Info}, {stop, Reason, State}.%%--------------------------------------------------------------------%% Func: terminate/2%% Purpose: Shutdown the server%% Returns: any (ignored by gen_server)%%--------------------------------------------------------------------terminate(_Reason, _State) -> ok.%%----------------------------------------------------------------------%% Func: code_change/3%% Purpose: Convert process state when code is changed%% Returns: {ok, NewState}%%----------------------------------------------------------------------code_change(_Vsn, State, _Extra) -> {ok, State}.%%%-------------------------------------------------------------------%%% Internal functions%%%-------------------------------------------------------------------handle_transport(Pid, #megaco_receive_handle{encoding_mod = EM, encoding_config = EC}, {Event, SendHandle, Bin}) -> Info = case (catch EM:decode_message(EC, Bin)) of {ok, MegMsg} -> MegMsg; Error -> d("handle_transport -> decode failed" "~n Error: ~p", [Error]), {bad_message, Error, Bin} end, Pid ! {transport_event, {Event, SendHandle, Info}, self()}, receive {transport_reply, Reply, Pid} -> d("handle_transport -> received reply" "~n Reply: ~p", [Reply]), Reply after 10000 -> receive Any -> d("handle_transport -> received crap after timeout" "~n Any: ~p", [Any]), exit({timeout, Any}) after 0 -> d("handle_transport -> timeout"), exit(timeout) end end.%% This function is used to simulate incomming messageshandle_incomming_message(Msg, #megaco_receive_handle{encoding_mod = EM, encoding_config = EC} = RH) -> Self = self(), case EM:encode_message(EC, Msg) of {ok, Bin} -> spawn(fun() -> megaco:process_received_message(RH, Self, Self, Bin) end), ok; Error -> d("handle_incomming_message -> encode failed" "~n Error: ~p", [Error]), exit(Error) end. %%-------------------------------------------------------------------call(Req) -> call(Req, infinity).call(Req, Timeout) -> case (catch gen_server:call(?SERVER, Req, Timeout)) of {'EXIT', _} -> {error, not_started}; Res -> Res end.%% cast(Msg) ->%% cast(whereis(?SERVER), Msg).cast(Pid, Msg) -> d("cast -> entry with" "~n Pid: ~p" "~n Msg: ~p", [Pid, Msg]), case (catch gen_server:cast(Pid, Msg)) of {'EXIT', Reason} -> d("cast -> failed casting" "~n Reason: ~p", [Reason]), {error, not_started}; Res -> Res end. %%-------------------------------------------------------------------d(F) -> d(F, []).d(F, A) -> print(now(), F, A).print(Ts, F, A) -> io:format("*** [~s] GENERIC TRANSPORT [~p] ***" "~n " ++ F ++ "~n", [format_timestamp(Ts), self() | A]).format_timestamp({_N1, _N2, N3} = Now) -> {Date, Time} = calendar:now_to_datetime(Now), {YYYY,MM,DD} = Date, {Hour,Min,Sec} = Time, FormatDate = io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), lists:flatten(FormatDate).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -