⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 megaco_simple_mg.erl

📁 OTP是开放电信平台的简称
💻 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 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%%%%     $Id$%%%%----------------------------------------------------------------------%% Purpose: Simple example of an MG%%%% Example usage:%% %%   cd megaco/examples/simple%%   erl -pa ../../../megaco/ebin -s megaco_filter -s megaco%%   megaco_simple_mg:start().%%-----------------------------------------------------------------------module(megaco_simple_mg).-behaviour(megaco_user).-export([	 start_batch/0, start_batch/1, init_batch/4,	 start/0, start/3, 	 start/4, %% ????????????????????????	 stop/0, stop/1,	 start_tcp_text/2, start_tcp_binary/2, 	 start_udp_text/2, start_udp_binary/2	 ]).-export([         handle_connect/2,         handle_disconnect/3,         handle_syntax_error/3,         handle_message_error/3,         handle_trans_request/3,         handle_trans_long_request/3,         handle_trans_reply/4,         handle_trans_ack/4,	 handle_unexpected_trans/3,	 handle_trans_request_abort/4        ]).-include_lib("megaco/include/megaco.hrl").-include_lib("megaco/include/megaco_message_v1.hrl").%%----------------------------------------------------------------------%% To be used at command line: erl -s ?MODULE start_batch%%----------------------------------------------------------------------start_batch() ->    start_batch([]).start_batch(Args0) when list(Args0) ->    {ok, LocalHost} = inet:gethostname(),    Defs    = [{mgc_host, LocalHost}, {trace,false}, {debug, false}],    Args    = parse_args(Args0, Defs),    MgcHost = get_arg(mgc_host, Args),    Trace   = get_arg(trace, Args),    Debug   = get_arg(debug, Args),    Pid     = spawn(?MODULE, init_batch, [self(), MgcHost, Trace, Debug]),    receive	{init_batch, Pid, Res} ->	    io:format("~p(~p): ~p~n", [?MODULE, ?LINE, Res]),	    Res    end.	    parse_args([], Acc) ->    Acc;parse_args([Arg|Args], Acc) when atom(Arg) ->    case string:tokens(atom_to_list(Arg),"{},") of	["mgc_host", Host] when list(Host) ->	    parse_args(Args, parse_args(mgc_host, Host, Acc));	["trace",Trace] ->	    parse_args(Args, parse_args(trace, list_to_atom(Trace), Acc));	["debug",Debug] ->	    parse_args(Args, parse_args(debug, list_to_atom(Debug), Acc));	_Invalid ->	    parse_args(Args, Acc)    end.parse_args(Key, Val, Args) ->    Entry = {Key, Val},    case lists:keyreplace(Key, 1, Args, {Key, Val}) of	Args ->	    [Entry|Args];	Args2 ->	    Args2    end.get_arg(Key, Args) ->    {value, {Key, Val}} = lists:keysearch(Key, 1, Args),    Val.init_batch(ReplyTo, MgcHost, Trace, Debug) ->    register(?MODULE, self()),    Res = start(MgcHost, Trace, Debug),    ReplyTo ! {init_batch, self(), Res},    receive    after infinity -> Res    end.%%----------------------------------------------------------------------%% Starting the MG%%----------------------------------------------------------------------%% -----------------------------------------------------------------------init_inline_trace(true) ->    megaco:enable_trace(max, io);init_inline_trace(_) ->    ok.%% -----------------------------------------------------------------------start() ->    {ok, LocalHost} = inet:gethostname(),    start(LocalHost, false, false).%% Used when calling from the erlang shell:start(MgcHost, Trace, Debug) when atom(MgcHost), atom(Trace), atom(Debug) ->    start(atom_to_list(MgcHost), Trace, Debug);start(MgcHost, Trace, Debug) when list(MgcHost), atom(Trace), atom(Debug) ->    put(debug, Debug),    d("start -> entry with"      "~n   MgcHost: ~s"      "~n   Trace:   ~p", [MgcHost, Trace]),    init_inline_trace(Trace),    Starters = [fun start_tcp_text/2,		fun start_tcp_binary/2,		fun start_udp_text/2,		fun start_udp_binary/2],    [Fun(MgcHost, []) || Fun <- Starters].start_tcp_text(MgcHost, Default) ->    d("start_tcp_text -> entry with"      "~n   MgcHost: ~p", [MgcHost]),    Config = [{encoding_mod, megaco_pretty_text_encoder},	      {encoding_config, []},	      {send_mod, megaco_tcp} | Default],    Mid = {deviceName, "gateway_tt"},    {Mid, start(MgcHost, ?megaco_ip_port_text, Mid, Config)}.start_tcp_binary(MgcHost, Default) ->    d("start_tcp_binary -> entry with"      "~n   MgcHost: ~p", [MgcHost]),    Config = [{encoding_mod, megaco_binary_encoder},	      {encoding_config, []},	      {send_mod, megaco_tcp} | Default],    Mid = {deviceName, "gateway_tb"},    {Mid, start(MgcHost, ?megaco_ip_port_binary, Mid, Config)}.start_udp_text(MgcHost, Default) ->    d("start_udp_text -> entry with"      "~n   MgcHost: ~p", [MgcHost]),    Config = [{encoding_mod, megaco_pretty_text_encoder},	      {encoding_config, []},	      {send_mod, megaco_udp} | Default],    Mid = {deviceName, "gateway_ut"},    {Mid, start(MgcHost, ?megaco_ip_port_text, Mid, Config)}.start_udp_binary(MgcHost, Default) ->    d("start_udp_binary -> entry with"      "~n   MgcHost: ~p", [MgcHost]),    Config = [{encoding_mod, megaco_binary_encoder},	      {encoding_config, []},	      {send_mod, megaco_udp} | Default],    Mid = {deviceName, "gateway_ub"},    {Mid, start(MgcHost, ?megaco_ip_port_binary, Mid, Config)}.start(MgcHost, MgcPort, Mid, Config) ->    case megaco:start_user(Mid, [{user_mod, ?MODULE} | Config]) of	ok ->	    case start_transport(MgcHost, MgcPort, Mid) of		{ok, ConnHandle} ->		    service_change(ConnHandle);		{error, Reason} ->		    {error, Reason}	    end;	{error, Reason} ->	    {error, {start_user, Reason}}    end.start_transport(MgcHost, MgcPort, Mid) ->    RecHandle = megaco:user_info(Mid, receive_handle),    case RecHandle#megaco_receive_handle.send_mod of	megaco_tcp -> start_tcp(MgcHost, MgcPort, RecHandle);	megaco_udp -> start_udp(MgcHost, MgcPort, RecHandle);	SendMod    -> {error, {bad_send_mod, SendMod}}    end.start_tcp(MgcHost, MgcPort, RecHandle) ->    d("start_tcp -> start transport"),    case megaco_tcp:start_transport() of	{ok, Pid} ->	    d("start_tcp -> transport started: ~p", [Pid]),	    Options = [{host, MgcHost},		       {port, MgcPort},		       {receive_handle, RecHandle}],	    case megaco_tcp:connect(Pid, Options) of		{ok, SendHandle, ControlPid} ->		    d("start_tcp -> connected: ~p", [ControlPid]),		    MgcMid = preliminary_mid,		    megaco:connect(RecHandle, MgcMid, SendHandle, ControlPid);		{error, Reason} ->		    d("start_tcp -> connection failed: ~p", [Reason]),		    {error, {megaco_tcp_connect, Reason}}	    end;	{error, Reason} ->	    d("start_tcp -> failed starting transport: ~p", [Reason]),	    {error, {megaco_tcp_start_transport, Reason}}    end.start_udp(MgcHost, MgcPort, RecHandle) ->    d("start_udp -> start transport"),    case megaco_udp:start_transport() of	{ok, SupPid} ->	    d("start_udp -> transport started: ~p", [SupPid]),	    Options = [{port, 0}, {receive_handle, RecHandle}],	    case megaco_udp:open(SupPid, Options) of		{ok, Handle, ControlPid} ->		    d("start_udp -> port opened: ~p", [ControlPid]),		    %% Socket = megaco_udp:socket(Handle),		    %% MgPort = inet:port(Socket), BUGBUG BUGBUG		    MgcMid = preliminary_mid,		    SendHandle = megaco_udp:create_send_handle(Handle, 							       MgcHost, % BUGBUG BUGBUG							       MgcPort),		    megaco:connect(RecHandle, MgcMid, SendHandle, ControlPid);		{error, Reason} ->		    d("start_udp -> failed open port: ~p", [Reason]),		    {error, {megaco_udp_open, Reason}}	    end;	{error, Reason} ->	    d("start_udp -> failed starting transport: ~p", [Reason]),	    {error, {megaco_udp_start_transport, Reason}}    end.service_change(ConnHandle) ->    service_change(ConnHandle, restart, ?megaco_cold_boot).service_change(ConnHandle, Method, Reason) ->    SCP = #'ServiceChangeParm'{serviceChangeMethod = Method,			       serviceChangeReason = [Reason]},    TermId = [?megaco_root_termination_id],    SCR = #'ServiceChangeRequest'{terminationID = TermId,				  serviceChangeParms = SCP},    CR = #'CommandRequest'{command = {serviceChangeReq, SCR}},    AR = #'ActionRequest'{contextId = ?megaco_null_context_id,			  commandRequests = [CR]},    megaco:call(ConnHandle, [AR], []).    %%----------------------------------------------------------------------%% Stopping the MG%%----------------------------------------------------------------------stop() ->    [{Mid, stop(Mid)} || Mid <- megaco:system_info(users)].stop(Mid) ->    Reason = stopped_by_user,    Disco = fun(CH) ->		    Pid = megaco:conn_info(CH, control_pid),		    megaco:disconnect(CH, Reason),		    megaco:cancel(CH, Reason),		    exit(Pid, Reason)	    end,    lists:map(Disco, megaco:user_info(Mid, connections)),    megaco:stop_user(Mid).%%----------------------------------------------------------------------%% Invoked when a new connection is established%%----------------------------------------------------------------------handle_connect(ConnHandle, ProtocolVersion) ->    d("handle_connect -> entry with"      "~n   ConnHandle:      ~p"      "~n   ProtocolVersion: ~p", [ConnHandle, ProtocolVersion]),    ok.%%----------------------------------------------------------------------%% Invoked when a connection is teared down%%----------------------------------------------------------------------handle_disconnect(ConnHandle, ProtocolVersion, Reason) ->    d("handle_disconnect -> entry with"      "~n   ConnHandle:      ~p"      "~n   ProtocolVersion: ~p"      "~n   Reason:          ~p", [ConnHandle, ProtocolVersion, Reason]),    megaco:cancel(ConnHandle, Reason), % Cancel the outstanding messages    d("handle_disconnect -> done", []),    ok.%%----------------------------------------------------------------------%% Invoked when  a received message had syntax errors%%----------------------------------------------------------------------handle_syntax_error(ReceiveHandle, ProtocolVersion, ErrorDescriptor) ->    d("handle_syntax_error -> entry with"      "~n   ReceiveHandle:   ~p"      "~n   ProtocolVersion: ~p"      "~n   ErrorDescriptor: ~p",       [ReceiveHandle, ProtocolVersion, ErrorDescriptor]),    reply.%%----------------------------------------------------------------------%% Invoked when a received message contained no transactions%%----------------------------------------------------------------------handle_message_error(ConnHandle, ProtocolVersion, ErrorDescriptor) ->    d("handle_message_error -> entry with"      "~n   ConnHandle:      ~p"      "~n   ProtocolVersion: ~p"      "~n   ErrorDescriptor: ~p",       [ConnHandle, ProtocolVersion, ErrorDescriptor]),    no_reply.%%----------------------------------------------------------------------%% Invoked for each transaction request%%----------------------------------------------------------------------handle_trans_request(ConnHandle, ProtocolVersion, ActionRequests) ->    d("handle_trans_request -> entry with"       "~n   ConnHandle:      ~p"      "~n   ProtocolVersion: ~p"      "~n   ActionRequests:  ~p",       [ConnHandle, ProtocolVersion, ActionRequests]),    ED =  #'ErrorDescriptor'{errorCode = ?megaco_not_implemented,                             errorText = "Transaction requests not handled"},    {discard_ack, ED}.%%----------------------------------------------------------------------%% Optionally invoked for a time consuming transaction request%%----------------------------------------------------------------------handle_trans_long_request(ConnHandle, ProtocolVersion, ReqData) ->    d("handle_trans_long_request -> entry with"      "~n   ConnHandle:      ~p"      "~n   ProtocolVersion: ~p"      "~n   ReqData:         ~p", [ConnHandle, ProtocolVersion, ReqData]),    ED = #'ErrorDescriptor'{errorCode = ?megaco_not_implemented,                            errorText = "Long transaction requests not handled"},    {discard_ack,  ED}.%%----------------------------------------------------------------------%% Optionally invoked for a transaction reply%%----------------------------------------------------------------------handle_trans_reply(ConnHandle, ProtocolVersion, ActualReply, ReplyData) ->    d("handle_trans_reply -> entry with"      "~n   ConnHandle:      ~p"      "~n   ProtocolVersion: ~p"      "~n   ActualReply:     ~p"      "~n   ReplyData:       ~p",       [ConnHandle, ProtocolVersion, ActualReply, ReplyData]),    ok.%%----------------------------------------------------------------------%% Optionally invoked for a transaction acknowledgement%%----------------------------------------------------------------------handle_trans_ack(ConnHandle, ProtocolVersion, AckStatus, AckData) ->    d("handle_trans_ack -> entry with"       "~n   ConnHandle:      ~p"       "~n   ProtocolVersion: ~p"       "~n   AckStatus:       ~p"       "~n   AckData:         ~p",       [ConnHandle, ProtocolVersion, AckStatus, AckData]),    ok.%%----------------------------------------------------------------------%% Invoked when  an unexpected message has been received%%----------------------------------------------------------------------handle_unexpected_trans(ConnHandle, ProtocolVersion, Trans) ->    d("handle_unexpected_trans -> entry with"       "~n   ConnHandle:      ~p"       "~n   ProtocolVersion: ~p"       "~n   AckStatus:       ~p"       "~n   AckData:         ~p",       [ConnHandle, ProtocolVersion, Trans]),    ok.%%----------------------------------------------------------------------%% Invoked when  an unexpected message has been received%%----------------------------------------------------------------------handle_trans_request_abort(ConnHandle, ProtocolVersion, TransId, Pid) ->    d("handle_trans_request_abort -> entry with"       "~n   ConnHandle:      ~p"       "~n   ProtocolVersion: ~p"       "~n   TransId:         ~p"       "~n   Pid:             ~p",       [ConnHandle, ProtocolVersion, TransId, Pid]),    ok.%%----------------------------------------------------------------------%% DEBUGGING%%----------------------------------------------------------------------d(F) ->    d(F, []).d(F,A) ->    d(get(debug),F,A).d(true,F,A) ->    io:format("SIMPLE_MG: " ++ F ++ "~n", A);d(_, _F, _A) ->    ok.

⌨️ 快捷键说明

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