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

📄 megaco_sessionfactory_impl.erl

📁 一个Megaco实现源代码
💻 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 : Actual implementation of the Megaco SessionFactory interface.%%-----------------------------------------------------------------------module('Megaco_SessionFactory_impl').%% Genserver callbacks:-export([init/1,  terminate/2,  code_change/3,  handle_info/2]).%% Requests from the (C-) user:-export([startSession/3,  startSession/4,  sessions/3,  stopSession/4]).-export([select_session/2]).-include_lib("megaco/include/megaco.hrl").-include_lib("megaco/include/megaco_message_v1.hrl").-include_lib("megaco_session/include/Megaco.hrl").-include_lib("megaco_session/include/MegacoMessage.hrl").%% -include("megaco_session_et.hrl").%% Records:-record(state, {parent_pid, sessions = [], ref_counter = 0}).-record(session, {local_pid,  remote_pid, remote_ref}).%% Defines:-define(EXT(Fun, Value), megaco_session_externalizer:Fun(Value, undefined)).-define(INT(Fun, Value), megaco_session_internalizer:Fun(Value, undefined)).-define(SERVER, megaco_session_factory).-define(d(F,A),dbg(F,A)).select_session(ConnHandle, SessionPid) ->    case whereis(?SERVER) of	undefined ->	    no_session;	Pid ->	    Pid ! {self(), {select_session, ConnHandle, SessionPid}},	    receive		{Pid, Session = {a_session, RemotePid, Ref}} ->		    Session;		{Pid, no_session} ->		    no_session	    end    end.%% ----------------------------------------------------------------------%% Gen-server callbacks:%% ----------------------------------------------------------------------init([{parent_pid, ParentPid}]) when pid(ParentPid) ->    process_flag(trap_exit, true),    put(debug, get_debug()),    ?d("init -> entry with"       "~n   ParentPid: ~p", [ParentPid]),    {ok, #state{parent_pid = ParentPid}};init(BadEnv) ->    {stop, {bad_env, BadEnv}}.terminate(Reason, State) ->    ?d("terminate -> entry with"       "~n   Reason: ~p", [Reason]),    ok.code_change({down, Vsn}, State, Extra) ->    {ok, State};code_change(Vsn, State, Extra) ->    {ok, State}.handle_info({ReplyTo, {select_session, ConnHandle, SessionPid}}, State) ->    ?d("handle_info(select_session) -> entry when"       "~n   ReplyTo:    ~p"       "~n   ConnHandle: ~p"       "~n   SessionPid: ~p", [ReplyTo, ConnHandle, SessionPid]),    case lists:keysearch(SessionPid, #session.local_pid, State#state.sessions) of	{value, Session} ->	    %% BUGBUG: Do we need to sync ref counters between Erlang nodes?	    ?d("handle_info(select_session) -> Session: ~p", [Session]),	    RemotePid = Session#session.remote_pid,	    case State#state.ref_counter + 1 of		Ref when Ref > 16#FFFFFFFF -> % Must fit within 32 bits		    Ref2 = 1,		    ReplyTo ! {self(), {a_session, RemotePid, Ref2}},		    {noreply, State#state{ref_counter = Ref2}};		Ref ->		    ReplyTo ! {self(), {a_session, RemotePid, Ref}},		    {noreply, State#state{ref_counter = Ref}}	    end;	false ->	    ?d("handle_info(select_session) -> no sessions", []),	    ReplyTo ! {self(), no_session},	    {noreply, State}    end;	handle_info({'EXIT', Pid, Reason}, State) when Pid == State#state.parent_pid ->    ?d("handle_info(EXIT) -> entry when parent (~p) dies"       "~n   Reason: ~p", [Pid, Reason]),    {stop, Reason, State};handle_info({'EXIT', Pid, Reason} = Info, State) ->    report("handle_info(~p, ~p)", [Info, State]),    Sessions = State#state.sessions,    case lists:keysearch(Pid, #session.local_pid, Sessions) of	{value, Session} ->	    %% Local server died. 	    report("local session server (~w) died: ~w~n", [Pid, Reason]), 	    erlang:monitor_node(Session#session.remote_ref, false),	    %% Sessions = [Session | State#state.sessions],	    {noreply, State#state{sessions = Sessions -- [Session]}};	false ->	    {noreply, State}    end;handle_info({nodedown, Node}, State) ->    ?d("handle_info(nodedown) -> entry when"       "~n   Node:   ~p", [Node]),    report("SessionUser node died - ~p", [Node]),    Sessions  = State#state.sessions,    Sessions2 = [Session || #session{remote_ref = N} = Session <- Sessions,			    N == Node],    Fun = fun(Session) -> 		  %% Remote user died. Tell the local server about it.		  LocalPid = Session#session.local_pid,		  unlink(LocalPid),		  exit(LocalPid, shutdown)	  end,    lists:map(Fun, Sessions2),    {noreply, State#state{sessions = Sessions -- Sessions2}};handle_info(Info, State) ->    report("handle_info(~p, ~p)", [Info, State]),    {noreply, State}.%% ----------------------------------------------------------------------%% Requests from the (C-) user:%% ----------------------------------------------------------------------startSession(State, Ref, ReplyTo) ->    startSession(State, Ref, ReplyTo, false).startSession(State, Ref, ReplyTo, AutoStopUser) ->    ?d("startSession -> entry with"       "~n   Ref:          ~p"       "~n   ReplyTo:      ~p"       "~n   AutoStopUser: ~p", [Ref, ReplyTo, AutoStopUser]),    case 'Megaco_Session':oe_create_link([{parent_pid,     self()}, 					 {auto_stop_user, AutoStopUser}]) of	{ok, Pid} ->	    ?d("startSession -> Pid: ~p", [Pid]),	    Node = node(ReplyTo),	    ?d("startSession -> Node: ~p", [Node]),	    erlang:monitor_node(Node, true),	    Session = #session{local_pid  = Pid,			       remote_pid = ReplyTo,			       remote_ref = Node},	    Status = ?EXT(tr_Status, ok),	    'Megaco_SessionUser':startSessionResponse(ReplyTo, Ref, 						      Status,  Pid),	    Sessions = State#state.sessions ++ [Session] ,	    ?d("startSession -> done", []),	    {noreply, State#state{sessions = Sessions}};	{error, Reason} ->	    ?d("startSession -> error: ~p", [Reason]),	    Status = ?EXT(tr_Status, {error, Reason}),	    Dummy = ReplyTo,	    'Megaco_SessionUser':startSessionResponse(ReplyTo, Ref, Status, Dummy),	    ?d("startSession -> done", []),	    {noreply, State}    end.sessions(State, Ref, ReplyTo) ->    Status = ?EXT(tr_Status, ok),    SessionPids = [S#session.local_pid || S <- State#state.sessions],    'Megaco_SessionUser':sessionsResponse(ReplyTo, Ref, Status, SessionPids),    {noreply, State}.stopSession(State, Ref, ReplyTo, SessionPid) ->    ?d("stopSession -> entry when"       "~n   Ref:        ~p"       "~n   ReplyTo:    ~p"       "~n   SessionPid: ~p", [Ref, ReplyTo, SessionPid]),    case lists:keysearch(SessionPid, #session.local_pid, State#state.sessions) of	{value, #session{remote_ref = Remote} = Session} ->	    ?d("stopSession -> demonitor node: ~p", [Remote]),	    erlang:monitor_node(Remote, false),	    Status = ?EXT(tr_Status, ok),	    ?d("stopSession -> reply to session user", []),	    'Megaco_SessionUser':stopSessionResponse(ReplyTo, Ref, Status),	    ?d("stopSession -> unlink from the session process", []),	    unlink(SessionPid),	    ?d("stopSession -> stop the session process", []),	    'Megaco_Session':stop(SessionPid),	    Sessions = State#state.sessions,	    ?d("stopSession -> done", []),	    {noreply, State#state{sessions = Sessions -- [Session]}};	false ->	    ?d("stopSession -> session not found", []),	    Status = ?EXT(tr_Status, {errorString, "No such session"}),	    'Megaco_SessionUser':stopSessionResponse(ReplyTo, Ref, Status),	    ?d("stopSession -> done", []),	    {noreply, State}    end.%% ----------------------------------------------------------------------%% Internal functions%% ----------------------------------------------------------------------report(F, A) ->    ok = error_logger:format("~p(~p): " ++ F ++ "~n", [?MODULE, self()|A]).get_debug() ->    app_get_env(factory_debug, false).app_get_env(Key, Default) ->    case application:get_env(megaco_session, Key) of	{ok, Value} ->	    Value;	_ ->	    Default    end.dbg(F, A) ->    dbg(get(debug), F, A).dbg(true, F, A) ->    io:format("MSFI-DBG:~w: " ++ F ++ "~n", [self()|A]);dbg(_, _, _) ->    ok.

⌨️ 快捷键说明

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