diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index aab87550e..1c0046897 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -31,7 +31,7 @@ -behaviour(gen_server). %% API --export([start_link/0, route/3, set_session/6, +-export([start_link/0, route/3, do_route1/3, set_session/6, open_session/5, open_session/6, close_session/4, close_migrated_session/4, drop_session/1, check_in_subscription/6, bounce_offline_message/3, @@ -439,7 +439,7 @@ init([]) -> end, ?MYHOSTS), ejabberd_commands:register_commands(commands()), - start_dispatchers(), + start_handlers(), {ok, #state{}}. handle_call(_Request, _From, State) -> @@ -447,18 +447,19 @@ handle_call(_Request, _From, State) -> handle_cast(_Msg, State) -> {noreply, State}. -handle_info({route, From, To, Packet} = Msg, State) -> - case get_proc_num() of - N when N > 1 -> - #jid{luser = U, lserver = S} = To, - get_proc_by_hash({U, S}) ! Msg; - _ -> - case catch do_route(From, To, Packet) of - {'EXIT', Reason} -> - ?ERROR_MSG("~p~nwhen processing: ~p", - [Reason, {From, To, Packet}]); - _ -> ok - end +%%-------------------------------------------------------------------- +%% Function: handle_info(Info, State) -> {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} +%% Description: Handling all non call/cast messages +%%-------------------------------------------------------------------- +handle_info({route, From, To, Packet}, State) -> + case catch do_route(From, To, Packet) of + {'EXIT', Reason} -> + ?ERROR_MSG("~p~nwhen processing: ~p", + [Reason, {From, To, Packet}]); + _ -> + ok end, {noreply, State}; handle_info({register_iq_handler, Host, XMLNS, Module, @@ -503,7 +504,7 @@ terminate(_Reason, _State) -> ejabberd_hooks:delete(node_hash_update, ?MODULE, migrate, 100), ejabberd_commands:unregister_commands(commands()), - stop_dispatchers(), + stop_handlers(), ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. @@ -548,9 +549,10 @@ do_route(From, To, Packet) -> [From, To, Packet, 8]), {U, S, _} = jlib:jid_tolower(To), case ejabberd_cluster:get_node({U, S}) of - Node when Node /= node() -> - {?MODULE, Node} ! {route, From, To, Packet}; - _ -> do_route1(From, To, Packet) + Node when Node /= node() -> + {?MODULE, Node} ! {route, From, To, Packet}; + _ -> + dispatch(From, To, Packet) end. do_route1(From, To, {broadcast, _} = Packet) -> @@ -925,38 +927,23 @@ get_proc(N) -> "_", (iolist_to_binary(integer_to_list(N)))/binary>>). -start_dispatchers() -> - case get_proc_num() of - N when N > 1 -> - lists:foreach(fun (I) -> - Pid = spawn(fun dispatch/0), - erlang:register(get_proc(I), Pid) - end, - lists:seq(1, N)); - _ -> ok - end. +start_handlers() -> + N = get_proc_num(), + lists:foreach( + fun(I) -> + ejabberd_sm_handler:start(get_proc(I)) + end, lists:seq(1, N)). -stop_dispatchers() -> - case get_proc_num() of - N when N > 1 -> - lists:foreach(fun (I) -> get_proc(I) ! stop end, - lists:seq(1, N)); - _ -> ok - end. +stop_handlers() -> + N = get_proc_num(), + lists:foreach( + fun(I) -> + ejabberd_sm_handler:stop(get_proc(I)) + end, lists:seq(1, N)). -dispatch() -> - receive - {route, From, To, Packet} -> - case catch do_route(From, To, Packet) of - {'EXIT', Reason} -> - ?ERROR_MSG("~p~nwhen processing: ~p", - [Reason, {From, To, Packet}]); - _ -> ok - end, - dispatch(); - stop -> stopped; - _ -> dispatch() - end. +dispatch(From, To, Packet) -> + #jid{luser = U, lserver = S} = To, + ejabberd_sm_handler:route(get_proc_by_hash({U, S}), From, To, Packet). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Update Mnesia tables diff --git a/src/ejabberd_sm_handler.erl b/src/ejabberd_sm_handler.erl new file mode 100644 index 000000000..6f0fcdac4 --- /dev/null +++ b/src/ejabberd_sm_handler.erl @@ -0,0 +1,146 @@ +%%%---------------------------------------------------------------------- +%%% File : ejabberd_sm.erl +%%% Author : Alexey Shchepin +%%% Purpose : Session manager +%%% Created : 28 Dec 2011 by Alexey Shchepin +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2011 ProcessOne +%%% +%%% This program is free software; you can redistribute it and/or +%%% modify it under the terms of the GNU General Public License as +%%% published by the Free Software Foundation; either version 2 of the +%%% License, or (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%%% General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License +%%% along with this program; if not, write to the Free Software +%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +%%% 02111-1307 USA +%%% +%%%---------------------------------------------------------------------- + +-module(ejabberd_sm_handler). +-author('alexey@process-one.net'). + +-behaviour(gen_server). + +%% API +-export([start_link/1, + start/1, + stop/1, + route/4]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-include("ejabberd.hrl"). + +-record(state, {}). + +%%==================================================================== +%% API +%%==================================================================== +%%-------------------------------------------------------------------- +%% Function: start_link() -> {ok,Pid} | ignore | {error,Error} +%% Description: Starts the server +%%-------------------------------------------------------------------- +start_link(Name) -> + gen_server:start_link({local, Name}, ?MODULE, [], []). + +start(Name) -> + Spec = {Name, + {?MODULE, start_link, [Name]}, + permanent, + brutal_kill, + worker, + [?MODULE]}, + supervisor:start_child(ejabberd_sm_sup, Spec). + +stop(Name) -> + supervisor:terminate_child(ejabberd_sm_sup, Name), + supervisor:delete_child(ejabberd_sm_sup, Name). + +route(Name, From, To, Packet) -> + gen_server:cast(Name, {route, From, To, Packet}). + +%%==================================================================== +%% gen_server callbacks +%%==================================================================== + +%%-------------------------------------------------------------------- +%% Function: init(Args) -> {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%% Description: Initiates the server +%%-------------------------------------------------------------------- +init([]) -> + {ok, #state{}}. + +%%-------------------------------------------------------------------- +%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} | +%% {reply, Reply, State, Timeout} | +%% {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, Reply, State} | +%% {stop, Reason, State} +%% Description: Handling call messages +%%-------------------------------------------------------------------- +handle_call(_Request, _From, State) -> + Reply = ok, + {reply, Reply, State}. + +%%-------------------------------------------------------------------- +%% Function: handle_cast(Msg, State) -> {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} +%% Description: Handling cast messages +%%-------------------------------------------------------------------- +handle_cast({route, From, To, Packet}, State) -> + case catch ejabberd_sm:do_route1(From, To, Packet) of + {'EXIT', Reason} -> + ?ERROR_MSG("~p~nwhen processing: ~p", + [Reason, {From, To, Packet}]); + _ -> + ok + end, + {noreply, State}; +handle_cast(_Msg, State) -> + {noreply, State}. + +%%-------------------------------------------------------------------- +%% Function: handle_info(Info, State) -> {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} +%% Description: Handling all non call/cast messages +%%-------------------------------------------------------------------- +handle_info(_Info, State) -> + {noreply, State}. + +%%-------------------------------------------------------------------- +%% Function: terminate(Reason, State) -> void() +%% Description: This function is called by a gen_server when it is about to +%% terminate. It should be the opposite of Module:init/1 and do any necessary +%% cleaning up. When it returns, the gen_server terminates with Reason. +%% The return value is ignored. +%%-------------------------------------------------------------------- +terminate(_Reason, _State) -> + ok. + +%%-------------------------------------------------------------------- +%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} +%% Description: Convert process state when code is changed +%%-------------------------------------------------------------------- +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%-------------------------------------------------------------------- +%%% Internal functions +%%-------------------------------------------------------------------- + diff --git a/src/ejabberd_sm_sup.erl b/src/ejabberd_sm_sup.erl new file mode 100644 index 000000000..187520c69 --- /dev/null +++ b/src/ejabberd_sm_sup.erl @@ -0,0 +1,35 @@ +%%%------------------------------------------------------------------- +%%% @author Evgeniy Khramtsov +%%% @copyright (C) 2012, Evgeniy Khramtsov +%%% @doc +%%% +%%% @end +%%% Created : 25 May 2012 by Evgeniy Khramtsov +%%%------------------------------------------------------------------- +-module(ejabberd_sm_sup). + +-behaviour(supervisor). + +%% API +-export([start_link/0]). + +%% Supervisor callbacks +-export([init/1]). + +-define(SERVER, ?MODULE). + +%%%=================================================================== +%%% API functions +%%%=================================================================== +start_link() -> + supervisor:start_link({local, ?SERVER}, ?MODULE, []). + +%%%=================================================================== +%%% Supervisor callbacks +%%%=================================================================== +init([]) -> + {ok, {{one_for_one,10,1}, []}}. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== diff --git a/src/ejabberd_sup.erl b/src/ejabberd_sup.erl index 3ac0cf65e..baf3e9fff 100644 --- a/src/ejabberd_sup.erl +++ b/src/ejabberd_sup.erl @@ -168,6 +168,13 @@ init([]) -> infinity, supervisor, [ejabberd_iq_sup]}, + SMHandlerSup = + {ejabberd_sm_sup, + {ejabberd_sm_sup, start_link, []}, + permanent, + infinity, + supervisor, + [ejabberd_sm_sup]}, STUNSupervisor = {ejabberd_stun_sup, {ejabberd_tmp_sup, start_link, @@ -188,6 +195,7 @@ init([]) -> SystemMonitor, Router, Router_multicast, + SMHandlerSup, SM, S2S, Local,