mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
* src/odbc/pg.sql: Fixed syntax error
* src/ejabberd_router.erl: Updated to use gen_server behaviour * src/ejabberd_sm.erl: Likewise * src/ejabberd_s2s.erl: Likewise * src/gen_iq_handler.erl: Likewise * src/ejabberd_sup.erl: Added supervisor for ejabberd_receiver * src/ejabberd_receiver.erl: Updated SVN Revision: 495
This commit is contained in:
parent
ef456ab645
commit
50f44530d2
14
ChangeLog
14
ChangeLog
@ -1,3 +1,17 @@
|
|||||||
|
2006-01-29 Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
|
||||||
|
* src/odbc/pg.sql: Fixed syntax error
|
||||||
|
|
||||||
|
2006-01-28 Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
|
||||||
|
* src/ejabberd_router.erl: Updated to use gen_server behaviour
|
||||||
|
* src/ejabberd_sm.erl: Likewise
|
||||||
|
* src/ejabberd_s2s.erl: Likewise
|
||||||
|
* src/gen_iq_handler.erl: Likewise
|
||||||
|
|
||||||
|
* src/ejabberd_sup.erl: Added supervisor for ejabberd_receiver
|
||||||
|
* src/ejabberd_receiver.erl: Updating
|
||||||
|
|
||||||
2006-01-27 Alexey Shchepin <alexey@sevcom.net>
|
2006-01-27 Alexey Shchepin <alexey@sevcom.net>
|
||||||
|
|
||||||
* src/ejabberd_update.erl: Support for run-time ejabberd updating
|
* src/ejabberd_update.erl: Support for run-time ejabberd updating
|
||||||
|
@ -10,7 +10,10 @@
|
|||||||
-author('alexey@sevcom.net').
|
-author('alexey@sevcom.net').
|
||||||
-vsn('$Revision$ ').
|
-vsn('$Revision$ ').
|
||||||
|
|
||||||
-export([start_link/0, init/0]).
|
-behaviour(gen_server).
|
||||||
|
|
||||||
|
%% API
|
||||||
|
-export([start_link/0]).
|
||||||
|
|
||||||
-export([route/3,
|
-export([route/3,
|
||||||
register_iq_handler/4,
|
register_iq_handler/4,
|
||||||
@ -20,102 +23,26 @@
|
|||||||
bounce_resource_packet/3
|
bounce_resource_packet/3
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
%% gen_server callbacks
|
||||||
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
|
terminate/2, code_change/3]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
|
-record(state, {}).
|
||||||
|
|
||||||
-define(IQTABLE, local_iqtable).
|
-define(IQTABLE, local_iqtable).
|
||||||
|
|
||||||
|
%%====================================================================
|
||||||
|
%% API
|
||||||
|
%%====================================================================
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
|
||||||
|
%% Description: Starts the server
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
start_link() ->
|
start_link() ->
|
||||||
register(ejabberd_local,
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||||
Pid = proc_lib:spawn_link(ejabberd_local, init, [])),
|
|
||||||
{ok, Pid}.
|
|
||||||
|
|
||||||
init() ->
|
|
||||||
lists:foreach(
|
|
||||||
fun(Host) ->
|
|
||||||
ejabberd_router:register_route(Host, {apply, ?MODULE, route}),
|
|
||||||
ejabberd_hooks:add(local_send_to_resource_hook, Host,
|
|
||||||
?MODULE, bounce_resource_packet, 100)
|
|
||||||
end, ?MYHOSTS),
|
|
||||||
catch ets:new(?IQTABLE, [named_table, public]),
|
|
||||||
loop().
|
|
||||||
|
|
||||||
loop() ->
|
|
||||||
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,
|
|
||||||
loop();
|
|
||||||
{register_iq_handler, Host, XMLNS, Module, Function} ->
|
|
||||||
ets:insert(?IQTABLE, {{XMLNS, Host}, Module, Function}),
|
|
||||||
catch mod_disco:register_feature(Host, XMLNS),
|
|
||||||
loop();
|
|
||||||
{register_iq_handler, Host, XMLNS, Module, Function, Opts} ->
|
|
||||||
ets:insert(?IQTABLE, {{XMLNS, Host}, Module, Function, Opts}),
|
|
||||||
catch mod_disco:register_feature(Host, XMLNS),
|
|
||||||
loop();
|
|
||||||
{unregister_iq_handler, Host, XMLNS} ->
|
|
||||||
case ets:lookup(?IQTABLE, {XMLNS, Host}) of
|
|
||||||
[{_, Module, Function, Opts}] ->
|
|
||||||
gen_iq_handler:stop_iq_handler(Module, Function, Opts);
|
|
||||||
_ ->
|
|
||||||
ok
|
|
||||||
end,
|
|
||||||
ets:delete(?IQTABLE, {XMLNS, Host}),
|
|
||||||
catch mod_disco:unregister_feature(Host, XMLNS),
|
|
||||||
loop();
|
|
||||||
refresh_iq_handlers ->
|
|
||||||
lists:foreach(
|
|
||||||
fun(T) ->
|
|
||||||
case T of
|
|
||||||
{{XMLNS, Host}, _Module, _Function, _Opts} ->
|
|
||||||
catch mod_disco:register_feature(Host, XMLNS);
|
|
||||||
{{XMLNS, Host}, _Module, _Function} ->
|
|
||||||
catch mod_disco:register_feature(Host, XMLNS);
|
|
||||||
_ ->
|
|
||||||
ok
|
|
||||||
end
|
|
||||||
end, ets:tab2list(?IQTABLE)),
|
|
||||||
loop();
|
|
||||||
_ ->
|
|
||||||
loop()
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
do_route(From, To, Packet) ->
|
|
||||||
?DEBUG("local route~n\tfrom ~p~n\tto ~p~n\tpacket ~P~n",
|
|
||||||
[From, To, Packet, 8]),
|
|
||||||
if
|
|
||||||
To#jid.luser /= "" ->
|
|
||||||
ejabberd_sm:route(From, To, Packet);
|
|
||||||
To#jid.lresource == "" ->
|
|
||||||
{xmlelement, Name, Attrs, _Els} = Packet,
|
|
||||||
case Name of
|
|
||||||
"iq" ->
|
|
||||||
process_iq(From, To, Packet);
|
|
||||||
"message" ->
|
|
||||||
ok;
|
|
||||||
"presence" ->
|
|
||||||
ok;
|
|
||||||
_ ->
|
|
||||||
ok
|
|
||||||
end;
|
|
||||||
true ->
|
|
||||||
{xmlelement, Name, Attrs, _Els} = Packet,
|
|
||||||
case xml:get_attr_s("type", Attrs) of
|
|
||||||
"error" -> ok;
|
|
||||||
"result" -> ok;
|
|
||||||
_ ->
|
|
||||||
ejabberd_hooks:run(local_send_to_resource_hook,
|
|
||||||
To#jid.lserver,
|
|
||||||
[From, To, Packet])
|
|
||||||
end
|
|
||||||
end.
|
|
||||||
|
|
||||||
process_iq(From, To, Packet) ->
|
process_iq(From, To, Packet) ->
|
||||||
IQ = jlib:iq_query_info(Packet),
|
IQ = jlib:iq_query_info(Packet),
|
||||||
@ -173,3 +100,146 @@ bounce_resource_packet(From, To, Packet) ->
|
|||||||
Err = jlib:make_error_reply(Packet, ?ERR_ITEM_NOT_FOUND),
|
Err = jlib:make_error_reply(Packet, ?ERR_ITEM_NOT_FOUND),
|
||||||
ejabberd_router:route(To, From, Err),
|
ejabberd_router:route(To, From, Err),
|
||||||
stop.
|
stop.
|
||||||
|
|
||||||
|
%%====================================================================
|
||||||
|
%% gen_server callbacks
|
||||||
|
%%====================================================================
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Function: init(Args) -> {ok, State} |
|
||||||
|
%% {ok, State, Timeout} |
|
||||||
|
%% ignore |
|
||||||
|
%% {stop, Reason}
|
||||||
|
%% Description: Initiates the server
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
init([]) ->
|
||||||
|
lists:foreach(
|
||||||
|
fun(Host) ->
|
||||||
|
ejabberd_router:register_route(Host, {apply, ?MODULE, route}),
|
||||||
|
ejabberd_hooks:add(local_send_to_resource_hook, Host,
|
||||||
|
?MODULE, bounce_resource_packet, 100)
|
||||||
|
end, ?MYHOSTS),
|
||||||
|
catch ets:new(?IQTABLE, [named_table, public]),
|
||||||
|
{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(_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({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, Function}, State) ->
|
||||||
|
ets:insert(?IQTABLE, {{XMLNS, Host}, Module, Function}),
|
||||||
|
catch mod_disco:register_feature(Host, XMLNS),
|
||||||
|
{noreply, State};
|
||||||
|
handle_info({register_iq_handler, Host, XMLNS, Module, Function, Opts}, State) ->
|
||||||
|
ets:insert(?IQTABLE, {{XMLNS, Host}, Module, Function, Opts}),
|
||||||
|
catch mod_disco:register_feature(Host, XMLNS),
|
||||||
|
{noreply, State};
|
||||||
|
handle_info({unregister_iq_handler, Host, XMLNS}, State) ->
|
||||||
|
case ets:lookup(?IQTABLE, {XMLNS, Host}) of
|
||||||
|
[{_, Module, Function, Opts}] ->
|
||||||
|
gen_iq_handler:stop_iq_handler(Module, Function, Opts);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end,
|
||||||
|
ets:delete(?IQTABLE, {XMLNS, Host}),
|
||||||
|
catch mod_disco:unregister_feature(Host, XMLNS),
|
||||||
|
{noreply, State};
|
||||||
|
handle_info(refresh_iq_handlers, State) ->
|
||||||
|
lists:foreach(
|
||||||
|
fun(T) ->
|
||||||
|
case T of
|
||||||
|
{{XMLNS, Host}, _Module, _Function, _Opts} ->
|
||||||
|
catch mod_disco:register_feature(Host, XMLNS);
|
||||||
|
{{XMLNS, Host}, _Module, _Function} ->
|
||||||
|
catch mod_disco:register_feature(Host, XMLNS);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end
|
||||||
|
end, ets:tab2list(?IQTABLE)),
|
||||||
|
{noreply, State};
|
||||||
|
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
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
do_route(From, To, Packet) ->
|
||||||
|
?DEBUG("local route~n\tfrom ~p~n\tto ~p~n\tpacket ~P~n",
|
||||||
|
[From, To, Packet, 8]),
|
||||||
|
if
|
||||||
|
To#jid.luser /= "" ->
|
||||||
|
ejabberd_sm:route(From, To, Packet);
|
||||||
|
To#jid.lresource == "" ->
|
||||||
|
{xmlelement, Name, _Attrs, _Els} = Packet,
|
||||||
|
case Name of
|
||||||
|
"iq" ->
|
||||||
|
process_iq(From, To, Packet);
|
||||||
|
"message" ->
|
||||||
|
ok;
|
||||||
|
"presence" ->
|
||||||
|
ok;
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end;
|
||||||
|
true ->
|
||||||
|
{xmlelement, _Name, Attrs, _Els} = Packet,
|
||||||
|
case xml:get_attr_s("type", Attrs) of
|
||||||
|
"error" -> ok;
|
||||||
|
"result" -> ok;
|
||||||
|
_ ->
|
||||||
|
ejabberd_hooks:run(local_send_to_resource_hook,
|
||||||
|
To#jid.lserver,
|
||||||
|
[From, To, Packet])
|
||||||
|
end
|
||||||
|
end.
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
-behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([start/3,
|
-export([start_link/4,
|
||||||
|
start/3,
|
||||||
change_shaper/2,
|
change_shaper/2,
|
||||||
reset_stream/1,
|
reset_stream/1,
|
||||||
starttls/2,
|
starttls/2,
|
||||||
@ -37,13 +38,20 @@
|
|||||||
%%====================================================================
|
%%====================================================================
|
||||||
%% API
|
%% API
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
|
||||||
|
%% Description: Starts the server
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
start_link(Socket, SockMod, Shaper, C2SPid) ->
|
||||||
|
gen_server:start_link(?MODULE, [Socket, SockMod, Shaper, C2SPid], []).
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% Function: start() -> {ok,Pid} | ignore | {error,Error}
|
%% Function: start() -> {ok,Pid} | ignore | {error,Error}
|
||||||
%% Description: Starts the server
|
%% Description: Starts the server
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
start(Socket, SockMod, Shaper) ->
|
start(Socket, SockMod, Shaper) ->
|
||||||
{ok, Pid} = gen_server:start(
|
{ok, Pid} = supervisor:start_child(ejabberd_receiver_sup,
|
||||||
?MODULE, [Socket, SockMod, Shaper, self()], []),
|
[Socket, SockMod, Shaper, self()]),
|
||||||
Pid.
|
Pid.
|
||||||
|
|
||||||
change_shaper(Pid, Shaper) ->
|
change_shaper(Pid, Shaper) ->
|
||||||
|
@ -10,6 +10,9 @@
|
|||||||
-author('alexey@sevcom.net').
|
-author('alexey@sevcom.net').
|
||||||
-vsn('$Revision$ ').
|
-vsn('$Revision$ ').
|
||||||
|
|
||||||
|
-behaviour(gen_server).
|
||||||
|
|
||||||
|
%% API
|
||||||
-export([route/3,
|
-export([route/3,
|
||||||
register_route/1,
|
register_route/1,
|
||||||
register_route/2,
|
register_route/2,
|
||||||
@ -20,114 +23,28 @@
|
|||||||
dirty_get_all_domains/0
|
dirty_get_all_domains/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export([start_link/0, init/0]).
|
-export([start_link/0]).
|
||||||
|
|
||||||
|
%% gen_server callbacks
|
||||||
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
|
terminate/2, code_change/3]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
-record(route, {domain, pid, local_hint}).
|
-record(route, {domain, pid, local_hint}).
|
||||||
|
-record(state, {}).
|
||||||
|
|
||||||
|
%%====================================================================
|
||||||
|
%% API
|
||||||
|
%%====================================================================
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
|
||||||
|
%% Description: Starts the server
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
start_link() ->
|
start_link() ->
|
||||||
update_tables(),
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||||
mnesia:create_table(route,
|
|
||||||
[{ram_copies, [node()]},
|
|
||||||
{type, bag},
|
|
||||||
{attributes,
|
|
||||||
record_info(fields, route)}]),
|
|
||||||
mnesia:add_table_copy(route, node(), ram_copies),
|
|
||||||
Pid = proc_lib:spawn_link(ejabberd_router, init, []),
|
|
||||||
register(ejabberd_router, Pid),
|
|
||||||
{ok, Pid}.
|
|
||||||
|
|
||||||
init() ->
|
|
||||||
mnesia:subscribe({table, route, simple}),
|
|
||||||
lists:foreach(
|
|
||||||
fun(Pid) ->
|
|
||||||
erlang:monitor(process, Pid)
|
|
||||||
end,
|
|
||||||
mnesia:dirty_select(route, [{{route, '_', '$1', '_'}, [], ['$1']}])),
|
|
||||||
loop().
|
|
||||||
|
|
||||||
loop() ->
|
|
||||||
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,
|
|
||||||
loop();
|
|
||||||
{mnesia_table_event, {write, #route{pid = Pid}, _ActivityId}} ->
|
|
||||||
erlang:monitor(process, Pid),
|
|
||||||
loop();
|
|
||||||
{'DOWN', _Ref, _Type, Pid, _Info} ->
|
|
||||||
F = fun() ->
|
|
||||||
Es = mnesia:select(
|
|
||||||
route,
|
|
||||||
[{#route{pid = Pid, _ = '_'},
|
|
||||||
[],
|
|
||||||
['$_']}]),
|
|
||||||
lists:foreach(fun(E) ->
|
|
||||||
mnesia:delete_object(E)
|
|
||||||
end, Es)
|
|
||||||
end,
|
|
||||||
mnesia:transaction(F),
|
|
||||||
loop();
|
|
||||||
_ ->
|
|
||||||
loop()
|
|
||||||
end.
|
|
||||||
|
|
||||||
do_route(OrigFrom, OrigTo, OrigPacket) ->
|
|
||||||
?DEBUG("route~n\tfrom ~p~n\tto ~p~n\tpacket ~p~n",
|
|
||||||
[OrigFrom, OrigTo, OrigPacket]),
|
|
||||||
LOrigDstDomain = OrigTo#jid.lserver,
|
|
||||||
case ejabberd_hooks:run_fold(filter_packet, LOrigDstDomain,
|
|
||||||
{OrigFrom, OrigTo, OrigPacket}, []) of
|
|
||||||
{From, To, Packet} ->
|
|
||||||
LDstDomain = To#jid.lserver,
|
|
||||||
case mnesia:dirty_read(route, LDstDomain) of
|
|
||||||
[] ->
|
|
||||||
ejabberd_s2s:route(From, To, Packet);
|
|
||||||
[R] ->
|
|
||||||
Pid = R#route.pid,
|
|
||||||
if
|
|
||||||
node(Pid) == node() ->
|
|
||||||
case R#route.local_hint of
|
|
||||||
{apply, Module, Function} ->
|
|
||||||
Module:Function(From, To, Packet);
|
|
||||||
_ ->
|
|
||||||
Pid ! {route, From, To, Packet}
|
|
||||||
end;
|
|
||||||
true ->
|
|
||||||
Pid ! {route, From, To, Packet}
|
|
||||||
end;
|
|
||||||
Rs ->
|
|
||||||
case [R || R <- Rs, node(R#route.pid) == node()] of
|
|
||||||
[] ->
|
|
||||||
R = lists:nth(erlang:phash(now(), length(Rs)), Rs),
|
|
||||||
Pid = R#route.pid,
|
|
||||||
Pid ! {route, From, To, Packet};
|
|
||||||
LRs ->
|
|
||||||
LRs,
|
|
||||||
R = lists:nth(erlang:phash(now(), length(LRs)), LRs),
|
|
||||||
Pid = R#route.pid,
|
|
||||||
case R#route.local_hint of
|
|
||||||
{apply, Module, Function} ->
|
|
||||||
Module:Function(From, To, Packet);
|
|
||||||
_ ->
|
|
||||||
Pid ! {route, From, To, Packet}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end;
|
|
||||||
drop ->
|
|
||||||
ok
|
|
||||||
end.
|
|
||||||
|
|
||||||
%route(From, To, Packet) ->
|
|
||||||
% ejabberd_router ! {route, From, To, Packet}.
|
|
||||||
|
|
||||||
route(From, To, Packet) ->
|
route(From, To, Packet) ->
|
||||||
case catch do_route(From, To, Packet) of
|
case catch do_route(From, To, Packet) of
|
||||||
@ -196,6 +113,157 @@ dirty_get_all_domains() ->
|
|||||||
lists:usort(mnesia:dirty_all_keys(route)).
|
lists:usort(mnesia:dirty_all_keys(route)).
|
||||||
|
|
||||||
|
|
||||||
|
%%====================================================================
|
||||||
|
%% gen_server callbacks
|
||||||
|
%%====================================================================
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Function: init(Args) -> {ok, State} |
|
||||||
|
%% {ok, State, Timeout} |
|
||||||
|
%% ignore |
|
||||||
|
%% {stop, Reason}
|
||||||
|
%% Description: Initiates the server
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
init([]) ->
|
||||||
|
update_tables(),
|
||||||
|
mnesia:create_table(route,
|
||||||
|
[{ram_copies, [node()]},
|
||||||
|
{type, bag},
|
||||||
|
{attributes,
|
||||||
|
record_info(fields, route)}]),
|
||||||
|
mnesia:add_table_copy(route, node(), ram_copies),
|
||||||
|
mnesia:subscribe({table, route, simple}),
|
||||||
|
lists:foreach(
|
||||||
|
fun(Pid) ->
|
||||||
|
erlang:monitor(process, Pid)
|
||||||
|
end,
|
||||||
|
mnesia:dirty_select(route, [{{route, '_', '$1', '_'}, [], ['$1']}])),
|
||||||
|
{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(_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({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({mnesia_table_event, {write, #route{pid = Pid}, _ActivityId}},
|
||||||
|
State) ->
|
||||||
|
erlang:monitor(process, Pid),
|
||||||
|
{noreply, State};
|
||||||
|
handle_info({'DOWN', _Ref, _Type, Pid, _Info}, State) ->
|
||||||
|
F = fun() ->
|
||||||
|
Es = mnesia:select(
|
||||||
|
route,
|
||||||
|
[{#route{pid = Pid, _ = '_'},
|
||||||
|
[],
|
||||||
|
['$_']}]),
|
||||||
|
lists:foreach(fun(E) ->
|
||||||
|
mnesia:delete_object(E)
|
||||||
|
end, Es)
|
||||||
|
end,
|
||||||
|
mnesia:transaction(F),
|
||||||
|
{noreply, State};
|
||||||
|
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
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
do_route(OrigFrom, OrigTo, OrigPacket) ->
|
||||||
|
?DEBUG("route~n\tfrom ~p~n\tto ~p~n\tpacket ~p~n",
|
||||||
|
[OrigFrom, OrigTo, OrigPacket]),
|
||||||
|
LOrigDstDomain = OrigTo#jid.lserver,
|
||||||
|
case ejabberd_hooks:run_fold(filter_packet, LOrigDstDomain,
|
||||||
|
{OrigFrom, OrigTo, OrigPacket}, []) of
|
||||||
|
{From, To, Packet} ->
|
||||||
|
LDstDomain = To#jid.lserver,
|
||||||
|
case mnesia:dirty_read(route, LDstDomain) of
|
||||||
|
[] ->
|
||||||
|
ejabberd_s2s:route(From, To, Packet);
|
||||||
|
[R] ->
|
||||||
|
Pid = R#route.pid,
|
||||||
|
if
|
||||||
|
node(Pid) == node() ->
|
||||||
|
case R#route.local_hint of
|
||||||
|
{apply, Module, Function} ->
|
||||||
|
Module:Function(From, To, Packet);
|
||||||
|
_ ->
|
||||||
|
Pid ! {route, From, To, Packet}
|
||||||
|
end;
|
||||||
|
true ->
|
||||||
|
Pid ! {route, From, To, Packet}
|
||||||
|
end;
|
||||||
|
Rs ->
|
||||||
|
case [R || R <- Rs, node(R#route.pid) == node()] of
|
||||||
|
[] ->
|
||||||
|
R = lists:nth(erlang:phash(now(), length(Rs)), Rs),
|
||||||
|
Pid = R#route.pid,
|
||||||
|
Pid ! {route, From, To, Packet};
|
||||||
|
LRs ->
|
||||||
|
LRs,
|
||||||
|
R = lists:nth(erlang:phash(now(), length(LRs)), LRs),
|
||||||
|
Pid = R#route.pid,
|
||||||
|
case R#route.local_hint of
|
||||||
|
{apply, Module, Function} ->
|
||||||
|
Module:Function(From, To, Packet);
|
||||||
|
_ ->
|
||||||
|
Pid ! {route, From, To, Packet}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
drop ->
|
||||||
|
ok
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
update_tables() ->
|
update_tables() ->
|
||||||
case catch mnesia:table_info(route, attributes) of
|
case catch mnesia:table_info(route, attributes) of
|
||||||
|
@ -10,7 +10,10 @@
|
|||||||
-author('alexey@sevcom.net').
|
-author('alexey@sevcom.net').
|
||||||
-vsn('$Revision$ ').
|
-vsn('$Revision$ ').
|
||||||
|
|
||||||
-export([start_link/0, init/0,
|
-behaviour(gen_server).
|
||||||
|
|
||||||
|
%% API
|
||||||
|
-export([start_link/0,
|
||||||
route/3,
|
route/3,
|
||||||
have_connection/1,
|
have_connection/1,
|
||||||
get_key/1,
|
get_key/1,
|
||||||
@ -18,43 +21,25 @@
|
|||||||
remove_connection/1,
|
remove_connection/1,
|
||||||
dirty_get_connections/0]).
|
dirty_get_connections/0]).
|
||||||
|
|
||||||
|
%% gen_server callbacks
|
||||||
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
|
terminate/2, code_change/3]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
-record(s2s, {fromto, pid, key}).
|
-record(s2s, {fromto, pid, key}).
|
||||||
|
-record(state, {}).
|
||||||
|
|
||||||
|
%%====================================================================
|
||||||
|
%% API
|
||||||
|
%%====================================================================
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
|
||||||
|
%% Description: Starts the server
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
start_link() ->
|
start_link() ->
|
||||||
Pid = proc_lib:spawn_link(ejabberd_s2s, init, []),
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||||
register(ejabberd_s2s, Pid),
|
|
||||||
{ok, Pid}.
|
|
||||||
|
|
||||||
init() ->
|
|
||||||
update_tables(),
|
|
||||||
mnesia:create_table(s2s, [{ram_copies, [node()]},
|
|
||||||
{attributes, record_info(fields, s2s)}]),
|
|
||||||
mnesia:add_table_copy(s2s, node(), ram_copies),
|
|
||||||
mnesia:subscribe(system),
|
|
||||||
loop().
|
|
||||||
|
|
||||||
loop() ->
|
|
||||||
receive
|
|
||||||
{mnesia_system_event, {mnesia_down, Node}} ->
|
|
||||||
clean_table_from_bad_node(Node),
|
|
||||||
loop();
|
|
||||||
{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,
|
|
||||||
loop();
|
|
||||||
_ ->
|
|
||||||
loop()
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
route(From, To, Packet) ->
|
route(From, To, Packet) ->
|
||||||
case catch do_route(From, To, Packet) of
|
case catch do_route(From, To, Packet) of
|
||||||
@ -65,28 +50,12 @@ route(From, To, Packet) ->
|
|||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
remove_connection(FromTo) ->
|
remove_connection(FromTo) ->
|
||||||
F = fun() ->
|
F = fun() ->
|
||||||
mnesia:delete({s2s, FromTo})
|
mnesia:delete({s2s, FromTo})
|
||||||
end,
|
end,
|
||||||
mnesia:transaction(F).
|
mnesia:transaction(F).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
clean_table_from_bad_node(Node) ->
|
|
||||||
F = fun() ->
|
|
||||||
Es = mnesia:select(
|
|
||||||
s2s,
|
|
||||||
[{#s2s{pid = '$1', _ = '_'},
|
|
||||||
[{'==', {node, '$1'}, Node}],
|
|
||||||
['$_']}]),
|
|
||||||
lists:foreach(fun(E) ->
|
|
||||||
mnesia:delete_object(E)
|
|
||||||
end, Es)
|
|
||||||
end,
|
|
||||||
mnesia:transaction(F).
|
|
||||||
|
|
||||||
have_connection(FromTo) ->
|
have_connection(FromTo) ->
|
||||||
case catch mnesia:dirty_read(s2s, FromTo) of
|
case catch mnesia:dirty_read(s2s, FromTo) of
|
||||||
[_] ->
|
[_] ->
|
||||||
@ -123,9 +92,103 @@ try_register(FromTo) ->
|
|||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
dirty_get_connections() ->
|
||||||
|
mnesia:dirty_all_keys(s2s).
|
||||||
|
|
||||||
|
%%====================================================================
|
||||||
|
%% gen_server callbacks
|
||||||
|
%%====================================================================
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%--------------------------------------------------------------------
|
||||||
|
%% Function: init(Args) -> {ok, State} |
|
||||||
|
%% {ok, State, Timeout} |
|
||||||
|
%% ignore |
|
||||||
|
%% {stop, Reason}
|
||||||
|
%% Description: Initiates the server
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
init([]) ->
|
||||||
|
update_tables(),
|
||||||
|
mnesia:create_table(s2s, [{ram_copies, [node()]},
|
||||||
|
{attributes, record_info(fields, s2s)}]),
|
||||||
|
mnesia:add_table_copy(s2s, node(), ram_copies),
|
||||||
|
mnesia:subscribe(system),
|
||||||
|
{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(_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({mnesia_system_event, {mnesia_down, Node}}, State) ->
|
||||||
|
clean_table_from_bad_node(Node),
|
||||||
|
{noreply, State};
|
||||||
|
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(_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
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
clean_table_from_bad_node(Node) ->
|
||||||
|
F = fun() ->
|
||||||
|
Es = mnesia:select(
|
||||||
|
s2s,
|
||||||
|
[{#s2s{pid = '$1', _ = '_'},
|
||||||
|
[{'==', {node, '$1'}, Node}],
|
||||||
|
['$_']}]),
|
||||||
|
lists:foreach(fun(E) ->
|
||||||
|
mnesia:delete_object(E)
|
||||||
|
end, Es)
|
||||||
|
end,
|
||||||
|
mnesia:transaction(F).
|
||||||
|
|
||||||
do_route(From, To, Packet) ->
|
do_route(From, To, Packet) ->
|
||||||
?DEBUG("s2s manager~n\tfrom ~p~n\tto ~p~n\tpacket ~P~n",
|
?DEBUG("s2s manager~n\tfrom ~p~n\tto ~p~n\tpacket ~P~n",
|
||||||
@ -174,15 +237,9 @@ find_connection(From, To) ->
|
|||||||
{atomic, El#s2s.pid}
|
{atomic, El#s2s.pid}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
send_element(Pid, El) ->
|
send_element(Pid, El) ->
|
||||||
Pid ! {send_element, El}.
|
Pid ! {send_element, El}.
|
||||||
|
|
||||||
|
|
||||||
dirty_get_connections() ->
|
|
||||||
mnesia:dirty_all_keys(s2s).
|
|
||||||
|
|
||||||
|
|
||||||
update_tables() ->
|
update_tables() ->
|
||||||
case catch mnesia:table_info(s2s, attributes) of
|
case catch mnesia:table_info(s2s, attributes) of
|
||||||
[fromto, node, key] ->
|
[fromto, node, key] ->
|
||||||
|
@ -10,7 +10,10 @@
|
|||||||
-author('alexey@sevcom.net').
|
-author('alexey@sevcom.net').
|
||||||
-vsn('$Revision$ ').
|
-vsn('$Revision$ ').
|
||||||
|
|
||||||
-export([start_link/0, init/0,
|
-behaviour(gen_server).
|
||||||
|
|
||||||
|
%% API
|
||||||
|
-export([start_link/0,
|
||||||
route/3,
|
route/3,
|
||||||
open_session/4, close_session/1,
|
open_session/4, close_session/1,
|
||||||
bounce_offline_message/3,
|
bounce_offline_message/3,
|
||||||
@ -27,17 +30,124 @@
|
|||||||
unregister_iq_handler/2
|
unregister_iq_handler/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
%% gen_server callbacks
|
||||||
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
|
terminate/2, code_change/3]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("jlib.hrl").
|
-include("jlib.hrl").
|
||||||
|
|
||||||
-record(session, {sid, usr, us, priority}).
|
-record(session, {sid, usr, us, priority}).
|
||||||
|
-record(state, {}).
|
||||||
|
|
||||||
|
%%====================================================================
|
||||||
|
%% API
|
||||||
|
%%====================================================================
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
|
||||||
|
%% Description: Starts the server
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
start_link() ->
|
start_link() ->
|
||||||
Pid = proc_lib:spawn_link(ejabberd_sm, init, []),
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||||
register(ejabberd_sm, Pid),
|
|
||||||
{ok, Pid}.
|
|
||||||
|
|
||||||
init() ->
|
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.
|
||||||
|
|
||||||
|
open_session(SID, User, Server, Resource) ->
|
||||||
|
set_session(SID, User, Server, Resource, undefined).
|
||||||
|
|
||||||
|
close_session(SID) ->
|
||||||
|
F = fun() ->
|
||||||
|
mnesia:delete({session, SID})
|
||||||
|
end,
|
||||||
|
mnesia:sync_dirty(F).
|
||||||
|
|
||||||
|
bounce_offline_message(From, To, Packet) ->
|
||||||
|
Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE),
|
||||||
|
ejabberd_router:route(To, From, Err),
|
||||||
|
stop.
|
||||||
|
|
||||||
|
disconnect_removed_user(User, Server) ->
|
||||||
|
ejabberd_sm:route(jlib:make_jid("", "", ""),
|
||||||
|
jlib:make_jid(User, Server, ""),
|
||||||
|
{xmlelement, "broadcast", [],
|
||||||
|
[{exit, "User removed"}]}).
|
||||||
|
|
||||||
|
get_user_resources(User, Server) ->
|
||||||
|
LUser = jlib:nodeprep(User),
|
||||||
|
LServer = jlib:nameprep(Server),
|
||||||
|
US = {LUser, LServer},
|
||||||
|
case catch mnesia:dirty_index_read(session, US, #session.us) of
|
||||||
|
{'EXIT', _Reason} ->
|
||||||
|
[];
|
||||||
|
Ss ->
|
||||||
|
[element(3, S#session.usr) || S <- clean_session_list(Ss)]
|
||||||
|
end.
|
||||||
|
|
||||||
|
set_presence(SID, User, Server, Resource, Priority) ->
|
||||||
|
set_session(SID, User, Server, Resource, Priority).
|
||||||
|
|
||||||
|
unset_presence(SID, User, Server, Resource, Status) ->
|
||||||
|
set_session(SID, User, Server, Resource, undefined),
|
||||||
|
ejabberd_hooks:run(unset_presence_hook, jlib:nameprep(Server),
|
||||||
|
[User, Server, Resource, Status]).
|
||||||
|
|
||||||
|
close_session_unset_presence(SID, User, Server, Resource, Status) ->
|
||||||
|
close_session(SID),
|
||||||
|
ejabberd_hooks:run(unset_presence_hook, jlib:nameprep(Server),
|
||||||
|
[User, Server, Resource, Status]).
|
||||||
|
|
||||||
|
|
||||||
|
dirty_get_sessions_list() ->
|
||||||
|
mnesia:dirty_select(
|
||||||
|
session,
|
||||||
|
[{#session{usr = '$1', _ = '_'},
|
||||||
|
[],
|
||||||
|
['$1']}]).
|
||||||
|
|
||||||
|
dirty_get_my_sessions_list() ->
|
||||||
|
mnesia:dirty_select(
|
||||||
|
session,
|
||||||
|
[{#session{sid = {'_', '$1'}, _ = '_'},
|
||||||
|
[{'==', {node, '$1'}, node()}],
|
||||||
|
['$_']}]).
|
||||||
|
|
||||||
|
get_vh_session_list(Server) ->
|
||||||
|
LServer = jlib:nameprep(Server),
|
||||||
|
mnesia:dirty_select(
|
||||||
|
session,
|
||||||
|
[{#session{usr = '$1', _ = '_'},
|
||||||
|
[{'==', {element, 2, '$1'}, LServer}],
|
||||||
|
['$1']}]).
|
||||||
|
|
||||||
|
register_iq_handler(Host, XMLNS, Module, Fun) ->
|
||||||
|
ejabberd_sm ! {register_iq_handler, Host, XMLNS, Module, Fun}.
|
||||||
|
|
||||||
|
register_iq_handler(Host, XMLNS, Module, Fun, Opts) ->
|
||||||
|
ejabberd_sm ! {register_iq_handler, Host, XMLNS, Module, Fun, Opts}.
|
||||||
|
|
||||||
|
unregister_iq_handler(Host, XMLNS) ->
|
||||||
|
ejabberd_sm ! {unregister_iq_handler, Host, XMLNS}.
|
||||||
|
|
||||||
|
|
||||||
|
%%====================================================================
|
||||||
|
%% gen_server callbacks
|
||||||
|
%%====================================================================
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Function: init(Args) -> {ok, State} |
|
||||||
|
%% {ok, State, Timeout} |
|
||||||
|
%% ignore |
|
||||||
|
%% {stop, Reason}
|
||||||
|
%% Description: Initiates the server
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
init([]) ->
|
||||||
update_tables(),
|
update_tables(),
|
||||||
mnesia:create_table(session,
|
mnesia:create_table(session,
|
||||||
[{ram_copies, [node()]},
|
[{ram_copies, [node()]},
|
||||||
@ -54,11 +164,37 @@ init() ->
|
|||||||
ejabberd_hooks:add(remove_user, Host,
|
ejabberd_hooks:add(remove_user, Host,
|
||||||
ejabberd_sm, disconnect_removed_user, 100)
|
ejabberd_sm, disconnect_removed_user, 100)
|
||||||
end, ?MYHOSTS),
|
end, ?MYHOSTS),
|
||||||
loop().
|
{ok, #state{}}.
|
||||||
|
|
||||||
loop() ->
|
%%--------------------------------------------------------------------
|
||||||
receive
|
%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
|
||||||
{route, From, To, Packet} ->
|
%% {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(_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({route, From, To, Packet}, State) ->
|
||||||
case catch do_route(From, To, Packet) of
|
case catch do_route(From, To, Packet) of
|
||||||
{'EXIT', Reason} ->
|
{'EXIT', Reason} ->
|
||||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
?ERROR_MSG("~p~nwhen processing: ~p",
|
||||||
@ -66,17 +202,17 @@ loop() ->
|
|||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
loop();
|
{noreply, State};
|
||||||
{mnesia_system_event, {mnesia_down, Node}} ->
|
handle_info({mnesia_system_event, {mnesia_down, Node}}, State) ->
|
||||||
clean_table_from_bad_node(Node),
|
clean_table_from_bad_node(Node),
|
||||||
loop();
|
{noreply, State};
|
||||||
{register_iq_handler, Host, XMLNS, Module, Function} ->
|
handle_info({register_iq_handler, Host, XMLNS, Module, Function}, State) ->
|
||||||
ets:insert(sm_iqtable, {{XMLNS, Host}, Module, Function}),
|
ets:insert(sm_iqtable, {{XMLNS, Host}, Module, Function}),
|
||||||
loop();
|
{noreply, State};
|
||||||
{register_iq_handler, Host, XMLNS, Module, Function, Opts} ->
|
handle_info({register_iq_handler, Host, XMLNS, Module, Function, Opts}, State) ->
|
||||||
ets:insert(sm_iqtable, {{XMLNS, Host}, Module, Function, Opts}),
|
ets:insert(sm_iqtable, {{XMLNS, Host}, Module, Function, Opts}),
|
||||||
loop();
|
{noreply, State};
|
||||||
{unregister_iq_handler, Host, XMLNS} ->
|
handle_info({unregister_iq_handler, Host, XMLNS}, State) ->
|
||||||
case ets:lookup(sm_iqtable, {XMLNS, Host}) of
|
case ets:lookup(sm_iqtable, {XMLNS, Host}) of
|
||||||
[{_, Module, Function, Opts}] ->
|
[{_, Module, Function, Opts}] ->
|
||||||
gen_iq_handler:stop_iq_handler(Module, Function, Opts);
|
gen_iq_handler:stop_iq_handler(Module, Function, Opts);
|
||||||
@ -84,23 +220,30 @@ loop() ->
|
|||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
ets:delete(sm_iqtable, {XMLNS, Host}),
|
ets:delete(sm_iqtable, {XMLNS, Host}),
|
||||||
loop();
|
{noreply, State};
|
||||||
_ ->
|
handle_info(_Info, State) ->
|
||||||
loop()
|
{noreply, State}.
|
||||||
end.
|
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% 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.
|
||||||
|
|
||||||
route(From, To, Packet) ->
|
%%--------------------------------------------------------------------
|
||||||
case catch do_route(From, To, Packet) of
|
%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
|
||||||
{'EXIT', Reason} ->
|
%% Description: Convert process state when code is changed
|
||||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
%%--------------------------------------------------------------------
|
||||||
[Reason, {From, To, Packet}]);
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
_ ->
|
{ok, State}.
|
||||||
ok
|
|
||||||
end.
|
|
||||||
|
|
||||||
open_session(SID, User, Server, Resource) ->
|
%%--------------------------------------------------------------------
|
||||||
set_session(SID, User, Server, Resource, undefined).
|
%%% Internal functions
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
set_session(SID, User, Server, Resource, Priority) ->
|
set_session(SID, User, Server, Resource, Priority) ->
|
||||||
LUser = jlib:nodeprep(User),
|
LUser = jlib:nodeprep(User),
|
||||||
@ -131,12 +274,6 @@ set_session(SID, User, Server, Resource, Priority) ->
|
|||||||
end, SIDs)
|
end, SIDs)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
close_session(SID) ->
|
|
||||||
F = fun() ->
|
|
||||||
mnesia:delete({session, SID})
|
|
||||||
end,
|
|
||||||
mnesia:sync_dirty(F).
|
|
||||||
|
|
||||||
|
|
||||||
clean_table_from_bad_node(Node) ->
|
clean_table_from_bad_node(Node) ->
|
||||||
F = fun() ->
|
F = fun() ->
|
||||||
@ -314,31 +451,9 @@ route_message(From, To, Packet) ->
|
|||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
bounce_offline_message(From, To, Packet) ->
|
|
||||||
Err = jlib:make_error_reply(Packet, ?ERR_SERVICE_UNAVAILABLE),
|
|
||||||
ejabberd_router:route(To, From, Err),
|
|
||||||
stop.
|
|
||||||
|
|
||||||
disconnect_removed_user(User, Server) ->
|
|
||||||
ejabberd_sm:route(jlib:make_jid("", "", ""),
|
|
||||||
jlib:make_jid(User, Server, ""),
|
|
||||||
{xmlelement, "broadcast", [],
|
|
||||||
[{exit, "User removed"}]}).
|
|
||||||
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
get_user_resources(User, Server) ->
|
|
||||||
LUser = jlib:nodeprep(User),
|
|
||||||
LServer = jlib:nameprep(Server),
|
|
||||||
US = {LUser, LServer},
|
|
||||||
case catch mnesia:dirty_index_read(session, US, #session.us) of
|
|
||||||
{'EXIT', _Reason} ->
|
|
||||||
[];
|
|
||||||
Ss ->
|
|
||||||
[element(3, S#session.usr) || S <- clean_session_list(Ss)]
|
|
||||||
end.
|
|
||||||
|
|
||||||
clean_session_list(Ss) ->
|
clean_session_list(Ss) ->
|
||||||
clean_session_list(lists:keysort(#session.usr, Ss), []).
|
clean_session_list(lists:keysort(#session.usr, Ss), []).
|
||||||
|
|
||||||
@ -362,19 +477,6 @@ clean_session_list([S1, S2 | Rest], Res) ->
|
|||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
set_presence(SID, User, Server, Resource, Priority) ->
|
|
||||||
set_session(SID, User, Server, Resource, Priority).
|
|
||||||
|
|
||||||
unset_presence(SID, User, Server, Resource, Status) ->
|
|
||||||
set_session(SID, User, Server, Resource, undefined),
|
|
||||||
ejabberd_hooks:run(unset_presence_hook, jlib:nameprep(Server),
|
|
||||||
[User, Server, Resource, Status]).
|
|
||||||
|
|
||||||
close_session_unset_presence(SID, User, Server, Resource, Status) ->
|
|
||||||
close_session(SID),
|
|
||||||
ejabberd_hooks:run(unset_presence_hook, jlib:nameprep(Server),
|
|
||||||
[User, Server, Resource, Status]).
|
|
||||||
|
|
||||||
get_user_present_resources(LUser, LServer) ->
|
get_user_present_resources(LUser, LServer) ->
|
||||||
US = {LUser, LServer},
|
US = {LUser, LServer},
|
||||||
case catch mnesia:dirty_index_read(session, US, #session.us) of
|
case catch mnesia:dirty_index_read(session, US, #session.us) of
|
||||||
@ -385,28 +487,6 @@ get_user_present_resources(LUser, LServer) ->
|
|||||||
S <- clean_session_list(Ss), is_integer(S#session.priority)]
|
S <- clean_session_list(Ss), is_integer(S#session.priority)]
|
||||||
end.
|
end.
|
||||||
|
|
||||||
dirty_get_sessions_list() ->
|
|
||||||
mnesia:dirty_select(
|
|
||||||
session,
|
|
||||||
[{#session{usr = '$1', _ = '_'},
|
|
||||||
[],
|
|
||||||
['$1']}]).
|
|
||||||
|
|
||||||
dirty_get_my_sessions_list() ->
|
|
||||||
mnesia:dirty_select(
|
|
||||||
session,
|
|
||||||
[{#session{sid = {'_', '$1'}, _ = '_'},
|
|
||||||
[{'==', {node, '$1'}, node()}],
|
|
||||||
['$_']}]).
|
|
||||||
|
|
||||||
get_vh_session_list(Server) ->
|
|
||||||
LServer = jlib:nameprep(Server),
|
|
||||||
mnesia:dirty_select(
|
|
||||||
session,
|
|
||||||
[{#session{usr = '$1', _ = '_'},
|
|
||||||
[{'==', {element, 2, '$1'}, LServer}],
|
|
||||||
['$1']}]).
|
|
||||||
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
@ -441,15 +521,6 @@ process_iq(From, To, Packet) ->
|
|||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
register_iq_handler(Host, XMLNS, Module, Fun) ->
|
|
||||||
ejabberd_sm ! {register_iq_handler, Host, XMLNS, Module, Fun}.
|
|
||||||
|
|
||||||
register_iq_handler(Host, XMLNS, Module, Fun, Opts) ->
|
|
||||||
ejabberd_sm ! {register_iq_handler, Host, XMLNS, Module, Fun, Opts}.
|
|
||||||
|
|
||||||
unregister_iq_handler(Host, XMLNS) ->
|
|
||||||
ejabberd_sm ! {unregister_iq_handler, Host, XMLNS}.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
update_tables() ->
|
update_tables() ->
|
||||||
|
@ -68,6 +68,14 @@ init([]) ->
|
|||||||
infinity,
|
infinity,
|
||||||
supervisor,
|
supervisor,
|
||||||
[ejabberd_listener]},
|
[ejabberd_listener]},
|
||||||
|
ReceiverSupervisor =
|
||||||
|
{ejabberd_receiver_sup,
|
||||||
|
{ejabberd_tmp_sup, start_link,
|
||||||
|
[ejabberd_receiver_sup, ejabberd_receiver]},
|
||||||
|
permanent,
|
||||||
|
infinity,
|
||||||
|
supervisor,
|
||||||
|
[ejabberd_tmp_sup]},
|
||||||
C2SSupervisor =
|
C2SSupervisor =
|
||||||
{ejabberd_c2s_sup,
|
{ejabberd_c2s_sup,
|
||||||
{ejabberd_tmp_sup, start_link, [ejabberd_c2s_sup, ejabberd_c2s]},
|
{ejabberd_tmp_sup, start_link, [ejabberd_c2s_sup, ejabberd_c2s]},
|
||||||
@ -130,6 +138,7 @@ init([]) ->
|
|||||||
SM,
|
SM,
|
||||||
S2S,
|
S2S,
|
||||||
Local,
|
Local,
|
||||||
|
ReceiverSupervisor,
|
||||||
C2SSupervisor,
|
C2SSupervisor,
|
||||||
S2SInSupervisor,
|
S2SInSupervisor,
|
||||||
S2SOutSupervisor,
|
S2SOutSupervisor,
|
||||||
|
@ -95,11 +95,17 @@ update() ->
|
|||||||
make_script(UpdatedBeams) ->
|
make_script(UpdatedBeams) ->
|
||||||
lists:map(
|
lists:map(
|
||||||
fun(Module) ->
|
fun(Module) ->
|
||||||
{ok, {Module, [{attributes, Attrs}]}} =
|
{ok, {Module, [{attributes, NewAttrs}]}} =
|
||||||
beam_lib:chunks(code:which(Module), [attributes]),
|
beam_lib:chunks(code:which(Module), [attributes]),
|
||||||
case lists:keysearch(update_info, 1, Attrs) of
|
CurAttrs = Module:module_info(attributes),
|
||||||
|
case lists:keysearch(update_info, 1, NewAttrs) of
|
||||||
|
{value, {_, [{update, _}]}} ->
|
||||||
|
case lists:keysearch(update_info, 1, CurAttrs) of
|
||||||
{value, {_, [{update, Extra}]}} ->
|
{value, {_, [{update, Extra}]}} ->
|
||||||
{update, Module, {advanced, Extra}};
|
{update, Module, {advanced, Extra}};
|
||||||
|
false ->
|
||||||
|
{update, Module, {advanced, 0}}
|
||||||
|
end;
|
||||||
false ->
|
false ->
|
||||||
{load_module, Module}
|
{load_module, Module}
|
||||||
end
|
end
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
%%% File : gen_iq_handler.erl
|
%%% File : gen_iq_handler.erl
|
||||||
%%% Author : Alexey Shchepin <alexey@sevcom.net>
|
%%% Author : Alexey Shchepin <alexey@sevcom.net>
|
||||||
%%% Purpose :
|
%%% Purpose : IQ handler support
|
||||||
%%% Created : 22 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
|
%%% Created : 22 Jan 2003 by Alexey Shchepin <alexey@sevcom.net>
|
||||||
%%% Id : $Id$
|
%%% Id : $Id$
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
@ -10,19 +10,35 @@
|
|||||||
-author('alexey@sevcom.net').
|
-author('alexey@sevcom.net').
|
||||||
-vsn('$Revision$ ').
|
-vsn('$Revision$ ').
|
||||||
|
|
||||||
-export([start/0,
|
-behaviour(gen_server).
|
||||||
start_link/3,
|
|
||||||
|
%% API
|
||||||
|
-export([start_link/3,
|
||||||
add_iq_handler/6,
|
add_iq_handler/6,
|
||||||
remove_iq_handler/3,
|
remove_iq_handler/3,
|
||||||
stop_iq_handler/3,
|
stop_iq_handler/3,
|
||||||
handle/7,
|
handle/7,
|
||||||
process_iq/6,
|
process_iq/6]).
|
||||||
queue_init/3]).
|
|
||||||
|
%% gen_server callbacks
|
||||||
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
|
terminate/2, code_change/3]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
|
|
||||||
start() ->
|
-record(state, {host,
|
||||||
ok.
|
module,
|
||||||
|
function}).
|
||||||
|
|
||||||
|
%%====================================================================
|
||||||
|
%% API
|
||||||
|
%%====================================================================
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
|
||||||
|
%% Description: Starts the server
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
start_link(Host, Module, Function) ->
|
||||||
|
gen_server:start_link(?MODULE, [Host, Module, Function], []).
|
||||||
|
|
||||||
add_iq_handler(Component, Host, NS, Module, Function, Type) ->
|
add_iq_handler(Component, Host, NS, Module, Function, Type) ->
|
||||||
case Type of
|
case Type of
|
||||||
@ -40,10 +56,10 @@ add_iq_handler(Component, Host, NS, Module, Function, Type) ->
|
|||||||
remove_iq_handler(Component, Host, NS) ->
|
remove_iq_handler(Component, Host, NS) ->
|
||||||
Component:unregister_iq_handler(Host, NS).
|
Component:unregister_iq_handler(Host, NS).
|
||||||
|
|
||||||
stop_iq_handler(Module, Function, Opts) ->
|
stop_iq_handler(_Module, _Function, Opts) ->
|
||||||
case Opts of
|
case Opts of
|
||||||
{one_queue, Pid} ->
|
{one_queue, Pid} ->
|
||||||
exit(Pid, kill);
|
gen_server:call(Pid, stop);
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
@ -75,18 +91,76 @@ process_iq(_Host, Module, Function, From, To, IQ) ->
|
|||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
start_link(Host, Module, Function) ->
|
%%====================================================================
|
||||||
{ok, proc_lib:spawn_link(?MODULE, queue_init, [Host, Module, Function])}.
|
%% gen_server callbacks
|
||||||
|
%%====================================================================
|
||||||
|
|
||||||
queue_init(Host, Module, Function) ->
|
%%--------------------------------------------------------------------
|
||||||
queue_loop(Host, Module, Function).
|
%% Function: init(Args) -> {ok, State} |
|
||||||
|
%% {ok, State, Timeout} |
|
||||||
|
%% ignore |
|
||||||
|
%% {stop, Reason}
|
||||||
|
%% Description: Initiates the server
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
init([Host, Module, Function]) ->
|
||||||
|
{ok, #state{host = Host,
|
||||||
|
module = Module,
|
||||||
|
function = Function}}.
|
||||||
|
|
||||||
% TODO: use gen_event
|
%%--------------------------------------------------------------------
|
||||||
queue_loop(Host, Module, Function) ->
|
%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
|
||||||
receive
|
%% {reply, Reply, State, Timeout} |
|
||||||
{process_iq, From, To, IQ} ->
|
%% {noreply, State} |
|
||||||
|
%% {noreply, State, Timeout} |
|
||||||
|
%% {stop, Reason, Reply, State} |
|
||||||
|
%% {stop, Reason, State}
|
||||||
|
%% Description: Handling call messages
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
handle_call(stop, _From, State) ->
|
||||||
|
Reply = ok,
|
||||||
|
{stop, normal, Reply, State}.
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Function: handle_cast(Msg, State) -> {noreply, State} |
|
||||||
|
%% {noreply, State, Timeout} |
|
||||||
|
%% {stop, Reason, State}
|
||||||
|
%% Description: Handling cast messages
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
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({process_iq, From, To, IQ},
|
||||||
|
#state{host = Host,
|
||||||
|
module = Module,
|
||||||
|
function = Function} = State) ->
|
||||||
process_iq(Host, Module, Function, From, To, IQ),
|
process_iq(Host, Module, Function, From, To, IQ),
|
||||||
queue_loop(Host, Module, Function);
|
{noreply, State};
|
||||||
_ ->
|
handle_info(_Info, State) ->
|
||||||
queue_loop(Host, Module, Function)
|
{noreply, State}.
|
||||||
end.
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% 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
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
@ -36,12 +36,12 @@ CREATE TABLE rostergroups (
|
|||||||
|
|
||||||
CREATE INDEX pk_rosterg_user_jid ON rostergroups USING btree (username, jid);
|
CREATE INDEX pk_rosterg_user_jid ON rostergroups USING btree (username, jid);
|
||||||
|
|
||||||
;; To update from previous table definition:
|
--- To update from previous table definition:
|
||||||
; CREATE SEQUENCE spool_seq_seq;
|
-- CREATE SEQUENCE spool_seq_seq;
|
||||||
; ALTER TABLE spool ADD COLUMN seq integer;
|
-- ALTER TABLE spool ADD COLUMN seq integer;
|
||||||
; ALTER TABLE spool ALTER COLUMN seq SET DEFAULT nextval('spool_seq_seq');
|
-- ALTER TABLE spool ALTER COLUMN seq SET DEFAULT nextval('spool_seq_seq');
|
||||||
; UPDATE spool SET seq = DEFAULT;
|
-- UPDATE spool SET seq = DEFAULT;
|
||||||
; ALTER TABLE spool ALTER COLUMN seq SET NOT NULL;
|
-- ALTER TABLE spool ALTER COLUMN seq SET NOT NULL;
|
||||||
|
|
||||||
CREATE TABLE spool (
|
CREATE TABLE spool (
|
||||||
username text NOT NULL,
|
username text NOT NULL,
|
||||||
|
Loading…
Reference in New Issue
Block a user