mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-08 16:52:59 +01:00
Change routing API
Now 'From' and 'To' arguments must be omitted in functions and structures related to routing. The commit deprecates the following functions: ejabberd_router:route/3 in favor of ejabberd_router:route/1 ejabberd_router:route_error/4 in favor of ejabberd_router:route_error/2 ejabberd_local:route_iq/4 in favor of ejabberd_local:route_iq/2 ejabberd_local:route_iq/5 in favor of ejabberd_local:route_iq/3 The format of {route, From, To, Packet} is changed in favor of {route, Packet}
This commit is contained in:
parent
26a5811744
commit
8b2d308498
@ -752,26 +752,24 @@ bounce_receivers(State, Reason) ->
|
||||
State, Receivers ++ ShapedReceivers).
|
||||
|
||||
bounce_els_from_obuf(State) ->
|
||||
lists:foreach(fun ({xmlstreamelement, El}) ->
|
||||
case El of
|
||||
#xmlel{name = Name, attrs = Attrs}
|
||||
when Name == <<"presence">>;
|
||||
Name == <<"message">>;
|
||||
Name == <<"iq">> ->
|
||||
FromS = fxml:get_attr_s(<<"from">>, Attrs),
|
||||
ToS = fxml:get_attr_s(<<"to">>, Attrs),
|
||||
case {jid:from_string(FromS),
|
||||
jid:from_string(ToS)}
|
||||
of
|
||||
{#jid{} = From, #jid{} = To} ->
|
||||
ejabberd_router:route(From, To, El);
|
||||
_ -> ok
|
||||
end;
|
||||
_ -> ok
|
||||
end;
|
||||
(_) -> ok
|
||||
end,
|
||||
buf_to_list(State#state.el_obuf)).
|
||||
lists:foreach(
|
||||
fun({xmlstreamelement, El}) ->
|
||||
try xmpp:decode(El, ?NS_CLIENT, [ignore_els]) of
|
||||
Pkt when ?is_stanza(Pkt) ->
|
||||
case {xmpp:get_from(Pkt), xmpp:get_to(Pkt)} of
|
||||
{#jid{}, #jid{}} ->
|
||||
ejabberd_router:route(Pkt);
|
||||
_ ->
|
||||
ok
|
||||
end;
|
||||
_ ->
|
||||
ok
|
||||
catch _:{xmpp_codec, _} ->
|
||||
ok
|
||||
end;
|
||||
(_) ->
|
||||
ok
|
||||
end, buf_to_list(State#state.el_obuf)).
|
||||
|
||||
is_valid_key(<<"">>, <<"">>) -> true;
|
||||
is_valid_key(PrevKey, Key) ->
|
||||
|
@ -187,9 +187,7 @@ open_session(#{user := U, server := S, resource := R,
|
||||
%%%===================================================================
|
||||
%%% Hooks
|
||||
%%%===================================================================
|
||||
process_info(#{lserver := LServer} = State,
|
||||
{route, From, To, Packet0}) ->
|
||||
Packet = xmpp:set_from_to(Packet0, From, To),
|
||||
process_info(#{lserver := LServer} = State, {route, Packet}) ->
|
||||
{Pass, State1} = case Packet of
|
||||
#presence{} ->
|
||||
process_presence_in(State, Packet);
|
||||
@ -545,7 +543,7 @@ process_iq_in(State, #iq{} = IQ) ->
|
||||
allow ->
|
||||
{true, State};
|
||||
deny ->
|
||||
route_error(IQ, xmpp:err_service_unavailable()),
|
||||
ejabberd_router:route_error(IQ, xmpp:err_service_unavailable()),
|
||||
{false, State}
|
||||
end.
|
||||
|
||||
@ -561,7 +559,8 @@ process_message_in(State, #message{type = T} = Msg) ->
|
||||
true ->
|
||||
ok;
|
||||
false ->
|
||||
route_error(Msg, xmpp:err_service_unavailable())
|
||||
ejabberd_router:route_error(
|
||||
Msg, xmpp:err_service_unavailable())
|
||||
end,
|
||||
{false, State}
|
||||
end.
|
||||
@ -611,7 +610,8 @@ route_probe_reply(From, To, #{lserver := LServer, pres_f := PresF,
|
||||
%% Don't route a presence probe to oneself
|
||||
case From == To of
|
||||
false ->
|
||||
route(xmpp:set_from_to(Packet, To, From));
|
||||
ejabberd_router:route(
|
||||
xmpp:set_from_to(Packet, To, From));
|
||||
true ->
|
||||
ok
|
||||
end
|
||||
@ -649,14 +649,14 @@ process_presence_out(#{user := User, server := Server, lserver := LServer,
|
||||
LServer,
|
||||
[User, Server, To, Type]),
|
||||
BareFrom = jid:remove_resource(From),
|
||||
route(xmpp:set_from_to(Pres, BareFrom, To)),
|
||||
ejabberd_router:route(xmpp:set_from_to(Pres, BareFrom, To)),
|
||||
State
|
||||
end;
|
||||
allow when Type == error; Type == probe ->
|
||||
route(Pres),
|
||||
ejabberd_router:route(Pres),
|
||||
State;
|
||||
allow ->
|
||||
route(Pres),
|
||||
ejabberd_router:route(Pres),
|
||||
A = case Type of
|
||||
available -> ?SETS:add_element(LTo, PresA);
|
||||
unavailable -> ?SETS:del_element(LTo, PresA)
|
||||
@ -728,7 +728,7 @@ check_privacy_then_route(#{lang := Lang} = State, Pkt) ->
|
||||
Err = xmpp:err_not_acceptable(ErrText, Lang),
|
||||
xmpp_stream_in:send_error(State, Pkt, Err);
|
||||
allow ->
|
||||
route(Pkt),
|
||||
ejabberd_router:route(Pkt),
|
||||
State
|
||||
end.
|
||||
|
||||
@ -755,18 +755,6 @@ filter_blocked(#{jid := From} = State, Pres, LJIDSet) ->
|
||||
end
|
||||
end, [], LJIDSet).
|
||||
|
||||
-spec route(stanza()) -> ok.
|
||||
route(Pkt) ->
|
||||
From = xmpp:get_from(Pkt),
|
||||
To = xmpp:get_to(Pkt),
|
||||
ejabberd_router:route(From, To, Pkt).
|
||||
|
||||
-spec route_error(stanza(), stanza_error()) -> ok.
|
||||
route_error(Pkt, Err) ->
|
||||
From = xmpp:get_from(Pkt),
|
||||
To = xmpp:get_to(Pkt),
|
||||
ejabberd_router:route_error(To, From, Pkt, Err).
|
||||
|
||||
-spec route_multiple(state(), [jid()], stanza()) -> ok.
|
||||
route_multiple(#{lserver := LServer}, JIDs, Pkt) ->
|
||||
From = xmpp:get_from(Pkt),
|
||||
@ -805,8 +793,8 @@ resource_conflict_action(U, S, R) ->
|
||||
|
||||
-spec bounce_message_queue() -> ok.
|
||||
bounce_message_queue() ->
|
||||
receive {route, From, To, Pkt} ->
|
||||
ejabberd_router:route(From, To, Pkt),
|
||||
receive {route, Pkt} ->
|
||||
ejabberd_router:route(Pkt),
|
||||
bounce_message_queue()
|
||||
after 0 ->
|
||||
ok
|
||||
|
@ -32,11 +32,11 @@
|
||||
%% API
|
||||
-export([start/0, start_link/0]).
|
||||
|
||||
-export([route/3, route_iq/4, route_iq/5, process_iq/3,
|
||||
process_iq_reply/3, get_features/1,
|
||||
-export([route/1, route_iq/2, route_iq/3, process_iq/1,
|
||||
process_iq_reply/1, get_features/1,
|
||||
register_iq_handler/5, register_iq_response_handler/4,
|
||||
register_iq_response_handler/5, unregister_iq_handler/2,
|
||||
unregister_iq_response_handler/2, bounce_resource_packet/3]).
|
||||
unregister_iq_response_handler/2, bounce_resource_packet/1]).
|
||||
|
||||
%% gen_server callbacks
|
||||
-export([init/1, handle_call/3, handle_cast/2,
|
||||
@ -77,55 +77,53 @@ start_link() ->
|
||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [],
|
||||
[]).
|
||||
|
||||
-spec process_iq(jid(), jid(), iq()) -> any().
|
||||
process_iq(From, To, #iq{type = T, lang = Lang, sub_els = [El]} = Packet)
|
||||
-spec process_iq(iq()) -> any().
|
||||
process_iq(#iq{to = To, type = T, lang = Lang, sub_els = [El]} = Packet)
|
||||
when T == get; T == set ->
|
||||
XMLNS = xmpp:get_ns(El),
|
||||
Host = To#jid.lserver,
|
||||
case ets:lookup(?IQTABLE, {Host, XMLNS}) of
|
||||
[{_, Module, Function, Opts}] ->
|
||||
gen_iq_handler:handle(Host, Module, Function, Opts,
|
||||
From, To, Packet);
|
||||
gen_iq_handler:handle(Host, Module, Function, Opts, Packet);
|
||||
[] ->
|
||||
Txt = <<"No module is handling this query">>,
|
||||
Err = xmpp:err_service_unavailable(Txt, Lang),
|
||||
ejabberd_router:route_error(To, From, Packet, Err)
|
||||
ejabberd_router:route_error(Packet, Err)
|
||||
end;
|
||||
process_iq(From, To, #iq{type = T, lang = Lang, sub_els = SubEls} = Packet)
|
||||
process_iq(#iq{type = T, lang = Lang, sub_els = SubEls} = Packet)
|
||||
when T == get; T == set ->
|
||||
Txt = case SubEls of
|
||||
[] -> <<"No child elements found">>;
|
||||
_ -> <<"Too many child elements">>
|
||||
end,
|
||||
Err = xmpp:err_bad_request(Txt, Lang),
|
||||
ejabberd_router:route_error(To, From, Packet, Err);
|
||||
process_iq(From, To, #iq{type = T} = Packet) when T == result; T == error ->
|
||||
process_iq_reply(From, To, Packet).
|
||||
ejabberd_router:route_error(Packet, Err);
|
||||
process_iq(#iq{type = T} = Packet) when T == result; T == error ->
|
||||
process_iq_reply(Packet).
|
||||
|
||||
-spec process_iq_reply(jid(), jid(), iq()) -> any().
|
||||
process_iq_reply(From, To, #iq{id = ID} = IQ) ->
|
||||
-spec process_iq_reply(iq()) -> any().
|
||||
process_iq_reply(#iq{id = ID} = IQ) ->
|
||||
case get_iq_callback(ID) of
|
||||
{ok, undefined, Function} -> Function(IQ), ok;
|
||||
{ok, Module, Function} ->
|
||||
Module:Function(From, To, IQ), ok;
|
||||
Module:Function(IQ), ok;
|
||||
_ -> nothing
|
||||
end.
|
||||
|
||||
-spec route(jid(), jid(), stanza()) -> any().
|
||||
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
|
||||
-spec route(stanza()) -> any().
|
||||
route(Packet) ->
|
||||
try do_route(Packet)
|
||||
catch E:R ->
|
||||
?ERROR_MSG("failed to route packet:~n~s~nReason = ~p",
|
||||
[xmpp:pp(Packet), {E, {R, erlang:get_stacktrace()}}])
|
||||
end.
|
||||
|
||||
-spec route_iq(jid(), jid(), iq(), function()) -> any().
|
||||
route_iq(From, To, IQ, F) ->
|
||||
route_iq(From, To, IQ, F, undefined).
|
||||
-spec route_iq(iq(), function()) -> any().
|
||||
route_iq(IQ, F) ->
|
||||
route_iq(IQ, F, undefined).
|
||||
|
||||
-spec route_iq(jid(), jid(), iq(), function(), ping_timeout()) -> any().
|
||||
route_iq(From, To, #iq{type = Type} = IQ, F, Timeout)
|
||||
-spec route_iq(iq(), function(), ping_timeout()) -> any().
|
||||
route_iq(#iq{from = From, type = Type} = IQ, F, Timeout)
|
||||
when is_function(F) ->
|
||||
Packet = if Type == set; Type == get ->
|
||||
ID = randoms:get_string(),
|
||||
@ -135,7 +133,7 @@ route_iq(From, To, #iq{type = Type} = IQ, F, Timeout)
|
||||
true ->
|
||||
IQ
|
||||
end,
|
||||
ejabberd_router:route(From, To, Packet).
|
||||
ejabberd_router:route(Packet).
|
||||
|
||||
-spec register_iq_response_handler(binary(), binary(), module(),
|
||||
atom() | function()) -> any().
|
||||
@ -172,17 +170,16 @@ unregister_iq_response_handler(_Host, ID) ->
|
||||
unregister_iq_handler(Host, XMLNS) ->
|
||||
gen_server:cast(?MODULE, {unregister_iq_handler, Host, XMLNS}).
|
||||
|
||||
-spec bounce_resource_packet(jid(), jid(), stanza()) -> stop.
|
||||
bounce_resource_packet(_From, #jid{lresource = <<"">>}, #presence{}) ->
|
||||
-spec bounce_resource_packet(stanza()) -> ok | stop.
|
||||
bounce_resource_packet(#presence{to = #jid{lresource = <<"">>}}) ->
|
||||
ok;
|
||||
bounce_resource_packet(_From, #jid{lresource = <<"">>},
|
||||
#message{type = headline}) ->
|
||||
bounce_resource_packet(#message{to = #jid{lresource = <<"">>}, type = headline}) ->
|
||||
ok;
|
||||
bounce_resource_packet(From, To, Packet) ->
|
||||
bounce_resource_packet(Packet) ->
|
||||
Lang = xmpp:get_lang(Packet),
|
||||
Txt = <<"No available resource found">>,
|
||||
Err = xmpp:err_item_not_found(Txt, Lang),
|
||||
ejabberd_router:route_error(To, From, Packet, Err),
|
||||
ejabberd_router:route_error(Packet, Err),
|
||||
stop.
|
||||
|
||||
-spec get_features(binary()) -> [binary()].
|
||||
@ -237,13 +234,8 @@ handle_cast({unregister_iq_handler, Host, XMLNS},
|
||||
{noreply, State};
|
||||
handle_cast(_Msg, State) -> {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,
|
||||
handle_info({route, Packet}, State) ->
|
||||
route(Packet),
|
||||
{noreply, State};
|
||||
handle_info({timeout, _TRef, ID}, State) ->
|
||||
process_iq_timeout(ID),
|
||||
@ -261,21 +253,20 @@ code_change(_OldVsn, State, _Extra) ->
|
||||
%%--------------------------------------------------------------------
|
||||
%%% Internal functions
|
||||
%%--------------------------------------------------------------------
|
||||
-spec do_route(jid(), jid(), stanza()) -> any().
|
||||
do_route(From, To, Packet) ->
|
||||
?DEBUG("local route~n\tfrom ~p~n\tto ~p~n\tpacket "
|
||||
"~P~n",
|
||||
[From, To, Packet, 8]),
|
||||
-spec do_route(stanza()) -> any().
|
||||
do_route(Packet) ->
|
||||
?DEBUG("local route:~n~s", [xmpp:pp(Packet)]),
|
||||
Type = xmpp:get_type(Packet),
|
||||
To = xmpp:get_to(Packet),
|
||||
if To#jid.luser /= <<"">> ->
|
||||
ejabberd_sm:route(From, To, Packet);
|
||||
ejabberd_sm:route(Packet);
|
||||
is_record(Packet, iq), To#jid.lresource == <<"">> ->
|
||||
process_iq(From, To, Packet);
|
||||
process_iq(Packet);
|
||||
Type == result; Type == error ->
|
||||
ok;
|
||||
true ->
|
||||
ejabberd_hooks:run(local_send_to_resource_hook,
|
||||
To#jid.lserver, [From, To, Packet])
|
||||
To#jid.lserver, [Packet])
|
||||
end.
|
||||
|
||||
-spec update_table() -> ok.
|
||||
|
@ -524,24 +524,19 @@ process_vcard(El, State = #state{user = U, server = S}) ->
|
||||
process_offline_msg(#message{from = undefined}, _State) ->
|
||||
stop("No 'from' attribute found", []);
|
||||
process_offline_msg(Msg, State = #state{user = U, server = S}) ->
|
||||
From = xmpp:get_from(Msg),
|
||||
To = jid:make(U, S, <<>>),
|
||||
NewMsg = xmpp:set_from_to(Msg, From, To),
|
||||
case catch mod_offline:store_packet(pass, From, To, NewMsg) of
|
||||
{'EXIT', _} = Err ->
|
||||
stop("Failed to store offline message: ~p", [Err]);
|
||||
_ ->
|
||||
{ok, State}
|
||||
end.
|
||||
To = jid:make(U, S),
|
||||
ejabberd_hooks:run_fold(
|
||||
offline_message_hook, To#jid.lserver, pass,
|
||||
[xmpp:set_to(Msg, To)]),
|
||||
{ok, State}.
|
||||
|
||||
-spec process_presence(presence(), state()) -> {ok, state()} | {error, _}.
|
||||
process_presence(#presence{from = undefined}, _State) ->
|
||||
stop("No 'from' attribute found", []);
|
||||
process_presence(Pres, #state{user = U, server = S} = State) ->
|
||||
From = xmpp:get_from(Pres),
|
||||
To = jid:make(U, S, <<>>),
|
||||
NewPres = xmpp:set_from_to(Pres, From, To),
|
||||
ejabberd_router:route(From, To, NewPres),
|
||||
To = jid:make(U, S),
|
||||
NewPres = xmpp:set_to(Pres, To),
|
||||
ejabberd_router:route(NewPres),
|
||||
{ok, State}.
|
||||
|
||||
stop(Fmt, Args) ->
|
||||
|
@ -35,13 +35,13 @@
|
||||
-behaviour(?GEN_SERVER).
|
||||
|
||||
%% API
|
||||
-export([route/3,
|
||||
route_error/4,
|
||||
-export([route/1,
|
||||
route_error/2,
|
||||
register_route/2,
|
||||
register_route/3,
|
||||
register_routes/1,
|
||||
host_of_route/1,
|
||||
process_iq/3,
|
||||
process_iq/1,
|
||||
unregister_route/1,
|
||||
unregister_routes/1,
|
||||
get_all_routes/0,
|
||||
@ -54,6 +54,10 @@
|
||||
-export([init/1, handle_call/3, handle_cast/2,
|
||||
handle_info/2, terminate/2, code_change/3, opt_type/1]).
|
||||
|
||||
%% Deprecated functions
|
||||
-export([route/3, route_error/4]).
|
||||
-deprecated([{route, 3}, {route_error, 4}]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
-include("logger.hrl").
|
||||
-include("ejabberd_router.hrl").
|
||||
@ -82,6 +86,14 @@ start() ->
|
||||
start_link() ->
|
||||
?GEN_SERVER:start_link({local, ?MODULE}, ?MODULE, [], []).
|
||||
|
||||
-spec route(stanza()) -> ok.
|
||||
route(Packet) ->
|
||||
try do_route(Packet)
|
||||
catch E:R ->
|
||||
?ERROR_MSG("failed to route packet:~n~s~nReason = ~p",
|
||||
[xmpp:pp(Packet), {E, {R, erlang:get_stacktrace()}}])
|
||||
end.
|
||||
|
||||
-spec route(jid(), jid(), xmlel() | stanza()) -> ok.
|
||||
route(#jid{} = From, #jid{} = To, #xmlel{} = El) ->
|
||||
try xmpp:decode(El, ?NS_CLIENT, [ignore_els]) of
|
||||
@ -93,7 +105,7 @@ route(#jid{} = From, #jid{} = To, #xmlel{} = El) ->
|
||||
xmpp:format_error(Why)])
|
||||
end;
|
||||
route(#jid{} = From, #jid{} = To, Packet) ->
|
||||
case catch do_route(From, To, xmpp:set_from_to(Packet, From, To)) of
|
||||
case catch do_route(xmpp:set_from_to(Packet, From, To)) of
|
||||
{'EXIT', Reason} ->
|
||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
||||
[Reason, {From, To, Packet}]);
|
||||
@ -101,6 +113,15 @@ route(#jid{} = From, #jid{} = To, Packet) ->
|
||||
ok
|
||||
end.
|
||||
|
||||
-spec route_error(stanza(), stanza_error()) -> ok.
|
||||
route_error(Packet, Err) ->
|
||||
Type = xmpp:get_type(Packet),
|
||||
if Type == error; Type == result ->
|
||||
ok;
|
||||
true ->
|
||||
route(xmpp:make_error(Packet, Err))
|
||||
end.
|
||||
|
||||
%% Route the error packet only if the originating packet is not an error itself.
|
||||
%% RFC3920 9.3.1
|
||||
-spec route_error(jid(), jid(), xmlel(), xmlel()) -> ok;
|
||||
@ -116,7 +137,7 @@ route_error(From, To, Packet, #stanza_error{} = Err) ->
|
||||
if Type == error; Type == result ->
|
||||
ok;
|
||||
true ->
|
||||
ejabberd_router:route(From, To, xmpp:make_error(Packet, Err))
|
||||
route(From, To, xmpp:make_error(Packet, Err))
|
||||
end.
|
||||
|
||||
-spec register_route(binary(), binary()) -> ok.
|
||||
@ -208,12 +229,12 @@ is_my_host(Domain) ->
|
||||
Mod:is_my_host(LDomain)
|
||||
end.
|
||||
|
||||
-spec process_iq(jid(), jid(), iq()) -> any().
|
||||
process_iq(From, To, #iq{} = IQ) ->
|
||||
-spec process_iq(iq()) -> any().
|
||||
process_iq(#iq{to = To} = IQ) ->
|
||||
if To#jid.luser == <<"">> ->
|
||||
ejabberd_local:process_iq(From, To, IQ);
|
||||
ejabberd_local:process_iq(IQ);
|
||||
true ->
|
||||
ejabberd_sm:process_iq(From, To, IQ)
|
||||
ejabberd_sm:process_iq(IQ)
|
||||
end.
|
||||
|
||||
%%====================================================================
|
||||
@ -231,13 +252,8 @@ handle_call(_Request, _From, State) ->
|
||||
handle_cast(_Msg, State) ->
|
||||
{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,
|
||||
handle_info({route, Packet}, State) ->
|
||||
route(Packet),
|
||||
{noreply, State};
|
||||
handle_info(Info, State) ->
|
||||
?ERROR_MSG("unexpected info: ~p", [Info]),
|
||||
@ -252,37 +268,39 @@ code_change(_OldVsn, State, _Extra) ->
|
||||
%%--------------------------------------------------------------------
|
||||
%%% Internal functions
|
||||
%%--------------------------------------------------------------------
|
||||
-spec do_route(jid(), jid(), stanza()) -> any().
|
||||
do_route(OrigFrom, OrigTo, OrigPacket) ->
|
||||
-spec do_route(stanza()) -> ok.
|
||||
do_route(OrigPacket) ->
|
||||
?DEBUG("route:~n~s", [xmpp:pp(OrigPacket)]),
|
||||
case ejabberd_hooks:run_fold(filter_packet,
|
||||
{OrigFrom, OrigTo, OrigPacket}, []) of
|
||||
{From, To, Packet} ->
|
||||
case ejabberd_hooks:run_fold(filter_packet, OrigPacket, []) of
|
||||
drop ->
|
||||
ok;
|
||||
Packet ->
|
||||
To = xmpp:get_to(Packet),
|
||||
LDstDomain = To#jid.lserver,
|
||||
Mod = get_backend(),
|
||||
case Mod:find_routes(LDstDomain) of
|
||||
[] ->
|
||||
ejabberd_s2s:route(From, To, Packet);
|
||||
ejabberd_s2s:route(Packet);
|
||||
[Route] ->
|
||||
do_route(From, To, Packet, Route);
|
||||
do_route(Packet, Route);
|
||||
Routes ->
|
||||
From = xmpp:get_from(Packet),
|
||||
balancing_route(From, To, Packet, Routes)
|
||||
end;
|
||||
drop ->
|
||||
end,
|
||||
ok
|
||||
end.
|
||||
|
||||
-spec do_route(jid(), jid(), stanza(), #route{}) -> any().
|
||||
do_route(From, To, Pkt, #route{local_hint = LocalHint,
|
||||
pid = Pid}) when is_pid(Pid) ->
|
||||
-spec do_route(stanza(), #route{}) -> any().
|
||||
do_route(Pkt, #route{local_hint = LocalHint,
|
||||
pid = Pid}) when is_pid(Pid) ->
|
||||
case LocalHint of
|
||||
{apply, Module, Function} when node(Pid) == node() ->
|
||||
Module:Function(From, To, Pkt);
|
||||
Module:Function(Pkt);
|
||||
_ ->
|
||||
Pid ! {route, From, To, Pkt}
|
||||
Pid ! {route, Pkt}
|
||||
end;
|
||||
do_route(_From, _To, _Pkt, _Route) ->
|
||||
drop.
|
||||
do_route(_Pkt, _Route) ->
|
||||
ok.
|
||||
|
||||
-spec balancing_route(jid(), jid(), stanza(), [#route{}]) -> any().
|
||||
balancing_route(From, To, Packet, Rs) ->
|
||||
@ -293,15 +311,15 @@ balancing_route(From, To, Packet, Rs) ->
|
||||
case [R || R <- Rs, node(R#route.pid) == node()] of
|
||||
[] ->
|
||||
R = lists:nth(erlang:phash(Value, length(Rs)), Rs),
|
||||
do_route(From, To, Packet, R);
|
||||
do_route(Packet, R);
|
||||
LRs ->
|
||||
R = lists:nth(erlang:phash(Value, length(LRs)), LRs),
|
||||
do_route(From, To, Packet, R)
|
||||
do_route(Packet, R)
|
||||
end;
|
||||
_ ->
|
||||
SRs = lists:ukeysort(#route.local_hint, Rs),
|
||||
R = lists:nth(erlang:phash(Value, length(SRs)), SRs),
|
||||
do_route(From, To, Packet, R)
|
||||
do_route(Packet, R)
|
||||
end.
|
||||
|
||||
-spec get_component_number(binary()) -> pos_integer() | undefined.
|
||||
|
@ -66,7 +66,7 @@ start_link() ->
|
||||
|
||||
-spec route_multicast(jid(), binary(), [jid()], stanza()) -> ok.
|
||||
route_multicast(From, Domain, Destinations, Packet) ->
|
||||
case catch do_route(From, Domain, Destinations, Packet) of
|
||||
case catch do_route(Domain, Destinations, xmpp:set_from(Packet, From)) of
|
||||
{'EXIT', Reason} ->
|
||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
||||
[Reason, {From, Domain, Destinations, Packet}]);
|
||||
@ -162,11 +162,11 @@ handle_cast(_Msg, State) ->
|
||||
%% {stop, Reason, State}
|
||||
%% Description: Handling all non call/cast messages
|
||||
%%--------------------------------------------------------------------
|
||||
handle_info({route_multicast, From, Domain, Destinations, Packet}, State) ->
|
||||
case catch do_route(From, Domain, Destinations, Packet) of
|
||||
handle_info({route_multicast, Domain, Destinations, Packet}, State) ->
|
||||
case catch do_route(Domain, Destinations, Packet) of
|
||||
{'EXIT', Reason} ->
|
||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
||||
[Reason, {From, Domain, Destinations, Packet}]);
|
||||
[Reason, {Domain, Destinations, Packet}]);
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
@ -214,25 +214,21 @@ code_change(_OldVsn, State, _Extra) ->
|
||||
%%--------------------------------------------------------------------
|
||||
%% From = #jid
|
||||
%% Destinations = [#jid]
|
||||
-spec do_route(jid(), binary(), [jid()], stanza()) -> any().
|
||||
do_route(From, Domain, Destinations, Packet) ->
|
||||
|
||||
?DEBUG("route_multicast~n\tfrom ~s~n\tdomain ~s~n\tdestinations ~p~n\tpacket ~p~n",
|
||||
[jid:to_string(From),
|
||||
Domain,
|
||||
[jid:to_string(To) || To <- Destinations],
|
||||
Packet]),
|
||||
|
||||
-spec do_route(binary(), [jid()], stanza()) -> any().
|
||||
do_route(Domain, Destinations, Packet) ->
|
||||
?DEBUG("route multicast:~n~s~nDomain: ~s~nDestinations: ~s~n",
|
||||
[xmpp:pp(Packet), Domain,
|
||||
str:join([jid:to_string(To) || To <- Destinations], ", ")]),
|
||||
%% Try to find an appropriate multicast service
|
||||
case mnesia:dirty_read(route_multicast, Domain) of
|
||||
|
||||
%% If no multicast service is available in this server, send manually
|
||||
[] -> do_route_normal(From, Destinations, Packet);
|
||||
[] -> do_route_normal(Destinations, Packet);
|
||||
|
||||
%% If some is available, send the packet using multicast service
|
||||
Rs when is_list(Rs) ->
|
||||
Pid = pick_multicast_pid(Rs),
|
||||
Pid ! {route_trusted, From, Destinations, Packet}
|
||||
Pid ! {route_trusted, Destinations, Packet}
|
||||
end.
|
||||
|
||||
-spec pick_multicast_pid([#route_multicast{}]) -> pid().
|
||||
@ -243,6 +239,6 @@ pick_multicast_pid(Rs) ->
|
||||
end,
|
||||
(hd(List))#route_multicast.pid.
|
||||
|
||||
-spec do_route_normal(jid(), [jid()], stanza()) -> any().
|
||||
do_route_normal(From, Destinations, Packet) ->
|
||||
[ejabberd_router:route(From, To, Packet) || To <- Destinations].
|
||||
-spec do_route_normal([jid()], stanza()) -> any().
|
||||
do_route_normal(Destinations, Packet) ->
|
||||
[ejabberd_router:route(xmpp:set_to(Packet, To)) || To <- Destinations].
|
||||
|
@ -34,7 +34,7 @@
|
||||
-behaviour(gen_server).
|
||||
|
||||
%% API
|
||||
-export([start_link/0, route/3, have_connection/1,
|
||||
-export([start_link/0, route/1, have_connection/1,
|
||||
get_connections_pids/1, try_register/1,
|
||||
remove_connection/2, start_connection/2, start_connection/3,
|
||||
dirty_get_connections/0, allow_host/2,
|
||||
@ -90,14 +90,13 @@ start_link() ->
|
||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [],
|
||||
[]).
|
||||
|
||||
-spec route(jid(), jid(), xmpp_element()) -> ok.
|
||||
-spec route(stanza()) -> ok.
|
||||
|
||||
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
|
||||
route(Packet) ->
|
||||
try do_route(Packet)
|
||||
catch E:R ->
|
||||
?ERROR_MSG("failed to route packet:~n~s~nReason = ~p",
|
||||
[xmpp:pp(Packet), {E, {R, erlang:get_stacktrace()}}])
|
||||
end.
|
||||
|
||||
clean_temporarily_blocked_table() ->
|
||||
@ -314,13 +313,8 @@ handle_cast(_Msg, State) ->
|
||||
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,
|
||||
handle_info({route, Packet}, State) ->
|
||||
route(Packet),
|
||||
{noreply, State};
|
||||
handle_info(_Info, State) -> {noreply, State}.
|
||||
|
||||
@ -348,17 +342,17 @@ clean_table_from_bad_node(Node) ->
|
||||
end,
|
||||
mnesia:async_dirty(F).
|
||||
|
||||
-spec do_route(jid(), jid(), stanza()) -> ok.
|
||||
do_route(From, To, Packet) ->
|
||||
?DEBUG("s2s manager~n\tfrom ~p~n\tto ~p~n\tpacket "
|
||||
"~P~n",
|
||||
[From, To, Packet, 8]),
|
||||
-spec do_route(stanza()) -> ok.
|
||||
do_route(Packet) ->
|
||||
?DEBUG("local route:~n~s", [xmpp:pp(Packet)]),
|
||||
From = xmpp:get_from(Packet),
|
||||
To = xmpp:get_to(Packet),
|
||||
case start_connection(From, To) of
|
||||
{ok, Pid} when is_pid(Pid) ->
|
||||
?DEBUG("sending to process ~p~n", [Pid]),
|
||||
#jid{lserver = MyServer} = From,
|
||||
ejabberd_hooks:run(s2s_send_packet, MyServer, [From, To, Packet]),
|
||||
ejabberd_s2s_out:route(Pid, xmpp:set_from_to(Packet, From, To));
|
||||
ejabberd_hooks:run(s2s_send_packet, MyServer, [Packet]),
|
||||
ejabberd_s2s_out:route(Pid, Packet);
|
||||
{error, Reason} ->
|
||||
Lang = xmpp:get_lang(Packet),
|
||||
Err = case Reason of
|
||||
@ -371,7 +365,7 @@ do_route(From, To, Packet) ->
|
||||
internal_server_error ->
|
||||
xmpp:err_internal_server_error()
|
||||
end,
|
||||
ejabberd_router:route_error(To, From, Packet, Err)
|
||||
ejabberd_router:route_error(Packet, Err)
|
||||
end.
|
||||
|
||||
-spec start_connection(jid(), jid())
|
||||
|
@ -213,7 +213,7 @@ handle_authenticated_packet(Pkt0, #{ip := {IP, _}} = State) ->
|
||||
{Pkt, State1}, []),
|
||||
case Pkt1 of
|
||||
drop -> ok;
|
||||
_ -> ejabberd_router:route(From, To, Pkt1)
|
||||
_ -> ejabberd_router:route(Pkt1)
|
||||
end,
|
||||
State2;
|
||||
{error, Err} ->
|
||||
|
@ -330,11 +330,9 @@ bounce_message_queue(State) ->
|
||||
|
||||
-spec bounce_packet(xmpp_element(), state()) -> state().
|
||||
bounce_packet(Pkt, State) when ?is_stanza(Pkt) ->
|
||||
From = xmpp:get_from(Pkt),
|
||||
To = xmpp:get_to(Pkt),
|
||||
Lang = xmpp:get_lang(Pkt),
|
||||
Err = mk_bounce_error(Lang, State),
|
||||
ejabberd_router:route_error(To, From, Pkt, Err),
|
||||
ejabberd_router:route_error(Pkt, Err),
|
||||
State;
|
||||
bounce_packet(_, State) ->
|
||||
State.
|
||||
|
@ -190,8 +190,7 @@ handle_authenticated_packet(Pkt0, #{ip := {IP, _}, lang := Lang} = State)
|
||||
From = xmpp:get_from(Pkt),
|
||||
case check_from(From, State) of
|
||||
true ->
|
||||
To = xmpp:get_to(Pkt),
|
||||
ejabberd_router:route(From, To, Pkt),
|
||||
ejabberd_router:route(Pkt),
|
||||
State;
|
||||
false ->
|
||||
Txt = <<"Improper domain part of 'from' attribute">>,
|
||||
@ -201,15 +200,14 @@ handle_authenticated_packet(Pkt0, #{ip := {IP, _}, lang := Lang} = State)
|
||||
handle_authenticated_packet(_Pkt, State) ->
|
||||
State.
|
||||
|
||||
handle_info({route, From, To, Packet}, #{access := Access} = State) ->
|
||||
case acl:match_rule(global, Access, From) of
|
||||
handle_info({route, Packet}, #{access := Access} = State) ->
|
||||
case acl:match_rule(global, Access, xmpp:get_from(Packet)) of
|
||||
allow ->
|
||||
Pkt = xmpp:set_from_to(Packet, From, To),
|
||||
xmpp_stream_in:send(State, Pkt);
|
||||
xmpp_stream_in:send(State, Packet);
|
||||
deny ->
|
||||
Lang = xmpp:get_lang(Packet),
|
||||
Err = xmpp:err_not_allowed(<<"Denied by ACL">>, Lang),
|
||||
ejabberd_router:route_error(To, From, Packet, Err),
|
||||
ejabberd_router:route_error(Packet, Err),
|
||||
State
|
||||
end;
|
||||
handle_info(Info, State) ->
|
||||
|
@ -37,14 +37,14 @@
|
||||
%% API
|
||||
-export([start/0,
|
||||
start_link/0,
|
||||
route/1,
|
||||
route/2,
|
||||
route/3,
|
||||
process_iq/3,
|
||||
process_iq/1,
|
||||
open_session/5,
|
||||
open_session/6,
|
||||
close_session/4,
|
||||
check_in_subscription/6,
|
||||
bounce_offline_message/4,
|
||||
bounce_offline_message/2,
|
||||
disconnect_removed_user/2,
|
||||
get_user_resources/2,
|
||||
get_user_present_resources/2,
|
||||
@ -126,14 +126,12 @@ route(To, Term) ->
|
||||
ok
|
||||
end.
|
||||
|
||||
-spec route(jid(), jid(), stanza()) -> ok.
|
||||
|
||||
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
|
||||
-spec route(stanza()) -> ok.
|
||||
route(Packet) ->
|
||||
try do_route(Packet), ok
|
||||
catch E:R ->
|
||||
?ERROR_MSG("failed to route packet:~n~s~nReason = ~p",
|
||||
[xmpp:pp(Packet), {E, {R, erlang:get_stacktrace()}}])
|
||||
end.
|
||||
|
||||
-spec open_session(sid(), binary(), binary(), binary(), prio(), info()) -> ok.
|
||||
@ -174,15 +172,15 @@ check_in_subscription(Acc, User, Server, _JID, _Type, _Reason) ->
|
||||
false -> {stop, false}
|
||||
end.
|
||||
|
||||
-spec bounce_offline_message(bounce | any(), jid(), jid(), message()) -> stop.
|
||||
-spec bounce_offline_message(bounce | any(), message()) -> stop.
|
||||
|
||||
bounce_offline_message(bounce = Acc, From, To, Packet) ->
|
||||
bounce_offline_message(bounce = Acc, Packet) ->
|
||||
Lang = xmpp:get_lang(Packet),
|
||||
Txt = <<"User session not found">>,
|
||||
Err = xmpp:err_service_unavailable(Txt, Lang),
|
||||
ejabberd_router:route_error(To, From, Packet, Err),
|
||||
ejabberd_router:route_error(Packet, Err),
|
||||
{stop, Acc};
|
||||
bounce_offline_message(Acc, _From, _To, _Packet) ->
|
||||
bounce_offline_message(Acc, _Packet) ->
|
||||
Acc.
|
||||
|
||||
-spec disconnect_removed_user(binary(), binary()) -> ok.
|
||||
@ -427,14 +425,8 @@ handle_cast({unregister_iq_handler, Host, XMLNS},
|
||||
{noreply, State};
|
||||
handle_cast(_Msg, State) -> {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,
|
||||
handle_info({route, Packet}, State) ->
|
||||
route(Packet),
|
||||
{noreply, State};
|
||||
handle_info(Info, State) ->
|
||||
?WARNING_MSG("unexpected info: ~p", [Info]),
|
||||
@ -505,8 +497,8 @@ do_route(To, Term) ->
|
||||
Pid ! Term
|
||||
end.
|
||||
|
||||
-spec do_route(jid(), jid(), stanza()) -> any().
|
||||
do_route(From, To, #presence{type = T, status = Status} = Packet)
|
||||
-spec do_route(stanza()) -> any().
|
||||
do_route(#presence{from = From, to = To, type = T, status = Status} = Packet)
|
||||
when T == subscribe; T == subscribed; T == unsubscribe; T == unsubscribed ->
|
||||
?DEBUG("processing subscription:~n~s", [xmpp:pp(Packet)]),
|
||||
#jid{user = User, server = Server,
|
||||
@ -514,7 +506,7 @@ do_route(From, To, #presence{type = T, status = Status} = Packet)
|
||||
Reason = if T == subscribe -> xmpp:get_text(Status);
|
||||
true -> <<"">>
|
||||
end,
|
||||
case is_privacy_allow(From, To, Packet) andalso
|
||||
case is_privacy_allow(Packet) andalso
|
||||
ejabberd_hooks:run_fold(
|
||||
roster_in_subscription,
|
||||
LServer, false,
|
||||
@ -525,37 +517,39 @@ do_route(From, To, #presence{type = T, status = Status} = Packet)
|
||||
fun(#session{sid = SID, usr = {_, _, R},
|
||||
priority = Prio}) when is_integer(Prio) ->
|
||||
Pid = element(2, SID),
|
||||
Packet1 = Packet#presence{to = jid:replace_resource(To, R)},
|
||||
?DEBUG("sending to process ~p:~n~s",
|
||||
[Pid, xmpp:pp(Packet)]),
|
||||
Pid ! {route, From, jid:replace_resource(To, R), Packet};
|
||||
[Pid, xmpp:pp(Packet1)]),
|
||||
Pid ! {route, Packet1};
|
||||
(_) ->
|
||||
ok
|
||||
end, online(Mod:get_sessions(LUser, LServer)));
|
||||
false ->
|
||||
ok
|
||||
end;
|
||||
do_route(From, #jid{lresource = <<"">>} = To, #presence{} = Packet) ->
|
||||
do_route(#presence{to = #jid{lresource = <<"">>} = To} = Packet) ->
|
||||
?DEBUG("processing presence to bare JID:~n~s", [xmpp:pp(Packet)]),
|
||||
{LUser, LServer, _} = jid:tolower(To),
|
||||
lists:foreach(
|
||||
fun({_, R}) ->
|
||||
do_route(From, jid:replace_resource(To, R), Packet)
|
||||
do_route(Packet#presence{to = jid:replace_resource(To, R)})
|
||||
end, get_user_present_resources(LUser, LServer));
|
||||
do_route(From, #jid{lresource = <<"">>} = To, #message{type = T} = Packet) ->
|
||||
do_route(#message{to = #jid{lresource = <<"">>}, type = T} = Packet) ->
|
||||
?DEBUG("processing message to bare JID:~n~s", [xmpp:pp(Packet)]),
|
||||
if T == chat; T == headline; T == normal; T == groupchat ->
|
||||
route_message(From, To, Packet, T);
|
||||
route_message(Packet);
|
||||
true ->
|
||||
Lang = xmpp:get_lang(Packet),
|
||||
ErrTxt = <<"User session not found">>,
|
||||
Err = xmpp:err_service_unavailable(ErrTxt, Lang),
|
||||
ejabberd_router:route_error(To, From, Packet, Err)
|
||||
ejabberd_router:route_error(Packet, Err)
|
||||
end;
|
||||
do_route(From, #jid{lresource = <<"">>} = To, #iq{} = Packet) ->
|
||||
do_route(#iq{to = #jid{lresource = <<"">>}} = Packet) ->
|
||||
?DEBUG("processing IQ to bare JID:~n~s", [xmpp:pp(Packet)]),
|
||||
process_iq(From, To, Packet);
|
||||
do_route(From, To, Packet) ->
|
||||
process_iq(Packet);
|
||||
do_route(Packet) ->
|
||||
?DEBUG("processing packet to full JID:~n~s", [xmpp:pp(Packet)]),
|
||||
To = xmpp:get_to(Packet),
|
||||
{LUser, LServer, LResource} = jid:tolower(To),
|
||||
Mod = get_sm_backend(LServer),
|
||||
case online(Mod:get_sessions(LUser, LServer, LResource)) of
|
||||
@ -563,7 +557,7 @@ do_route(From, To, Packet) ->
|
||||
case Packet of
|
||||
#message{type = T} when T == chat; T == normal;
|
||||
T == headline; T == groupchat ->
|
||||
route_message(From, To, Packet, T);
|
||||
route_message(Packet);
|
||||
#presence{} ->
|
||||
?DEBUG("dropping presence to unavalable resource:~n~s",
|
||||
[xmpp:pp(Packet)]);
|
||||
@ -571,28 +565,29 @@ do_route(From, To, Packet) ->
|
||||
Lang = xmpp:get_lang(Packet),
|
||||
ErrTxt = <<"User session not found">>,
|
||||
Err = xmpp:err_service_unavailable(ErrTxt, Lang),
|
||||
ejabberd_router:route_error(To, From, Packet, Err)
|
||||
ejabberd_router:route_error(Packet, Err)
|
||||
end;
|
||||
Ss ->
|
||||
Session = lists:max(Ss),
|
||||
Pid = element(2, Session#session.sid),
|
||||
?DEBUG("sending to process ~p:~n~s", [Pid, xmpp:pp(Packet)]),
|
||||
Pid ! {route, From, To, Packet}
|
||||
Pid ! {route, Packet}
|
||||
end.
|
||||
|
||||
%% The default list applies to the user as a whole,
|
||||
%% and is processed if there is no active list set
|
||||
%% for the target session/resource to which a stanza is addressed,
|
||||
%% or if there are no current sessions for the user.
|
||||
-spec is_privacy_allow(jid(), jid(), stanza()) -> boolean().
|
||||
is_privacy_allow(From, To, Packet) ->
|
||||
-spec is_privacy_allow(stanza()) -> boolean().
|
||||
is_privacy_allow(Packet) ->
|
||||
To = xmpp:get_to(Packet),
|
||||
LServer = To#jid.server,
|
||||
allow == ejabberd_hooks:run_fold(
|
||||
privacy_check_packet, LServer, allow,
|
||||
[To, xmpp:set_from_to(Packet, From, To), in]).
|
||||
[To, Packet, in]).
|
||||
|
||||
-spec route_message(jid(), jid(), message(), message_type()) -> any().
|
||||
route_message(From, To, Packet, Type) ->
|
||||
-spec route_message(message()) -> any().
|
||||
route_message(#message{to = To, type = Type} = Packet) ->
|
||||
LUser = To#jid.luser,
|
||||
LServer = To#jid.lserver,
|
||||
PrioRes = get_user_present_resources(LUser, LServer),
|
||||
@ -616,7 +611,7 @@ route_message(From, To, Packet, Type) ->
|
||||
LResource,
|
||||
LMaxRes,
|
||||
P, MaxPrio),
|
||||
Pid ! {route, From, To, Packet1}
|
||||
Pid ! {route, Packet1}
|
||||
end;
|
||||
%% Ignore other priority:
|
||||
({_Prio, _Res}) -> ok
|
||||
@ -624,14 +619,14 @@ route_message(From, To, Packet, Type) ->
|
||||
PrioRes);
|
||||
_ ->
|
||||
case ejabberd_auth:is_user_exists(LUser, LServer) andalso
|
||||
is_privacy_allow(From, To, Packet) of
|
||||
is_privacy_allow(Packet) of
|
||||
true ->
|
||||
ejabberd_hooks:run_fold(offline_message_hook,
|
||||
LServer, bounce,
|
||||
[From, To, Packet]);
|
||||
[Packet]);
|
||||
false ->
|
||||
Err = xmpp:err_service_unavailable(),
|
||||
ejabberd_router:route_error(To, From, Packet, Err)
|
||||
ejabberd_router:route_error(Packet, Err)
|
||||
end
|
||||
end.
|
||||
|
||||
@ -737,29 +732,28 @@ get_max_user_sessions(LUser, Host) ->
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
-spec process_iq(jid(), jid(), iq()) -> any().
|
||||
process_iq(From, To, #iq{type = T, lang = Lang, sub_els = [El]} = Packet)
|
||||
-spec process_iq(iq()) -> any().
|
||||
process_iq(#iq{to = To, type = T, lang = Lang, sub_els = [El]} = Packet)
|
||||
when T == get; T == set ->
|
||||
XMLNS = xmpp:get_ns(El),
|
||||
Host = To#jid.lserver,
|
||||
case ets:lookup(sm_iqtable, {Host, XMLNS}) of
|
||||
[{_, Module, Function, Opts}] ->
|
||||
gen_iq_handler:handle(Host, Module, Function, Opts,
|
||||
From, To, Packet);
|
||||
gen_iq_handler:handle(Host, Module, Function, Opts, Packet);
|
||||
[] ->
|
||||
Txt = <<"No module is handling this query">>,
|
||||
Err = xmpp:err_service_unavailable(Txt, Lang),
|
||||
ejabberd_router:route_error(To, From, Packet, Err)
|
||||
ejabberd_router:route_error(Packet, Err)
|
||||
end;
|
||||
process_iq(From, To, #iq{type = T, lang = Lang, sub_els = SubEls} = Packet)
|
||||
process_iq(#iq{type = T, lang = Lang, sub_els = SubEls} = Packet)
|
||||
when T == get; T == set ->
|
||||
Txt = case SubEls of
|
||||
[] -> <<"No child elements found">>;
|
||||
_ -> <<"Too many child elements">>
|
||||
end,
|
||||
Err = xmpp:err_bad_request(Txt, Lang),
|
||||
ejabberd_router:route_error(To, From, Packet, Err);
|
||||
process_iq(_From, _To, #iq{}) ->
|
||||
ejabberd_router:route_error(Packet, Err);
|
||||
process_iq(#iq{}) ->
|
||||
ok.
|
||||
|
||||
-spec force_update_presence({binary(), binary()}) -> ok.
|
||||
|
@ -32,7 +32,7 @@
|
||||
-behaviour(gen_server).
|
||||
|
||||
%% API
|
||||
-export([start_link/0, process_command/3, register_hook/1,
|
||||
-export([start_link/0, process_command/1, register_hook/1,
|
||||
process_remote_command/1]).
|
||||
|
||||
-export([init/1, handle_call/3, handle_cast/2,
|
||||
@ -61,28 +61,26 @@ start_link() ->
|
||||
gen_server:start_link({local, ?MODULE}, ?MODULE, Opts,
|
||||
[]).
|
||||
|
||||
-spec process_command(jid(), jid(), stanza()) -> ok.
|
||||
process_command(From, To, Packet) ->
|
||||
-spec process_command(stanza()) -> ok.
|
||||
process_command(#message{from = From, to = To, body = Body}) ->
|
||||
case To of
|
||||
#jid{luser = <<"">>, lresource = <<"watchdog">>} ->
|
||||
case Packet of
|
||||
#message{body = Body} ->
|
||||
LFrom =
|
||||
jid:tolower(jid:remove_resource(From)),
|
||||
case lists:member(LFrom, get_admin_jids()) of
|
||||
true ->
|
||||
BodyText = xmpp:get_text(Body),
|
||||
spawn(fun () ->
|
||||
process_flag(priority, high),
|
||||
process_command1(From, To, BodyText)
|
||||
end),
|
||||
ok;
|
||||
false -> ok
|
||||
end;
|
||||
_ -> ok
|
||||
end;
|
||||
_ -> ok
|
||||
end.
|
||||
#jid{luser = <<"">>, lresource = <<"watchdog">>} ->
|
||||
LFrom = jid:tolower(jid:remove_resource(From)),
|
||||
case lists:member(LFrom, get_admin_jids()) of
|
||||
true ->
|
||||
BodyText = xmpp:get_text(Body),
|
||||
spawn(fun () ->
|
||||
process_flag(priority, high),
|
||||
process_command1(From, To, BodyText)
|
||||
end),
|
||||
ok;
|
||||
false -> ok
|
||||
end;
|
||||
_ ->
|
||||
ok
|
||||
end;
|
||||
process_command(_) ->
|
||||
ok.
|
||||
|
||||
register_hook(Host) ->
|
||||
ejabberd_hooks:add(local_send_to_resource_hook, Host,
|
||||
@ -194,8 +192,9 @@ send_message(From, To, Body) ->
|
||||
send_message(From, To, Body, []).
|
||||
|
||||
send_message(From, To, Body, ExtraEls) ->
|
||||
ejabberd_router:route(From, To,
|
||||
#message{type = chat,
|
||||
ejabberd_router:route(#message{type = chat,
|
||||
from = From,
|
||||
to = To,
|
||||
body = xmpp:mk_text(Body),
|
||||
sub_els = ExtraEls}).
|
||||
|
||||
|
@ -34,8 +34,8 @@
|
||||
|
||||
%% API
|
||||
-export([start_link/3, add_iq_handler/6,
|
||||
remove_iq_handler/3, stop_iq_handler/3, handle/7,
|
||||
process_iq/6, check_type/1, transform_module_options/1]).
|
||||
remove_iq_handler/3, stop_iq_handler/3, handle/5,
|
||||
process_iq/4, check_type/1, transform_module_options/1]).
|
||||
|
||||
%% gen_server callbacks
|
||||
-export([init/1, handle_call/3, handle_cast/2,
|
||||
@ -110,38 +110,38 @@ stop_iq_handler(_Module, _Function, Opts) ->
|
||||
_ -> ok
|
||||
end.
|
||||
|
||||
-spec handle(binary(), atom(), atom(), opts(), jid(), jid(), iq()) -> any().
|
||||
-spec handle(binary(), atom(), atom(), opts(), iq()) -> any().
|
||||
|
||||
handle(Host, Module, Function, Opts, From, To, IQ) ->
|
||||
handle(Host, Module, Function, Opts, IQ) ->
|
||||
case Opts of
|
||||
no_queue ->
|
||||
process_iq(Host, Module, Function, From, To, IQ);
|
||||
process_iq(Host, Module, Function, IQ);
|
||||
{one_queue, Pid} ->
|
||||
Pid ! {process_iq, From, To, IQ};
|
||||
Pid ! {process_iq, IQ};
|
||||
{queues, Pids} ->
|
||||
Pid = lists:nth(erlang:phash(p1_time_compat:unique_integer(),
|
||||
length(Pids)), Pids),
|
||||
Pid ! {process_iq, From, To, IQ};
|
||||
Pid ! {process_iq, IQ};
|
||||
parallel ->
|
||||
spawn(?MODULE, process_iq,
|
||||
[Host, Module, Function, From, To, IQ]);
|
||||
spawn(?MODULE, process_iq, [Host, Module, Function, IQ]);
|
||||
_ -> todo
|
||||
end.
|
||||
|
||||
-spec process_iq(binary(), atom(), atom(), jid(), jid(), iq()) -> any().
|
||||
-spec process_iq(binary(), atom(), atom(), iq()) -> any().
|
||||
|
||||
process_iq(_Host, Module, Function, From, To, IQ0) ->
|
||||
IQ = xmpp:set_from_to(IQ0, From, To),
|
||||
process_iq(_Host, Module, Function, IQ) ->
|
||||
try
|
||||
ResIQ = case erlang:function_exported(Module, Function, 1) of
|
||||
true ->
|
||||
process_iq(Module, Function, IQ);
|
||||
false ->
|
||||
From = xmpp:get_from(IQ),
|
||||
To = xmpp:get_to(IQ),
|
||||
process_iq(Module, Function, From, To,
|
||||
jlib:iq_query_info(xmpp:encode(IQ)))
|
||||
end,
|
||||
if ResIQ /= ignore ->
|
||||
ejabberd_router:route(To, From, ResIQ);
|
||||
ejabberd_router:route(ResIQ);
|
||||
true ->
|
||||
ok
|
||||
end
|
||||
@ -150,7 +150,7 @@ process_iq(_Host, Module, Function, From, To, IQ0) ->
|
||||
[xmpp:pp(IQ), {E, {R, erlang:get_stacktrace()}}]),
|
||||
Txt = <<"Module failed to handle the query">>,
|
||||
Err = xmpp:err_internal_server_error(Txt, IQ#iq.lang),
|
||||
ejabberd_router:route_error(To, From, IQ, Err)
|
||||
ejabberd_router:route_error(IQ, Err)
|
||||
end.
|
||||
|
||||
-spec process_iq(module(), atom(), iq()) -> ignore | iq().
|
||||
@ -170,7 +170,10 @@ process_iq(Module, Function, #iq{lang = Lang, sub_els = [El]} = IQ) ->
|
||||
process_iq(Module, Function, From, To, IQ) ->
|
||||
case Module:Function(From, To, IQ) of
|
||||
ignore |