mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +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).
|
State, Receivers ++ ShapedReceivers).
|
||||||
|
|
||||||
bounce_els_from_obuf(State) ->
|
bounce_els_from_obuf(State) ->
|
||||||
lists:foreach(fun ({xmlstreamelement, El}) ->
|
lists:foreach(
|
||||||
case El of
|
fun({xmlstreamelement, El}) ->
|
||||||
#xmlel{name = Name, attrs = Attrs}
|
try xmpp:decode(El, ?NS_CLIENT, [ignore_els]) of
|
||||||
when Name == <<"presence">>;
|
Pkt when ?is_stanza(Pkt) ->
|
||||||
Name == <<"message">>;
|
case {xmpp:get_from(Pkt), xmpp:get_to(Pkt)} of
|
||||||
Name == <<"iq">> ->
|
{#jid{}, #jid{}} ->
|
||||||
FromS = fxml:get_attr_s(<<"from">>, Attrs),
|
ejabberd_router:route(Pkt);
|
||||||
ToS = fxml:get_attr_s(<<"to">>, Attrs),
|
_ ->
|
||||||
case {jid:from_string(FromS),
|
ok
|
||||||
jid:from_string(ToS)}
|
end;
|
||||||
of
|
_ ->
|
||||||
{#jid{} = From, #jid{} = To} ->
|
ok
|
||||||
ejabberd_router:route(From, To, El);
|
catch _:{xmpp_codec, _} ->
|
||||||
_ -> ok
|
ok
|
||||||
end;
|
end;
|
||||||
_ -> ok
|
(_) ->
|
||||||
end;
|
ok
|
||||||
(_) -> ok
|
end, buf_to_list(State#state.el_obuf)).
|
||||||
end,
|
|
||||||
buf_to_list(State#state.el_obuf)).
|
|
||||||
|
|
||||||
is_valid_key(<<"">>, <<"">>) -> true;
|
is_valid_key(<<"">>, <<"">>) -> true;
|
||||||
is_valid_key(PrevKey, Key) ->
|
is_valid_key(PrevKey, Key) ->
|
||||||
|
@ -187,9 +187,7 @@ open_session(#{user := U, server := S, resource := R,
|
|||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% Hooks
|
%%% Hooks
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
process_info(#{lserver := LServer} = State,
|
process_info(#{lserver := LServer} = State, {route, Packet}) ->
|
||||||
{route, From, To, Packet0}) ->
|
|
||||||
Packet = xmpp:set_from_to(Packet0, From, To),
|
|
||||||
{Pass, State1} = case Packet of
|
{Pass, State1} = case Packet of
|
||||||
#presence{} ->
|
#presence{} ->
|
||||||
process_presence_in(State, Packet);
|
process_presence_in(State, Packet);
|
||||||
@ -545,7 +543,7 @@ process_iq_in(State, #iq{} = IQ) ->
|
|||||||
allow ->
|
allow ->
|
||||||
{true, State};
|
{true, State};
|
||||||
deny ->
|
deny ->
|
||||||
route_error(IQ, xmpp:err_service_unavailable()),
|
ejabberd_router:route_error(IQ, xmpp:err_service_unavailable()),
|
||||||
{false, State}
|
{false, State}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -561,7 +559,8 @@ process_message_in(State, #message{type = T} = Msg) ->
|
|||||||
true ->
|
true ->
|
||||||
ok;
|
ok;
|
||||||
false ->
|
false ->
|
||||||
route_error(Msg, xmpp:err_service_unavailable())
|
ejabberd_router:route_error(
|
||||||
|
Msg, xmpp:err_service_unavailable())
|
||||||
end,
|
end,
|
||||||
{false, State}
|
{false, State}
|
||||||
end.
|
end.
|
||||||
@ -611,7 +610,8 @@ route_probe_reply(From, To, #{lserver := LServer, pres_f := PresF,
|
|||||||
%% Don't route a presence probe to oneself
|
%% Don't route a presence probe to oneself
|
||||||
case From == To of
|
case From == To of
|
||||||
false ->
|
false ->
|
||||||
route(xmpp:set_from_to(Packet, To, From));
|
ejabberd_router:route(
|
||||||
|
xmpp:set_from_to(Packet, To, From));
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end
|
end
|
||||||
@ -649,14 +649,14 @@ process_presence_out(#{user := User, server := Server, lserver := LServer,
|
|||||||
LServer,
|
LServer,
|
||||||
[User, Server, To, Type]),
|
[User, Server, To, Type]),
|
||||||
BareFrom = jid:remove_resource(From),
|
BareFrom = jid:remove_resource(From),
|
||||||
route(xmpp:set_from_to(Pres, BareFrom, To)),
|
ejabberd_router:route(xmpp:set_from_to(Pres, BareFrom, To)),
|
||||||
State
|
State
|
||||||
end;
|
end;
|
||||||
allow when Type == error; Type == probe ->
|
allow when Type == error; Type == probe ->
|
||||||
route(Pres),
|
ejabberd_router:route(Pres),
|
||||||
State;
|
State;
|
||||||
allow ->
|
allow ->
|
||||||
route(Pres),
|
ejabberd_router:route(Pres),
|
||||||
A = case Type of
|
A = case Type of
|
||||||
available -> ?SETS:add_element(LTo, PresA);
|
available -> ?SETS:add_element(LTo, PresA);
|
||||||
unavailable -> ?SETS:del_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),
|
Err = xmpp:err_not_acceptable(ErrText, Lang),
|
||||||
xmpp_stream_in:send_error(State, Pkt, Err);
|
xmpp_stream_in:send_error(State, Pkt, Err);
|
||||||
allow ->
|
allow ->
|
||||||
route(Pkt),
|
ejabberd_router:route(Pkt),
|
||||||
State
|
State
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -755,18 +755,6 @@ filter_blocked(#{jid := From} = State, Pres, LJIDSet) ->
|
|||||||
end
|
end
|
||||||
end, [], LJIDSet).
|
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.
|
-spec route_multiple(state(), [jid()], stanza()) -> ok.
|
||||||
route_multiple(#{lserver := LServer}, JIDs, Pkt) ->
|
route_multiple(#{lserver := LServer}, JIDs, Pkt) ->
|
||||||
From = xmpp:get_from(Pkt),
|
From = xmpp:get_from(Pkt),
|
||||||
@ -805,8 +793,8 @@ resource_conflict_action(U, S, R) ->
|
|||||||
|
|
||||||
-spec bounce_message_queue() -> ok.
|
-spec bounce_message_queue() -> ok.
|
||||||
bounce_message_queue() ->
|
bounce_message_queue() ->
|
||||||
receive {route, From, To, Pkt} ->
|
receive {route, Pkt} ->
|
||||||
ejabberd_router:route(From, To, Pkt),
|
ejabberd_router:route(Pkt),
|
||||||
bounce_message_queue()
|
bounce_message_queue()
|
||||||
after 0 ->
|
after 0 ->
|
||||||
ok
|
ok
|
||||||
|
@ -32,11 +32,11 @@
|
|||||||
%% API
|
%% API
|
||||||
-export([start/0, start_link/0]).
|
-export([start/0, start_link/0]).
|
||||||
|
|
||||||
-export([route/3, route_iq/4, route_iq/5, process_iq/3,
|
-export([route/1, route_iq/2, route_iq/3, process_iq/1,
|
||||||
process_iq_reply/3, get_features/1,
|
process_iq_reply/1, get_features/1,
|
||||||
register_iq_handler/5, register_iq_response_handler/4,
|
register_iq_handler/5, register_iq_response_handler/4,
|
||||||
register_iq_response_handler/5, unregister_iq_handler/2,
|
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
|
%% gen_server callbacks
|
||||||
-export([init/1, handle_call/3, handle_cast/2,
|
-export([init/1, handle_call/3, handle_cast/2,
|
||||||
@ -77,55 +77,53 @@ start_link() ->
|
|||||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [],
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [],
|
||||||
[]).
|
[]).
|
||||||
|
|
||||||
-spec process_iq(jid(), jid(), iq()) -> any().
|
-spec process_iq(iq()) -> any().
|
||||||
process_iq(From, To, #iq{type = T, lang = Lang, sub_els = [El]} = Packet)
|
process_iq(#iq{to = To, type = T, lang = Lang, sub_els = [El]} = Packet)
|
||||||
when T == get; T == set ->
|
when T == get; T == set ->
|
||||||
XMLNS = xmpp:get_ns(El),
|
XMLNS = xmpp:get_ns(El),
|
||||||
Host = To#jid.lserver,
|
Host = To#jid.lserver,
|
||||||
case ets:lookup(?IQTABLE, {Host, XMLNS}) of
|
case ets:lookup(?IQTABLE, {Host, XMLNS}) of
|
||||||
[{_, Module, Function, Opts}] ->
|
[{_, Module, Function, Opts}] ->
|
||||||
gen_iq_handler:handle(Host, Module, Function, Opts,
|
gen_iq_handler:handle(Host, Module, Function, Opts, Packet);
|
||||||
From, To, Packet);
|
|
||||||
[] ->
|
[] ->
|
||||||
Txt = <<"No module is handling this query">>,
|
Txt = <<"No module is handling this query">>,
|
||||||
Err = xmpp:err_service_unavailable(Txt, Lang),
|
Err = xmpp:err_service_unavailable(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end;
|
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 ->
|
when T == get; T == set ->
|
||||||
Txt = case SubEls of
|
Txt = case SubEls of
|
||||||
[] -> <<"No child elements found">>;
|
[] -> <<"No child elements found">>;
|
||||||
_ -> <<"Too many child elements">>
|
_ -> <<"Too many child elements">>
|
||||||
end,
|
end,
|
||||||
Err = xmpp:err_bad_request(Txt, Lang),
|
Err = xmpp:err_bad_request(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err);
|
ejabberd_router:route_error(Packet, Err);
|
||||||
process_iq(From, To, #iq{type = T} = Packet) when T == result; T == error ->
|
process_iq(#iq{type = T} = Packet) when T == result; T == error ->
|
||||||
process_iq_reply(From, To, Packet).
|
process_iq_reply(Packet).
|
||||||
|
|
||||||
-spec process_iq_reply(jid(), jid(), iq()) -> any().
|
-spec process_iq_reply(iq()) -> any().
|
||||||
process_iq_reply(From, To, #iq{id = ID} = IQ) ->
|
process_iq_reply(#iq{id = ID} = IQ) ->
|
||||||
case get_iq_callback(ID) of
|
case get_iq_callback(ID) of
|
||||||
{ok, undefined, Function} -> Function(IQ), ok;
|
{ok, undefined, Function} -> Function(IQ), ok;
|
||||||
{ok, Module, Function} ->
|
{ok, Module, Function} ->
|
||||||
Module:Function(From, To, IQ), ok;
|
Module:Function(IQ), ok;
|
||||||
_ -> nothing
|
_ -> nothing
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec route(jid(), jid(), stanza()) -> any().
|
-spec route(stanza()) -> any().
|
||||||
route(From, To, Packet) ->
|
route(Packet) ->
|
||||||
case catch do_route(From, To, Packet) of
|
try do_route(Packet)
|
||||||
{'EXIT', Reason} ->
|
catch E:R ->
|
||||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
?ERROR_MSG("failed to route packet:~n~s~nReason = ~p",
|
||||||
[Reason, {From, To, Packet}]);
|
[xmpp:pp(Packet), {E, {R, erlang:get_stacktrace()}}])
|
||||||
_ -> ok
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec route_iq(jid(), jid(), iq(), function()) -> any().
|
-spec route_iq(iq(), function()) -> any().
|
||||||
route_iq(From, To, IQ, F) ->
|
route_iq(IQ, F) ->
|
||||||
route_iq(From, To, IQ, F, undefined).
|
route_iq(IQ, F, undefined).
|
||||||
|
|
||||||
-spec route_iq(jid(), jid(), iq(), function(), ping_timeout()) -> any().
|
-spec route_iq(iq(), function(), ping_timeout()) -> any().
|
||||||
route_iq(From, To, #iq{type = Type} = IQ, F, Timeout)
|
route_iq(#iq{from = From, type = Type} = IQ, F, Timeout)
|
||||||
when is_function(F) ->
|
when is_function(F) ->
|
||||||
Packet = if Type == set; Type == get ->
|
Packet = if Type == set; Type == get ->
|
||||||
ID = randoms:get_string(),
|
ID = randoms:get_string(),
|
||||||
@ -135,7 +133,7 @@ route_iq(From, To, #iq{type = Type} = IQ, F, Timeout)
|
|||||||
true ->
|
true ->
|
||||||
IQ
|
IQ
|
||||||
end,
|
end,
|
||||||
ejabberd_router:route(From, To, Packet).
|
ejabberd_router:route(Packet).
|
||||||
|
|
||||||
-spec register_iq_response_handler(binary(), binary(), module(),
|
-spec register_iq_response_handler(binary(), binary(), module(),
|
||||||
atom() | function()) -> any().
|
atom() | function()) -> any().
|
||||||
@ -172,17 +170,16 @@ unregister_iq_response_handler(_Host, ID) ->
|
|||||||
unregister_iq_handler(Host, XMLNS) ->
|
unregister_iq_handler(Host, XMLNS) ->
|
||||||
gen_server:cast(?MODULE, {unregister_iq_handler, Host, XMLNS}).
|
gen_server:cast(?MODULE, {unregister_iq_handler, Host, XMLNS}).
|
||||||
|
|
||||||
-spec bounce_resource_packet(jid(), jid(), stanza()) -> stop.
|
-spec bounce_resource_packet(stanza()) -> ok | stop.
|
||||||
bounce_resource_packet(_From, #jid{lresource = <<"">>}, #presence{}) ->
|
bounce_resource_packet(#presence{to = #jid{lresource = <<"">>}}) ->
|
||||||
ok;
|
ok;
|
||||||
bounce_resource_packet(_From, #jid{lresource = <<"">>},
|
bounce_resource_packet(#message{to = #jid{lresource = <<"">>}, type = headline}) ->
|
||||||
#message{type = headline}) ->
|
|
||||||
ok;
|
ok;
|
||||||
bounce_resource_packet(From, To, Packet) ->
|
bounce_resource_packet(Packet) ->
|
||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
Txt = <<"No available resource found">>,
|
Txt = <<"No available resource found">>,
|
||||||
Err = xmpp:err_item_not_found(Txt, Lang),
|
Err = xmpp:err_item_not_found(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err),
|
ejabberd_router:route_error(Packet, Err),
|
||||||
stop.
|
stop.
|
||||||
|
|
||||||
-spec get_features(binary()) -> [binary()].
|
-spec get_features(binary()) -> [binary()].
|
||||||
@ -237,13 +234,8 @@ handle_cast({unregister_iq_handler, Host, XMLNS},
|
|||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_cast(_Msg, State) -> {noreply, State}.
|
handle_cast(_Msg, State) -> {noreply, State}.
|
||||||
|
|
||||||
handle_info({route, From, To, Packet}, State) ->
|
handle_info({route, Packet}, State) ->
|
||||||
case catch do_route(From, To, Packet) of
|
route(Packet),
|
||||||
{'EXIT', Reason} ->
|
|
||||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
|
||||||
[Reason, {From, To, Packet}]);
|
|
||||||
_ -> ok
|
|
||||||
end,
|
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info({timeout, _TRef, ID}, State) ->
|
handle_info({timeout, _TRef, ID}, State) ->
|
||||||
process_iq_timeout(ID),
|
process_iq_timeout(ID),
|
||||||
@ -261,21 +253,20 @@ code_change(_OldVsn, State, _Extra) ->
|
|||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
-spec do_route(jid(), jid(), stanza()) -> any().
|
-spec do_route(stanza()) -> any().
|
||||||
do_route(From, To, Packet) ->
|
do_route(Packet) ->
|
||||||
?DEBUG("local route~n\tfrom ~p~n\tto ~p~n\tpacket "
|
?DEBUG("local route:~n~s", [xmpp:pp(Packet)]),
|
||||||
"~P~n",
|
|
||||||
[From, To, Packet, 8]),
|
|
||||||
Type = xmpp:get_type(Packet),
|
Type = xmpp:get_type(Packet),
|
||||||
|
To = xmpp:get_to(Packet),
|
||||||
if To#jid.luser /= <<"">> ->
|
if To#jid.luser /= <<"">> ->
|
||||||
ejabberd_sm:route(From, To, Packet);
|
ejabberd_sm:route(Packet);
|
||||||
is_record(Packet, iq), To#jid.lresource == <<"">> ->
|
is_record(Packet, iq), To#jid.lresource == <<"">> ->
|
||||||
process_iq(From, To, Packet);
|
process_iq(Packet);
|
||||||
Type == result; Type == error ->
|
Type == result; Type == error ->
|
||||||
ok;
|
ok;
|
||||||
true ->
|
true ->
|
||||||
ejabberd_hooks:run(local_send_to_resource_hook,
|
ejabberd_hooks:run(local_send_to_resource_hook,
|
||||||
To#jid.lserver, [From, To, Packet])
|
To#jid.lserver, [Packet])
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec update_table() -> ok.
|
-spec update_table() -> ok.
|
||||||
|
@ -524,24 +524,19 @@ process_vcard(El, State = #state{user = U, server = S}) ->
|
|||||||
process_offline_msg(#message{from = undefined}, _State) ->
|
process_offline_msg(#message{from = undefined}, _State) ->
|
||||||
stop("No 'from' attribute found", []);
|
stop("No 'from' attribute found", []);
|
||||||
process_offline_msg(Msg, State = #state{user = U, server = S}) ->
|
process_offline_msg(Msg, State = #state{user = U, server = S}) ->
|
||||||
From = xmpp:get_from(Msg),
|
To = jid:make(U, S),
|
||||||
To = jid:make(U, S, <<>>),
|
ejabberd_hooks:run_fold(
|
||||||
NewMsg = xmpp:set_from_to(Msg, From, To),
|
offline_message_hook, To#jid.lserver, pass,
|
||||||
case catch mod_offline:store_packet(pass, From, To, NewMsg) of
|
[xmpp:set_to(Msg, To)]),
|
||||||
{'EXIT', _} = Err ->
|
{ok, State}.
|
||||||
stop("Failed to store offline message: ~p", [Err]);
|
|
||||||
_ ->
|
|
||||||
{ok, State}
|
|
||||||
end.
|
|
||||||
|
|
||||||
-spec process_presence(presence(), state()) -> {ok, state()} | {error, _}.
|
-spec process_presence(presence(), state()) -> {ok, state()} | {error, _}.
|
||||||
process_presence(#presence{from = undefined}, _State) ->
|
process_presence(#presence{from = undefined}, _State) ->
|
||||||
stop("No 'from' attribute found", []);
|
stop("No 'from' attribute found", []);
|
||||||
process_presence(Pres, #state{user = U, server = S} = State) ->
|
process_presence(Pres, #state{user = U, server = S} = State) ->
|
||||||
From = xmpp:get_from(Pres),
|
To = jid:make(U, S),
|
||||||
To = jid:make(U, S, <<>>),
|
NewPres = xmpp:set_to(Pres, To),
|
||||||
NewPres = xmpp:set_from_to(Pres, From, To),
|
ejabberd_router:route(NewPres),
|
||||||
ejabberd_router:route(From, To, NewPres),
|
|
||||||
{ok, State}.
|
{ok, State}.
|
||||||
|
|
||||||
stop(Fmt, Args) ->
|
stop(Fmt, Args) ->
|
||||||
|
@ -35,13 +35,13 @@
|
|||||||
-behaviour(?GEN_SERVER).
|
-behaviour(?GEN_SERVER).
|
||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([route/3,
|
-export([route/1,
|
||||||
route_error/4,
|
route_error/2,
|
||||||
register_route/2,
|
register_route/2,
|
||||||
register_route/3,
|
register_route/3,
|
||||||
register_routes/1,
|
register_routes/1,
|
||||||
host_of_route/1,
|
host_of_route/1,
|
||||||
process_iq/3,
|
process_iq/1,
|
||||||
unregister_route/1,
|
unregister_route/1,
|
||||||
unregister_routes/1,
|
unregister_routes/1,
|
||||||
get_all_routes/0,
|
get_all_routes/0,
|
||||||
@ -54,6 +54,10 @@
|
|||||||
-export([init/1, handle_call/3, handle_cast/2,
|
-export([init/1, handle_call/3, handle_cast/2,
|
||||||
handle_info/2, terminate/2, code_change/3, opt_type/1]).
|
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("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
-include("ejabberd_router.hrl").
|
-include("ejabberd_router.hrl").
|
||||||
@ -82,6 +86,14 @@ start() ->
|
|||||||
start_link() ->
|
start_link() ->
|
||||||
?GEN_SERVER:start_link({local, ?MODULE}, ?MODULE, [], []).
|
?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.
|
-spec route(jid(), jid(), xmlel() | stanza()) -> ok.
|
||||||
route(#jid{} = From, #jid{} = To, #xmlel{} = El) ->
|
route(#jid{} = From, #jid{} = To, #xmlel{} = El) ->
|
||||||
try xmpp:decode(El, ?NS_CLIENT, [ignore_els]) of
|
try xmpp:decode(El, ?NS_CLIENT, [ignore_els]) of
|
||||||
@ -93,7 +105,7 @@ route(#jid{} = From, #jid{} = To, #xmlel{} = El) ->
|
|||||||
xmpp:format_error(Why)])
|
xmpp:format_error(Why)])
|
||||||
end;
|
end;
|
||||||
route(#jid{} = From, #jid{} = To, Packet) ->
|
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} ->
|
{'EXIT', Reason} ->
|
||||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
?ERROR_MSG("~p~nwhen processing: ~p",
|
||||||
[Reason, {From, To, Packet}]);
|
[Reason, {From, To, Packet}]);
|
||||||
@ -101,6 +113,15 @@ route(#jid{} = From, #jid{} = To, Packet) ->
|
|||||||
ok
|
ok
|
||||||
end.
|
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.
|
%% Route the error packet only if the originating packet is not an error itself.
|
||||||
%% RFC3920 9.3.1
|
%% RFC3920 9.3.1
|
||||||
-spec route_error(jid(), jid(), xmlel(), xmlel()) -> ok;
|
-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 ->
|
if Type == error; Type == result ->
|
||||||
ok;
|
ok;
|
||||||
true ->
|
true ->
|
||||||
ejabberd_router:route(From, To, xmpp:make_error(Packet, Err))
|
route(From, To, xmpp:make_error(Packet, Err))
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec register_route(binary(), binary()) -> ok.
|
-spec register_route(binary(), binary()) -> ok.
|
||||||
@ -208,12 +229,12 @@ is_my_host(Domain) ->
|
|||||||
Mod:is_my_host(LDomain)
|
Mod:is_my_host(LDomain)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec process_iq(jid(), jid(), iq()) -> any().
|
-spec process_iq(iq()) -> any().
|
||||||
process_iq(From, To, #iq{} = IQ) ->
|
process_iq(#iq{to = To} = IQ) ->
|
||||||
if To#jid.luser == <<"">> ->
|
if To#jid.luser == <<"">> ->
|
||||||
ejabberd_local:process_iq(From, To, IQ);
|
ejabberd_local:process_iq(IQ);
|
||||||
true ->
|
true ->
|
||||||
ejabberd_sm:process_iq(From, To, IQ)
|
ejabberd_sm:process_iq(IQ)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
@ -231,13 +252,8 @@ handle_call(_Request, _From, State) ->
|
|||||||
handle_cast(_Msg, State) ->
|
handle_cast(_Msg, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
handle_info({route, From, To, Packet}, State) ->
|
handle_info({route, Packet}, State) ->
|
||||||
case catch do_route(From, To, Packet) of
|
route(Packet),
|
||||||
{'EXIT', Reason} ->
|
|
||||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
|
||||||
[Reason, {From, To, Packet}]);
|
|
||||||
_ -> ok
|
|
||||||
end,
|
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info(Info, State) ->
|
handle_info(Info, State) ->
|
||||||
?ERROR_MSG("unexpected info: ~p", [Info]),
|
?ERROR_MSG("unexpected info: ~p", [Info]),
|
||||||
@ -252,37 +268,39 @@ code_change(_OldVsn, State, _Extra) ->
|
|||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
-spec do_route(jid(), jid(), stanza()) -> any().
|
-spec do_route(stanza()) -> ok.
|
||||||
do_route(OrigFrom, OrigTo, OrigPacket) ->
|
do_route(OrigPacket) ->
|
||||||
?DEBUG("route:~n~s", [xmpp:pp(OrigPacket)]),
|
?DEBUG("route:~n~s", [xmpp:pp(OrigPacket)]),
|
||||||
case ejabberd_hooks:run_fold(filter_packet,
|
case ejabberd_hooks:run_fold(filter_packet, OrigPacket, []) of
|
||||||
{OrigFrom, OrigTo, OrigPacket}, []) of
|
drop ->
|
||||||
{From, To, Packet} ->
|
ok;
|
||||||
|
Packet ->
|
||||||
|
To = xmpp:get_to(Packet),
|
||||||
LDstDomain = To#jid.lserver,
|
LDstDomain = To#jid.lserver,
|
||||||
Mod = get_backend(),
|
Mod = get_backend(),
|
||||||
case Mod:find_routes(LDstDomain) of
|
case Mod:find_routes(LDstDomain) of
|
||||||
[] ->
|
[] ->
|
||||||
ejabberd_s2s:route(From, To, Packet);
|
ejabberd_s2s:route(Packet);
|
||||||
[Route] ->
|
[Route] ->
|
||||||
do_route(From, To, Packet, Route);
|
do_route(Packet, Route);
|
||||||
Routes ->
|
Routes ->
|
||||||
|
From = xmpp:get_from(Packet),
|
||||||
balancing_route(From, To, Packet, Routes)
|
balancing_route(From, To, Packet, Routes)
|
||||||
end;
|
end,
|
||||||
drop ->
|
|
||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec do_route(jid(), jid(), stanza(), #route{}) -> any().
|
-spec do_route(stanza(), #route{}) -> any().
|
||||||
do_route(From, To, Pkt, #route{local_hint = LocalHint,
|
do_route(Pkt, #route{local_hint = LocalHint,
|
||||||
pid = Pid}) when is_pid(Pid) ->
|
pid = Pid}) when is_pid(Pid) ->
|
||||||
case LocalHint of
|
case LocalHint of
|
||||||
{apply, Module, Function} when node(Pid) == node() ->
|
{apply, Module, Function} when node(Pid) == node() ->
|
||||||
Module:Function(From, To, Pkt);
|
Module:Function(Pkt);
|
||||||
_ ->
|
_ ->
|
||||||
Pid ! {route, From, To, Pkt}
|
Pid ! {route, Pkt}
|
||||||
end;
|
end;
|
||||||
do_route(_From, _To, _Pkt, _Route) ->
|
do_route(_Pkt, _Route) ->
|
||||||
drop.
|
ok.
|
||||||
|
|
||||||
-spec balancing_route(jid(), jid(), stanza(), [#route{}]) -> any().
|
-spec balancing_route(jid(), jid(), stanza(), [#route{}]) -> any().
|
||||||
balancing_route(From, To, Packet, Rs) ->
|
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
|
case [R || R <- Rs, node(R#route.pid) == node()] of
|
||||||
[] ->
|
[] ->
|
||||||
R = lists:nth(erlang:phash(Value, length(Rs)), Rs),
|
R = lists:nth(erlang:phash(Value, length(Rs)), Rs),
|
||||||
do_route(From, To, Packet, R);
|
do_route(Packet, R);
|
||||||
LRs ->
|
LRs ->
|
||||||
R = lists:nth(erlang:phash(Value, length(LRs)), LRs),
|
R = lists:nth(erlang:phash(Value, length(LRs)), LRs),
|
||||||
do_route(From, To, Packet, R)
|
do_route(Packet, R)
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
SRs = lists:ukeysort(#route.local_hint, Rs),
|
SRs = lists:ukeysort(#route.local_hint, Rs),
|
||||||
R = lists:nth(erlang:phash(Value, length(SRs)), SRs),
|
R = lists:nth(erlang:phash(Value, length(SRs)), SRs),
|
||||||
do_route(From, To, Packet, R)
|
do_route(Packet, R)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec get_component_number(binary()) -> pos_integer() | undefined.
|
-spec get_component_number(binary()) -> pos_integer() | undefined.
|
||||||
|
@ -66,7 +66,7 @@ start_link() ->
|
|||||||
|
|
||||||
-spec route_multicast(jid(), binary(), [jid()], stanza()) -> ok.
|
-spec route_multicast(jid(), binary(), [jid()], stanza()) -> ok.
|
||||||
route_multicast(From, Domain, Destinations, Packet) ->
|
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} ->
|
{'EXIT', Reason} ->
|
||||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
?ERROR_MSG("~p~nwhen processing: ~p",
|
||||||
[Reason, {From, Domain, Destinations, Packet}]);
|
[Reason, {From, Domain, Destinations, Packet}]);
|
||||||
@ -162,11 +162,11 @@ handle_cast(_Msg, State) ->
|
|||||||
%% {stop, Reason, State}
|
%% {stop, Reason, State}
|
||||||
%% Description: Handling all non call/cast messages
|
%% Description: Handling all non call/cast messages
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
handle_info({route_multicast, From, Domain, Destinations, Packet}, State) ->
|
handle_info({route_multicast, Domain, Destinations, Packet}, State) ->
|
||||||
case catch do_route(From, Domain, Destinations, Packet) of
|
case catch do_route(Domain, Destinations, Packet) of
|
||||||
{'EXIT', Reason} ->
|
{'EXIT', Reason} ->
|
||||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
?ERROR_MSG("~p~nwhen processing: ~p",
|
||||||
[Reason, {From, Domain, Destinations, Packet}]);
|
[Reason, {Domain, Destinations, Packet}]);
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
@ -214,25 +214,21 @@ code_change(_OldVsn, State, _Extra) ->
|
|||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% From = #jid
|
%% From = #jid
|
||||||
%% Destinations = [#jid]
|
%% Destinations = [#jid]
|
||||||
-spec do_route(jid(), binary(), [jid()], stanza()) -> any().
|
-spec do_route(binary(), [jid()], stanza()) -> any().
|
||||||
do_route(From, Domain, Destinations, Packet) ->
|
do_route(Domain, Destinations, Packet) ->
|
||||||
|
?DEBUG("route multicast:~n~s~nDomain: ~s~nDestinations: ~s~n",
|
||||||
?DEBUG("route_multicast~n\tfrom ~s~n\tdomain ~s~n\tdestinations ~p~n\tpacket ~p~n",
|
[xmpp:pp(Packet), Domain,
|
||||||
[jid:to_string(From),
|
str:join([jid:to_string(To) || To <- Destinations], ", ")]),
|
||||||
Domain,
|
|
||||||
[jid:to_string(To) || To <- Destinations],
|
|
||||||
Packet]),
|
|
||||||
|
|
||||||
%% Try to find an appropriate multicast service
|
%% Try to find an appropriate multicast service
|
||||||
case mnesia:dirty_read(route_multicast, Domain) of
|
case mnesia:dirty_read(route_multicast, Domain) of
|
||||||
|
|
||||||
%% If no multicast service is available in this server, send manually
|
%% 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
|
%% If some is available, send the packet using multicast service
|
||||||
Rs when is_list(Rs) ->
|
Rs when is_list(Rs) ->
|
||||||
Pid = pick_multicast_pid(Rs),
|
Pid = pick_multicast_pid(Rs),
|
||||||
Pid ! {route_trusted, From, Destinations, Packet}
|
Pid ! {route_trusted, Destinations, Packet}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec pick_multicast_pid([#route_multicast{}]) -> pid().
|
-spec pick_multicast_pid([#route_multicast{}]) -> pid().
|
||||||
@ -243,6 +239,6 @@ pick_multicast_pid(Rs) ->
|
|||||||
end,
|
end,
|
||||||
(hd(List))#route_multicast.pid.
|
(hd(List))#route_multicast.pid.
|
||||||
|
|
||||||
-spec do_route_normal(jid(), [jid()], stanza()) -> any().
|
-spec do_route_normal([jid()], stanza()) -> any().
|
||||||
do_route_normal(From, Destinations, Packet) ->
|
do_route_normal(Destinations, Packet) ->
|
||||||
[ejabberd_router:route(From, To, Packet) || To <- Destinations].
|
[ejabberd_router:route(xmpp:set_to(Packet, To)) || To <- Destinations].
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
-behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
|
|
||||||
%% API
|
%% 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,
|
get_connections_pids/1, try_register/1,
|
||||||
remove_connection/2, start_connection/2, start_connection/3,
|
remove_connection/2, start_connection/2, start_connection/3,
|
||||||
dirty_get_connections/0, allow_host/2,
|
dirty_get_connections/0, allow_host/2,
|
||||||
@ -90,14 +90,13 @@ start_link() ->
|
|||||||
gen_server:start_link({local, ?MODULE}, ?MODULE, [],
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [],
|
||||||
[]).
|
[]).
|
||||||
|
|
||||||
-spec route(jid(), jid(), xmpp_element()) -> ok.
|
-spec route(stanza()) -> ok.
|
||||||
|
|
||||||
route(From, To, Packet) ->
|
route(Packet) ->
|
||||||
case catch do_route(From, To, Packet) of
|
try do_route(Packet)
|
||||||
{'EXIT', Reason} ->
|
catch E:R ->
|
||||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
?ERROR_MSG("failed to route packet:~n~s~nReason = ~p",
|
||||||
[Reason, {From, To, Packet}]);
|
[xmpp:pp(Packet), {E, {R, erlang:get_stacktrace()}}])
|
||||||
_ -> ok
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
clean_temporarily_blocked_table() ->
|
clean_temporarily_blocked_table() ->
|
||||||
@ -314,13 +313,8 @@ handle_cast(_Msg, State) ->
|
|||||||
handle_info({mnesia_system_event, {mnesia_down, Node}}, State) ->
|
handle_info({mnesia_system_event, {mnesia_down, Node}}, State) ->
|
||||||
clean_table_from_bad_node(Node),
|
clean_table_from_bad_node(Node),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info({route, From, To, Packet}, State) ->
|
handle_info({route, Packet}, State) ->
|
||||||
case catch do_route(From, To, Packet) of
|
route(Packet),
|
||||||
{'EXIT', Reason} ->
|
|
||||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
|
||||||
[Reason, {From, To, Packet}]);
|
|
||||||
_ -> ok
|
|
||||||
end,
|
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info(_Info, State) -> {noreply, State}.
|
handle_info(_Info, State) -> {noreply, State}.
|
||||||
|
|
||||||
@ -348,17 +342,17 @@ clean_table_from_bad_node(Node) ->
|
|||||||
end,
|
end,
|
||||||
mnesia:async_dirty(F).
|
mnesia:async_dirty(F).
|
||||||
|
|
||||||
-spec do_route(jid(), jid(), stanza()) -> ok.
|
-spec do_route(stanza()) -> ok.
|
||||||
do_route(From, To, Packet) ->
|
do_route(Packet) ->
|
||||||
?DEBUG("s2s manager~n\tfrom ~p~n\tto ~p~n\tpacket "
|
?DEBUG("local route:~n~s", [xmpp:pp(Packet)]),
|
||||||
"~P~n",
|
From = xmpp:get_from(Packet),
|
||||||
[From, To, Packet, 8]),
|
To = xmpp:get_to(Packet),
|
||||||
case start_connection(From, To) of
|
case start_connection(From, To) of
|
||||||
{ok, Pid} when is_pid(Pid) ->
|
{ok, Pid} when is_pid(Pid) ->
|
||||||
?DEBUG("sending to process ~p~n", [Pid]),
|
?DEBUG("sending to process ~p~n", [Pid]),
|
||||||
#jid{lserver = MyServer} = From,
|
#jid{lserver = MyServer} = From,
|
||||||
ejabberd_hooks:run(s2s_send_packet, MyServer, [From, To, Packet]),
|
ejabberd_hooks:run(s2s_send_packet, MyServer, [Packet]),
|
||||||
ejabberd_s2s_out:route(Pid, xmpp:set_from_to(Packet, From, To));
|
ejabberd_s2s_out:route(Pid, Packet);
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
Err = case Reason of
|
Err = case Reason of
|
||||||
@ -371,7 +365,7 @@ do_route(From, To, Packet) ->
|
|||||||
internal_server_error ->
|
internal_server_error ->
|
||||||
xmpp:err_internal_server_error()
|
xmpp:err_internal_server_error()
|
||||||
end,
|
end,
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec start_connection(jid(), jid())
|
-spec start_connection(jid(), jid())
|
||||||
|
@ -213,7 +213,7 @@ handle_authenticated_packet(Pkt0, #{ip := {IP, _}} = State) ->
|
|||||||
{Pkt, State1}, []),
|
{Pkt, State1}, []),
|
||||||
case Pkt1 of
|
case Pkt1 of
|
||||||
drop -> ok;
|
drop -> ok;
|
||||||
_ -> ejabberd_router:route(From, To, Pkt1)
|
_ -> ejabberd_router:route(Pkt1)
|
||||||
end,
|
end,
|
||||||
State2;
|
State2;
|
||||||
{error, Err} ->
|
{error, Err} ->
|
||||||
|
@ -330,11 +330,9 @@ bounce_message_queue(State) ->
|
|||||||
|
|
||||||
-spec bounce_packet(xmpp_element(), state()) -> state().
|
-spec bounce_packet(xmpp_element(), state()) -> state().
|
||||||
bounce_packet(Pkt, State) when ?is_stanza(Pkt) ->
|
bounce_packet(Pkt, State) when ?is_stanza(Pkt) ->
|
||||||
From = xmpp:get_from(Pkt),
|
|
||||||
To = xmpp:get_to(Pkt),
|
|
||||||
Lang = xmpp:get_lang(Pkt),
|
Lang = xmpp:get_lang(Pkt),
|
||||||
Err = mk_bounce_error(Lang, State),
|
Err = mk_bounce_error(Lang, State),
|
||||||
ejabberd_router:route_error(To, From, Pkt, Err),
|
ejabberd_router:route_error(Pkt, Err),
|
||||||
State;
|
State;
|
||||||
bounce_packet(_, State) ->
|
bounce_packet(_, State) ->
|
||||||
State.
|
State.
|
||||||
|
@ -190,8 +190,7 @@ handle_authenticated_packet(Pkt0, #{ip := {IP, _}, lang := Lang} = State)
|
|||||||
From = xmpp:get_from(Pkt),
|
From = xmpp:get_from(Pkt),
|
||||||
case check_from(From, State) of
|
case check_from(From, State) of
|
||||||
true ->
|
true ->
|
||||||
To = xmpp:get_to(Pkt),
|
ejabberd_router:route(Pkt),
|
||||||
ejabberd_router:route(From, To, Pkt),
|
|
||||||
State;
|
State;
|
||||||
false ->
|
false ->
|
||||||
Txt = <<"Improper domain part of 'from' attribute">>,
|
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) ->
|
handle_authenticated_packet(_Pkt, State) ->
|
||||||
State.
|
State.
|
||||||
|
|
||||||
handle_info({route, From, To, Packet}, #{access := Access} = State) ->
|
handle_info({route, Packet}, #{access := Access} = State) ->
|
||||||
case acl:match_rule(global, Access, From) of
|
case acl:match_rule(global, Access, xmpp:get_from(Packet)) of
|
||||||
allow ->
|
allow ->
|
||||||
Pkt = xmpp:set_from_to(Packet, From, To),
|
xmpp_stream_in:send(State, Packet);
|
||||||
xmpp_stream_in:send(State, Pkt);
|
|
||||||
deny ->
|
deny ->
|
||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
Err = xmpp:err_not_allowed(<<"Denied by ACL">>, Lang),
|
Err = xmpp:err_not_allowed(<<"Denied by ACL">>, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err),
|
ejabberd_router:route_error(Packet, Err),
|
||||||
State
|
State
|
||||||
end;
|
end;
|
||||||
handle_info(Info, State) ->
|
handle_info(Info, State) ->
|
||||||
|
@ -37,14 +37,14 @@
|
|||||||
%% API
|
%% API
|
||||||
-export([start/0,
|
-export([start/0,
|
||||||
start_link/0,
|
start_link/0,
|
||||||
|
route/1,
|
||||||
route/2,
|
route/2,
|
||||||
route/3,
|
process_iq/1,
|
||||||
process_iq/3,
|
|
||||||
open_session/5,
|
open_session/5,
|
||||||
open_session/6,
|
open_session/6,
|
||||||
close_session/4,
|
close_session/4,
|
||||||
check_in_subscription/6,
|
check_in_subscription/6,
|
||||||
bounce_offline_message/4,
|
bounce_offline_message/2,
|
||||||
disconnect_removed_user/2,
|
disconnect_removed_user/2,
|
||||||
get_user_resources/2,
|
get_user_resources/2,
|
||||||
get_user_present_resources/2,
|
get_user_present_resources/2,
|
||||||
@ -126,14 +126,12 @@ route(To, Term) ->
|
|||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec route(jid(), jid(), stanza()) -> ok.
|
-spec route(stanza()) -> ok.
|
||||||
|
route(Packet) ->
|
||||||
route(From, To, Packet) ->
|
try do_route(Packet), ok
|
||||||
case catch do_route(From, To, Packet) of
|
catch E:R ->
|
||||||
{'EXIT', Reason} ->
|
?ERROR_MSG("failed to route packet:~n~s~nReason = ~p",
|
||||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
[xmpp:pp(Packet), {E, {R, erlang:get_stacktrace()}}])
|
||||||
[Reason, {From, To, Packet}]);
|
|
||||||
_ -> ok
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec open_session(sid(), binary(), binary(), binary(), prio(), info()) -> ok.
|
-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}
|
false -> {stop, false}
|
||||||
end.
|
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),
|
Lang = xmpp:get_lang(Packet),
|
||||||
Txt = <<"User session not found">>,
|
Txt = <<"User session not found">>,
|
||||||
Err = xmpp:err_service_unavailable(Txt, Lang),
|
Err = xmpp:err_service_unavailable(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err),
|
ejabberd_router:route_error(Packet, Err),
|
||||||
{stop, Acc};
|
{stop, Acc};
|
||||||
bounce_offline_message(Acc, _From, _To, _Packet) ->
|
bounce_offline_message(Acc, _Packet) ->
|
||||||
Acc.
|
Acc.
|
||||||
|
|
||||||
-spec disconnect_removed_user(binary(), binary()) -> ok.
|
-spec disconnect_removed_user(binary(), binary()) -> ok.
|
||||||
@ -427,14 +425,8 @@ handle_cast({unregister_iq_handler, Host, XMLNS},
|
|||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_cast(_Msg, State) -> {noreply, State}.
|
handle_cast(_Msg, State) -> {noreply, State}.
|
||||||
|
|
||||||
handle_info({route, From, To, Packet}, State) ->
|
handle_info({route, Packet}, State) ->
|
||||||
case catch do_route(From, To, Packet) of
|
route(Packet),
|
||||||
{'EXIT', Reason} ->
|
|
||||||
?ERROR_MSG("~p~nwhen processing: ~p",
|
|
||||||
[Reason, {From, To, Packet}]);
|
|
||||||
_ ->
|
|
||||||
ok
|
|
||||||
end,
|
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info(Info, State) ->
|
handle_info(Info, State) ->
|
||||||
?WARNING_MSG("unexpected info: ~p", [Info]),
|
?WARNING_MSG("unexpected info: ~p", [Info]),
|
||||||
@ -505,8 +497,8 @@ do_route(To, Term) ->
|
|||||||
Pid ! Term
|
Pid ! Term
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec do_route(jid(), jid(), stanza()) -> any().
|
-spec do_route(stanza()) -> any().
|
||||||
do_route(From, To, #presence{type = T, status = Status} = Packet)
|
do_route(#presence{from = From, to = To, type = T, status = Status} = Packet)
|
||||||
when T == subscribe; T == subscribed; T == unsubscribe; T == unsubscribed ->
|
when T == subscribe; T == subscribed; T == unsubscribe; T == unsubscribed ->
|
||||||
?DEBUG("processing subscription:~n~s", [xmpp:pp(Packet)]),
|
?DEBUG("processing subscription:~n~s", [xmpp:pp(Packet)]),
|
||||||
#jid{user = User, server = Server,
|
#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);
|
Reason = if T == subscribe -> xmpp:get_text(Status);
|
||||||
true -> <<"">>
|
true -> <<"">>
|
||||||
end,
|
end,
|
||||||
case is_privacy_allow(From, To, Packet) andalso
|
case is_privacy_allow(Packet) andalso
|
||||||
ejabberd_hooks:run_fold(
|
ejabberd_hooks:run_fold(
|
||||||
roster_in_subscription,
|
roster_in_subscription,
|
||||||
LServer, false,
|
LServer, false,
|
||||||
@ -525,37 +517,39 @@ do_route(From, To, #presence{type = T, status = Status} = Packet)
|
|||||||
fun(#session{sid = SID, usr = {_, _, R},
|
fun(#session{sid = SID, usr = {_, _, R},
|
||||||
priority = Prio}) when is_integer(Prio) ->
|
priority = Prio}) when is_integer(Prio) ->
|
||||||
Pid = element(2, SID),
|
Pid = element(2, SID),
|
||||||
|
Packet1 = Packet#presence{to = jid:replace_resource(To, R)},
|
||||||
?DEBUG("sending to process ~p:~n~s",
|
?DEBUG("sending to process ~p:~n~s",
|
||||||
[Pid, xmpp:pp(Packet)]),
|
[Pid, xmpp:pp(Packet1)]),
|
||||||
Pid ! {route, From, jid:replace_resource(To, R), Packet};
|
Pid ! {route, Packet1};
|
||||||
(_) ->
|
(_) ->
|
||||||
ok
|
ok
|
||||||
end, online(Mod:get_sessions(LUser, LServer)));
|
end, online(Mod:get_sessions(LUser, LServer)));
|
||||||
false ->
|
false ->
|
||||||
ok
|
ok
|
||||||
end;
|
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)]),
|
?DEBUG("processing presence to bare JID:~n~s", [xmpp:pp(Packet)]),
|
||||||
{LUser, LServer, _} = jid:tolower(To),
|
{LUser, LServer, _} = jid:tolower(To),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({_, R}) ->
|
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));
|
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)]),
|
?DEBUG("processing message to bare JID:~n~s", [xmpp:pp(Packet)]),
|
||||||
if T == chat; T == headline; T == normal; T == groupchat ->
|
if T == chat; T == headline; T == normal; T == groupchat ->
|
||||||
route_message(From, To, Packet, T);
|
route_message(Packet);
|
||||||
true ->
|
true ->
|
||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
ErrTxt = <<"User session not found">>,
|
ErrTxt = <<"User session not found">>,
|
||||||
Err = xmpp:err_service_unavailable(ErrTxt, Lang),
|
Err = xmpp:err_service_unavailable(ErrTxt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end;
|
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)]),
|
?DEBUG("processing IQ to bare JID:~n~s", [xmpp:pp(Packet)]),
|
||||||
process_iq(From, To, Packet);
|
process_iq(Packet);
|
||||||
do_route(From, To, Packet) ->
|
do_route(Packet) ->
|
||||||
?DEBUG("processing packet to full JID:~n~s", [xmpp:pp(Packet)]),
|
?DEBUG("processing packet to full JID:~n~s", [xmpp:pp(Packet)]),
|
||||||
|
To = xmpp:get_to(Packet),
|
||||||
{LUser, LServer, LResource} = jid:tolower(To),
|
{LUser, LServer, LResource} = jid:tolower(To),
|
||||||
Mod = get_sm_backend(LServer),
|
Mod = get_sm_backend(LServer),
|
||||||
case online(Mod:get_sessions(LUser, LServer, LResource)) of
|
case online(Mod:get_sessions(LUser, LServer, LResource)) of
|
||||||
@ -563,7 +557,7 @@ do_route(From, To, Packet) ->
|
|||||||
case Packet of
|
case Packet of
|
||||||
#message{type = T} when T == chat; T == normal;
|
#message{type = T} when T == chat; T == normal;
|
||||||
T == headline; T == groupchat ->
|
T == headline; T == groupchat ->
|
||||||
route_message(From, To, Packet, T);
|
route_message(Packet);
|
||||||
#presence{} ->
|
#presence{} ->
|
||||||
?DEBUG("dropping presence to unavalable resource:~n~s",
|
?DEBUG("dropping presence to unavalable resource:~n~s",
|
||||||
[xmpp:pp(Packet)]);
|
[xmpp:pp(Packet)]);
|
||||||
@ -571,28 +565,29 @@ do_route(From, To, Packet) ->
|
|||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
ErrTxt = <<"User session not found">>,
|
ErrTxt = <<"User session not found">>,
|
||||||
Err = xmpp:err_service_unavailable(ErrTxt, Lang),
|
Err = xmpp:err_service_unavailable(ErrTxt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end;
|
end;
|
||||||
Ss ->
|
Ss ->
|
||||||
Session = lists:max(Ss),
|
Session = lists:max(Ss),
|
||||||
Pid = element(2, Session#session.sid),
|
Pid = element(2, Session#session.sid),
|
||||||
?DEBUG("sending to process ~p:~n~s", [Pid, xmpp:pp(Packet)]),
|
?DEBUG("sending to process ~p:~n~s", [Pid, xmpp:pp(Packet)]),
|
||||||
Pid ! {route, From, To, Packet}
|
Pid ! {route, Packet}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% The default list applies to the user as a whole,
|
%% The default list applies to the user as a whole,
|
||||||
%% and is processed if there is no active list set
|
%% and is processed if there is no active list set
|
||||||
%% for the target session/resource to which a stanza is addressed,
|
%% for the target session/resource to which a stanza is addressed,
|
||||||
%% or if there are no current sessions for the user.
|
%% or if there are no current sessions for the user.
|
||||||
-spec is_privacy_allow(jid(), jid(), stanza()) -> boolean().
|
-spec is_privacy_allow(stanza()) -> boolean().
|
||||||
is_privacy_allow(From, To, Packet) ->
|
is_privacy_allow(Packet) ->
|
||||||
|
To = xmpp:get_to(Packet),
|
||||||
LServer = To#jid.server,
|
LServer = To#jid.server,
|
||||||
allow == ejabberd_hooks:run_fold(
|
allow == ejabberd_hooks:run_fold(
|
||||||
privacy_check_packet, LServer, allow,
|
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().
|
-spec route_message(message()) -> any().
|
||||||
route_message(From, To, Packet, Type) ->
|
route_message(#message{to = To, type = Type} = Packet) ->
|
||||||
LUser = To#jid.luser,
|
LUser = To#jid.luser,
|
||||||
LServer = To#jid.lserver,
|
LServer = To#jid.lserver,
|
||||||
PrioRes = get_user_present_resources(LUser, LServer),
|
PrioRes = get_user_present_resources(LUser, LServer),
|
||||||
@ -616,7 +611,7 @@ route_message(From, To, Packet, Type) ->
|
|||||||
LResource,
|
LResource,
|
||||||
LMaxRes,
|
LMaxRes,
|
||||||
P, MaxPrio),
|
P, MaxPrio),
|
||||||
Pid ! {route, From, To, Packet1}
|
Pid ! {route, Packet1}
|
||||||
end;
|
end;
|
||||||
%% Ignore other priority:
|
%% Ignore other priority:
|
||||||
({_Prio, _Res}) -> ok
|
({_Prio, _Res}) -> ok
|
||||||
@ -624,14 +619,14 @@ route_message(From, To, Packet, Type) ->
|
|||||||
PrioRes);
|
PrioRes);
|
||||||
_ ->
|
_ ->
|
||||||
case ejabberd_auth:is_user_exists(LUser, LServer) andalso
|
case ejabberd_auth:is_user_exists(LUser, LServer) andalso
|
||||||
is_privacy_allow(From, To, Packet) of
|
is_privacy_allow(Packet) of
|
||||||
true ->
|
true ->
|
||||||
ejabberd_hooks:run_fold(offline_message_hook,
|
ejabberd_hooks:run_fold(offline_message_hook,
|
||||||
LServer, bounce,
|
LServer, bounce,
|
||||||
[From, To, Packet]);
|
[Packet]);
|
||||||
false ->
|
false ->
|
||||||
Err = xmpp:err_service_unavailable(),
|
Err = xmpp:err_service_unavailable(),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -737,29 +732,28 @@ get_max_user_sessions(LUser, Host) ->
|
|||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
-spec process_iq(jid(), jid(), iq()) -> any().
|
-spec process_iq(iq()) -> any().
|
||||||
process_iq(From, To, #iq{type = T, lang = Lang, sub_els = [El]} = Packet)
|
process_iq(#iq{to = To, type = T, lang = Lang, sub_els = [El]} = Packet)
|
||||||
when T == get; T == set ->
|
when T == get; T == set ->
|
||||||
XMLNS = xmpp:get_ns(El),
|
XMLNS = xmpp:get_ns(El),
|
||||||
Host = To#jid.lserver,
|
Host = To#jid.lserver,
|
||||||
case ets:lookup(sm_iqtable, {Host, XMLNS}) of
|
case ets:lookup(sm_iqtable, {Host, XMLNS}) of
|
||||||
[{_, Module, Function, Opts}] ->
|
[{_, Module, Function, Opts}] ->
|
||||||
gen_iq_handler:handle(Host, Module, Function, Opts,
|
gen_iq_handler:handle(Host, Module, Function, Opts, Packet);
|
||||||
From, To, Packet);
|
|
||||||
[] ->
|
[] ->
|
||||||
Txt = <<"No module is handling this query">>,
|
Txt = <<"No module is handling this query">>,
|
||||||
Err = xmpp:err_service_unavailable(Txt, Lang),
|
Err = xmpp:err_service_unavailable(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end;
|
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 ->
|
when T == get; T == set ->
|
||||||
Txt = case SubEls of
|
Txt = case SubEls of
|
||||||
[] -> <<"No child elements found">>;
|
[] -> <<"No child elements found">>;
|
||||||
_ -> <<"Too many child elements">>
|
_ -> <<"Too many child elements">>
|
||||||
end,
|
end,
|
||||||
Err = xmpp:err_bad_request(Txt, Lang),
|
Err = xmpp:err_bad_request(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err);
|
ejabberd_router:route_error(Packet, Err);
|
||||||
process_iq(_From, _To, #iq{}) ->
|
process_iq(#iq{}) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec force_update_presence({binary(), binary()}) -> ok.
|
-spec force_update_presence({binary(), binary()}) -> ok.
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
-behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
|
|
||||||
%% API
|
%% 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]).
|
process_remote_command/1]).
|
||||||
|
|
||||||
-export([init/1, handle_call/3, handle_cast/2,
|
-export([init/1, handle_call/3, handle_cast/2,
|
||||||
@ -61,28 +61,26 @@ start_link() ->
|
|||||||
gen_server:start_link({local, ?MODULE}, ?MODULE, Opts,
|
gen_server:start_link({local, ?MODULE}, ?MODULE, Opts,
|
||||||
[]).
|
[]).
|
||||||
|
|
||||||
-spec process_command(jid(), jid(), stanza()) -> ok.
|
-spec process_command(stanza()) -> ok.
|
||||||
process_command(From, To, Packet) ->
|
process_command(#message{from = From, to = To, body = Body}) ->
|
||||||
case To of
|
case To of
|
||||||
#jid{luser = <<"">>, lresource = <<"watchdog">>} ->
|
#jid{luser = <<"">>, lresource = <<"watchdog">>} ->
|
||||||
case Packet of
|
LFrom = jid:tolower(jid:remove_resource(From)),
|
||||||
#message{body = Body} ->
|
case lists:member(LFrom, get_admin_jids()) of
|
||||||
LFrom =
|
true ->
|
||||||
jid:tolower(jid:remove_resource(From)),
|
BodyText = xmpp:get_text(Body),
|
||||||
case lists:member(LFrom, get_admin_jids()) of
|
spawn(fun () ->
|
||||||
true ->
|
process_flag(priority, high),
|
||||||
BodyText = xmpp:get_text(Body),
|
process_command1(From, To, BodyText)
|
||||||
spawn(fun () ->
|
end),
|
||||||
process_flag(priority, high),
|
ok;
|
||||||
process_command1(From, To, BodyText)
|
false -> ok
|
||||||
end),
|
end;
|
||||||
ok;
|
_ ->
|
||||||
false -> ok
|
ok
|
||||||
end;
|
end;
|
||||||
_ -> ok
|
process_command(_) ->
|
||||||
end;
|
ok.
|
||||||
_ -> ok
|
|
||||||
end.
|
|
||||||
|
|
||||||
register_hook(Host) ->
|
register_hook(Host) ->
|
||||||
ejabberd_hooks:add(local_send_to_resource_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, []).
|
||||||
|
|
||||||
send_message(From, To, Body, ExtraEls) ->
|
send_message(From, To, Body, ExtraEls) ->
|
||||||
ejabberd_router:route(From, To,
|
ejabberd_router:route(#message{type = chat,
|
||||||
#message{type = chat,
|
from = From,
|
||||||
|
to = To,
|
||||||
body = xmpp:mk_text(Body),
|
body = xmpp:mk_text(Body),
|
||||||
sub_els = ExtraEls}).
|
sub_els = ExtraEls}).
|
||||||
|
|
||||||
|
@ -34,8 +34,8 @@
|
|||||||
|
|
||||||
%% API
|
%% API
|
||||||
-export([start_link/3, add_iq_handler/6,
|
-export([start_link/3, add_iq_handler/6,
|
||||||
remove_iq_handler/3, stop_iq_handler/3, handle/7,
|
remove_iq_handler/3, stop_iq_handler/3, handle/5,
|
||||||
process_iq/6, check_type/1, transform_module_options/1]).
|
process_iq/4, check_type/1, transform_module_options/1]).
|
||||||
|
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
-export([init/1, handle_call/3, handle_cast/2,
|
-export([init/1, handle_call/3, handle_cast/2,
|
||||||
@ -110,38 +110,38 @@ stop_iq_handler(_Module, _Function, Opts) ->
|
|||||||
_ -> ok
|
_ -> ok
|
||||||
end.
|
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
|
case Opts of
|
||||||
no_queue ->
|
no_queue ->
|
||||||
process_iq(Host, Module, Function, From, To, IQ);
|
process_iq(Host, Module, Function, IQ);
|
||||||
{one_queue, Pid} ->
|
{one_queue, Pid} ->
|
||||||
Pid ! {process_iq, From, To, IQ};
|
Pid ! {process_iq, IQ};
|
||||||
{queues, Pids} ->
|
{queues, Pids} ->
|
||||||
Pid = lists:nth(erlang:phash(p1_time_compat:unique_integer(),
|
Pid = lists:nth(erlang:phash(p1_time_compat:unique_integer(),
|
||||||
length(Pids)), Pids),
|
length(Pids)), Pids),
|
||||||
Pid ! {process_iq, From, To, IQ};
|
Pid ! {process_iq, IQ};
|
||||||
parallel ->
|
parallel ->
|
||||||
spawn(?MODULE, process_iq,
|
spawn(?MODULE, process_iq, [Host, Module, Function, IQ]);
|
||||||
[Host, Module, Function, From, To, IQ]);
|
|
||||||
_ -> todo
|
_ -> todo
|
||||||
end.
|
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) ->
|
process_iq(_Host, Module, Function, IQ) ->
|
||||||
IQ = xmpp:set_from_to(IQ0, From, To),
|
|
||||||
try
|
try
|
||||||
ResIQ = case erlang:function_exported(Module, Function, 1) of
|
ResIQ = case erlang:function_exported(Module, Function, 1) of
|
||||||
true ->
|
true ->
|
||||||
process_iq(Module, Function, IQ);
|
process_iq(Module, Function, IQ);
|
||||||
false ->
|
false ->
|
||||||
|
From = xmpp:get_from(IQ),
|
||||||
|
To = xmpp:get_to(IQ),
|
||||||
process_iq(Module, Function, From, To,
|
process_iq(Module, Function, From, To,
|
||||||
jlib:iq_query_info(xmpp:encode(IQ)))
|
jlib:iq_query_info(xmpp:encode(IQ)))
|
||||||
end,
|
end,
|
||||||
if ResIQ /= ignore ->
|
if ResIQ /= ignore ->
|
||||||
ejabberd_router:route(To, From, ResIQ);
|
ejabberd_router:route(ResIQ);
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end
|
end
|
||||||
@ -150,7 +150,7 @@ process_iq(_Host, Module, Function, From, To, IQ0) ->
|
|||||||
[xmpp:pp(IQ), {E, {R, erlang:get_stacktrace()}}]),
|
[xmpp:pp(IQ), {E, {R, erlang:get_stacktrace()}}]),
|
||||||
Txt = <<"Module failed to handle the query">>,
|
Txt = <<"Module failed to handle the query">>,
|
||||||
Err = xmpp:err_internal_server_error(Txt, IQ#iq.lang),
|
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.
|
end.
|
||||||
|
|
||||||
-spec process_iq(module(), atom(), iq()) -> ignore | iq().
|
-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) ->
|
process_iq(Module, Function, From, To, IQ) ->
|
||||||
case Module:Function(From, To, IQ) of
|
case Module:Function(From, To, IQ) of
|
||||||
ignore -> ignore;
|
ignore -> ignore;
|
||||||
ResIQ -> xmpp:decode(jlib:iq_to_xml(ResIQ), ?NS_CLIENT, [ignore_els])
|
ResIQ ->
|
||||||
|
xmpp:set_from_to(
|
||||||
|
xmpp:decode(jlib:iq_to_xml(ResIQ), ?NS_CLIENT, [ignore_els]),
|
||||||
|
To, From)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec check_type(type()) -> type().
|
-spec check_type(type()) -> type().
|
||||||
@ -204,11 +207,11 @@ handle_call(stop, _From, State) ->
|
|||||||
|
|
||||||
handle_cast(_Msg, State) -> {noreply, State}.
|
handle_cast(_Msg, State) -> {noreply, State}.
|
||||||
|
|
||||||
handle_info({process_iq, From, To, IQ},
|
handle_info({process_iq, IQ},
|
||||||
#state{host = Host, module = Module,
|
#state{host = Host, module = Module,
|
||||||
function = Function} =
|
function = Function} =
|
||||||
State) ->
|
State) ->
|
||||||
process_iq(Host, Module, Function, From, To, IQ),
|
process_iq(Host, Module, Function, IQ),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info(_Info, State) -> {noreply, State}.
|
handle_info(_Info, State) -> {noreply, State}.
|
||||||
|
|
||||||
|
@ -156,13 +156,14 @@ process_offline(Server, To, #xmlel{children = Els}) ->
|
|||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(#xmlel{} = El) ->
|
fun(#xmlel{} = El) ->
|
||||||
try xmpp:decode(El, ?NS_CLIENT, [ignore_els]) of
|
try xmpp:decode(El, ?NS_CLIENT, [ignore_els]) of
|
||||||
#message{from = JID} ->
|
#message{from = JID} = Msg ->
|
||||||
From = case JID of
|
From = case JID of
|
||||||
undefined -> jid:make(Server);
|
undefined -> jid:make(Server);
|
||||||
_ -> JID
|
_ -> JID
|
||||||
end,
|
end,
|
||||||
ejabberd_hooks:run_fold(offline_message_hook,
|
ejabberd_hooks:run_fold(
|
||||||
LServer, pass, [From, To, El]);
|
offline_message_hook,
|
||||||
|
LServer, pass, [xmpp:set_from_to(Msg, From, To)]);
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
catch _:{xmpp_codec, Why} ->
|
catch _:{xmpp_codec, Why} ->
|
||||||
|
@ -1037,7 +1037,7 @@ set_presence(User, Host, Resource, Type, Show, Status, Priority0) ->
|
|||||||
show = jlib:binary_to_atom(Show),
|
show = jlib:binary_to_atom(Show),
|
||||||
status = xmpp:mk_text(Status),
|
status = xmpp:mk_text(Status),
|
||||||
priority = Priority},
|
priority = Priority},
|
||||||
Pid ! {route, From, To, Presence},
|
Pid ! {route, Presence},
|
||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -1312,7 +1312,8 @@ push_roster_item(LU, LS, R, U, S, Action) ->
|
|||||||
ejabberd_sm:route(LJID, BroadcastEl),
|
ejabberd_sm:route(LJID, BroadcastEl),
|
||||||
Item = build_roster_item(U, S, Action),
|
Item = build_roster_item(U, S, Action),
|
||||||
ResIQ = build_iq_roster_push(Item),
|
ResIQ = build_iq_roster_push(Item),
|
||||||
ejabberd_router:route(jid:remove_resource(LJID), LJID, ResIQ).
|
ejabberd_router:route(
|
||||||
|
xmpp:set_from_to(ResIQ, jid:remove_resource(LJID), LJID)).
|
||||||
|
|
||||||
build_roster_item(U, S, {add, Nick, Subs, Group}) ->
|
build_roster_item(U, S, {add, Nick, Subs, Group}) ->
|
||||||
Groups = binary:split(Group,<<";">>, [global]),
|
Groups = binary:split(Group,<<";">>, [global]),
|
||||||
@ -1448,7 +1449,7 @@ send_message(Type, From, To, Subject, Body) ->
|
|||||||
FromJID = jid:from_string(From),
|
FromJID = jid:from_string(From),
|
||||||
ToJID = jid:from_string(To),
|
ToJID = jid:from_string(To),
|
||||||
Packet = build_packet(Type, Subject, Body),
|
Packet = build_packet(Type, Subject, Body),
|
||||||
ejabberd_router:route(FromJID, ToJID, Packet).
|
ejabberd_router:route(xmpp:set_from_to(Packet, FromJID, ToJID)).
|
||||||
|
|
||||||
build_packet(Type, Subject, Body) ->
|
build_packet(Type, Subject, Body) ->
|
||||||
#message{type = jlib:binary_to_atom(Type),
|
#message{type = jlib:binary_to_atom(Type),
|
||||||
@ -1461,7 +1462,7 @@ send_stanza(FromString, ToString, Stanza) ->
|
|||||||
#jid{} = From = jid:from_string(FromString),
|
#jid{} = From = jid:from_string(FromString),
|
||||||
#jid{} = To = jid:to_string(ToString),
|
#jid{} = To = jid:to_string(ToString),
|
||||||
Pkt = xmpp:decode(El, ?NS_CLIENT, [ignore_els]),
|
Pkt = xmpp:decode(El, ?NS_CLIENT, [ignore_els]),
|
||||||
ejabberd_router:route(From, To, Pkt)
|
ejabberd_router:route(xmpp:set_from_to(Pkt, From, To))
|
||||||
catch _:{xmpp_codec, Why} ->
|
catch _:{xmpp_codec, Why} ->
|
||||||
io:format("incorrect stanza: ~s~n", [xmpp:format_error(Why)]),
|
io:format("incorrect stanza: ~s~n", [xmpp:format_error(Why)]),
|
||||||
{error, Why};
|
{error, Why};
|
||||||
|
@ -33,12 +33,22 @@
|
|||||||
-behaviour(gen_mod).
|
-behaviour(gen_mod).
|
||||||
|
|
||||||
-export([start/2, stop/1, export/1, import_info/0,
|
-export([start/2, stop/1, export/1, import_info/0,
|
||||||
import_start/2, import/5, announce/3, send_motd/1, disco_identity/5,
|
import_start/2, import/5, announce/1, send_motd/1, disco_identity/5,
|
||||||
disco_features/5, disco_items/5, depends/2,
|
disco_features/5, disco_items/5, depends/2,
|
||||||
send_announcement_to_all/3, announce_commands/4,
|
send_announcement_to_all/3, announce_commands/4,
|
||||||
announce_items/4, mod_opt_type/1]).
|
announce_items/4, mod_opt_type/1]).
|
||||||
-export([init/1, handle_call/3, handle_cast/2,
|
-export([init/1, handle_call/3, handle_cast/2,
|
||||||
handle_info/2, terminate/2, code_change/3]).
|
handle_info/2, terminate/2, code_change/3]).
|
||||||
|
-export([announce_all/1,
|
||||||
|
announce_all_hosts_all/1,
|
||||||
|
announce_online/1,
|
||||||
|
announce_all_hosts_online/1,
|
||||||
|
announce_motd/1,
|
||||||
|
announce_all_hosts_motd/1,
|
||||||
|
announce_motd_update/1,
|
||||||
|
announce_all_hosts_motd_update/1,
|
||||||
|
announce_motd_delete/1,
|
||||||
|
announce_all_hosts_motd_delete/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -94,33 +104,33 @@ init([Host, Opts]) ->
|
|||||||
handle_call(_Call, _From, State) ->
|
handle_call(_Call, _From, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
handle_cast(Msg, State) ->
|
handle_cast({F, #message{from = From, to = To} = Pkt}, State) when is_atom(F) ->
|
||||||
case Msg of
|
LServer = To#jid.lserver,
|
||||||
{announce_all, From, To, Packet} ->
|
Host = case F of
|
||||||
announce_all(From, To, Packet);
|
announce_all -> LServer;
|
||||||
{announce_all_hosts_all, From, To, Packet} ->
|
announce_all_hosts_all -> global;
|
||||||
announce_all_hosts_all(From, To, Packet);
|
announce_online -> LServer;
|
||||||
{announce_online, From, To, Packet} ->
|
announce_all_hosts_online -> global;
|
||||||
announce_online(From, To, Packet);
|
announce_motd -> LServer;
|
||||||
{announce_all_hosts_online, From, To, Packet} ->
|
announce_all_hosts_motd -> global;
|
||||||
announce_all_hosts_online(From, To, Packet);
|
announce_motd_update -> LServer;
|
||||||
{announce_motd, From, To, Packet} ->
|
announce_all_hosts_motd_update -> global;
|
||||||
announce_motd(From, To, Packet);
|
announce_motd_delete -> LServer;
|
||||||
{announce_all_hosts_motd, From, To, Packet} ->
|
announce_all_hosts_motd_delete -> global
|
||||||
announce_all_hosts_motd(From, To, Packet);
|
end,
|
||||||
{announce_motd_update, From, To, Packet} ->
|
Access = get_access(Host),
|
||||||
announce_motd_update(From, To, Packet);
|
case acl:match_rule(Host, Access, From) of
|
||||||
{announce_all_hosts_motd_update, From, To, Packet} ->
|
deny ->
|
||||||
announce_all_hosts_motd_update(From, To, Packet);
|
route_forbidden_error(Pkt);
|
||||||
{announce_motd_delete, From, To, Packet} ->
|
allow ->
|
||||||
announce_motd_delete(From, To, Packet);
|
?MODULE:F(Pkt)
|
||||||
{announce_all_hosts_motd_delete, From, To, Packet} ->
|
|
||||||
announce_all_hosts_motd_delete(From, To, Packet);
|
|
||||||
_ ->
|
|
||||||
?WARNING_MSG("unexpected cast: ~p", [Msg])
|
|
||||||
end,
|
end,
|
||||||
|
{noreply, State};
|
||||||
|
handle_cast(Msg, State) ->
|
||||||
|
?WARNING_MSG("unexpected cast: ~p", [Msg]),
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
|
|
||||||
handle_info(Info, State) ->
|
handle_info(Info, State) ->
|
||||||
?WARNING_MSG("unexpected info: ~p", [Info]),
|
?WARNING_MSG("unexpected info: ~p", [Info]),
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
@ -138,30 +148,30 @@ code_change(_OldVsn, State, _Extra) ->
|
|||||||
{ok, State}.
|
{ok, State}.
|
||||||
|
|
||||||
%% Announcing via messages to a custom resource
|
%% Announcing via messages to a custom resource
|
||||||
-spec announce(jid(), jid(), stanza()) -> ok | stop.
|
-spec announce(stanza()) -> ok | stop.
|
||||||
announce(From, #jid{luser = <<>>} = To, #message{} = Packet) ->
|
announce(#message{to = #jid{luser = <<>>} = To} = Packet) ->
|
||||||
Proc = gen_mod:get_module_proc(To#jid.lserver, ?MODULE),
|
Proc = gen_mod:get_module_proc(To#jid.lserver, ?MODULE),
|
||||||
Res = case To#jid.lresource of
|
Res = case To#jid.lresource of
|
||||||
<<"announce/all">> ->
|
<<"announce/all">> ->
|
||||||
gen_server:cast(Proc, {announce_all, From, To, Packet});
|
gen_server:cast(Proc, {announce_all, Packet});
|
||||||
<<"announce/all-hosts/all">> ->
|
<<"announce/all-hosts/all">> ->
|
||||||
gen_server:cast(Proc, {announce_all_hosts_all, From, To, Packet});
|
gen_server:cast(Proc, {announce_all_hosts_all, Packet});
|
||||||
<<"announce/online">> ->
|
<<"announce/online">> ->
|
||||||
gen_server:cast(Proc, {announce_online, From, To, Packet});
|
gen_server:cast(Proc, {announce_online, Packet});
|
||||||
<<"announce/all-hosts/online">> ->
|
<<"announce/all-hosts/online">> ->
|
||||||
gen_server:cast(Proc, {announce_all_hosts_online, From, To, Packet});
|
gen_server:cast(Proc, {announce_all_hosts_online, Packet});
|
||||||
<<"announce/motd">> ->
|
<<"announce/motd">> ->
|
||||||
gen_server:cast(Proc, {announce_motd, From, To, Packet});
|
gen_server:cast(Proc, {announce_motd, Packet});
|
||||||
<<"announce/all-hosts/motd">> ->
|
<<"announce/all-hosts/motd">> ->
|
||||||
gen_server:cast(Proc, {announce_all_hosts_motd, From, To, Packet});
|
gen_server:cast(Proc, {announce_all_hosts_motd, Packet});
|
||||||
<<"announce/motd/update">> ->
|
<<"announce/motd/update">> ->
|
||||||
gen_server:cast(Proc, {announce_motd_update, From, To, Packet});
|
gen_server:cast(Proc, {announce_motd_update, Packet});
|
||||||
<<"announce/all-hosts/motd/update">> ->
|
<<"announce/all-hosts/motd/update">> ->
|
||||||
gen_server:cast(Proc, {announce_all_hosts_motd_update, From, To, Packet});
|
gen_server:cast(Proc, {announce_all_hosts_motd_update, Packet});
|
||||||
<<"announce/motd/delete">> ->
|
<<"announce/motd/delete">> ->
|
||||||
gen_server:cast(Proc, {announce_motd_delete, From, To, Packet});
|
gen_server:cast(Proc, {announce_motd_delete, Packet});
|
||||||
<<"announce/all-hosts/motd/delete">> ->
|
<<"announce/all-hosts/motd/delete">> ->
|
||||||
gen_server:cast(Proc, {announce_all_hosts_motd_delete, From, To, Packet});
|
gen_server:cast(Proc, {announce_all_hosts_motd_delete, Packet});
|
||||||
_ ->
|
_ ->
|
||||||
undefined
|
undefined
|
||||||
end,
|
end,
|
||||||
@ -169,7 +179,7 @@ announce(From, #jid{luser = <<>>} = To, #message{} = Packet) ->
|
|||||||
ok -> stop;
|
ok -> stop;
|
||||||
_ -> ok
|
_ -> ok
|
||||||
end;
|
end;
|
||||||
announce(_From, _To, _Packet) ->
|
announce(_Packet) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
%%-------------------------------------------------------------------------
|
%%-------------------------------------------------------------------------
|
||||||
@ -521,21 +531,23 @@ handle_adhoc_form(From, #jid{lserver = LServer} = To,
|
|||||||
Body = join_lines(xmpp_util:get_xdata_values(<<"body">>, XData)),
|
Body = join_lines(xmpp_util:get_xdata_values(<<"body">>, XData)),
|
||||||
Response = #adhoc_command{lang = Lang, node = Node, sid = SessionID,
|
Response = #adhoc_command{lang = Lang, node = Node, sid = SessionID,
|
||||||
status = completed},
|
status = completed},
|
||||||
Packet = #message{type = headline,
|
Packet = #message{from = From,
|
||||||
|
to = To,
|
||||||
|
type = headline,
|
||||||
body = xmpp:mk_text(Body),
|
body = xmpp:mk_text(Body),
|
||||||
subject = xmpp:mk_text(Subject)},
|
subject = xmpp:mk_text(Subject)},
|
||||||
Proc = gen_mod:get_module_proc(LServer, ?MODULE),
|
Proc = gen_mod:get_module_proc(LServer, ?MODULE),
|
||||||
case {Node, Body} of
|
case {Node, Body} of
|
||||||
{?NS_ADMIN_DELETE_MOTD, _} ->
|
{?NS_ADMIN_DELETE_MOTD, _} ->
|
||||||
if Confirm ->
|
if Confirm ->
|
||||||
gen_server:cast(Proc, {announce_motd_delete, From, To, Packet}),
|
gen_server:cast(Proc, {announce_motd_delete, Packet}),
|
||||||
Response;
|
Response;
|
||||||
true ->
|
true ->
|
||||||
Response
|
Response
|
||||||
end;
|
end;
|
||||||
{?NS_ADMIN_DELETE_MOTD_ALLHOSTS, _} ->
|
{?NS_ADMIN_DELETE_MOTD_ALLHOSTS, _} ->
|
||||||
if Confirm ->
|
if Confirm ->
|
||||||
gen_server:cast(Proc, {announce_all_hosts_motd_delete, From, To, Packet}),
|
gen_server:cast(Proc, {announce_all_hosts_motd_delete, Packet}),
|
||||||
Response;
|
Response;
|
||||||
true ->
|
true ->
|
||||||
Response
|
Response
|
||||||
@ -549,28 +561,28 @@ handle_adhoc_form(From, #jid{lserver = LServer} = To,
|
|||||||
%% We don't use direct announce_* functions because it
|
%% We don't use direct announce_* functions because it
|
||||||
%% leads to large delay in response and <iq/> queries processing
|
%% leads to large delay in response and <iq/> queries processing
|
||||||
{?NS_ADMIN_ANNOUNCE, _} ->
|
{?NS_ADMIN_ANNOUNCE, _} ->
|
||||||
gen_server:cast(Proc, {announce_online, From, To, Packet}),
|
gen_server:cast(Proc, {announce_online, Packet}),
|
||||||
Response;
|
Response;
|
||||||
{?NS_ADMIN_ANNOUNCE_ALLHOSTS, _} ->
|
{?NS_ADMIN_ANNOUNCE_ALLHOSTS, _} ->
|
||||||
gen_server:cast(Proc, {announce_all_hosts_online, From, To, Packet}),
|
gen_server:cast(Proc, {announce_all_hosts_online, Packet}),
|
||||||
Response;
|
Response;
|
||||||
{?NS_ADMIN_ANNOUNCE_ALL, _} ->
|
{?NS_ADMIN_ANNOUNCE_ALL, _} ->
|
||||||
gen_server:cast(Proc, {announce_all, From, To, Packet}),
|
gen_server:cast(Proc, {announce_all, Packet}),
|
||||||
Response;
|
Response;
|
||||||
{?NS_ADMIN_ANNOUNCE_ALL_ALLHOSTS, _} ->
|
{?NS_ADMIN_ANNOUNCE_ALL_ALLHOSTS, _} ->
|
||||||
gen_server:cast(Proc, {announce_all_hosts_all, From, To, Packet}),
|
gen_server:cast(Proc, {announce_all_hosts_all, Packet}),
|
||||||
Response;
|
Response;
|
||||||
{?NS_ADMIN_SET_MOTD, _} ->
|
{?NS_ADMIN_SET_MOTD, _} ->
|
||||||
gen_server:cast(Proc, {announce_motd, From, To, Packet}),
|
gen_server:cast(Proc, {announce_motd, Packet}),
|
||||||
Response;
|
Response;
|
||||||
{?NS_ADMIN_SET_MOTD_ALLHOSTS, _} ->
|
{?NS_ADMIN_SET_MOTD_ALLHOSTS, _} ->
|
||||||
gen_server:cast(Proc, {announce_all_hosts_motd, From, To, Packet}),
|
gen_server:cast(Proc, {announce_all_hosts_motd, Packet}),
|
||||||
Response;
|
Response;
|
||||||
{?NS_ADMIN_EDIT_MOTD, _} ->
|
{?NS_ADMIN_EDIT_MOTD, _} ->
|
||||||
gen_server:cast(Proc, {announce_motd_update, From, To, Packet}),
|
gen_server:cast(Proc, {announce_motd_update, Packet}),
|
||||||
Response;
|
Response;
|
||||||
{?NS_ADMIN_EDIT_MOTD_ALLHOSTS, _} ->
|
{?NS_ADMIN_EDIT_MOTD_ALLHOSTS, _} ->
|
||||||
gen_server:cast(Proc, {announce_all_hosts_motd_update, From, To, Packet}),
|
gen_server:cast(Proc, {announce_all_hosts_motd_update, Packet}),
|
||||||
Response;
|
Response;
|
||||||
Junk ->
|
Junk ->
|
||||||
%% This can't happen, as we haven't registered any other
|
%% This can't happen, as we haven't registered any other
|
||||||
@ -604,85 +616,46 @@ get_title(Lang, ?NS_ADMIN_DELETE_MOTD_ALLHOSTS) ->
|
|||||||
|
|
||||||
%%-------------------------------------------------------------------------
|
%%-------------------------------------------------------------------------
|
||||||
|
|
||||||
announce_all(From, To, Packet) ->
|
announce_all(#message{to = To} = Packet) ->
|
||||||
Host = To#jid.lserver,
|
Local = jid:make(To#jid.server),
|
||||||
Access = get_access(Host),
|
lists:foreach(
|
||||||
case acl:match_rule(Host, Access, From) of
|
fun({User, Server}) ->
|
||||||
deny ->
|
Dest = jid:make(User, Server, <<>>),
|
||||||
route_forbidden_error(From, To, Packet);
|
ejabberd_router:route(
|
||||||
allow ->
|
xmpp:set_from_to(add_store_hint(Packet), Local, Dest))
|
||||||
Local = jid:make(To#jid.server),
|
end, ejabberd_auth:get_vh_registered_users(To#jid.lserver)).
|
||||||
lists:foreach(
|
|
||||||
fun({User, Server}) ->
|
|
||||||
Dest = jid:make(User, Server, <<>>),
|
|
||||||
ejabberd_router:route(Local, Dest, add_store_hint(Packet))
|
|
||||||
end, ejabberd_auth:get_vh_registered_users(Host))
|
|
||||||
end.
|
|
||||||
|
|
||||||
announce_all_hosts_all(From, To, Packet) ->
|
announce_all_hosts_all(#message{to = To} = Packet) ->
|
||||||
Access = get_access(global),
|
Local = jid:make(To#jid.server),
|
||||||
case acl:match_rule(global, Access, From) of
|
lists:foreach(
|
||||||
deny ->
|
fun({User, Server}) ->
|
||||||
route_forbidden_error(From, To, Packet);
|
Dest = jid:make(User, Server, <<>>),
|
||||||
allow ->
|
ejabberd_router:route(
|
||||||
Local = jid:make(To#jid.server),
|
xmpp:set_from_to(add_store_hint(Packet), Local, Dest))
|
||||||
lists:foreach(
|
end, ejabberd_auth:dirty_get_registered_users()).
|
||||||
fun({User, Server}) ->
|
|
||||||
Dest = jid:make(User, Server, <<>>),
|
|
||||||
ejabberd_router:route(Local, Dest, add_store_hint(Packet))
|
|
||||||
end, ejabberd_auth:dirty_get_registered_users())
|
|
||||||
end.
|
|
||||||
|
|
||||||
announce_online(From, To, Packet) ->
|
announce_online(#message{to = To} = Packet) ->
|
||||||
Host = To#jid.lserver,
|
announce_online1(ejabberd_sm:get_vh_session_list(To#jid.lserver),
|
||||||
Access = get_access(Host),
|
To#jid.server, Packet).
|
||||||
case acl:match_rule(Host, Access, From) of
|
|
||||||
deny ->
|
|
||||||
route_forbidden_error(From, To, Packet);
|
|
||||||
allow ->
|
|
||||||
announce_online1(ejabberd_sm:get_vh_session_list(Host),
|
|
||||||
To#jid.server,
|
|
||||||
Packet)
|
|
||||||
end.
|
|
||||||
|
|
||||||
announce_all_hosts_online(From, To, Packet) ->
|
announce_all_hosts_online(#message{to = To} = Packet) ->
|
||||||
Access = get_access(global),
|
announce_online1(ejabberd_sm:dirty_get_sessions_list(),
|
||||||
case acl:match_rule(global, Access, From) of
|
To#jid.server, Packet).
|
||||||
deny ->
|
|
||||||
route_forbidden_error(From, To, Packet);
|
|
||||||
allow ->
|
|
||||||
announce_online1(ejabberd_sm:dirty_get_sessions_list(),
|
|
||||||
To#jid.server,
|
|
||||||
Packet)
|
|
||||||
end.
|
|
||||||
|
|
||||||
announce_online1(Sessions, Server, Packet) ->
|
announce_online1(Sessions, Server, Packet) ->
|
||||||
Local = jid:make(Server),
|
Local = jid:make(Server),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({U, S, R}) ->
|
fun({U, S, R}) ->
|
||||||
Dest = jid:make(U, S, R),
|
Dest = jid:make(U, S, R),
|
||||||
ejabberd_router:route(Local, Dest, Packet)
|
ejabberd_router:route(xmpp:set_from_to(Packet, Local, Dest))
|
||||||
end, Sessions).
|
end, Sessions).
|
||||||
|
|
||||||
announce_motd(From, To, Packet) ->
|
announce_motd(#message{to = To} = Packet) ->
|
||||||
Host = To#jid.lserver,
|
announce_motd(To#jid.lserver, Packet).
|
||||||
Access = get_access(Host),
|
|
||||||
case acl:match_rule(Host, Access, From) of
|
|
||||||
deny ->
|
|
||||||
route_forbidden_error(From, To, Packet);
|
|
||||||
allow ->
|
|
||||||
announce_motd(Host, Packet)
|
|
||||||
end.
|
|
||||||
|
|
||||||
announce_all_hosts_motd(From, To, Packet) ->
|
announce_all_hosts_motd(Packet) ->
|
||||||
Access = get_access(global),
|
Hosts = ?MYHOSTS,
|
||||||
case acl:match_rule(global, Access, From) of
|
[announce_motd(Host, Packet) || Host <- Hosts].
|
||||||
deny ->
|
|
||||||
route_forbidden_error(From, To, Packet);
|
|
||||||
allow ->
|
|
||||||
Hosts = ?MYHOSTS,
|
|
||||||
[announce_motd(Host, Packet) || Host <- Hosts]
|
|
||||||
end.
|
|
||||||
|
|
||||||
announce_motd(Host, Packet) ->
|
announce_motd(Host, Packet) ->
|
||||||
LServer = jid:nameprep(Host),
|
LServer = jid:nameprep(Host),
|
||||||
@ -692,55 +665,30 @@ announce_motd(Host, Packet) ->
|
|||||||
Mod = gen_mod:db_mod(LServer, ?MODULE),
|
Mod = gen_mod:db_mod(LServer, ?MODULE),
|
||||||
Mod:set_motd_users(LServer, Sessions).
|
Mod:set_motd_users(LServer, Sessions).
|
||||||
|
|
||||||
announce_motd_update(From, To, Packet) ->
|
announce_motd_update(#message{to = To} = Packet) ->
|
||||||
Host = To#jid.lserver,
|
announce_motd_update(To#jid.lserver, Packet).
|
||||||
Access = get_access(Host),
|
|
||||||
case acl:match_rule(Host, Access, From) of
|
|
||||||
deny ->
|
|
||||||
route_forbidden_error(From, To, Packet);
|
|
||||||
allow ->
|
|
||||||
announce_motd_update(Host, Packet)
|
|
||||||
end.
|
|
||||||
|
|
||||||
announce_all_hosts_motd_update(From, To, Packet) ->
|
announce_all_hosts_motd_update(Packet) ->
|
||||||
Access = get_access(global),
|
Hosts = ?MYHOSTS,
|
||||||
case acl:match_rule(global, Access, From) of
|
[announce_motd_update(Host, Packet) || Host <- Hosts].
|
||||||
deny ->
|
|
||||||
route_forbidden_error(From, To, Packet);
|
|
||||||
allow ->
|
|
||||||
Hosts = ?MYHOSTS,
|
|
||||||
[announce_motd_update(Host, Packet) || Host <- Hosts]
|
|
||||||
end.
|
|
||||||
|
|
||||||
announce_motd_update(LServer, Packet) ->
|
announce_motd_update(LServer, Packet) ->
|
||||||
announce_motd_delete(LServer),
|
|
||||||
Mod = gen_mod:db_mod(LServer, ?MODULE),
|
Mod = gen_mod:db_mod(LServer, ?MODULE),
|
||||||
|
Mod:delete_motd(LServer),
|
||||||
Mod:set_motd(LServer, xmpp:encode(Packet)).
|
Mod:set_motd(LServer, xmpp:encode(Packet)).
|
||||||
|
|
||||||
announce_motd_delete(From, To, Packet) ->
|
announce_motd_delete(#message{to = To}) ->
|
||||||
Host = To#jid.lserver,
|
LServer = To#jid.lserver,
|
||||||
Access = get_access(Host),
|
|
||||||
case acl:match_rule(Host, Access, From) of
|
|
||||||
deny ->
|
|
||||||
route_forbidden_error(From, To, Packet);
|
|
||||||
allow ->
|
|
||||||
announce_motd_delete(Host)
|
|
||||||
end.
|
|
||||||
|
|
||||||
announce_all_hosts_motd_delete(From, To, Packet) ->
|
|
||||||
Access = get_access(global),
|
|
||||||
case acl:match_rule(global, Access, From) of
|
|
||||||
deny ->
|
|
||||||
route_forbidden_error(From, To, Packet);
|
|
||||||
allow ->
|
|
||||||
Hosts = ?MYHOSTS,
|
|
||||||
[announce_motd_delete(Host) || Host <- Hosts]
|
|
||||||
end.
|
|
||||||
|
|
||||||
announce_motd_delete(LServer) ->
|
|
||||||
Mod = gen_mod:db_mod(LServer, ?MODULE),
|
Mod = gen_mod:db_mod(LServer, ?MODULE),
|
||||||
Mod:delete_motd(LServer).
|
Mod:delete_motd(LServer).
|
||||||
|
|
||||||
|
announce_all_hosts_motd_delete(_Packet) ->
|
||||||
|
lists:foreach(
|
||||||
|
fun(Host) ->
|
||||||
|
Mod = gen_mod:db_mod(Host, ?MODULE),
|
||||||
|
Mod:delete_motd(Host)
|
||||||
|
end, ?MYHOSTS).
|
||||||
|
|
||||||
-spec send_motd({presence(), ejabberd_c2s:state()}) -> {presence(), ejabberd_c2s:state()}.
|
-spec send_motd({presence(), ejabberd_c2s:state()}) -> {presence(), ejabberd_c2s:state()}.
|
||||||
send_motd({_, #{pres_last := _}} = Acc) ->
|
send_motd({_, #{pres_last := _}} = Acc) ->
|
||||||
%% This is just a presence update, nothing to do
|
%% This is just a presence update, nothing to do
|
||||||
@ -756,7 +704,8 @@ send_motd({#presence{type = available},
|
|||||||
case Mod:is_motd_user(LUser, LServer) of
|
case Mod:is_motd_user(LUser, LServer) of
|
||||||
false ->
|
false ->
|
||||||
Local = jid:make(LServer),
|
Local = jid:make(LServer),
|
||||||
ejabberd_router:route(Local, JID, Msg),
|
ejabberd_router:route(
|
||||||
|
xmpp:set_from_to(Msg, Local, JID)),
|
||||||
Mod:set_motd_user(LUser, LServer);
|
Mod:set_motd_user(LUser, LServer);
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
@ -797,7 +746,8 @@ send_announcement_to_all(Host, SubjectS, BodyS) ->
|
|||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({U, S, R}) ->
|
fun({U, S, R}) ->
|
||||||
Dest = jid:make(U, S, R),
|
Dest = jid:make(U, S, R),
|
||||||
ejabberd_router:route(Local, Dest, add_store_hint(Packet))
|
ejabberd_router:route(
|
||||||
|
xmpp:set_from_to(add_store_hint(Packet), Local, Dest))
|
||||||
end, Sessions).
|
end, Sessions).
|
||||||
|
|
||||||
-spec get_access(global | binary()) -> atom().
|
-spec get_access(global | binary()) -> atom().
|
||||||
@ -811,11 +761,11 @@ get_access(Host) ->
|
|||||||
add_store_hint(El) ->
|
add_store_hint(El) ->
|
||||||
xmpp:set_subtag(El, #hint{type = store}).
|
xmpp:set_subtag(El, #hint{type = store}).
|
||||||
|
|
||||||
-spec route_forbidden_error(jid(), jid(), stanza()) -> ok.
|
-spec route_forbidden_error(stanza()) -> ok.
|
||||||
route_forbidden_error(From, To, Packet) ->
|
route_forbidden_error(Packet) ->
|
||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
Err = xmpp:err_forbidden(<<"Denied by ACL">>, Lang),
|
Err = xmpp:err_forbidden(<<"Denied by ACL">>, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err).
|
ejabberd_router:route_error(Packet, Err).
|
||||||
|
|
||||||
%%-------------------------------------------------------------------------
|
%%-------------------------------------------------------------------------
|
||||||
export(LServer) ->
|
export(LServer) ->
|
||||||
|
@ -235,7 +235,7 @@ broadcast_event(LUser, LServer, Event) ->
|
|||||||
IQ = #iq{type = set, from = From, to = To,
|
IQ = #iq{type = set, from = From, to = To,
|
||||||
id = <<"push", (randoms:get_string())/binary>>,
|
id = <<"push", (randoms:get_string())/binary>>,
|
||||||
sub_els = [Event]},
|
sub_els = [Event]},
|
||||||
ejabberd_router:route(From, To, IQ)
|
ejabberd_router:route(IQ)
|
||||||
end, ejabberd_sm:get_user_resources(LUser, LServer)).
|
end, ejabberd_sm:get_user_resources(LUser, LServer)).
|
||||||
|
|
||||||
-spec process_get(iq()) -> iq().
|
-spec process_get(iq()) -> iq().
|
||||||
|
@ -316,6 +316,8 @@ feature_request(Host, From, Caps,
|
|||||||
end,
|
end,
|
||||||
if NeedRequest ->
|
if NeedRequest ->
|
||||||
IQ = #iq{type = get,
|
IQ = #iq{type = get,
|
||||||
|
from = jid:make(Host),
|
||||||
|
to = From,
|
||||||
sub_els = [#disco_info{node = <<Node/binary, "#",
|
sub_els = [#disco_info{node = <<Node/binary, "#",
|
||||||
SubNode/binary>>}]},
|
SubNode/binary>>}]},
|
||||||
cache_tab:insert(caps_features, NodePair, now_ts(),
|
cache_tab:insert(caps_features, NodePair, now_ts(),
|
||||||
@ -324,9 +326,7 @@ feature_request(Host, From, Caps,
|
|||||||
feature_response(IQReply, Host, From, Caps,
|
feature_response(IQReply, Host, From, Caps,
|
||||||
SubNodes)
|
SubNodes)
|
||||||
end,
|
end,
|
||||||
ejabberd_local:route_iq(jid:make(<<"">>, Host,
|
ejabberd_local:route_iq(IQ, F);
|
||||||
<<"">>),
|
|
||||||
From, IQ, F);
|
|
||||||
true -> feature_request(Host, From, Caps, Tail)
|
true -> feature_request(Host, From, Caps, Tail)
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
@ -212,7 +212,7 @@ send_copies(JID, To, Packet, Direction)->
|
|||||||
Sender = jid:make({U, S, <<>>}),
|
Sender = jid:make({U, S, <<>>}),
|
||||||
%{xmlelement, N, A, C} = Packet,
|
%{xmlelement, N, A, C} = Packet,
|
||||||
New = build_forward_packet(JID, Packet, Sender, Dest, Direction),
|
New = build_forward_packet(JID, Packet, Sender, Dest, Direction),
|
||||||
ejabberd_router:route(Sender, Dest, New)
|
ejabberd_router:route(xmpp:set_from_to(New, Sender, Dest))
|
||||||
end, TargetJIDs),
|
end, TargetJIDs),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ handle_cast({disco_info, Type, Host, NS, Info}, State) ->
|
|||||||
Delegations = dict:store({NS, Type}, {Host, Info}, State#state.delegations),
|
Delegations = dict:store({NS, Type}, {Host, Info}, State#state.delegations),
|
||||||
gen_iq_handler:add_iq_handler(Type, State#state.server_host, NS,
|
gen_iq_handler:add_iq_handler(Type, State#state.server_host, NS,
|
||||||
?MODULE, Type, one_queue),
|
?MODULE, Type, one_queue),
|
||||||
ejabberd_router:route(From, To, Msg),
|
ejabberd_router:route(Msg),
|
||||||
?INFO_MSG("Namespace '~s' is delegated to external component '~s'",
|
?INFO_MSG("Namespace '~s' is delegated to external component '~s'",
|
||||||
[NS, Host]),
|
[NS, Host]),
|
||||||
{noreply, State#state{delegations = Delegations}};
|
{noreply, State#state{delegations = Delegations}};
|
||||||
@ -238,7 +238,6 @@ process_iq(#iq{to = To, lang = Lang, sub_els = [SubEl]} = IQ, Type) ->
|
|||||||
NewFrom = jid:make(LServer),
|
NewFrom = jid:make(LServer),
|
||||||
NewTo = jid:make(Host),
|
NewTo = jid:make(Host),
|
||||||
ejabberd_local:route_iq(
|
ejabberd_local:route_iq(
|
||||||
NewFrom, NewTo,
|
|
||||||
#iq{type = set,
|
#iq{type = set,
|
||||||
from = NewFrom,
|
from = NewFrom,
|
||||||
to = NewTo,
|
to = NewTo,
|
||||||
@ -259,22 +258,22 @@ process_iq_result(#iq{from = From, to = To, id = ID, lang = Lang} = IQ,
|
|||||||
case xmpp:decode(SubEl, ?NS_CLIENT, [ignore_els]) of
|
case xmpp:decode(SubEl, ?NS_CLIENT, [ignore_els]) of
|
||||||
#iq{from = To, to = From, type = Type, id = ID} = Reply
|
#iq{from = To, to = From, type = Type, id = ID} = Reply
|
||||||
when Type == error; Type == result ->
|
when Type == error; Type == result ->
|
||||||
ejabberd_router:route(To, From, Reply)
|
ejabberd_router:route(Reply)
|
||||||
end
|
end
|
||||||
catch _:_ ->
|
catch _:_ ->
|
||||||
?ERROR_MSG("got iq-result with invalid delegated "
|
?ERROR_MSG("got iq-result with invalid delegated "
|
||||||
"payload:~n~s", [xmpp:pp(ResIQ)]),
|
"payload:~n~s", [xmpp:pp(ResIQ)]),
|
||||||
Txt = <<"External component failure">>,
|
Txt = <<"External component failure">>,
|
||||||
Err = xmpp:err_internal_server_error(Txt, Lang),
|
Err = xmpp:err_internal_server_error(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, IQ, Err)
|
ejabberd_router:route_error(IQ, Err)
|
||||||
end;
|
end;
|
||||||
process_iq_result(#iq{from = From, to = To}, #iq{type = error} = ResIQ) ->
|
process_iq_result(#iq{from = From, to = To}, #iq{type = error} = ResIQ) ->
|
||||||
Err = xmpp:set_from_to(ResIQ, To, From),
|
Err = xmpp:set_from_to(ResIQ, To, From),
|
||||||
ejabberd_router:route(To, From, Err);
|
ejabberd_router:route(Err);
|
||||||
process_iq_result(#iq{from = From, to = To, lang = Lang} = IQ, timeout) ->
|
process_iq_result(#iq{lang = Lang} = IQ, timeout) ->
|
||||||
Txt = <<"External component timeout">>,
|
Txt = <<"External component timeout">>,
|
||||||
Err = xmpp:err_internal_server_error(Txt, Lang),
|
Err = xmpp:err_internal_server_error(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, IQ, Err).
|
ejabberd_router:route_error(IQ, Err).
|
||||||
|
|
||||||
-spec send_disco_queries(binary(), binary(), binary()) -> ok.
|
-spec send_disco_queries(binary(), binary(), binary()) -> ok.
|
||||||
send_disco_queries(LServer, Host, NS) ->
|
send_disco_queries(LServer, Host, NS) ->
|
||||||
@ -283,8 +282,8 @@ send_disco_queries(LServer, Host, NS) ->
|
|||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({Type, Node}) ->
|
fun({Type, Node}) ->
|
||||||
ejabberd_local:route_iq(
|
ejabberd_local:route_iq(
|
||||||
From, To, #iq{type = get, from = From, to = To,
|
#iq{type = get, from = From, to = To,
|
||||||
sub_els = [#disco_info{node = Node}]},
|
sub_els = [#disco_info{node = Node}]},
|
||||||
fun(#iq{type = result, sub_els = [SubEl]}) ->
|
fun(#iq{type = result, sub_els = [SubEl]}) ->
|
||||||
try xmpp:decode(SubEl) of
|
try xmpp:decode(SubEl) of
|
||||||
#disco_info{} = Info->
|
#disco_info{} = Info->
|
||||||
|
@ -104,17 +104,20 @@ handle_cast(_Msg, State) -> {noreply, State}.
|
|||||||
%% {stop, Reason, State}
|
%% {stop, Reason, State}
|
||||||
%% Description: Handling all non call/cast messages
|
%% Description: Handling all non call/cast messages
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
handle_info({route, From, To, Packet}, State) ->
|
handle_info({route, Packet}, State) ->
|
||||||
|
From = xmpp:get_from(Packet),
|
||||||
|
To = xmpp:get_to(Packet),
|
||||||
Packet2 = case From#jid.user of
|
Packet2 = case From#jid.user of
|
||||||
<<"">> ->
|
<<"">> ->
|
||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
Txt = <<"User part of JID in 'from' is empty">>,
|
Txt = <<"User part of JID in 'from' is empty">>,
|
||||||
xmpp:make_error(
|
xmpp:make_error(
|
||||||
Packet, xmpp:err_bad_request(Txt, Lang));
|
Packet, xmpp:err_bad_request(Txt, Lang));
|
||||||
_ -> Packet
|
_ ->
|
||||||
|
xmpp:set_from_to(Packet, To, From)
|
||||||
end,
|
end,
|
||||||
do_client_version(disabled, To, From),
|
do_client_version(disabled, To, From),
|
||||||
ejabberd_router:route(To, From, Packet2),
|
ejabberd_router:route(Packet2),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info(_Info, State) -> {noreply, State}.
|
handle_info(_Info, State) -> {noreply, State}.
|
||||||
|
|
||||||
@ -166,13 +169,14 @@ do_client_version(enabled, From, To) ->
|
|||||||
From2 = From#jid{resource = Random_resource,
|
From2 = From#jid{resource = Random_resource,
|
||||||
lresource = Random_resource},
|
lresource = Random_resource},
|
||||||
ID = randoms:get_string(),
|
ID = randoms:get_string(),
|
||||||
Packet = #iq{from = From, to = To, type = get,
|
Packet = #iq{from = From2, to = To, type = get,
|
||||||
id = randoms:get_string(),
|
id = randoms:get_string(),
|
||||||
sub_els = [#version{}]},
|
sub_els = [#version{}]},
|
||||||
ejabberd_router:route(From2, To, Packet),
|
ejabberd_router:route(Packet),
|
||||||
receive
|
receive
|
||||||
{route, To, From2,
|
{route,
|
||||||
#iq{id = ID, type = result, sub_els = [#version{} = V]}} ->
|
#iq{to = To, from = From2,
|
||||||
|
id = ID, type = result, sub_els = [#version{} = V]}} ->
|
||||||
?INFO_MSG("Version of the client ~s:~n~s",
|
?INFO_MSG("Version of the client ~s:~n~s",
|
||||||
[jid:to_string(To), xmpp:pp(V)])
|
[jid:to_string(To), xmpp:pp(V)])
|
||||||
after 5000 -> % Timeout in miliseconds: 5 seconds
|
after 5000 -> % Timeout in miliseconds: 5 seconds
|
||||||
|
@ -339,9 +339,9 @@ handle_cast(Request, State) ->
|
|||||||
|
|
||||||
-spec handle_info(timeout | _, state()) -> {noreply, state()}.
|
-spec handle_info(timeout | _, state()) -> {noreply, state()}.
|
||||||
|
|
||||||
handle_info({route, From, To, #iq{} = Packet}, State) ->
|
handle_info({route, #iq{} = Packet}, State) ->
|
||||||
IQ = xmpp:decode_els(Packet),
|
IQ = xmpp:decode_els(Packet),
|
||||||
{Reply, NewState} = case process_iq(From, IQ, State) of
|
{Reply, NewState} = case process_iq(IQ, State) of
|
||||||
R when is_record(R, iq) ->
|
R when is_record(R, iq) ->
|
||||||
{R, State};
|
{R, State};
|
||||||
{R, S} ->
|
{R, S} ->
|
||||||
@ -350,7 +350,7 @@ handle_info({route, From, To, #iq{} = Packet}, State) ->
|
|||||||
{none, State}
|
{none, State}
|
||||||
end,
|
end,
|
||||||
if Reply /= none ->
|
if Reply /= none ->
|
||||||
ejabberd_router:route(To, From, Reply);
|
ejabberd_router:route(Reply);
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
@ -510,19 +510,18 @@ expand_host(Subject, Host) ->
|
|||||||
|
|
||||||
%% XMPP request handling.
|
%% XMPP request handling.
|
||||||
|
|
||||||
-spec process_iq(jid(), iq(), state()) -> {iq(), state()} | iq() | not_request.
|
-spec process_iq(iq(), state()) -> {iq(), state()} | iq() | not_request.
|
||||||
|
|
||||||
process_iq(_From,
|
process_iq(#iq{type = get, lang = Lang, sub_els = [#disco_info{}]} = IQ,
|
||||||
#iq{type = get, lang = Lang, sub_els = [#disco_info{}]} = IQ,
|
|
||||||
#state{server_host = ServerHost, name = Name}) ->
|
#state{server_host = ServerHost, name = Name}) ->
|
||||||
AddInfo = ejabberd_hooks:run_fold(disco_info, ServerHost, [],
|
AddInfo = ejabberd_hooks:run_fold(disco_info, ServerHost, [],
|
||||||
[ServerHost, ?MODULE, <<"">>, <<"">>]),
|
[ServerHost, ?MODULE, <<"">>, <<"">>]),
|
||||||
xmpp:make_iq_result(IQ, iq_disco_info(ServerHost, Lang, Name, AddInfo));
|
xmpp:make_iq_result(IQ, iq_disco_info(ServerHost, Lang, Name, AddInfo));
|
||||||
process_iq(From, #iq{type = get, lang = Lang,
|
process_iq(#iq{type = get, lang = Lang, from = From,
|
||||||
sub_els = [#upload_request{filename = File,
|
sub_els = [#upload_request{filename = File,
|
||||||
size = Size,
|
size = Size,
|
||||||
'content-type' = CType,
|
'content-type' = CType,
|
||||||
xmlns = XMLNS}]} = IQ,
|
xmlns = XMLNS}]} = IQ,
|
||||||
#state{server_host = ServerHost, access = Access} = State) ->
|
#state{server_host = ServerHost, access = Access} = State) ->
|
||||||
case acl:match_rule(ServerHost, Access, From) of
|
case acl:match_rule(ServerHost, Access, From) of
|
||||||
allow ->
|
allow ->
|
||||||
@ -547,9 +546,9 @@ process_iq(From, #iq{type = get, lang = Lang,
|
|||||||
Txt = <<"Denied by ACL">>,
|
Txt = <<"Denied by ACL">>,
|
||||||
xmpp:make_error(IQ, xmpp:err_forbidden(Txt, Lang))
|
xmpp:make_error(IQ, xmpp:err_forbidden(Txt, Lang))
|
||||||
end;
|
end;
|
||||||
process_iq(_From, #iq{type = T} = IQ, _State) when T == get; T == set ->
|
process_iq(#iq{type = T} = IQ, _State) when T == get; T == set ->
|
||||||
xmpp:make_error(IQ, xmpp:err_not_allowed());
|
xmpp:make_error(IQ, xmpp:err_not_allowed());
|
||||||
process_iq(_From, #iq{}, _State) ->
|
process_iq(#iq{}, _State) ->
|
||||||
not_request.
|
not_request.
|
||||||
|
|
||||||
-spec create_slot(state(), jid(), binary(), pos_integer(), binary(), binary())
|
-spec create_slot(state(), jid(), binary(), pos_integer(), binary(), binary())
|
||||||
|
@ -148,13 +148,11 @@ handle_cast(_Msg, State) -> {noreply, State}.
|
|||||||
%% {stop, Reason, State}
|
%% {stop, Reason, State}
|
||||||
%% Description: Handling all non call/cast messages
|
%% Description: Handling all non call/cast messages
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
handle_info({route, From, To, Packet},
|
handle_info({route, Packet},
|
||||||
#state{host = Host, server_host = ServerHost,
|
#state{host = Host, server_host = ServerHost,
|
||||||
access = Access} =
|
access = Access} =
|
||||||
State) ->
|
State) ->
|
||||||
case catch do_route(Host, ServerHost, Access, From, To,
|
case catch do_route(Host, ServerHost, Access, Packet) of
|
||||||
Packet)
|
|
||||||
of
|
|
||||||
{'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]);
|
{'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]);
|
||||||
_ -> ok
|
_ -> ok
|
||||||
end,
|
end,
|
||||||
@ -200,23 +198,24 @@ stop_supervisor(Host) ->
|
|||||||
supervisor:terminate_child(ejabberd_sup, Proc),
|
supervisor:terminate_child(ejabberd_sup, Proc),
|
||||||
supervisor:delete_child(ejabberd_sup, Proc).
|
supervisor:delete_child(ejabberd_sup, Proc).
|
||||||
|
|
||||||
do_route(Host, ServerHost, Access, From,
|
do_route(Host, ServerHost, Access, Packet) ->
|
||||||
#jid{luser = LUser, lresource = LResource} = To, Packet) ->
|
#jid{luser = LUser, lresource = LResource} = xmpp:get_to(Packet),
|
||||||
|
From = xmpp:get_from(Packet),
|
||||||
case acl:match_rule(ServerHost, Access, From) of
|
case acl:match_rule(ServerHost, Access, From) of
|
||||||
allow ->
|
allow ->
|
||||||
case Packet of
|
case Packet of
|
||||||
#iq{} when LUser == <<"">>, LResource == <<"">> ->
|
#iq{} when LUser == <<"">>, LResource == <<"">> ->
|
||||||
ejabberd_router:process_iq(From, To, Packet);
|
ejabberd_router:process_iq(Packet);
|
||||||
#iq{} when LUser == <<"">>, LResource /= <<"">> ->
|
#iq{} when LUser == <<"">>, LResource /= <<"">> ->
|
||||||
Err = xmpp:err_service_unavailable(),
|
Err = xmpp:err_service_unavailable(),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err);
|
ejabberd_router:route_error(Packet, Err);
|
||||||
_ ->
|
_ ->
|
||||||
sm_route(Host, ServerHost, From, To, Packet)
|
sm_route(Host, ServerHost, Packet)
|
||||||
end;
|
end;
|
||||||
deny ->
|
deny ->
|
||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
Err = xmpp:err_forbidden(<<"Denied by ACL">>, Lang),
|
Err = xmpp:err_forbidden(<<"Denied by ACL">>, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
process_disco_info(#iq{type = set, lang = Lang} = IQ) ->
|
process_disco_info(#iq{type = set, lang = Lang} = IQ) ->
|
||||||
@ -320,8 +319,9 @@ process_command(#iq{type = set, lang = Lang, to = To, from = From,
|
|||||||
xmpp:make_error(IQ, xmpp:err_item_not_found(Txt, Lang))
|
xmpp:make_error(IQ, xmpp:err_item_not_found(Txt, Lang))
|
||||||
end.
|
end.
|
||||||
|
|
||||||
sm_route(Host, ServerHost, From, To, Packet) ->
|
sm_route(Host, ServerHost, Packet) ->
|
||||||
#jid{user = ChanServ, resource = Resource} = To,
|
From = xmpp:get_from(Packet),
|
||||||
|
#jid{user = ChanServ, resource = Resource} = xmpp:get_to(Packet),
|
||||||
case str:tokens(ChanServ, <<"%">>) of
|
case str:tokens(ChanServ, <<"%">>) of
|
||||||
[<<_, _/binary>> = Channel, <<_, _/binary>> = Server] ->
|
[<<_, _/binary>> = Channel, <<_, _/binary>> = Server] ->
|
||||||
case ets:lookup(irc_connection, {From, Server, Host}) of
|
case ets:lookup(irc_connection, {From, Server, Host}) of
|
||||||
@ -368,7 +368,7 @@ sm_route(Host, ServerHost, From, To, Packet) ->
|
|||||||
[] ->
|
[] ->
|
||||||
Txt = <<"IRC connection not found">>,
|
Txt = <<"IRC connection not found">>,
|
||||||
Err = xmpp:err_service_unavailable(Txt, Lang),
|
Err = xmpp:err_service_unavailable(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err);
|
ejabberd_router:route_error(Packet, Err);
|
||||||
[R] ->
|
[R] ->
|
||||||
Pid = R#irc_connection.pid,
|
Pid = R#irc_connection.pid,
|
||||||
?DEBUG("send to process ~p~n", [Pid]),
|
?DEBUG("send to process ~p~n", [Pid]),
|
||||||
@ -377,7 +377,7 @@ sm_route(Host, ServerHost, From, To, Packet) ->
|
|||||||
_ ->
|
_ ->
|
||||||
Txt = <<"Failed to parse chanserv">>,
|
Txt = <<"Failed to parse chanserv">>,
|
||||||
Err = xmpp:err_bad_request(Txt, Lang),
|
Err = xmpp:err_bad_request(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -643,13 +643,14 @@ adhoc_join(From, To, #adhoc_command{lang = Lang, xdata = X} = Request) ->
|
|||||||
BodyTxt = {<<"Join the IRC channel in this Jabber ID: ~s">>,
|
BodyTxt = {<<"Join the IRC channel in this Jabber ID: ~s">>,
|
||||||
[jid:to_string(RoomJID)]},
|
[jid:to_string(RoomJID)]},
|
||||||
Invite = #message{
|
Invite = #message{
|
||||||
|
from = RoomJID, to = From,
|
||||||
body = xmpp:mk_text(BodyTxt, Lang),
|
body = xmpp:mk_text(BodyTxt, Lang),
|
||||||
sub_els = [#muc_user{
|
sub_els = [#muc_user{
|
||||||
invites = [#muc_invite{from = From,
|
invites = [#muc_invite{from = From,
|
||||||
reason = Reason}]},
|
reason = Reason}]},
|
||||||
#x_conference{reason = Reason,
|
#x_conference{reason = Reason,
|
||||||
jid = RoomJID}]},
|
jid = RoomJID}]},
|
||||||
ejabberd_router:route(RoomJID, From, Invite),
|
ejabberd_router:route(Invite),
|
||||||
xmpp_util:make_adhoc_response(
|
xmpp_util:make_adhoc_response(
|
||||||
Request, #adhoc_command{status = completed});
|
Request, #adhoc_command{status = completed});
|
||||||
true ->
|
true ->
|
||||||
|
@ -284,13 +284,13 @@ handle_info({route_chan, Channel, _Resource, #message{type = groupchat} = Msg},
|
|||||||
case xmpp:get_text(Msg#message.subject) of
|
case xmpp:get_text(Msg#message.subject) of
|
||||||
<<"">> ->
|
<<"">> ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(
|
xmpp:set_from_to(
|
||||||
iolist_to_binary([Channel,
|
Msg,
|
||||||
<<"%">>,
|
jid:make(
|
||||||
StateData#state.server]),
|
iolist_to_binary([Channel, <<"%">>, StateData#state.server]),
|
||||||
StateData#state.host,
|
StateData#state.host,
|
||||||
StateData#state.nick),
|
StateData#state.nick),
|
||||||
StateData#state.user, Msg),
|
StateData#state.user)),
|
||||||
Body = xmpp:get_text(Msg#message.body),
|
Body = xmpp:get_text(Msg#message.body),
|
||||||
case Body of
|
case Body of
|
||||||
<<"/quote ", Rest/binary>> ->
|
<<"/quote ", Rest/binary>> ->
|
||||||
@ -401,34 +401,31 @@ handle_info({route_chan, Channel, Resource,
|
|||||||
[Resource]),
|
[Resource]),
|
||||||
_ = (?SEND(Res)),
|
_ = (?SEND(Res)),
|
||||||
Err = xmpp:err_feature_not_implemented(),
|
Err = xmpp:err_feature_not_implemented(),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err);
|
ejabberd_router:route_error(Packet, Err);
|
||||||
?NS_TIME ->
|
?NS_TIME ->
|
||||||
Res = io_lib:format("PRIVMSG ~s :\001TIME\001\r\n",
|
Res = io_lib:format("PRIVMSG ~s :\001TIME\001\r\n",
|
||||||
[Resource]),
|
[Resource]),
|
||||||
_ = (?SEND(Res)),
|
_ = (?SEND(Res)),
|
||||||
Err = xmpp:err_feature_not_implemented(),
|
Err = xmpp:err_feature_not_implemented(),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err);
|
ejabberd_router:route_error(Packet, Err);
|
||||||
?NS_VCARD ->
|
?NS_VCARD ->
|
||||||
Res = io_lib:format("WHOIS ~s \r\n", [Resource]),
|
Res = io_lib:format("WHOIS ~s \r\n", [Resource]),
|
||||||
_ = (?SEND(Res)),
|
_ = (?SEND(Res)),
|
||||||
Err = xmpp:err_feature_not_implemented(),
|
Err = xmpp:err_feature_not_implemented(),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err);
|
ejabberd_router:route_error(Packet, Err);
|
||||||
_ ->
|
_ ->
|
||||||
Err = xmpp:err_feature_not_implemented(),
|
Err = xmpp:err_feature_not_implemented(),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end
|
end
|
||||||
catch _:{xmpp_codec, Why} ->
|
catch _:{xmpp_codec, Why} ->
|
||||||
Err = xmpp:err_bad_request(
|
Err = xmpp:err_bad_request(
|
||||||
xmpp:format_error(Why), xmpp:get_lang(Packet)),
|
xmpp:format_error(Why), xmpp:get_lang(Packet)),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end,
|
end,
|
||||||
{next_state, StateName, StateData};
|
{next_state, StateName, StateData};
|
||||||
handle_info({route_chan, Channel, _, #iq{} = IQ}, StateName, StateData) ->
|
handle_info({route_chan, _Channel, _, #iq{} = IQ}, StateName, StateData) ->
|
||||||
From = StateData#state.user,
|
|
||||||
To = jid:make(iolist_to_binary([Channel, <<"%">>, StateData#state.server]),
|
|
||||||
StateData#state.host, StateData#state.nick),
|
|
||||||
Err = xmpp:err_feature_not_implemented(),
|
Err = xmpp:err_feature_not_implemented(),
|
||||||
ejabberd_router:route_error(To, From, IQ, Err),
|
ejabberd_router:route_error(IQ, Err),
|
||||||
{next_state, StateName, StateData};
|
{next_state, StateName, StateData};
|
||||||
handle_info({route_nick, Nick, #message{type = chat} = Msg},
|
handle_info({route_nick, Nick, #message{type = chat} = Msg},
|
||||||
StateName, StateData) ->
|
StateName, StateData) ->
|
||||||
@ -670,10 +667,12 @@ terminate(_Reason, _StateName, FullStateData) ->
|
|||||||
-spec send_stanza(binary(), state(), stanza()) -> ok.
|
-spec send_stanza(binary(), state(), stanza()) -> ok.
|
||||||
send_stanza(Chan, StateData, Stanza) ->
|
send_stanza(Chan, StateData, Stanza) ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
xmpp:set_from_to(
|
||||||
StateData#state.host,
|
Stanza,
|
||||||
StateData#state.nick),
|
jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
||||||
StateData#state.user, Stanza).
|
StateData#state.host,
|
||||||
|
StateData#state.nick),
|
||||||
|
StateData#state.user)).
|
||||||
|
|
||||||
-spec send_stanza_unavailable(binary(), state()) -> ok.
|
-spec send_stanza_unavailable(binary(), state()) -> ok.
|
||||||
send_stanza_unavailable(Chan, StateData) ->
|
send_stanza_unavailable(Chan, StateData) ->
|
||||||
@ -708,11 +707,9 @@ send_text(#state{socket = Socket, encoding = Encoding},
|
|||||||
bounce_messages(Reason) ->
|
bounce_messages(Reason) ->
|
||||||
receive
|
receive
|
||||||
{send_element, El} ->
|
{send_element, El} ->
|
||||||
From = xmpp:get_from(El),
|
|
||||||
To = xmpp:get_to(El),
|
|
||||||
Lang = xmpp:get_lang(El),
|
Lang = xmpp:get_lang(El),
|
||||||
Err = xmpp:err_internal_server_error(Reason, Lang),
|
Err = xmpp:err_internal_server_error(Reason, Lang),
|
||||||
ejabberd_router:route_error(To, From, El, Err),
|
ejabberd_router:route_error(El, Err),
|
||||||
bounce_messages(Reason)
|
bounce_messages(Reason)
|
||||||
after 0 -> ok
|
after 0 -> ok
|
||||||
end.
|
end.
|
||||||
@ -768,10 +765,10 @@ process_channel_list_user(StateData, Chan, User) ->
|
|||||||
_ -> {User1, member, participant}
|
_ -> {User1, member, participant}
|
||||||
end,
|
end,
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
|
||||||
StateData#state.host, User2),
|
|
||||||
StateData#state.user,
|
|
||||||
#presence{
|
#presence{
|
||||||
|
from = jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
||||||
|
StateData#state.host, User2),
|
||||||
|
to = StateData#state.user,
|
||||||
sub_els = [#muc_user{items = [#muc_item{affiliation = Affiliation,
|
sub_els = [#muc_user{items = [#muc_item{affiliation = Affiliation,
|
||||||
role = Role}]}]}),
|
role = Role}]}]}),
|
||||||
case catch dict:update(Chan,
|
case catch dict:update(Chan,
|
||||||
@ -787,10 +784,10 @@ process_channel_topic(StateData, Chan, String) ->
|
|||||||
Subject = filter_message(Msg),
|
Subject = filter_message(Msg),
|
||||||
Body = <<"Topic for #", Chan/binary, ": ", Subject/binary>>,
|
Body = <<"Topic for #", Chan/binary, ": ", Subject/binary>>,
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
#message{from = jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
||||||
StateData#state.host),
|
StateData#state.host),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
#message{type = groupchat,
|
type = groupchat,
|
||||||
subject = xmpp:mk_text(Subject),
|
subject = xmpp:mk_text(Subject),
|
||||||
body = xmpp:mk_text(Body)}).
|
body = xmpp:mk_text(Body)}).
|
||||||
|
|
||||||
@ -808,10 +805,10 @@ process_channel_topic_who(StateData, Chan, String) ->
|
|||||||
end,
|
end,
|
||||||
Msg2 = filter_message(Msg1),
|
Msg2 = filter_message(Msg1),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
#message{from = jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
||||||
StateData#state.host, <<"">>),
|
StateData#state.host, <<"">>),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
#message{type = groupchat, body = xmpp:mk_text(Msg2)}).
|
type = groupchat, body = xmpp:mk_text(Msg2)}).
|
||||||
|
|
||||||
error_nick_in_use(_StateData, String) ->
|
error_nick_in_use(_StateData, String) ->
|
||||||
Msg = ejabberd_regexp:replace(String,
|
Msg = ejabberd_regexp:replace(String,
|
||||||
@ -827,11 +824,11 @@ process_nick_in_use(StateData, String) ->
|
|||||||
StateData;
|
StateData;
|
||||||
Chan ->
|
Chan ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
#presence{from = jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
||||||
StateData#state.host,
|
StateData#state.host,
|
||||||
StateData#state.nick),
|
StateData#state.nick),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
xmpp:make_error(#presence{}, Error)),
|
type = error, sub_els = [Error]}),
|
||||||
StateData#state{nickchannel = undefined}
|
StateData#state{nickchannel = undefined}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -840,30 +837,30 @@ process_num_error(StateData, String) ->
|
|||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(Chan) ->
|
fun(Chan) ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, $%, StateData#state.server]),
|
#message{from = jid:make(iolist_to_binary([Chan, $%, StateData#state.server]),
|
||||||
StateData#state.host,
|
StateData#state.host,
|
||||||
StateData#state.nick),
|
StateData#state.nick),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
xmpp:make_error(#message{}, Error))
|
type = error, sub_els = [Error]})
|
||||||
end, dict:fetch_keys(StateData#state.channels)),
|
end, dict:fetch_keys(StateData#state.channels)),
|
||||||
StateData.
|
StateData.
|
||||||
|
|
||||||
process_endofwhois(StateData, _String, Nick) ->
|
process_endofwhois(StateData, _String, Nick) ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Nick, <<"!">>, StateData#state.server]),
|
#message{from = jid:make(iolist_to_binary([Nick, <<"!">>, StateData#state.server]),
|
||||||
StateData#state.host),
|
StateData#state.host),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
#message{type = chat, body = xmpp:mk_text(<<"End of WHOIS">>)}).
|
type = chat, body = xmpp:mk_text(<<"End of WHOIS">>)}).
|
||||||
|
|
||||||
process_whois311(StateData, String, Nick, Ident,
|
process_whois311(StateData, String, Nick, Ident,
|
||||||
Irchost) ->
|
Irchost) ->
|
||||||
Fullname = ejabberd_regexp:replace(String,
|
Fullname = ejabberd_regexp:replace(String,
|
||||||
<<".*311[^:]*:">>, <<"">>),
|
<<".*311[^:]*:">>, <<"">>),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Nick, <<"!">>, StateData#state.server]),
|
#message{from = jid:make(iolist_to_binary([Nick, <<"!">>, StateData#state.server]),
|
||||||
StateData#state.host, <<"">>),
|
StateData#state.host, <<"">>),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
#message{type = chat,
|
type = chat,
|
||||||
body = xmpp:mk_text(
|
body = xmpp:mk_text(
|
||||||
iolist_to_binary(
|
iolist_to_binary(
|
||||||
[<<"WHOIS: ">>, Nick, <<" is ">>, Ident,
|
[<<"WHOIS: ">>, Nick, <<" is ">>, Ident,
|
||||||
@ -873,10 +870,10 @@ process_whois312(StateData, String, Nick, Ircserver) ->
|
|||||||
Ircserverdesc = ejabberd_regexp:replace(String,
|
Ircserverdesc = ejabberd_regexp:replace(String,
|
||||||
<<".*312[^:]*:">>, <<"">>),
|
<<".*312[^:]*:">>, <<"">>),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Nick, <<"!">>, StateData#state.server]),
|
#message{from = jid:make(iolist_to_binary([Nick, <<"!">>, StateData#state.server]),
|
||||||
StateData#state.host, <<"">>),
|
StateData#state.host, <<"">>),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
#message{type = chat,
|
type = chat,
|
||||||
body = xmpp:mk_text(
|
body = xmpp:mk_text(
|
||||||
iolist_to_binary(
|
iolist_to_binary(
|
||||||
[<<"WHOIS: ">>, Nick, <<" use ">>, Ircserver,
|
[<<"WHOIS: ">>, Nick, <<" use ">>, Ircserver,
|
||||||
@ -886,10 +883,10 @@ process_whois319(StateData, String, Nick) ->
|
|||||||
Chanlist = ejabberd_regexp:replace(String,
|
Chanlist = ejabberd_regexp:replace(String,
|
||||||
<<".*319[^:]*:">>, <<"">>),
|
<<".*319[^:]*:">>, <<"">>),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Nick, <<"!">>, StateData#state.server]),
|
#message{from = jid:make(iolist_to_binary([Nick, <<"!">>, StateData#state.server]),
|
||||||
StateData#state.host, <<"">>),
|
StateData#state.host, <<"">>),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
#message{type = chat,
|
type = chat,
|
||||||
body = xmpp:mk_text(
|
body = xmpp:mk_text(
|
||||||
iolist_to_binary(
|
iolist_to_binary(
|
||||||
[<<"WHOIS: ">>, Nick, <<" is on ">>, Chanlist]))}).
|
[<<"WHOIS: ">>, Nick, <<" is on ">>, Chanlist]))}).
|
||||||
@ -905,10 +902,10 @@ process_chanprivmsg(StateData, Chan, From, String) ->
|
|||||||
end,
|
end,
|
||||||
Msg2 = filter_message(Msg1),
|
Msg2 = filter_message(Msg1),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
#message{from = jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
||||||
StateData#state.host, FromUser),
|
StateData#state.host, FromUser),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
#message{type = groupchat, body = xmpp:mk_text(Msg2)}).
|
type = groupchat, body = xmpp:mk_text(Msg2)}).
|
||||||
|
|
||||||
process_channotice(StateData, Chan, From, String) ->
|
process_channotice(StateData, Chan, From, String) ->
|
||||||
[FromUser | _] = str:tokens(From, <<"!">>),
|
[FromUser | _] = str:tokens(From, <<"!">>),
|
||||||
@ -921,10 +918,10 @@ process_channotice(StateData, Chan, From, String) ->
|
|||||||
end,
|
end,
|
||||||
Msg2 = filter_message(Msg1),
|
Msg2 = filter_message(Msg1),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
#message{from = jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
||||||
StateData#state.host, FromUser),
|
StateData#state.host, FromUser),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
#message{type = groupchat, body = xmpp:mk_text(Msg2)}).
|
type = groupchat, body = xmpp:mk_text(Msg2)}).
|
||||||
|
|
||||||
process_privmsg(StateData, _Nick, From, String) ->
|
process_privmsg(StateData, _Nick, From, String) ->
|
||||||
[FromUser | _] = str:tokens(From, <<"!">>),
|
[FromUser | _] = str:tokens(From, <<"!">>),
|
||||||
@ -937,10 +934,10 @@ process_privmsg(StateData, _Nick, From, String) ->
|
|||||||
end,
|
end,
|
||||||
Msg2 = filter_message(Msg1),
|
Msg2 = filter_message(Msg1),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([FromUser, <<"!">>, StateData#state.server]),
|
#message{from = jid:make(iolist_to_binary([FromUser, <<"!">>, StateData#state.server]),
|
||||||
StateData#state.host, <<"">>),
|
StateData#state.host, <<"">>),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
#message{type = chat, body = xmpp:mk_text(Msg2)}).
|
type = chat, body = xmpp:mk_text(Msg2)}).
|
||||||
|
|
||||||
process_notice(StateData, _Nick, From, String) ->
|
process_notice(StateData, _Nick, From, String) ->
|
||||||
[FromUser | _] = str:tokens(From, <<"!">>),
|
[FromUser | _] = str:tokens(From, <<"!">>),
|
||||||
@ -953,10 +950,10 @@ process_notice(StateData, _Nick, From, String) ->
|
|||||||
end,
|
end,
|
||||||
Msg2 = filter_message(Msg1),
|
Msg2 = filter_message(Msg1),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([FromUser, <<"!">>, StateData#state.server]),
|
#message{from = jid:make(iolist_to_binary([FromUser, <<"!">>, StateData#state.server]),
|
||||||
StateData#state.host),
|
StateData#state.host),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
#message{type = chat, body = xmpp:mk_text(Msg2)}).
|
type = chat, body = xmpp:mk_text(Msg2)}).
|
||||||
|
|
||||||
process_version(StateData, _Nick, From) ->
|
process_version(StateData, _Nick, From) ->
|
||||||
[FromUser | _] = str:tokens(From, <<"!">>),
|
[FromUser | _] = str:tokens(From, <<"!">>),
|
||||||
@ -982,10 +979,10 @@ process_topic(StateData, Chan, From, String) ->
|
|||||||
<<".*TOPIC[^:]*:">>, <<"">>),
|
<<".*TOPIC[^:]*:">>, <<"">>),
|
||||||
Msg1 = filter_message(Msg),
|
Msg1 = filter_message(Msg),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
#message{from = jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
||||||
StateData#state.host, FromUser),
|
StateData#state.host, FromUser),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
#message{type = groupchat,
|
type = groupchat,
|
||||||
subject = xmpp:mk_text(Msg1),
|
subject = xmpp:mk_text(Msg1),
|
||||||
body = xmpp:mk_text(<<"/me has changed the subject to: ",
|
body = xmpp:mk_text(<<"/me has changed the subject to: ",
|
||||||
Msg1/binary>>)}).
|
Msg1/binary>>)}).
|
||||||
@ -996,10 +993,10 @@ process_part(StateData, Chan, From, String) ->
|
|||||||
<<".*PART[^:]*:">>, <<"">>),
|
<<".*PART[^:]*:">>, <<"">>),
|
||||||
Msg1 = filter_message(Msg),
|
Msg1 = filter_message(Msg),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
#presence{from = jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
||||||
StateData#state.host, FromUser),
|
StateData#state.host, FromUser),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
#presence{type = unavailable,
|
type = unavailable,
|
||||||
sub_els = [#muc_user{
|
sub_els = [#muc_user{
|
||||||
items = [#muc_item{affiliation = member,
|
items = [#muc_item{affiliation = member,
|
||||||
role = none}]}],
|
role = none}]}],
|
||||||
@ -1023,11 +1020,11 @@ process_quit(StateData, From, String) ->
|
|||||||
case (?SETS):is_member(FromUser, Ps) of
|
case (?SETS):is_member(FromUser, Ps) of
|
||||||
true ->
|
true ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, $%, StateData#state.server]),
|
#presence{from = jid:make(iolist_to_binary([Chan, $%, StateData#state.server]),
|
||||||
StateData#state.host,
|
StateData#state.host,
|
||||||
FromUser),
|
FromUser),
|
||||||
StateData#state.user,
|
to = StateData#state.user,
|
||||||
#presence{type = unavailable,
|
type = unavailable,
|
||||||
sub_els = [#muc_user{
|
sub_els = [#muc_user{
|
||||||
items = [#muc_item{
|
items = [#muc_item{
|
||||||
affiliation = member,
|
affiliation = member,
|
||||||
@ -1045,10 +1042,10 @@ process_join(StateData, Channel, From, _String) ->
|
|||||||
[FromUser | FromIdent] = str:tokens(From, <<"!">>),
|
[FromUser | FromIdent] = str:tokens(From, <<"!">>),
|
||||||
[Chan | _] = binary:split(Channel, <<":#">>),
|
[Chan | _] = binary:split(Channel, <<":#">>),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
|
||||||
StateData#state.host, FromUser),
|
|
||||||
StateData#state.user,
|
|
||||||
#presence{
|
#presence{
|
||||||
|
from = jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
||||||
|
StateData#state.host, FromUser),
|
||||||
|
to = StateData#state.user,
|
||||||
sub_els = [#muc_user{items = [#muc_item{affiliation = member,
|
sub_els = [#muc_user{items = [#muc_item{affiliation = member,
|
||||||
role = participant}]}],
|
role = participant}]}],
|
||||||
status = xmpp:mk_text(list_to_binary(FromIdent))}),
|
status = xmpp:mk_text(list_to_binary(FromIdent))}),
|
||||||
@ -1063,10 +1060,10 @@ process_join(StateData, Channel, From, _String) ->
|
|||||||
process_mode_o(StateData, Chan, _From, Nick,
|
process_mode_o(StateData, Chan, _From, Nick,
|
||||||
Affiliation, Role) ->
|
Affiliation, Role) ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
|
||||||
StateData#state.host, Nick),
|
|
||||||
StateData#state.user,
|
|
||||||
#presence{
|
#presence{
|
||||||
|
from = jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
||||||
|
StateData#state.host, Nick),
|
||||||
|
to = StateData#state.user,
|
||||||
sub_els = [#muc_user{items = [#muc_item{affiliation = Affiliation,
|
sub_els = [#muc_user{items = [#muc_item{affiliation = Affiliation,
|
||||||
role = Role}]}]}).
|
role = Role}]}]}).
|
||||||
|
|
||||||
@ -1075,15 +1072,17 @@ process_kick(StateData, Chan, From, Nick, String) ->
|
|||||||
Msg2 = <<Nick/binary, " kicked by ", From/binary, " (",
|
Msg2 = <<Nick/binary, " kicked by ", From/binary, " (",
|
||||||
(filter_message(Msg))/binary, ")">>,
|
(filter_message(Msg))/binary, ")">>,
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
#message{
|
||||||
StateData#state.host),
|
from = jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
||||||
StateData#state.user,
|
StateData#state.host),
|
||||||
#message{type = groupchat, body = xmpp:mk_text(Msg2)}),
|
to = StateData#state.user,
|
||||||
|
type = groupchat, body = xmpp:mk_text(Msg2)}),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
#presence{
|
||||||
StateData#state.host, Nick),
|
from = jid:make(iolist_to_binary([Chan, <<"%">>, StateData#state.server]),
|
||||||
StateData#state.user,
|
StateData#state.host, Nick),
|
||||||
#presence{type = unavailable,
|
to = StateData#state.user,
|
||||||
|
type = unavailable,
|
||||||
sub_els = [#muc_user{items = [#muc_item{
|
sub_els = [#muc_user{items = [#muc_item{
|
||||||
affiliation = none,
|
affiliation = none,
|
||||||
role = none}],
|
role = none}],
|
||||||
@ -1098,11 +1097,11 @@ process_nick(StateData, From, NewNick) ->
|
|||||||
case (?SETS):is_member(FromUser, Ps) of
|
case (?SETS):is_member(FromUser, Ps) of
|
||||||
true ->
|
true ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, $%, StateData#state.server]),
|
|
||||||
StateData#state.host,
|
|
||||||
FromUser),
|
|
||||||
StateData#state.user,
|
|
||||||
#presence{
|
#presence{
|
||||||
|
from = jid:make(iolist_to_binary([Chan, $%, StateData#state.server]),
|
||||||
|
StateData#state.host,
|
||||||
|
FromUser),
|
||||||
|
to = StateData#state.user,
|
||||||
type = unavailable,
|
type = unavailable,
|
||||||
sub_els = [#muc_user{
|
sub_els = [#muc_user{
|
||||||
items = [#muc_item{
|
items = [#muc_item{
|
||||||
@ -1111,10 +1110,10 @@ process_nick(StateData, From, NewNick) ->
|
|||||||
nick = Nick}],
|
nick = Nick}],
|
||||||
status_codes = [303]}]}),
|
status_codes = [303]}]}),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, $%, StateData#state.server]),
|
|
||||||
StateData#state.host, Nick),
|
|
||||||
StateData#state.user,
|
|
||||||
#presence{
|
#presence{
|
||||||
|
from = jid:make(iolist_to_binary([Chan, $%, StateData#state.server]),
|
||||||
|
StateData#state.host, Nick),
|
||||||
|
to = StateData#state.user,
|
||||||
sub_els = [#muc_user{
|
sub_els = [#muc_user{
|
||||||
items = [#muc_item{
|
items = [#muc_item{
|
||||||
affiliation = member,
|
affiliation = member,
|
||||||
@ -1133,13 +1132,13 @@ process_error(StateData, String) ->
|
|||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(Chan) ->
|
fun(Chan) ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(iolist_to_binary([Chan, $%, StateData#state.server]),
|
#presence{
|
||||||
StateData#state.host,
|
from = jid:make(iolist_to_binary([Chan, $%, StateData#state.server]),
|
||||||
StateData#state.nick),
|
StateData#state.host,
|
||||||
StateData#state.user,
|
StateData#state.nick),
|
||||||
xmpp:make_error(
|
to = StateData#state.user,
|
||||||
#presence{},
|
type = error,
|
||||||
xmpp:err_internal_server_error(String, ?MYLANG)))
|
sub_els = [xmpp:err_internal_server_error(String, ?MYLANG)]})
|
||||||
end, dict:fetch_keys(StateData#state.channels)).
|
end, dict:fetch_keys(StateData#state.channels)).
|
||||||
|
|
||||||
error_unknown_num(_StateData, String, Type) ->
|
error_unknown_num(_StateData, String, Type) ->
|
||||||
@ -1154,18 +1153,18 @@ remove_element(E, Set) ->
|
|||||||
_ -> Set
|
_ -> Set
|
||||||
end.
|
end.
|
||||||
|
|
||||||
iq_admin(StateData, Channel, From, To,
|
iq_admin(StateData, Channel, From, _To,
|
||||||
#iq{type = Type, sub_els = [SubEl]} = IQ) ->
|
#iq{type = Type, sub_els = [SubEl]} = IQ) ->
|
||||||
try process_iq_admin(StateData, Channel, Type, SubEl) of
|
try process_iq_admin(StateData, Channel, Type, SubEl) of
|
||||||
{result, Result} ->
|
{result, Result} ->
|
||||||
ejabberd_router:route(To, From, xmpp:make_iq_result(IQ, Result));
|
ejabberd_router:route(xmpp:make_iq_result(IQ, Result));
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
ejabberd_router:route_error(To, From, IQ, Error)
|
ejabberd_router:route_error(IQ, Error)
|
||||||
catch E:R ->
|
catch E:R ->
|
||||||
?ERROR_MSG("failed to process admin query from ~s: ~p",
|
?ERROR_MSG("failed to process admin query from ~s: ~p",
|
||||||
[jid:to_string(From), {E, {R, erlang:get_stacktrace()}}]),
|
[jid:to_string(From), {E, {R, erlang:get_stacktrace()}}]),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(
|
||||||
To, From, IQ, xmpp:err_internal_server_error())
|
IQ, xmpp:err_internal_server_error())
|
||||||
end.
|
end.
|
||||||
|
|
||||||
process_iq_admin(_StateData, _Channel, set, #muc_admin{items = []}) ->
|
process_iq_admin(_StateData, _Channel, set, #muc_admin{items = []}) ->
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
remove_user/2, remove_room/3, mod_opt_type/1, muc_process_iq/2,
|
remove_user/2, remove_room/3, mod_opt_type/1, muc_process_iq/2,
|
||||||
muc_filter_message/5, message_is_archived/3, delete_old_messages/2,
|
muc_filter_message/5, message_is_archived/3, delete_old_messages/2,
|
||||||
get_commands_spec/0, msg_to_el/4, get_room_config/4, set_room_option/3,
|
get_commands_spec/0, msg_to_el/4, get_room_config/4, set_room_option/3,
|
||||||
offline_message/4]).
|
offline_message/2]).
|
||||||
|
|
||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
-include("logger.hrl").
|
-include("logger.hrl").
|
||||||
@ -241,8 +241,8 @@ user_send_packet({Pkt, #{jid := JID} = C2SState}) ->
|
|||||||
end,
|
end,
|
||||||
{Pkt2, C2SState}.
|
{Pkt2, C2SState}.
|
||||||
|
|
||||||
-spec offline_message(any(), jid(), jid(), message()) -> any().
|
-spec offline_message(any(), message()) -> any().
|
||||||
offline_message(Acc, Peer, To, Pkt) ->
|
offline_message(Acc, #message{from = Peer, to = To} = Pkt) ->
|
||||||
LUser = To#jid.luser,
|
LUser = To#jid.luser,
|
||||||
LServer = To#jid.lserver,
|
LServer = To#jid.lserver,
|
||||||
case should_archive(Pkt, LServer) of
|
case should_archive(Pkt, LServer) of
|
||||||
@ -874,7 +874,9 @@ send(Msgs, Count, IsComplete,
|
|||||||
Hint = #hint{type = 'no-store'},
|
Hint = #hint{type = 'no-store'},
|
||||||
Els = lists:map(
|
Els = lists:map(
|
||||||
fun({ID, _IDInt, El}) ->
|
fun({ID, _IDInt, El}) ->
|
||||||
#message{sub_els = [#mam_result{xmlns = NS,
|
#message{from = To,
|
||||||
|
to = From,
|
||||||
|
sub_els = [#mam_result{xmlns = NS,
|
||||||
id = ID,
|
id = ID,
|
||||||
queryid = QID,
|
queryid = QID,
|
||||||
sub_els = [El]}]}
|
sub_els = [El]}]}
|
||||||
@ -889,16 +891,17 @@ send(Msgs, Count, IsComplete,
|
|||||||
if NS == ?NS_MAM_TMP; NS == ?NS_MAM_1 ->
|
if NS == ?NS_MAM_TMP; NS == ?NS_MAM_1 ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(El) ->
|
fun(El) ->
|
||||||
ejabberd_router:route(To, From, El)
|
ejabberd_router:route(El)
|
||||||
end, Els),
|
end, Els),
|
||||||
xmpp:make_iq_result(IQ, Result);
|
xmpp:make_iq_result(IQ, Result);
|
||||||
NS == ?NS_MAM_0 ->
|
NS == ?NS_MAM_0 ->
|
||||||
ejabberd_router:route(To, From, xmpp:make_iq_result(IQ)),
|
ejabberd_router:route(xmpp:make_iq_result(IQ)),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(El) ->
|
fun(El) ->
|
||||||
ejabberd_router:route(To, From, El)
|
ejabberd_router:route(El)
|
||||||
end, Els),
|
end, Els),
|
||||||
ejabberd_router:route(To, From, #message{sub_els = [Result, Hint]}),
|
ejabberd_router:route(
|
||||||
|
#message{from = To, to = From, sub_els = [Result, Hint]}),
|
||||||
ignore
|
ignore
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -36,10 +36,10 @@
|
|||||||
-export([start/2, stop/1, send_metrics/4, opt_type/1, mod_opt_type/1,
|
-export([start/2, stop/1, send_metrics/4, opt_type/1, mod_opt_type/1,
|
||||||
depends/2]).
|
depends/2]).
|
||||||
|
|
||||||
-export([offline_message_hook/4,
|
-export([offline_message_hook/2,
|
||||||
sm_register_connection_hook/3, sm_remove_connection_hook/3,
|
sm_register_connection_hook/3, sm_remove_connection_hook/3,
|
||||||
user_send_packet/1, user_receive_packet/1,
|
user_send_packet/1, user_receive_packet/1,
|
||||||
s2s_send_packet/3, s2s_receive_packet/1,
|
s2s_send_packet/1, s2s_receive_packet/1,
|
||||||
remove_user/2, register_user/2]).
|
remove_user/2, register_user/2]).
|
||||||
|
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
@ -74,8 +74,8 @@ depends(_Host, _Opts) ->
|
|||||||
%%====================================================================
|
%%====================================================================
|
||||||
%% Hooks handlers
|
%% Hooks handlers
|
||||||
%%====================================================================
|
%%====================================================================
|
||||||
-spec offline_message_hook(any(), jid(), jid(), message()) -> any().
|
-spec offline_message_hook(any(), message()) -> any().
|
||||||
offline_message_hook(Acc, _From, #jid{lserver=LServer}, _Packet) ->
|
offline_message_hook(Acc, #message{to = #jid{lserver = LServer}}) ->
|
||||||
push(LServer, offline_message),
|
push(LServer, offline_message),
|
||||||
Acc.
|
Acc.
|
||||||
|
|
||||||
@ -97,8 +97,9 @@ user_receive_packet({Packet, #{jid := #jid{lserver = LServer}} = C2SState}) ->
|
|||||||
push(LServer, user_receive_packet),
|
push(LServer, user_receive_packet),
|
||||||
{Packet, C2SState}.
|
{Packet, C2SState}.
|
||||||
|
|
||||||
-spec s2s_send_packet(jid(), jid(), stanza()) -> any().
|
-spec s2s_send_packet(stanza()) -> any().
|
||||||
s2s_send_packet(#jid{lserver=LServer}, _To, _Packet) ->
|
s2s_send_packet(Packet) ->
|
||||||
|
#jid{lserver = LServer} = xmpp:get_from(Packet),
|
||||||
push(LServer, s2s_send_packet).
|
push(LServer, s2s_send_packet).
|
||||||
|
|
||||||
-spec s2s_receive_packet({stanza(), ejabberd_s2s_in:state()}) ->
|
-spec s2s_receive_packet({stanza(), ejabberd_s2s_in:state()}) ->
|
||||||
|
@ -163,14 +163,14 @@ handle_call(_Request, _From, State) ->
|
|||||||
handle_cast(_Msg, State) ->
|
handle_cast(_Msg, State) ->
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
handle_info({route, From, To, Packet}, State) ->
|
handle_info({route, Packet}, State) ->
|
||||||
case catch do_route(State, From, To, Packet) of
|
case catch do_route(State, Packet) of
|
||||||
{'EXIT', _} = Err ->
|
{'EXIT', _} = Err ->
|
||||||
try
|
try
|
||||||
?ERROR_MSG("failed to route packet ~p from '~s' to '~s': ~p",
|
?ERROR_MSG("failed to route packet:~n~s~nReason: ~p",
|
||||||
[Packet, jid:to_string(From), jid:to_string(To), Err]),
|
[xmpp:pp(Packet), Err]),
|
||||||
Error = xmpp:err_internal_server_error(),
|
Error = xmpp:err_internal_server_error(),
|
||||||
ejabberd_router:route_error(To, From, Packet, Error)
|
ejabberd_router:route_error(Packet, Error)
|
||||||
catch _:_ ->
|
catch _:_ ->
|
||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
@ -204,12 +204,12 @@ code_change(_OldVsn, State, _Extra) ->
|
|||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
do_route(_State, From, To, #iq{} = Packet) ->
|
do_route(_State, #iq{} = Packet) ->
|
||||||
ejabberd_router:process_iq(From, To, Packet);
|
ejabberd_router:process_iq(Packet);
|
||||||
do_route(_State, From, To, #presence{type = unavailable})
|
do_route(_State, #presence{from = From, to = To, type = unavailable})
|
||||||
when To#jid.luser /= <<"">> ->
|
when To#jid.luser /= <<"">> ->
|
||||||
delete_presence(From, To);
|
delete_presence(From, To);
|
||||||
do_route(_State, _From, _To, _Packet) ->
|
do_route(_State, _Packet) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
subscribe_nodes(From, To, Nodes) ->
|
subscribe_nodes(From, To, Nodes) ->
|
||||||
|
@ -345,12 +345,14 @@ handle_call({create, Room, From, Nick, Opts}, _From,
|
|||||||
|
|
||||||
handle_cast(_Msg, State) -> {noreply, State}.
|
handle_cast(_Msg, State) -> {noreply, State}.
|
||||||
|
|
||||||
handle_info({route, From, To, Packet},
|
handle_info({route, Packet},
|
||||||
#state{host = Host, server_host = ServerHost,
|
#state{host = Host, server_host = ServerHost,
|
||||||
access = Access, default_room_opts = DefRoomOpts,
|
access = Access, default_room_opts = DefRoomOpts,
|
||||||
history_size = HistorySize,
|
history_size = HistorySize,
|
||||||
max_rooms_discoitems = MaxRoomsDiscoItems,
|
max_rooms_discoitems = MaxRoomsDiscoItems,
|
||||||
room_shaper = RoomShaper} = State) ->
|
room_shaper = RoomShaper} = State) ->
|
||||||
|
From = xmpp:get_from(Packet),
|
||||||
|
To = xmpp:get_to(Packet),
|
||||||
case catch do_route(Host, ServerHost, Access, HistorySize, RoomShaper,
|
case catch do_route(Host, ServerHost, Access, HistorySize, RoomShaper,
|
||||||
From, To, Packet, DefRoomOpts, MaxRoomsDiscoItems) of
|
From, To, Packet, DefRoomOpts, MaxRoomsDiscoItems) of
|
||||||
{'EXIT', Reason} ->
|
{'EXIT', Reason} ->
|
||||||
@ -395,15 +397,15 @@ do_route(Host, ServerHost, Access, HistorySize, RoomShaper,
|
|||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
ErrText = <<"Access denied by service policy">>,
|
ErrText = <<"Access denied by service policy">>,
|
||||||
Err = xmpp:err_forbidden(ErrText, Lang),
|
Err = xmpp:err_forbidden(ErrText, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
do_route1(_Host, _ServerHost, _Access, _HistorySize, _RoomShaper,
|
do_route1(_Host, _ServerHost, _Access, _HistorySize, _RoomShaper,
|
||||||
From, #jid{luser = <<"">>, lresource = <<"">>} = To,
|
_From, #jid{luser = <<"">>, lresource = <<"">>} = _To,
|
||||||
#iq{} = IQ, _DefRoomOpts) ->
|
#iq{} = IQ, _DefRoomOpts) ->
|
||||||
ejabberd_local:process_iq(From, To, IQ);
|
ejabberd_local:process_iq(IQ);
|
||||||
do_route1(Host, ServerHost, Access, _HistorySize, _RoomShaper,
|
do_route1(Host, ServerHost, Access, _HistorySize, _RoomShaper,
|
||||||
From, #jid{luser = <<"">>, lresource = <<"">>} = To,
|
From, #jid{luser = <<"">>, lresource = <<"">>} = _To,
|
||||||
#message{lang = Lang, body = Body, type = Type} = Packet, _) ->
|
#message{lang = Lang, body = Body, type = Type} = Packet, _) ->
|
||||||
{_AccessRoute, _AccessCreate, AccessAdmin, _AccessPersistent} = Access,
|
{_AccessRoute, _AccessCreate, AccessAdmin, _AccessPersistent} = Access,
|
||||||
if Type == error ->
|
if Type == error ->
|
||||||
@ -417,13 +419,13 @@ do_route1(Host, ServerHost, Access, _HistorySize, _RoomShaper,
|
|||||||
ErrText = <<"Only service administrators are allowed "
|
ErrText = <<"Only service administrators are allowed "
|
||||||
"to send service messages">>,
|
"to send service messages">>,
|
||||||
Err = xmpp:err_forbidden(ErrText, Lang),
|
Err = xmpp:err_forbidden(ErrText, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
do_route1(_Host, _ServerHost, _Access, _HistorySize, _RoomShaper,
|
do_route1(_Host, _ServerHost, _Access, _HistorySize, _RoomShaper,
|
||||||
From, #jid{luser = <<"">>} = To, Packet, _DefRoomOpts) ->
|
_From, #jid{luser = <<"">>} = _To, Packet, _DefRoomOpts) ->
|
||||||
Err = xmpp:err_service_unavailable(),
|
Err = xmpp:err_service_unavailable(),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err);
|
ejabberd_router:route_error(Packet, Err);
|
||||||
do_route1(Host, ServerHost, Access, HistorySize, RoomShaper,
|
do_route1(Host, ServerHost, Access, HistorySize, RoomShaper,
|
||||||
From, To, Packet, DefRoomOpts) ->
|
From, To, Packet, DefRoomOpts) ->
|
||||||
{_AccessRoute, AccessCreate, _AccessAdmin, _AccessPersistent} = Access,
|
{_AccessRoute, AccessCreate, _AccessAdmin, _AccessPersistent} = Access,
|
||||||
@ -442,23 +444,23 @@ do_route1(Host, ServerHost, Access, HistorySize, RoomShaper,
|
|||||||
Room, HistorySize,
|
Room, HistorySize,
|
||||||
RoomShaper, From, Nick, DefRoomOpts),
|
RoomShaper, From, Nick, DefRoomOpts),
|
||||||
RMod:register_online_room(Room, Host, Pid),
|
RMod:register_online_room(Room, Host, Pid),
|
||||||
mod_muc_room:route(Pid, From, Nick, Packet),
|
mod_muc_room:route(Pid, Packet),
|
||||||
ok;
|
ok;
|
||||||
false ->
|
false ->
|
||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
ErrText = <<"Room creation is denied by service policy">>,
|
ErrText = <<"Room creation is denied by service policy">>,
|
||||||
Err = xmpp:err_forbidden(ErrText, Lang),
|
Err = xmpp:err_forbidden(ErrText, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
ErrText = <<"Conference room does not exist">>,
|
ErrText = <<"Conference room does not exist">>,
|
||||||
Err = xmpp:err_item_not_found(ErrText, Lang),
|
Err = xmpp:err_item_not_found(ErrText, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end;
|
end;
|
||||||
{ok, Pid} ->
|
{ok, Pid} ->
|
||||||
?DEBUG("MUC: send to process ~p~n", [Pid]),
|
?DEBUG("MUC: send to process ~p~n", [Pid]),
|
||||||
mod_muc_room:route(Pid, From, Nick, Packet),
|
mod_muc_room:route(Pid, Packet),
|
||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -730,8 +730,7 @@ get_room_occupants_number(Room, Host) ->
|
|||||||
|
|
||||||
send_direct_invitation(RoomName, RoomService, Password, Reason, UsersString) ->
|
send_direct_invitation(RoomName, RoomService, Password, Reason, UsersString) ->
|
||||||
RoomJid = jid:make(RoomName, RoomService, <<"">>),
|
RoomJid = jid:make(RoomName, RoomService, <<"">>),
|
||||||
RoomString = jid:to_string(RoomJid),
|
XmlEl = build_invitation(Password, Reason, RoomJid),
|
||||||
XmlEl = build_invitation(Password, Reason, RoomString),
|
|
||||||
UsersStrings = get_users_to_invite(RoomJid, UsersString),
|
UsersStrings = get_users_to_invite(RoomJid, UsersString),
|
||||||
[send_direct_invitation(RoomJid, UserStrings, XmlEl)
|
[send_direct_invitation(RoomJid, UserStrings, XmlEl)
|
||||||
|| UserStrings <- UsersStrings],
|
|| UserStrings <- UsersStrings],
|
||||||
@ -759,24 +758,20 @@ get_users_to_invite(RoomJid, UsersString) ->
|
|||||||
end,
|
end,
|
||||||
UsersStrings).
|
UsersStrings).
|
||||||
|
|
||||||
build_invitation(Password, Reason, RoomString) ->
|
build_invitation(Password, Reason, RoomJid) ->
|
||||||
PasswordAttrList = case Password of
|
Invite = #x_conference{jid = RoomJid,
|
||||||
<<"none">> -> [];
|
password = case Password of
|
||||||
_ -> [{<<"password">>, Password}]
|
<<"none">> -> <<>>;
|
||||||
end,
|
_ -> Password
|
||||||
ReasonAttrList = case Reason of
|
end,
|
||||||
<<"none">> -> [];
|
reason = case Reason of
|
||||||
_ -> [{<<"reason">>, Reason}]
|
<<"none">> -> <<>>;
|
||||||
end,
|
_ -> Reason
|
||||||
XAttrs = [{<<"xmlns">>, ?NS_XCONFERENCE},
|
end},
|
||||||
{<<"jid">>, RoomString}]
|
#message{sub_els = [Invite]}.
|
||||||
++ PasswordAttrList
|
|
||||||
++ ReasonAttrList,
|
|
||||||
XEl = {xmlel, <<"x">>, XAttrs, []},
|
|
||||||
{xmlel, <<"message">>, [], [XEl]}.
|
|
||||||
|
|
||||||
send_direct_invitation(FromJid, UserJid, XmlEl) ->
|
send_direct_invitation(FromJid, UserJid, Msg) ->
|
||||||
ejabberd_router:route(FromJid, UserJid, XmlEl).
|
ejabberd_router:route(xmpp:set_from_to(Msg, FromJid, UserJid)).
|
||||||
|
|
||||||
%%----------------------------
|
%%----------------------------
|
||||||
%% Change Room Option
|
%% Change Room Option
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
get_role/2,
|
get_role/2,
|
||||||
get_affiliation/2,
|
get_affiliation/2,
|
||||||
is_occupant_or_admin/2,
|
is_occupant_or_admin/2,
|
||||||
route/4]).
|
route/2]).
|
||||||
|
|
||||||
%% gen_fsm callbacks
|
%% gen_fsm callbacks
|
||||||
-export([init/1,
|
-export([init/1,
|
||||||
@ -149,8 +149,9 @@ init([Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts]) ->
|
|||||||
add_to_log(room_existence, started, State),
|
add_to_log(room_existence, started, State),
|
||||||
{ok, normal_state, State}.
|
{ok, normal_state, State}.
|
||||||
|
|
||||||
normal_state({route, From, <<"">>,
|
normal_state({route, <<"">>,
|
||||||
#message{type = Type, lang = Lang} = Packet}, StateData) ->
|
#message{from = From, type = Type, lang = Lang} = Packet},
|
||||||
|
StateData) ->
|
||||||
case is_user_online(From, StateData) orelse
|
case is_user_online(From, StateData) orelse
|
||||||
is_subscriber(From, StateData) orelse
|
is_subscriber(From, StateData) orelse
|
||||||
is_user_allowed_message_nonparticipant(From, StateData) of
|
is_user_allowed_message_nonparticipant(From, StateData) of
|
||||||
@ -168,7 +169,7 @@ normal_state({route, From, <<"">>,
|
|||||||
if Activity#activity.message /= undefined ->
|
if Activity#activity.message /= undefined ->
|
||||||
ErrText = <<"Traffic rate limit is exceeded">>,
|
ErrText = <<"Traffic rate limit is exceeded">>,
|
||||||
Err = xmpp:err_resource_constraint(ErrText, Lang),
|
Err = xmpp:err_resource_constraint(ErrText, Lang),
|
||||||
ejabberd_router:route_error(StateData#state.jid, From, Packet, Err),
|
ejabberd_router:route_error(Packet, Err),
|
||||||
{next_state, normal_state, StateData};
|
{next_state, normal_state, StateData};
|
||||||
Now >= Activity#activity.message_time + MinMessageInterval,
|
Now >= Activity#activity.message_time + MinMessageInterval,
|
||||||
MessageShaperInterval == 0 ->
|
MessageShaperInterval == 0 ->
|
||||||
@ -237,7 +238,7 @@ normal_state({route, From, <<"">>,
|
|||||||
ErrText = <<"It is not allowed to send private messages "
|
ErrText = <<"It is not allowed to send private messages "
|
||||||
"to the conference">>,
|
"to the conference">>,
|
||||||
Err = xmpp:err_not_acceptable(ErrText, Lang),
|
Err = xmpp:err_not_acceptable(ErrText, Lang),
|
||||||
ejabberd_router:route_error(StateData#state.jid, From, Packet, Err),
|
ejabberd_router:route_error(Packet, Err),
|
||||||
{next_state, normal_state, StateData};
|
{next_state, normal_state, StateData};
|
||||||
true when Type == normal ->
|
true when Type == normal ->
|
||||||
{next_state, normal_state,
|
{next_state, normal_state,
|
||||||
@ -246,14 +247,13 @@ normal_state({route, From, <<"">>,
|
|||||||
catch _:{xmpp_codec, Why} ->
|
catch _:{xmpp_codec, Why} ->
|
||||||
Txt = xmpp:format_error(Why),
|
Txt = xmpp:format_error(Why),
|
||||||
Err = xmpp:err_bad_request(Txt, Lang),
|
Err = xmpp:err_bad_request(Txt, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err),
|
||||||
StateData#state.jid, From, Packet, Err),
|
|
||||||
StateData
|
StateData
|
||||||
end};
|
end};
|
||||||
true ->
|
true ->
|
||||||
ErrText = <<"Improper message type">>,
|
ErrText = <<"Improper message type">>,
|
||||||
Err = xmpp:err_not_acceptable(ErrText, Lang),
|
Err = xmpp:err_not_acceptable(ErrText, Lang),
|
||||||
ejabberd_router:route_error(StateData#state.jid, From, Packet, Err),
|
ejabberd_router:route_error(Packet, Err),
|
||||||
{next_state, normal_state, StateData};
|
{next_state, normal_state, StateData};
|
||||||
false when Type /= error ->
|
false when Type /= error ->
|
||||||
handle_roommessage_from_nonparticipant(Packet, StateData, From),
|
handle_roommessage_from_nonparticipant(Packet, StateData, From),
|
||||||
@ -261,8 +261,8 @@ normal_state({route, From, <<"">>,
|
|||||||
false ->
|
false ->
|
||||||
{next_state, normal_state, StateData}
|
{next_state, normal_state, StateData}
|
||||||
end;
|
end;
|
||||||
normal_state({route, From, <<"">>,
|
normal_state({route, <<"">>,
|
||||||
#iq{type = Type, lang = Lang, sub_els = [_]} = IQ0},
|
#iq{from = From, type = Type, lang = Lang, sub_els = [_]} = IQ0},
|
||||||
StateData) when Type == get; Type == set ->
|
StateData) when Type == get; Type == set ->
|
||||||
try
|
try
|
||||||
case ejabberd_hooks:run_fold(
|
case ejabberd_hooks:run_fold(
|
||||||
@ -274,7 +274,7 @@ normal_state({route, From, <<"">>,
|
|||||||
ignore ->
|
ignore ->
|
||||||
{next_state, normal_state, StateData};
|
{next_state, normal_state, StateData};
|
||||||
#iq{type = T} = IQRes when T == error; T == result ->
|
#iq{type = T} = IQRes when T == error; T == result ->
|
||||||
ejabberd_router:route(StateData#state.jid, From, IQRes),
|
ejabberd_router:route(IQRes),
|
||||||
{next_state, normal_state, StateData};
|
{next_state, normal_state, StateData};
|
||||||
#iq{sub_els = [SubEl]} = IQ ->
|
#iq{sub_els = [SubEl]} = IQ ->
|
||||||
Res1 = case xmpp:get_ns(SubEl) of
|
Res1 = case xmpp:get_ns(SubEl) of
|
||||||
@ -311,7 +311,7 @@ normal_state({route, From, <<"">>,
|
|||||||
{xmpp:make_error(IQ0, Error), StateData}
|
{xmpp:make_error(IQ0, Error), StateData}
|
||||||
end,
|
end,
|
||||||
if IQRes /= ignore ->
|
if IQRes /= ignore ->
|
||||||
ejabberd_router:route(StateData#state.jid, From, IQRes);
|
ejabberd_router:route(IQRes);
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
@ -327,16 +327,16 @@ normal_state({route, From, <<"">>,
|
|||||||
catch _:{xmpp_codec, Why} ->
|
catch _:{xmpp_codec, Why} ->
|
||||||
ErrTxt = xmpp:format_error(Why),
|
ErrTxt = xmpp:format_error(Why),
|
||||||
Err = xmpp:err_bad_request(ErrTxt, Lang),
|
Err = xmpp:err_bad_request(ErrTxt, Lang),
|
||||||
ejabberd_router:route_error(StateData#state.jid, From, IQ0, Err)
|
ejabberd_router:route_error(IQ0, Err)
|
||||||
end;
|
end;
|
||||||
normal_state({route, From, <<"">>, #iq{} = IQ}, StateData) ->
|
normal_state({route, <<"">>, #iq{} = IQ}, StateData) ->
|
||||||
Err = xmpp:err_bad_request(),
|
Err = xmpp:err_bad_request(),
|
||||||
ejabberd_router:route_error(StateData#state.jid, From, IQ, Err),
|
ejabberd_router:route_error(IQ, Err),
|
||||||
case StateData#state.just_created of
|
case StateData#state.just_created of
|
||||||
true -> {stop, normal, StateData};
|
true -> {stop, normal, StateData};
|
||||||
false -> {next_state, normal_state, StateData}
|
false -> {next_state, normal_state, StateData}
|
||||||
end;
|
end;
|
||||||
normal_state({route, From, Nick, #presence{} = Packet}, StateData) ->
|
normal_state({route, Nick, #presence{from = From} = Packet}, StateData) ->
|
||||||
Activity = get_user_activity(From, StateData),
|
Activity = get_user_activity(From, StateData),
|
||||||
Now = p1_time_compat:system_time(micro_seconds),
|
Now = p1_time_compat:system_time(micro_seconds),
|
||||||
MinPresenceInterval =
|
MinPresenceInterval =
|
||||||
@ -365,8 +365,8 @@ normal_state({route, From, Nick, #presence{} = Packet}, StateData) ->
|
|||||||
StateData),
|
StateData),
|
||||||
{next_state, normal_state, StateData1}
|
{next_state, normal_state, StateData1}
|
||||||
end;
|
end;
|
||||||
normal_state({route, From, ToNick,
|
normal_state({route, ToNick,
|
||||||
#message{type = Type, lang = Lang} = Packet},
|
#message{from = From, type = Type, lang = Lang} = Packet},
|
||||||
StateData) ->
|
StateData) ->
|
||||||
case decide_fate_message(Packet, From, StateData) of
|
case decide_fate_message(Packet, From, StateData) of
|
||||||
{expulse_sender, Reason} ->
|
{expulse_sender, Reason} ->
|
||||||
@ -387,17 +387,13 @@ normal_state({route, From, ToNick,
|
|||||||
ErrText = <<"It is not allowed to send private messages "
|
ErrText = <<"It is not allowed to send private messages "
|
||||||
"of type \"groupchat\"">>,
|
"of type \"groupchat\"">>,
|
||||||
Err = xmpp:err_bad_request(ErrText, Lang),
|
Err = xmpp:err_bad_request(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err);
|
||||||
jid:replace_resource(StateData#state.jid, ToNick),
|
|
||||||
From, Packet, Err);
|
|
||||||
{true, true} ->
|
{true, true} ->
|
||||||
case find_jids_by_nick(ToNick, StateData) of
|
case find_jids_by_nick(ToNick, StateData) of
|
||||||
[] ->
|
[] ->
|
||||||
ErrText = <<"Recipient is not in the conference room">>,
|
ErrText = <<"Recipient is not in the conference room">>,
|
||||||
Err = xmpp:err_item_not_found(ErrText, Lang),
|
Err = xmpp:err_item_not_found(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err);
|
||||||
jid:replace_resource(StateData#state.jid, ToNick),
|
|
||||||
From, Packet, Err);
|
|
||||||
ToJIDs ->
|
ToJIDs ->
|
||||||
SrcIsVisitor = is_visitor(From, StateData),
|
SrcIsVisitor = is_visitor(From, StateData),
|
||||||
DstIsModerator = is_moderator(hd(ToJIDs), StateData),
|
DstIsModerator = is_moderator(hd(ToJIDs), StateData),
|
||||||
@ -412,35 +408,31 @@ normal_state({route, From, ToNick,
|
|||||||
jid:replace_resource(StateData#state.jid,
|
jid:replace_resource(StateData#state.jid,
|
||||||
FromNick),
|
FromNick),
|
||||||
X = #muc_user{},
|
X = #muc_user{},
|
||||||
PrivMsg = xmpp:set_subtag(Packet, X),
|
PrivMsg = xmpp:set_from(
|
||||||
[ejabberd_router:route(FromNickJID, ToJID, PrivMsg)
|
xmpp:set_subtag(Packet, X),
|
||||||
|
FromNickJID),
|
||||||
|
[ejabberd_router:route(xmpp:set_to(PrivMsg, ToJID))
|
||||||
|| ToJID <- ToJIDs];
|
|| ToJID <- ToJIDs];
|
||||||
true ->
|
true ->
|
||||||
ErrText = <<"It is not allowed to send private messages">>,
|
ErrText = <<"It is not allowed to send private messages">>,
|
||||||
Err = xmpp:err_forbidden(ErrText, Lang),
|
Err = xmpp:err_forbidden(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err)
|
||||||
jid:replace_resource(StateData#state.jid, ToNick),
|
|
||||||
From, Packet, Err)
|
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
{true, false} ->
|
{true, false} ->
|
||||||
ErrText = <<"Only occupants are allowed to send messages "
|
ErrText = <<"Only occupants are allowed to send messages "
|
||||||
"to the conference">>,
|
"to the conference">>,
|
||||||
Err = xmpp:err_not_acceptable(ErrText, Lang),
|
Err = xmpp:err_not_acceptable(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err);
|
||||||
jid:replace_resource(StateData#state.jid, ToNick),
|
|
||||||
From, Packet, Err);
|
|
||||||
{false, _} ->
|
{false, _} ->
|
||||||
ErrText = <<"It is not allowed to send private messages">>,
|
ErrText = <<"It is not allowed to send private messages">>,
|
||||||
Err = xmpp:err_forbidden(ErrText, Lang),
|
Err = xmpp:err_forbidden(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err)
|
||||||
jid:replace_resource(StateData#state.jid, ToNick),
|
|
||||||
From, Packet, Err)
|
|
||||||
end,
|
end,
|
||||||
{next_state, normal_state, StateData}
|
{next_state, normal_state, StateData}
|
||||||
end;
|
end;
|
||||||
normal_state({route, From, ToNick,
|
normal_state({route, ToNick,
|
||||||
#iq{id = StanzaId, lang = Lang} = Packet},
|
#iq{from = From, id = StanzaId, lang = Lang} = Packet},
|
||||||
StateData) ->
|
StateData) ->
|
||||||
case {(StateData#state.config)#config.allow_query_users,
|
case {(StateData#state.config)#config.allow_query_users,
|
||||||
is_user_online_iq(StanzaId, From, StateData)} of
|
is_user_online_iq(StanzaId, From, StateData)} of
|
||||||
@ -449,31 +441,27 @@ normal_state({route, From, ToNick,
|
|||||||
false ->
|
false ->
|
||||||
ErrText = <<"Recipient is not in the conference room">>,
|
ErrText = <<"Recipient is not in the conference room">>,
|
||||||
Err = xmpp:err_item_not_found(ErrText, Lang),
|
Err = xmpp:err_item_not_found(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err);
|
||||||
jid:replace_resource(StateData#state.jid, ToNick),
|
|
||||||
From, Packet, Err);
|
|
||||||
ToJID ->
|
ToJID ->
|
||||||
{ok, #user{nick = FromNick}} =
|
{ok, #user{nick = FromNick}} =
|
||||||
(?DICT):find(jid:tolower(FromFull), StateData#state.users),
|
(?DICT):find(jid:tolower(FromFull), StateData#state.users),
|
||||||
{ToJID2, Packet2} = handle_iq_vcard(ToJID, NewId, Packet),
|
{ToJID2, Packet2} = handle_iq_vcard(ToJID, NewId, Packet),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:replace_resource(StateData#state.jid, FromNick),
|
xmpp:set_from_to(
|
||||||
ToJID2, Packet2)
|
Packet2,
|
||||||
|
jid:replace_resource(StateData#state.jid, FromNick),
|
||||||
|
ToJID2))
|
||||||
end;
|
end;
|
||||||
{_, {false, _, _}} ->
|
{_, {false, _, _}} ->
|
||||||
ErrText = <<"Only occupants are allowed to send queries "
|
ErrText = <<"Only occupants are allowed to send queries "
|
||||||
"to the conference">>,
|
"to the conference">>,
|
||||||
Err = xmpp:err_not_acceptable(ErrText, Lang),
|
Err = xmpp:err_not_acceptable(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err);
|
||||||
jid:replace_resource(StateData#state.jid, ToNick),
|
|
||||||
From, Packet, Err);
|
|
||||||
_ ->
|
_ ->
|
||||||
ErrText = <<"Queries to the conference members are "
|
ErrText = <<"Queries to the conference members are "
|
||||||
"not allowed in this room">>,
|
"not allowed in this room">>,
|
||||||
Err = xmpp:err_not_allowed(ErrText, Lang),
|
Err = xmpp:err_not_allowed(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err)
|
||||||
jid:replace_resource(StateData#state.jid, ToNick),
|
|
||||||
From, Packet, Err)
|
|
||||||
end,
|
end,
|
||||||
{next_state, normal_state, StateData};
|
{next_state, normal_state, StateData};
|
||||||
normal_state(_Event, StateData) ->
|
normal_state(_Event, StateData) ->
|
||||||
@ -667,14 +655,12 @@ handle_info({captcha_failed, From}, normal_state,
|
|||||||
NewState = case (?DICT):find(From,
|
NewState = case (?DICT):find(From,
|
||||||
StateData#state.robots)
|
StateData#state.robots)
|
||||||
of
|
of
|
||||||
{ok, {Nick, Packet}} ->
|
{ok, {_Nick, Packet}} ->
|
||||||
Robots = (?DICT):erase(From, StateData#state.robots),
|
Robots = (?DICT):erase(From, StateData#state.robots),
|
||||||
Txt = <<"The CAPTCHA verification has failed">>,
|
Txt = <<"The CAPTCHA verification has failed">>,
|
||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
Err = xmpp:err_not_authorized(Txt, Lang),
|
Err = xmpp:err_not_authorized(Txt, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err),
|
||||||
jid:replace_resource(StateData#state.jid, Nick),
|
|
||||||
From, Packet, Err),
|
|
||||||
StateData#state{robots = Robots};
|
StateData#state{robots = Robots};
|
||||||
_ -> StateData
|
_ -> StateData
|
||||||
end,
|
end,
|
||||||
@ -721,9 +707,10 @@ terminate(Reason, _StateName, StateData) ->
|
|||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
%%% Internal functions
|
%%% Internal functions
|
||||||
%%%----------------------------------------------------------------------
|
%%%----------------------------------------------------------------------
|
||||||
-spec route(pid(), jid(), binary(), stanza()) -> ok.
|
-spec route(pid(), stanza()) -> ok.
|
||||||
route(Pid, From, ToNick, Packet) ->
|
route(Pid, Packet) ->
|
||||||
gen_fsm:send_event(Pid, {route, From, ToNick, Packet}).
|
#jid{lresource = Nick} = xmpp:get_to(Packet),
|
||||||
|
gen_fsm:send_event(Pid, {route, Nick, Packet}).
|
||||||
|
|
||||||
-spec process_groupchat_message(jid(), message(), state()) -> fsm_next().
|
-spec process_groupchat_message(jid(), message(), state()) -> fsm_next().
|
||||||
process_groupchat_message(From, #message{lang = Lang} = Packet, StateData) ->
|
process_groupchat_message(From, #message{lang = Lang} = Packet, StateData) ->
|
||||||
@ -800,23 +787,21 @@ process_groupchat_message(From, #message{lang = Lang} = Packet, StateData) ->
|
|||||||
<<"Only moderators are allowed to change "
|
<<"Only moderators are allowed to change "
|
||||||
"the subject in this room">>, Lang)
|
"the subject in this room">>, Lang)
|
||||||
end,
|
end,
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err),
|
||||||
StateData#state.jid, From, Packet, Err),
|
|
||||||
{next_state, normal_state, StateData}
|
{next_state, normal_state, StateData}
|
||||||
end;
|
end;
|
||||||
true ->
|
true ->
|
||||||
ErrText = <<"Visitors are not allowed to send messages "
|
ErrText = <<"Visitors are not allowed to send messages "
|
||||||
"to all occupants">>,
|
"to all occupants">>,
|
||||||
Err = xmpp:err_forbidden(ErrText, Lang),
|
Err = xmpp:err_forbidden(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err),
|
||||||
StateData#state.jid, From, Packet, Err),
|
|
||||||
{next_state, normal_state, StateData}
|
{next_state, normal_state, StateData}
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
ErrText = <<"Only occupants are allowed to send messages "
|
ErrText = <<"Only occupants are allowed to send messages "
|
||||||
"to the conference">>,
|
"to the conference">>,
|
||||||
Err = xmpp:err_not_acceptable(ErrText, Lang),
|
Err = xmpp:err_not_acceptable(ErrText, Lang),
|
||||||
ejabberd_router:route_error(StateData#state.jid, From, Packet, Err),
|
ejabberd_router:route_error(Packet, Err),
|
||||||
{next_state, normal_state, StateData}
|
{next_state, normal_state, StateData}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -854,7 +839,7 @@ process_normal_message(From, #message{lang = Lang} = Pkt, StateData) ->
|
|||||||
{ok, VoiceApproval} ->
|
{ok, VoiceApproval} ->
|
||||||
process_voice_approval(From, Pkt, VoiceApproval, StateData);
|
process_voice_approval(From, Pkt, VoiceApproval, StateData);
|
||||||
{error, Err} ->
|
{error, Err} ->
|
||||||
ejabberd_router:route_error(StateData#state.jid, From, Pkt, Err),
|
ejabberd_router:route_error(Pkt, Err),
|
||||||
StateData;
|
StateData;
|
||||||
ok ->
|
ok ->
|
||||||
StateData
|
StateData
|
||||||
@ -902,15 +887,13 @@ process_voice_request(From, Pkt, StateData) ->
|
|||||||
ErrText = <<"Please, wait for a while before sending "
|
ErrText = <<"Please, wait for a while before sending "
|
||||||
"new voice request">>,
|
"new voice request">>,
|
||||||
Err = xmpp:err_resource_constraint(ErrText, Lang),
|
Err = xmpp:err_resource_constraint(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Pkt, Err),
|
||||||
StateData#state.jid, From, Pkt, Err),
|
|
||||||
StateData#state{last_voice_request_time = Times}
|
StateData#state{last_voice_request_time = Times}
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
ErrText = <<"Voice requests are disabled in this conference">>,
|
ErrText = <<"Voice requests are disabled in this conference">>,
|
||||||
Err = xmpp:err_forbidden(ErrText, Lang),
|
Err = xmpp:err_forbidden(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Pkt, Err),
|
||||||
StateData#state.jid, From, Pkt, Err),
|
|
||||||
StateData
|
StateData
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -936,15 +919,13 @@ process_voice_approval(From, Pkt, VoiceApproval, StateData) ->
|
|||||||
ErrText = <<"Failed to extract JID from your voice "
|
ErrText = <<"Failed to extract JID from your voice "
|
||||||
"request approval">>,
|
"request approval">>,
|
||||||
Err = xmpp:err_bad_request(ErrText, Lang),
|
Err = xmpp:err_bad_request(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Pkt, Err),
|
||||||
StateData#state.jid, From, Pkt, Err),
|
|
||||||
StateData
|
StateData
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
ErrText = <<"Only moderators can approve voice requests">>,
|
ErrText = <<"Only moderators can approve voice requests">>,
|
||||||
Err = xmpp:err_not_allowed(ErrText, Lang),
|
Err = xmpp:err_not_allowed(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Pkt, Err),
|
||||||
StateData#state.jid, From, Pkt, Err),
|
|
||||||
StateData
|
StateData
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -1023,25 +1004,19 @@ do_process_presence(From, Nick, #presence{type = available, lang = Lang} = Packe
|
|||||||
ErrText = <<"Visitors are not allowed to change their "
|
ErrText = <<"Visitors are not allowed to change their "
|
||||||
"nicknames in this room">>,
|
"nicknames in this room">>,
|
||||||
Err = xmpp:err_not_allowed(ErrText, Lang),
|
Err = xmpp:err_not_allowed(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err),
|
||||||
jid:replace_resource(StateData#state.jid, Nick),
|
|
||||||
From, Packet, Err),
|
|
||||||
StateData;
|
StateData;
|
||||||
{true, _, _} ->
|
{true, _, _} ->
|
||||||
ErrText = <<"That nickname is already in use by another "
|
ErrText = <<"That nickname is already in use by another "
|
||||||
"occupant">>,
|
"occupant">>,
|
||||||
Err = xmpp:err_conflict(ErrText, Lang),
|
Err = xmpp:err_conflict(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err),
|
||||||
jid:replace_resource(StateData#state.jid, Nick),
|
|
||||||
From, Packet, Err),
|
|
||||||
StateData;
|
StateData;
|
||||||
{_, false, _} ->
|
{_, false, _} ->
|
||||||
ErrText = <<"That nickname is registered by another "
|
ErrText = <<"That nickname is registered by another "
|
||||||
"person">>,
|
"person">>,
|
||||||
Err = xmpp:err_conflict(ErrText, Lang),
|
Err = xmpp:err_conflict(ErrText, Lang),
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err),
|
||||||
jid:replace_resource(StateData#state.jid, Nick),
|
|
||||||
From, Packet, Err),
|
|
||||||
StateData;
|
StateData;
|
||||||
_ ->
|
_ ->
|
||||||
change_nick(From, Nick, StateData)
|
change_nick(From, Nick, StateData)
|
||||||
@ -1782,7 +1757,6 @@ nick_collision(User, Nick, StateData) ->
|
|||||||
{result, xmpp_element(), state()}.
|
{result, xmpp_element(), state()}.
|
||||||
add_new_user(From, Nick, Packet, StateData) ->
|
add_new_user(From, Nick, Packet, StateData) ->
|
||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
UserRoomJID = jid:replace_resource(StateData#state.jid, Nick),
|
|
||||||
MaxUsers = get_max_users(StateData),
|
MaxUsers = get_max_users(StateData),
|
||||||
MaxAdminUsers = MaxUsers +
|
MaxAdminUsers = MaxUsers +
|
||||||
get_max_users_admin_threshold(StateData),
|
get_max_users_admin_threshold(StateData),
|
||||||
@ -1813,7 +1787,7 @@ add_new_user(From, Nick, Packet, StateData) ->
|
|||||||
Txt = <<"Too many users in this conference">>,
|
Txt = <<"Too many users in this conference">>,
|
||||||
Err = xmpp:err_resource_constraint(Txt, Lang),
|
Err = xmpp:err_resource_constraint(Txt, Lang),
|
||||||
if not IsSubscribeRequest ->
|
if not IsSubscribeRequest ->
|
||||||
ejabberd_router:route_error(UserRoomJID, From, Packet, Err),
|
ejabberd_router:route_error(Packet, Err),
|
||||||
StateData;
|
StateData;
|
||||||
true ->
|
true ->
|
||||||
{error, Err}
|
{error, Err}
|
||||||
@ -1822,7 +1796,7 @@ add_new_user(From, Nick, Packet, StateData) ->
|
|||||||
Txt = <<"You have joined too many conferences">>,
|
Txt = <<"You have joined too many conferences">>,
|
||||||
Err = xmpp:err_resource_constraint(Txt, Lang),
|
Err = xmpp:err_resource_constraint(Txt, Lang),
|
||||||
if not IsSubscribeRequest ->
|
if not IsSubscribeRequest ->
|
||||||
ejabberd_router:route_error(UserRoomJID, From, Packet, Err),
|
ejabberd_router:route_error(Packet, Err),
|
||||||
StateData;
|
StateData;
|
||||||
true ->
|
true ->
|
||||||
{error, Err}
|
{error, Err}
|
||||||
@ -1830,7 +1804,7 @@ add_new_user(From, Nick, Packet, StateData) ->
|
|||||||
{false, _, _, _} ->
|
{false, _, _, _} ->
|
||||||
Err = xmpp:err_service_unavailable(),
|
Err = xmpp:err_service_unavailable(),
|
||||||
if not IsSubscribeRequest ->
|
if not IsSubscribeRequest ->
|
||||||
ejabberd_router:route_error(UserRoomJID, From, Packet, Err),
|
ejabberd_router:route_error(Packet, Err),
|
||||||
StateData;
|
StateData;
|
||||||
true ->
|
true ->
|
||||||
{error, Err}
|
{error, Err}
|
||||||
@ -1845,7 +1819,7 @@ add_new_user(From, Nick, Packet, StateData) ->
|
|||||||
xmpp:err_registration_required(ErrText, Lang)
|
xmpp:err_registration_required(ErrText, Lang)
|
||||||
end,
|
end,
|
||||||
if not IsSubscribeRequest ->
|
if not IsSubscribeRequest ->
|
||||||
ejabberd_router:route_error(UserRoomJID, From, Packet, Err),
|
ejabberd_router:route_error(Packet, Err),
|
||||||
StateData;
|
StateData;
|
||||||
true ->
|
true ->
|
||||||
{error, Err}
|
{error, Err}
|
||||||
@ -1854,7 +1828,7 @@ add_new_user(From, Nick, Packet, StateData) ->
|
|||||||
ErrText = <<"That nickname is already in use by another occupant">>,
|
ErrText = <<"That nickname is already in use by another occupant">>,
|
||||||
Err = xmpp:err_conflict(ErrText, Lang),
|
Err = xmpp:err_conflict(ErrText, Lang),
|
||||||
if not IsSubscribeRequest ->
|
if not IsSubscribeRequest ->
|
||||||
ejabberd_router:route_error(UserRoomJID, From, Packet, Err),
|
ejabberd_router:route_error(Packet, Err),
|
||||||
StateData;
|
StateData;
|
||||||
true ->
|
true ->
|
||||||
{error, Err}
|
{error, Err}
|
||||||
@ -1863,7 +1837,7 @@ add_new_user(From, Nick, Packet, StateData) ->
|
|||||||
ErrText = <<"That nickname is registered by another person">>,
|
ErrText = <<"That nickname is registered by another person">>,
|
||||||
Err = xmpp:err_conflict(ErrText, Lang),
|
Err = xmpp:err_conflict(ErrText, Lang),
|
||||||
if not IsSubscribeRequest ->
|
if not IsSubscribeRequest ->
|
||||||
ejabberd_router:route_error(UserRoomJID, From, Packet, Err),
|
ejabberd_router:route_error(Packet, Err),
|
||||||
StateData;
|
StateData;
|
||||||
true ->
|
true ->
|
||||||
{error, Err}
|
{error, Err}
|
||||||
@ -1904,7 +1878,7 @@ add_new_user(From, Nick, Packet, StateData) ->
|
|||||||
ErrText = <<"A password is required to enter this room">>,
|
ErrText = <<"A password is required to enter this room">>,
|
||||||
Err = xmpp:err_not_authorized(ErrText, Lang),
|
Err = xmpp:err_not_authorized(ErrText, Lang),
|
||||||
if not IsSubscribeRequest ->
|
if not IsSubscribeRequest ->
|
||||||
ejabberd_router:route_error(UserRoomJID, From, Packet, Err),
|
ejabberd_router:route_error(Packet, Err),
|
||||||
StateData;
|
StateData;
|
||||||
true ->
|
true ->
|
||||||
{error, Err}
|
{error, Err}
|
||||||
@ -1918,11 +1892,13 @@ add_new_user(From, Nick, Packet, StateData) ->
|
|||||||
Lang, Limiter, From)
|
Lang, Limiter, From)
|
||||||
of
|
of
|
||||||
{ok, ID, Body, CaptchaEls} ->
|
{ok, ID, Body, CaptchaEls} ->
|
||||||
MsgPkt = #message{id = ID, body = Body,
|
MsgPkt = #message{from = RoomJID,
|
||||||
|
to = From,
|
||||||
|
id = ID, body = Body,
|
||||||
sub_els = CaptchaEls},
|
sub_els = CaptchaEls},
|
||||||
Robots = (?DICT):store(From, {Nick, Packet},
|
Robots = (?DICT):store(From, {Nick, Packet},
|
||||||
StateData#state.robots),
|
StateData#state.robots),
|
||||||
ejabberd_router:route(RoomJID, From, MsgPkt),
|
ejabberd_router:route(MsgPkt),
|
||||||
NewState = StateData#state{robots = Robots},
|
NewState = StateData#state{robots = Robots},
|
||||||
if not IsSubscribeRequest ->
|
if not IsSubscribeRequest ->
|
||||||
NewState;
|
NewState;
|
||||||
@ -1933,8 +1909,7 @@ add_new_user(From, Nick, Packet, StateData) ->
|
|||||||
ErrText = <<"Too many CAPTCHA requests">>,
|
ErrText = <<"Too many CAPTCHA requests">>,
|
||||||
Err = xmpp:err_resource_constraint(ErrText, Lang),
|
Err = xmpp:err_resource_constraint(ErrText, Lang),
|
||||||
if not IsSubscribeRequest ->
|
if not IsSubscribeRequest ->
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err),
|
||||||
UserRoomJID, From, Packet, Err),
|
|
||||||
StateData;
|
StateData;
|
||||||
true ->
|
true ->
|
||||||
{error, Err}
|
{error, Err}
|
||||||
@ -1943,8 +1918,7 @@ add_new_user(From, Nick, Packet, StateData) ->
|
|||||||
ErrText = <<"Unable to generate a CAPTCHA">>,
|
ErrText = <<"Unable to generate a CAPTCHA">>,
|
||||||
Err = xmpp:err_internal_server_error(ErrText, Lang),
|
Err = xmpp:err_internal_server_error(ErrText, Lang),
|
||||||
if not IsSubscribeRequest ->
|
if not IsSubscribeRequest ->
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err),
|
||||||
UserRoomJID, From, Packet, Err),
|
|
||||||
StateData;
|
StateData;
|
||||||
true ->
|
true ->
|
||||||
{error, Err}
|
{error, Err}
|
||||||
@ -1954,8 +1928,7 @@ add_new_user(From, Nick, Packet, StateData) ->
|
|||||||
ErrText = <<"Incorrect password">>,
|
ErrText = <<"Incorrect password">>,
|
||||||
Err = xmpp:err_not_authorized(ErrText, Lang),
|
Err = xmpp:err_not_authorized(ErrText, Lang),
|
||||||
if not IsSubscribeRequest ->
|
if not IsSubscribeRequest ->
|
||||||
ejabberd_router:route_error(
|
ejabberd_router:route_error(Packet, Err),
|
||||||
UserRoomJID, From, Packet, Err),
|
|
||||||
StateData;
|
StateData;
|
||||||
true ->
|
true ->
|
||||||
{error, Err}
|
{error, Err}
|
||||||
@ -2481,8 +2454,10 @@ send_history(JID, History, StateData) ->
|
|||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({Nick, Packet, _HaveSubject, _TimeStamp, _Size}) ->
|
fun({Nick, Packet, _HaveSubject, _TimeStamp, _Size}) ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:replace_resource(StateData#state.jid, Nick),
|
xmpp:set_from_to(
|
||||||
JID, Packet)
|
Packet,
|
||||||
|
jid:replace_resource(StateData#state.jid, Nick),
|
||||||
|
JID))
|
||||||
end, lqueue_to_list(History)).
|
end, lqueue_to_list(History)).
|
||||||
|
|
||||||
-spec send_subject(jid(), state()) -> ok.
|
-spec send_subject(jid(), state()) -> ok.
|
||||||
@ -2491,9 +2466,9 @@ send_subject(JID, #state{subject_author = Nick} = StateData) ->
|
|||||||
<<"">> -> [#text{}];
|
<<"">> -> [#text{}];
|
||||||
Subj -> xmpp:mk_text(Subj)
|
Subj -> xmpp:mk_text(Subj)
|
||||||
end,
|
end,
|
||||||
Packet = #message{type = groupchat, subject = Subject},
|
Packet = #message{from = jid:replace_resource(StateData#state.jid, Nick),
|
||||||
ejabberd_router:route(jid:replace_resource(StateData#state.jid, Nick), JID,
|
to = JID, type = groupchat, subject = Subject},
|
||||||
Packet).
|
ejabberd_router:route(Packet).
|
||||||
|
|
||||||
-spec check_subject(message()) -> false | binary().
|
-spec check_subject(message()) -> false | binary().
|
||||||
check_subject(#message{subject = [_|_] = Subj, body = [],
|
check_subject(#message{subject = [_|_] = Subj, body = [],
|
||||||
@ -3889,12 +3864,13 @@ prepare_request_form(Requester, Nick, Lang) ->
|
|||||||
send_voice_request(From, Lang, StateData) ->
|
send_voice_request(From, Lang, StateData) ->
|
||||||
Moderators = search_role(moderator, StateData),
|
Moderators = search_role(moderator, StateData),
|
||||||
FromNick = find_nick_by_jid(From, StateData),
|
FromNick = find_nick_by_jid(From, StateData),
|
||||||
lists:foreach(fun ({_, User}) ->
|
lists:foreach(
|
||||||
ejabberd_router:route(
|
fun({_, User}) ->
|
||||||
StateData#state.jid, User#user.jid,
|
ejabberd_router:route(
|
||||||
prepare_request_form(From, FromNick, Lang))
|
xmpp:set_from_to(
|
||||||
end,
|
prepare_request_form(From, FromNick, Lang),
|
||||||
Moderators).
|
StateData#state.jid, User#user.jid))
|
||||||
|
end, Moderators).
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Invitation support
|
% Invitation support
|
||||||
@ -3956,13 +3932,15 @@ route_invitation(From, Invitation, Lang, StateData) ->
|
|||||||
<<"">> -> <<"">>;
|
<<"">> -> <<"">>;
|
||||||
_ -> <<" (", Reason/binary, ") ">>
|
_ -> <<" (", Reason/binary, ") ">>
|
||||||
end]),
|
end]),
|
||||||
Msg = #message{type = normal,
|
Msg = #message{from = StateData#state.jid,
|
||||||
|
to = JID,
|
||||||
|
type = normal,
|
||||||
body = xmpp:mk_text(Body),
|
body = xmpp:mk_text(Body),
|
||||||
sub_els = [XUser, XConference]},
|
sub_els = [XUser, XConference]},
|
||||||
ejabberd_hooks:run(muc_invite, StateData#state.server_host,
|
ejabberd_hooks:run(muc_invite, StateData#state.server_host,
|
||||||
[StateData#state.jid, StateData#state.config,
|
[StateData#state.jid, StateData#state.config,
|
||||||
From, JID, Reason]),
|
From, JID, Reason]),
|
||||||
ejabberd_router:route(StateData#state.jid, JID, Msg),
|
ejabberd_router:route(Msg),
|
||||||
JID.
|
JID.
|
||||||
|
|
||||||
%% Handle a message sent to the room by a non-participant.
|
%% Handle a message sent to the room by a non-participant.
|
||||||
@ -3975,12 +3953,13 @@ handle_roommessage_from_nonparticipant(Packet, StateData, From) ->
|
|||||||
NewDecline = Decline#muc_decline{to = undefined, from = From},
|
NewDecline = Decline#muc_decline{to = undefined, from = From},
|
||||||
NewXUser = XUser#muc_user{decline = NewDecline},
|
NewXUser = XUser#muc_user{decline = NewDecline},
|
||||||
NewPacket = xmpp:set_subtag(Packet, NewXUser),
|
NewPacket = xmpp:set_subtag(Packet, NewXUser),
|
||||||
ejabberd_router:route(StateData#state.jid, To, NewPacket);
|
ejabberd_router:route(
|
||||||
|
xmpp:set_from_to(NewPacket, StateData#state.jid, To));
|
||||||
_ ->
|
_ ->
|
||||||
ErrText = <<"Only occupants are allowed to send messages "
|
ErrText = <<"Only occupants are allowed to send messages "
|
||||||
"to the conference">>,
|
"to the conference">>,
|
||||||
Err = xmpp:err_not_acceptable(ErrText, xmpp:get_lang(Packet)),
|
Err = xmpp:err_not_acceptable(ErrText, xmpp:get_lang(Packet)),
|
||||||
ejabberd_router:route_error(StateData#state.jid, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
@ -4052,7 +4031,8 @@ send_wrapped(From, To, Packet, Node, State) ->
|
|||||||
case lists:member(Node, Nodes) of
|
case lists:member(Node, Nodes) of
|
||||||
true ->
|
true ->
|
||||||
NewPacket = wrap(From, JID, Packet, Node),
|
NewPacket = wrap(From, JID, Packet, Node),
|
||||||
ejabberd_router:route(State#state.jid, JID, NewPacket);
|
ejabberd_router:route(
|
||||||
|
xmpp:set_from_to(NewPacket, State#state.jid, JID));
|
||||||
false ->
|
false ->
|
||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
@ -4060,7 +4040,7 @@ send_wrapped(From, To, Packet, Node, State) ->
|
|||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
true ->
|
true ->
|
||||||
ejabberd_router:route(From, To, Packet)
|
ejabberd_router:route(xmpp:set_from_to(Packet, From, To))
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec wrap(jid(), jid(), stanza(), binary()) -> message().
|
-spec wrap(jid(), jid(), stanza(), binary()) -> message().
|
||||||
|
@ -159,8 +159,8 @@ handle_cast(_Msg, State) -> {noreply, State}.
|
|||||||
%% Description: Handling all non call/cast messages
|
%% Description: Handling all non call/cast messages
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
handle_info({route, From, To, #iq{} = Packet}, State) ->
|
handle_info({route, #iq{} = Packet}, State) ->
|
||||||
case catch handle_iq(From, To, Packet, State) of
|
case catch handle_iq(Packet, State) of
|
||||||
{'EXIT', Reason} ->
|
{'EXIT', Reason} ->
|
||||||
?ERROR_MSG("Error when processing IQ stanza: ~p",
|
?ERROR_MSG("Error when processing IQ stanza: ~p",
|
||||||
[Reason]);
|
[Reason]);
|
||||||
@ -168,17 +168,17 @@ handle_info({route, From, To, #iq{} = Packet}, State) ->
|
|||||||
end,
|
end,
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
%% XEP33 allows only 'message' and 'presence' stanza type
|
%% XEP33 allows only 'message' and 'presence' stanza type
|
||||||
handle_info({route, From, To, Packet},
|
handle_info({route, Packet},
|
||||||
#state{lservice = LServiceS, lserver = LServerS,
|
#state{lservice = LServiceS, lserver = LServerS,
|
||||||
access = Access, service_limits = SLimits} =
|
access = Access, service_limits = SLimits} =
|
||||||
State) when ?is_stanza(Packet) ->
|
State) when ?is_stanza(Packet) ->
|
||||||
route_untrusted(LServiceS, LServerS, Access, SLimits,
|
route_untrusted(LServiceS, LServerS, Access, SLimits, Packet),
|
||||||
From, To, Packet),
|
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
%% Handle multicast packets sent by trusted local services
|
%% Handle multicast packets sent by trusted local services
|
||||||
handle_info({route_trusted, From, Destinations, Packet},
|
handle_info({route_trusted, Destinations, Packet},
|
||||||
#state{lservice = LServiceS, lserver = LServerS} =
|
#state{lservice = LServiceS, lserver = LServerS} =
|
||||||
State) ->
|
State) ->
|
||||||
|
From = xmpp:get_from(Packet),
|
||||||
case catch route_trusted(LServiceS, LServerS, From, Destinations,
|
case catch route_trusted(LServiceS, LServerS, From, Destinations,
|
||||||
Packet) of
|
Packet) of
|
||||||
{'EXIT', Reason} ->
|
{'EXIT', Reason} ->
|
||||||
@ -206,41 +206,42 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}.
|
|||||||
%%% IQ Request Processing
|
%%% IQ Request Processing
|
||||||
%%%------------------------
|
%%%------------------------
|
||||||
|
|
||||||
handle_iq(From, To, Packet, State) ->
|
handle_iq(Packet, State) ->
|
||||||
try
|
try
|
||||||
IQ = xmpp:decode_els(Packet),
|
IQ = xmpp:decode_els(Packet),
|
||||||
case process_iq(From, IQ, State) of
|
case process_iq(IQ, State) of
|
||||||
{result, SubEl} ->
|
{result, SubEl} ->
|
||||||
ejabberd_router:route(To, From, xmpp:make_iq_result(Packet, SubEl));
|
ejabberd_router:route(xmpp:make_iq_result(Packet, SubEl));
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
ejabberd_router:route_error(To, From, Packet, Error);
|
ejabberd_router:route_error(Packet, Error);
|
||||||
reply ->
|
reply ->
|
||||||
|
To = xmpp:get_to(IQ),
|
||||||
LServiceS = jid:to_string(To),
|
LServiceS = jid:to_string(To),
|
||||||
case Packet#iq.type of
|
case Packet#iq.type of
|
||||||
result ->
|
result ->
|
||||||
process_iqreply_result(From, LServiceS, IQ);
|
process_iqreply_result(LServiceS, IQ);
|
||||||
error ->
|
error ->
|
||||||
process_iqreply_error(From, LServiceS, IQ)
|
process_iqreply_error(LServiceS, IQ)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
catch _:{xmpp_codec, Why} ->
|
catch _:{xmpp_codec, Why} ->
|
||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
Err = xmpp:err_bad_request(xmpp:format_error(Why), Lang),
|
Err = xmpp:err_bad_request(xmpp:format_error(Why), Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec process_iq(jid(), iq(), state()) -> {result, xmpp_element()} |
|
-spec process_iq(iq(), state()) -> {result, xmpp_element()} |
|
||||||
{error, stanza_error()} | reply.
|
{error, stanza_error()} | reply.
|
||||||
process_iq(From, #iq{type = get, lang = Lang,
|
process_iq(#iq{type = get, lang = Lang, from = From,
|
||||||
sub_els = [#disco_info{}]}, State) ->
|
sub_els = [#disco_info{}]}, State) ->
|
||||||
{result, iq_disco_info(From, Lang, State)};
|
{result, iq_disco_info(From, Lang, State)};
|
||||||
process_iq(_, #iq{type = get, sub_els = [#disco_items{}]}, _) ->
|
process_iq(#iq{type = get, sub_els = [#disco_items{}]}, _) ->
|
||||||
{result, #disco_items{}};
|
{result, #disco_items{}};
|
||||||
process_iq(_, #iq{type = get, lang = Lang, sub_els = [#vcard_temp{}]}, _) ->
|
process_iq(#iq{type = get, lang = Lang, sub_els = [#vcard_temp{}]}, _) ->
|
||||||
{result, iq_vcard(Lang)};
|
{result, iq_vcard(Lang)};
|
||||||
process_iq(_, #iq{type = T}, _) when T == set; T == get ->
|
process_iq(#iq{type = T}, _) when T == set; T == get ->
|
||||||
{error, xmpp:err_service_unavailable()};
|
{error, xmpp:err_service_unavailable()};
|
||||||
process_iq(_, _, _) ->
|
process_iq(_, _) ->
|
||||||
reply.
|
reply.
|
||||||
|
|
||||||
-define(FEATURE(Feat), Feat).
|
-define(FEATURE(Feat), Feat).
|
||||||
@ -278,38 +279,37 @@ route_trusted(LServiceS, LServerS, FromJID,
|
|||||||
route_common(LServerS, LServiceS, FromJID, Groups,
|
route_common(LServerS, LServiceS, FromJID, Groups,
|
||||||
Delivereds, Packet_stripped, AAttrs).
|
Delivereds, Packet_stripped, AAttrs).
|
||||||
|
|
||||||
route_untrusted(LServiceS, LServerS, Access, SLimits,
|
route_untrusted(LServiceS, LServerS, Access, SLimits, Packet) ->
|
||||||
From, To, Packet) ->
|
|
||||||
try route_untrusted2(LServiceS, LServerS, Access,
|
try route_untrusted2(LServiceS, LServerS, Access,
|
||||||
SLimits, From, Packet)
|
SLimits, Packet)
|
||||||
catch
|
catch
|
||||||
adenied ->
|
adenied ->
|
||||||
route_error(To, From, Packet, forbidden,
|
route_error(Packet, forbidden,
|
||||||
<<"Access denied by service policy">>);
|
<<"Access denied by service policy">>);
|
||||||
eadsele ->
|
eadsele ->
|
||||||
route_error(To, From, Packet, bad_request,
|
route_error(Packet, bad_request,
|
||||||
<<"No addresses element found">>);
|
<<"No addresses element found">>);
|
||||||
eadeles ->
|
eadeles ->
|
||||||
route_error(To, From, Packet, bad_request,
|
route_error(Packet, bad_request,
|
||||||
<<"No address elements found">>);
|
<<"No address elements found">>);
|
||||||
ewxmlns ->
|
ewxmlns ->
|
||||||
route_error(To, From, Packet, bad_request,
|
route_error(Packet, bad_request,
|
||||||
<<"Wrong xmlns">>);
|
<<"Wrong xmlns">>);
|
||||||
etoorec ->
|
etoorec ->
|
||||||
route_error(To, From, Packet, not_acceptable,
|
route_error(Packet, not_acceptable,
|
||||||
<<"Too many receiver fields were specified">>);
|
<<"Too many receiver fields were specified">>);
|
||||||
edrelay ->
|
edrelay ->
|
||||||
route_error(To, From, Packet, forbidden,
|
route_error(Packet, forbidden,
|
||||||
<<"Packet relay is denied by service policy">>);
|
<<"Packet relay is denied by service policy">>);
|
||||||
EType:EReason ->
|
EType:EReason ->
|
||||||
?ERROR_MSG("Multicast unknown error: Type: ~p~nReason: ~p",
|
?ERROR_MSG("Multicast unknown error: Type: ~p~nReason: ~p",
|
||||||
[EType, EReason]),
|
[EType, EReason]),
|
||||||
route_error(To, From, Packet, internal_server_error,
|
route_error(Packet, internal_server_error,
|
||||||
<<"Unknown problem">>)
|
<<"Unknown problem">>)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
route_untrusted2(LServiceS, LServerS, Access, SLimits,
|
route_untrusted2(LServiceS, LServerS, Access, SLimits, Packet) ->
|
||||||
FromJID, Packet) ->
|
FromJID = xmpp:get_from(Packet),
|
||||||
ok = check_access(LServerS, Access, FromJID),
|
ok = check_access(LServerS, Access, FromJID),
|
||||||
{ok, Packet_stripped, Addresses} = strip_addresses_element(Packet),
|
{ok, Packet_stripped, Addresses} = strip_addresses_element(Packet),
|
||||||
{To_deliver, Delivereds} = split_addresses_todeliver(Addresses),
|
{To_deliver, Delivereds} = split_addresses_todeliver(Addresses),
|
||||||
@ -460,7 +460,7 @@ split_dests_jid(Dests) ->
|
|||||||
report_not_jid(From, Packet, Dests) ->
|
report_not_jid(From, Packet, Dests) ->
|
||||||
Dests2 = [fxml:element_to_binary(xmpp:encode(Dest#dest.full_xml))
|
Dests2 = [fxml:element_to_binary(xmpp:encode(Dest#dest.full_xml))
|
||||||
|| Dest <- Dests],
|
|| Dest <- Dests],
|
||||||
[route_error(From, From, Packet, jid_malformed,
|
[route_error(xmpp:set_from_to(Packet, From, From), jid_malformed,
|
||||||
<<"This service can not process the address: ",
|
<<"This service can not process the address: ",
|
||||||
D/binary>>)
|
D/binary>>)
|
||||||
|| D <- Dests2].
|
|| D <- Dests2].
|
||||||
@ -596,7 +596,7 @@ route_packet2(From, ToS, Dests, Packet, _AAttrs,
|
|||||||
end,
|
end,
|
||||||
Packet2 = xmpp:set_els(Packet, Els),
|
Packet2 = xmpp:set_els(Packet, Els),
|
||||||
ToJID = stj(ToS),
|
ToJID = stj(ToS),
|
||||||
ejabberd_router:route(From, ToJID, Packet2).
|
ejabberd_router:route(xmpp:set_from_to(Packet2, From, ToJID)).
|
||||||
|
|
||||||
-spec append_dests([#dest{}], {[address()], [address()]} | [address()]) -> [address()].
|
-spec append_dests([#dest{}], {[address()], [address()]} | [address()]) -> [address()].
|
||||||
append_dests(_Dests, {Others, Addresses}) ->
|
append_dests(_Dests, {Others, Addresses}) ->
|
||||||
@ -645,17 +645,18 @@ send_query_items(RServerS, LServiceS) ->
|
|||||||
|
|
||||||
-spec send_query(binary(), binary(), [disco_info()|disco_items()]) -> ok.
|
-spec send_query(binary(), binary(), [disco_info()|disco_items()]) -> ok.
|
||||||
send_query(RServerS, LServiceS, SubEl) ->
|
send_query(RServerS, LServiceS, SubEl) ->
|
||||||
Packet = #iq{id = randoms:get_string(),
|
Packet = #iq{from = stj(LServiceS),
|
||||||
|
to = stj(RServerS),
|
||||||
|
id = randoms:get_string(),
|
||||||
type = get, sub_els = [SubEl]},
|
type = get, sub_els = [SubEl]},
|
||||||
ejabberd_router:route(stj(LServiceS), stj(RServerS),
|
ejabberd_router:route(Packet).
|
||||||
Packet).
|
|
||||||
|
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
%%% Check protocol support: Receive response: Error
|
%%% Check protocol support: Receive response: Error
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
|
|
||||||
process_iqreply_error(From, LServiceS, _Packet) ->
|
process_iqreply_error(LServiceS, Packet) ->
|
||||||
FromS = jts(From),
|
FromS = jts(xmpp:get_from(Packet)),
|
||||||
case search_waiter(FromS, LServiceS, info) of
|
case search_waiter(FromS, LServiceS, info) of
|
||||||
{found_waiter, Waiter} ->
|
{found_waiter, Waiter} ->
|
||||||
received_awaiter(FromS, Waiter, LServiceS);
|
received_awaiter(FromS, Waiter, LServiceS);
|
||||||
@ -666,8 +667,8 @@ process_iqreply_error(From, LServiceS, _Packet) ->
|
|||||||
%%% Check protocol support: Receive response: Disco
|
%%% Check protocol support: Receive response: Disco
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
|
|
||||||
-spec process_iqreply_result(jid(), binary(), iq()) -> any().
|
-spec process_iqreply_result(binary(), iq()) -> any().
|
||||||
process_iqreply_result(From, LServiceS, #iq{sub_els = [SubEl]}) ->
|
process_iqreply_result(LServiceS, #iq{from = From, sub_els = [SubEl]}) ->
|
||||||
case SubEl of
|
case SubEl of
|
||||||
#disco_info{} ->
|
#disco_info{} ->
|
||||||
process_discoinfo_result(From, LServiceS, SubEl);
|
process_discoinfo_result(From, LServiceS, SubEl);
|
||||||
@ -1077,10 +1078,10 @@ to_binary(A) -> list_to_binary(hd(io_lib:format("~p", [A]))).
|
|||||||
%%% Error report
|
%%% Error report
|
||||||
%%%-------------------------
|
%%%-------------------------
|
||||||
|
|
||||||
route_error(From, To, Packet, ErrType, ErrText) ->
|
route_error(Packet, ErrType, ErrText) ->
|
||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
Err = make_reply(ErrType, Lang, ErrText),
|
Err = make_reply(ErrType, Lang, ErrText),
|
||||||
ejabberd_router:route_error(From, To, Packet, Err).
|
ejabberd_router:route_error(Packet, Err).
|
||||||
|
|
||||||
make_reply(bad_request, Lang, ErrText) ->
|
make_reply(bad_request, Lang, ErrText) ->
|
||||||
xmpp:err_bad_request(ErrText, Lang);
|
xmpp:err_bad_request(ErrText, Lang);
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
-export([start/2,
|
-export([start/2,
|
||||||
stop/1,
|
stop/1,
|
||||||
store_packet/4,
|
store_packet/2,
|
||||||
store_offline_msg/5,
|
store_offline_msg/5,
|
||||||
c2s_self_presence/1,
|
c2s_self_presence/1,
|
||||||
get_sm_features/5,
|
get_sm_features/5,
|
||||||
@ -353,11 +353,11 @@ handle_offline_items_view(JID, Items) ->
|
|||||||
case fetch_msg_by_node(JID, Node) of
|
case fetch_msg_by_node(JID, Node) of
|
||||||
{ok, OfflineMsg} ->
|
{ok, OfflineMsg} ->
|
||||||
case offline_msg_to_route(S, OfflineMsg) of
|
case offline_msg_to_route(S, OfflineMsg) of
|
||||||
{route, From, To, El} ->
|
{route, El} ->
|
||||||
NewEl = set_offline_tag(El, Node),
|
NewEl = set_offline_tag(El, Node),
|
||||||
case ejabberd_sm:get_session_pid(U, S, R) of
|
case ejabberd_sm:get_session_pid(U, S, R) of
|
||||||
Pid when is_pid(Pid) ->
|
Pid when is_pid(Pid) ->
|
||||||
Pid ! {route, From, To, NewEl};
|
Pid ! {route, NewEl};
|
||||||
none ->
|
none ->
|
||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
@ -387,9 +387,7 @@ handle_offline_fetch(#jid{luser = U, lserver = S} = JID) ->
|
|||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({Node, El}) ->
|
fun({Node, El}) ->
|
||||||
El1 = set_offline_tag(El, Node),
|
El1 = set_offline_tag(El, Node),
|
||||||
From = xmpp:get_from(El1),
|
ejabberd_router:route(El1)
|
||||||
To = xmpp:get_to(El1),
|
|
||||||
ejabberd_router:route(From, To, El1)
|
|
||||||
end, read_messages(U, S)).
|
end, read_messages(U, S)).
|
||||||
|
|
||||||
-spec fetch_msg_by_node(jid(), binary()) -> error | {ok, #offline_msg{}}.
|
-spec fetch_msg_by_node(jid(), binary()) -> error | {ok, #offline_msg{}}.
|
||||||
@ -448,11 +446,11 @@ need_to_store(LServer, #message{type = Type} = Packet) ->
|
|||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec store_packet(any(), jid(), jid(), message()) -> any().
|
-spec store_packet(any(), message()) -> any().
|
||||||
store_packet(Acc, From, To, Packet) ->
|
store_packet(Acc, #message{from = From, to = To} = Packet) ->
|
||||||
case need_to_store(To#jid.lserver, Packet) of
|
case need_to_store(To#jid.lserver, Packet) of
|
||||||
true ->
|
true ->
|
||||||
case check_event(From, To, Packet) of
|
case check_event(Packet) of
|
||||||
true ->
|
true ->
|
||||||
#jid{luser = LUser, lserver = LServer} = To,
|
#jid{luser = LUser, lserver = LServer} = To,
|
||||||
case ejabberd_hooks:run_fold(store_offline_message, LServer,
|
case ejabberd_hooks:run_fold(store_offline_message, LServer,
|
||||||
@ -501,16 +499,17 @@ has_no_store_hint(Packet) ->
|
|||||||
xmpp:has_subtag(Packet, #hint{type = 'no-storage'}).
|
xmpp:has_subtag(Packet, #hint{type = 'no-storage'}).
|
||||||
|
|
||||||
%% Check if the packet has any content about XEP-0022
|
%% Check if the packet has any content about XEP-0022
|
||||||
-spec check_event(jid(), jid(), message()) -> boolean().
|
-spec check_event(message()) -> boolean().
|
||||||
check_event(From, To, #message{id = ID} = Msg) ->
|
check_event(#message{from = From, to = To, id = ID} = Msg) ->
|
||||||
case xmpp:get_subtag(Msg, #xevent{}) of
|
case xmpp:get_subtag(Msg, #xevent{}) of
|
||||||
false ->
|
false ->
|
||||||
true;
|
true;
|
||||||
#xevent{id = undefined, offline = false} ->
|
#xevent{id = undefined, offline = false} ->
|
||||||
true;
|
true;
|
||||||
#xevent{id = undefined, offline = true} ->
|
#xevent{id = undefined, offline = true} ->
|
||||||
NewMsg = Msg#message{sub_els = [#xevent{id = ID, offline = true}]},
|
NewMsg = Msg#message{from = To, to = From,
|
||||||
ejabberd_router:route(To, From, xmpp:set_from_to(NewMsg, To, From)),
|
sub_els = [#xevent{id = ID, offline = true}]},
|
||||||
|
ejabberd_router:route(NewMsg),
|
||||||
true;
|
true;
|
||||||
_ ->
|
_ ->
|
||||||
false
|
false
|
||||||
@ -565,13 +564,13 @@ route_offline_message(#{lserver := LServer} = State,
|
|||||||
case offline_msg_to_route(LServer, OffMsg) of
|
case offline_msg_to_route(LServer, OffMsg) of
|
||||||
error ->
|
error ->
|
||||||
ok;
|
ok;
|
||||||
{route, From, To, Msg} ->
|
{route, Msg} ->
|
||||||
case is_message_expired(Expire, Msg) of
|
case is_message_expired(Expire, Msg) of
|
||||||
true ->
|
true ->
|
||||||
ok;
|
ok;
|
||||||
false ->
|
false ->
|
||||||
case privacy_check_packet(State, Msg, in) of
|
case privacy_check_packet(State, Msg, in) of
|
||||||
allow -> ejabberd_router:route(From, To, Msg);
|
allow -> ejabberd_router:route(Msg);
|
||||||
false -> ok
|
false -> ok
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -614,12 +613,12 @@ remove_user(User, Server) ->
|
|||||||
%% Warn senders that their messages have been discarded:
|
%% Warn senders that their messages have been discarded:
|
||||||
discard_warn_sender(Msgs) ->
|
discard_warn_sender(Msgs) ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(#offline_msg{from = From, to = To, packet = Packet}) ->
|
fun(#offline_msg{packet = Packet}) ->
|
||||||
ErrText = <<"Your contact offline message queue is "
|
ErrText = <<"Your contact offline message queue is "
|
||||||
"full. The message has been discarded.">>,
|
"full. The message has been discarded.">>,
|
||||||
Lang = xmpp:get_lang(Packet),
|
Lang = xmpp:get_lang(Packet),
|
||||||
Err = xmpp:err_resource_constraint(ErrText, Lang),
|
Err = xmpp:err_resource_constraint(ErrText, Lang),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end, Msgs).
|
end, Msgs).
|
||||||
|
|
||||||
webadmin_page(_, Host,
|
webadmin_page(_, Host,
|
||||||
@ -633,13 +632,13 @@ get_offline_els(LUser, LServer) ->
|
|||||||
[Packet || {_Seq, Packet} <- read_messages(LUser, LServer)].
|
[Packet || {_Seq, Packet} <- read_messages(LUser, LServer)].
|
||||||
|
|
||||||
-spec offline_msg_to_route(binary(), #offline_msg{}) ->
|
-spec offline_msg_to_route(binary(), #offline_msg{}) ->
|
||||||
{route, jid(), jid(), message()} | error.
|
{route, message()} | error.
|
||||||
offline_msg_to_route(LServer, #offline_msg{from = From, to = To} = R) ->
|
offline_msg_to_route(LServer, #offline_msg{from = From, to = To} = R) ->
|
||||||
try xmpp:decode(R#offline_msg.packet, ?NS_CLIENT, [ignore_els]) of
|
try xmpp:decode(R#offline_msg.packet, ?NS_CLIENT, [ignore_els]) of
|
||||||
Pkt ->
|
Pkt ->
|
||||||
Pkt1 = xmpp:set_from_to(Pkt, From, To),
|
Pkt1 = xmpp:set_from_to(Pkt, From, To),
|
||||||
Pkt2 = add_delay_info(Pkt1, LServer, R#offline_msg.timestamp),
|
Pkt2 = add_delay_info(Pkt1, LServer, R#offline_msg.timestamp),
|
||||||
{route, From, To, Pkt2}
|
{route, Pkt2}
|
||||||
catch _:{xmpp_codec, Why} ->
|
catch _:{xmpp_codec, Why} ->
|
||||||
?ERROR_MSG("failed to decode packet ~p of user ~s: ~s",
|
?ERROR_MSG("failed to decode packet ~p of user ~s: ~s",
|
||||||
[R#offline_msg.packet, jid:to_string(To),
|
[R#offline_msg.packet, jid:to_string(To),
|
||||||
|
@ -172,13 +172,13 @@ handle_cast({iq_pong, JID, timeout}, State) ->
|
|||||||
handle_cast(_Msg, State) -> {noreply, State}.
|
handle_cast(_Msg, State) -> {noreply, State}.
|
||||||
|
|
||||||
handle_info({timeout, _TRef, {ping, JID}}, State) ->
|
handle_info({timeout, _TRef, {ping, JID}}, State) ->
|
||||||
IQ = #iq{type = get, sub_els = [#ping{}]},
|
From = jid:make(State#state.host),
|
||||||
|
IQ = #iq{from = From, to = JID, type = get, sub_els = [#ping{}]},
|
||||||
Pid = self(),
|
Pid = self(),
|
||||||
F = fun (Response) ->
|
F = fun (Response) ->
|
||||||
gen_server:cast(Pid, {iq_pong, JID, Response})
|
gen_server:cast(Pid, {iq_pong, JID, Response})
|
||||||
end,
|
end,
|
||||||
From = jid:make(<<"">>, State#state.host, <<"">>),
|
ejabberd_local:route_iq(IQ, F, State#state.ping_ack_timeout),
|
||||||
ejabberd_local:route_iq(From, JID, IQ, F, State#state.ping_ack_timeout),
|
|
||||||
Timers = add_timer(JID, State#state.ping_interval,
|
Timers = add_timer(JID, State#state.ping_interval,
|
||||||
State#state.timers),
|
State#state.timers),
|
||||||
{noreply, State#state{timers = Timers}};
|
{noreply, State#state{timers = Timers}};
|
||||||
|
@ -366,7 +366,7 @@ push_list_update(From, List, Name) ->
|
|||||||
sub_els = [#privacy_query{
|
sub_els = [#privacy_query{
|
||||||
lists = [#privacy_list{name = Name}]}],
|
lists = [#privacy_list{name = Name}]}],
|
||||||
meta = #{privacy_updated_list => List}},
|
meta = #{privacy_updated_list => List}},
|
||||||
ejabberd_router:route(BareFrom, To, IQ)
|
ejabberd_router:route(IQ)
|
||||||
end, ejabberd_sm:get_user_resources(From#jid.luser, From#jid.lserver)).
|
end, ejabberd_sm:get_user_resources(From#jid.luser, From#jid.lserver)).
|
||||||
|
|
||||||
-spec user_send_packet({stanza(), ejabberd_c2s:state()}) -> {stanza(), ejabberd_c2s:state()}.
|
-spec user_send_packet({stanza(), ejabberd_c2s:state()}) -> {stanza(), ejabberd_c2s:state()}.
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||||
terminate/2, code_change/3]).
|
terminate/2, code_change/3]).
|
||||||
-export([component_connected/1, component_disconnected/2,
|
-export([component_connected/1, component_disconnected/2,
|
||||||
roster_access/2, process_message/3,
|
roster_access/2, process_message/1,
|
||||||
process_presence_out/1, process_presence_in/1]).
|
process_presence_out/1, process_presence_in/1]).
|
||||||
|
|
||||||
-include("ejabberd.hrl").
|
-include("ejabberd.hrl").
|
||||||
@ -80,10 +80,10 @@ component_disconnected(Host, _Reason) ->
|
|||||||
gen_server:cast(Proc, {component_disconnected, Host})
|
gen_server:cast(Proc, {component_disconnected, Host})
|
||||||
end, ?MYHOSTS).
|
end, ?MYHOSTS).
|
||||||
|
|
||||||
-spec process_message(jid(), jid(), stanza()) -> stop | ok.
|
-spec process_message(stanza()) -> stop | ok.
|
||||||
process_message(#jid{luser = <<"">>, lresource = <<"">>} = From,
|
process_message(#message{from = #jid{luser = <<"">>, lresource = <<"">>} = From,
|
||||||
#jid{lresource = <<"">>} = To,
|
to = #jid{lresource = <<"">>} = To,
|
||||||
#message{lang = Lang, type = T} = Msg) when T /= error ->
|
lang = Lang, type = T} = Msg) when T /= error ->
|
||||||
Host = From#jid.lserver,
|
Host = From#jid.lserver,
|
||||||
ServerHost = To#jid.lserver,
|
ServerHost = To#jid.lserver,
|
||||||
Permissions = get_permissions(ServerHost),
|
Permissions = get_permissions(ServerHost),
|
||||||
@ -91,18 +91,18 @@ process_message(#jid{luser = <<"">>, lresource = <<"">>} = From,
|
|||||||
{ok, Access} ->
|
{ok, Access} ->
|
||||||
case proplists:get_value(message, Access, none) of
|
case proplists:get_value(message, Access, none) of
|
||||||
outgoing ->
|
outgoing ->
|
||||||
forward_message(From, To, Msg);
|
forward_message(Msg);
|
||||||
none ->
|
none ->
|
||||||
Txt = <<"Insufficient privilege">>,
|
Txt = <<"Insufficient privilege">>,
|
||||||
Err = xmpp:err_forbidden(Txt, Lang),
|
Err = xmpp:err_forbidden(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Msg, Err)
|
ejabberd_router:route_error(Msg, Err)
|
||||||
end,
|
end,
|
||||||
stop;
|
stop;
|
||||||
error ->
|
error ->
|
||||||
%% Component is disconnected
|
%% Component is disconnected
|
||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
process_message(_From, _To, _Stanza) ->
|
process_message(_Stanza) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec roster_access(boolean(), iq()) -> boolean().
|
-spec roster_access(boolean(), iq()) -> boolean().
|
||||||
@ -137,7 +137,7 @@ process_presence_out({#presence{
|
|||||||
if Permission == roster; Permission == managed_entity ->
|
if Permission == roster; Permission == managed_entity ->
|
||||||
To = jid:make(Host),
|
To = jid:make(Host),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
From, To, xmpp:set_from_to(Pres, From, To));
|
xmpp:set_from_to(Pres, From, To));
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end
|
end
|
||||||
@ -162,7 +162,7 @@ process_presence_in({#presence{
|
|||||||
if Permission == both; Permission == get ->
|
if Permission == both; Permission == get ->
|
||||||
To = jid:make(Host),
|
To = jid:make(Host),
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
From, To, xmpp:set_from_to(Pres, From, To));
|
xmpp:set_from_to(Pres, From, To));
|
||||||
true ->
|
true ->
|
||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
@ -218,7 +218,7 @@ handle_cast({component_connected, Host}, State) ->
|
|||||||
"message = ~s",
|
"message = ~s",
|
||||||
[Host, RosterPerm, PresencePerm, MessagePerm]),
|
[Host, RosterPerm, PresencePerm, MessagePerm]),
|
||||||
Msg = #message{from = From, to = To, sub_els = [Priv]},
|
Msg = #message{from = From, to = To, sub_els = [Priv]},
|
||||||
ejabberd_router:route(From, To, Msg),
|
ejabberd_router:route(Msg),
|
||||||
Permissions = dict:store(Host, [{roster, RosterPerm},
|
Permissions = dict:store(Host, [{roster, RosterPerm},
|
||||||
{presence, PresencePerm},
|
{presence, PresencePerm},
|
||||||
{message, MessagePerm}],
|
{message, MessagePerm}],
|
||||||
@ -267,7 +267,7 @@ get_permissions(ServerHost) ->
|
|||||||
dict:new()
|
dict:new()
|
||||||
end.
|
end.
|
||||||
|
|
||||||
forward_message(From, To, Msg) ->
|
forward_message(#message{to = To} = Msg) ->
|
||||||
ServerHost = To#jid.lserver,
|
ServerHost = To#jid.lserver,
|
||||||
Lang = xmpp:get_lang(Msg),
|
Lang = xmpp:get_lang(Msg),
|
||||||
case xmpp:get_subtag(Msg, #privilege{}) of
|
case xmpp:get_subtag(Msg, #privilege{}) of
|
||||||
@ -276,27 +276,26 @@ forward_message(From, To, Msg) ->
|
|||||||
#message{} = NewMsg ->
|
#message{} = NewMsg ->
|
||||||
case NewMsg#message.from of
|
case NewMsg#message.from of
|
||||||
#jid{lresource = <<"">>, lserver = ServerHost} ->
|
#jid{lresource = <<"">>, lserver = ServerHost} ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(NewMsg);
|
||||||
xmpp:get_from(NewMsg), xmpp:get_to(NewMsg), NewMsg);
|
|
||||||
_ ->
|
_ ->
|
||||||
Lang = xmpp:get_lang(Msg),
|
Lang = xmpp:get_lang(Msg),
|
||||||
Txt = <<"Invalid 'from' attribute in forwarded message">>,
|
Txt = <<"Invalid 'from' attribute in forwarded message">>,
|
||||||
Err = xmpp:err_forbidden(Txt, Lang),
|
Err = xmpp:err_forbidden(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Msg, Err)
|
ejabberd_router:route_error(Msg, Err)
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
Txt = <<"Message not found in forwarded payload">>,
|
Txt = <<"Message not found in forwarded payload">>,
|
||||||
Err = xmpp:err_bad_request(Txt, Lang),
|
Err = xmpp:err_bad_request(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Msg, Err)
|
ejabberd_router:route_error(Msg, Err)
|
||||||
catch _:{xmpp_codec, Why} ->
|
catch _:{xmpp_codec, Why} ->
|
||||||
Txt = xmpp:format_error(Why),
|
Txt = xmpp:format_error(Why),
|
||||||
Err = xmpp:err_bad_request(Txt, Lang),
|
Err = xmpp:err_bad_request(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Msg, Err)
|
ejabberd_router:route_error(Msg, Err)
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
Txt = <<"Invalid <forwarded/> element">>,
|
Txt = <<"Invalid <forwarded/> element">>,
|
||||||
Err = xmpp:err_bad_request(Txt, Lang),
|
Err = xmpp:err_bad_request(Txt, Lang),
|
||||||
ejabberd_router:route_error(To, From, Msg, Err)
|
ejabberd_router:route_error(Msg, Err)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
get_roster_permission(ServerHost, Host) ->
|
get_roster_permission(ServerHost, Host) ->
|
||||||
|
@ -77,8 +77,8 @@ terminate(_Reason, #state{myhost = MyHost}) ->
|
|||||||
gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_VCARD),
|
gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_VCARD),
|
||||||
gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_BYTESTREAMS).
|
gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_BYTESTREAMS).
|
||||||
|
|
||||||
handle_info({route, From, To, #iq{} = Packet}, State) ->
|
handle_info({route, #iq{} = Packet}, State) ->
|
||||||
ejabberd_router:process_iq(From, To, Packet),
|
ejabberd_router:process_iq(Packet),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info(_Info, State) -> {noreply, State}.
|
handle_info(_Info, State) -> {noreply, State}.
|
||||||
|
|
||||||
|
@ -855,12 +855,13 @@ handle_cast(_Msg, State) -> {noreply, State}.
|
|||||||
%% Description: Handling all non call/cast messages
|
%% Description: Handling all non call/cast messages
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% @private
|
%% @private
|
||||||
handle_info({route, From, To, #iq{} = IQ},
|
handle_info({route, #iq{to = To} = IQ},
|
||||||
State) when To#jid.lresource == <<"">> ->
|
State) when To#jid.lresource == <<"">> ->
|
||||||
ejabberd_router:process_iq(From, To, IQ),
|
ejabberd_router:process_iq(IQ),
|
||||||
{noreply, State};
|
{noreply, State};
|
||||||
handle_info({route, From, To, Packet}, State) ->
|
handle_info({route, Packet}, State) ->
|
||||||
case catch do_route(To#jid.lserver, From, To, Packet) of
|
To = xmpp:get_to(Packet),
|
||||||
|
case catch do_route(To#jid.lserver, Packet) of
|
||||||
{'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]);
|
{'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]);
|
||||||
_ -> ok
|
_ -> ok
|
||||||
end,
|
end,
|
||||||
@ -1019,8 +1020,9 @@ process_commands(#iq{type = get, lang = Lang} = IQ) ->
|
|||||||
Txt = <<"Value 'get' of 'type' attribute is not allowed">>,
|
Txt = <<"Value 'get' of 'type' attribute is not allowed">>,
|
||||||
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang)).
|
xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang)).
|
||||||
|
|
||||||
-spec do_route(binary(), jid(), jid(), stanza()) -> ok.
|
-spec do_route(binary(), stanza()) -> ok.
|
||||||
do_route(Host, From, To, Packet) ->
|
do_route(Host, Packet) ->
|
||||||
|
To = xmpp:get_to(Packet),
|
||||||
case To of
|
case To of
|
||||||
#jid{luser = <<>>, lresource = <<>>} ->
|
#jid{luser = <<>>, lresource = <<>>} ->
|
||||||
case Packet of
|
case Packet of
|
||||||
@ -1029,18 +1031,18 @@ do_route(Host, From, To, Packet) ->
|
|||||||
undefined ->
|
undefined ->
|
||||||
ok;
|
ok;
|
||||||
{error, Err} ->
|
{error, Err} ->
|
||||||
ejabberd_router:route_error(To, From, Packet, Err);
|
ejabberd_router:route_error(Packet, Err);
|
||||||
AuthResponse ->
|
AuthResponse ->
|
||||||
handle_authorization_response(
|
handle_authorization_response(
|
||||||
Host, From, To, Packet, AuthResponse)
|
Host, Packet, AuthResponse)
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
Err = xmpp:err_service_unavailable(),
|
Err = xmpp:err_service_unavailable(),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
Err = xmpp:err_item_not_found(),
|
Err = xmpp:err_item_not_found(),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec command_disco_info(binary(), binary(), jid()) -> {result, disco_info()}.
|
-spec command_disco_info(binary(), binary(), jid()) -> {result, disco_info()}.
|
||||||
@ -1461,10 +1463,10 @@ send_authorization_request(#pubsub_node{nodeid = {Host, Node},
|
|||||||
<<"Choose whether to approve this entity's "
|
<<"Choose whether to approve this entity's "
|
||||||
"subscription.">>)],
|
"subscription.">>)],
|
||||||
fields = Fs},
|
fields = Fs},
|
||||||
Stanza = #message{sub_els = [X]},
|
Stanza = #message{from = service_jid(Host), sub_els = [X]},
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun (Owner) ->
|
fun (Owner) ->
|
||||||
ejabberd_router:route(service_jid(Host), jid:make(Owner), Stanza)
|
ejabberd_router:route(xmpp:set_to(Stanza, jid:make(Owner)))
|
||||||
end, node_owners_action(Host, Type, Nidx, O)).
|
end, node_owners_action(Host, Type, Nidx, O)).
|
||||||
|
|
||||||
-spec find_authorization_response(message()) -> undefined |
|
-spec find_authorization_response(message()) -> undefined |
|
||||||
@ -1495,12 +1497,12 @@ send_authorization_approval(Host, JID, SNode, Subscription) ->
|
|||||||
#ps_subscription{jid = JID,
|
#ps_subscription{jid = JID,
|
||||||
node = SNode,
|
node = SNode,
|
||||||
type = Subscription}},
|
type = Subscription}},
|
||||||
Stanza = #message{sub_els = [Event]},
|
Stanza = #message{from = service_jid(Host), to = JID, sub_els = [Event]},
|
||||||
ejabberd_router:route(service_jid(Host), JID, Stanza).
|
ejabberd_router:route(Stanza).
|
||||||
|
|
||||||
-spec handle_authorization_response(binary(), jid(), jid(), message(),
|
-spec handle_authorization_response(binary(), message(),
|
||||||
pubsub_subscribe_authorization:result()) -> ok.
|
pubsub_subscribe_authorization:result()) -> ok.
|
||||||
handle_authorization_response(Host, From, To, Packet, Response) ->
|
handle_authorization_response(Host, #message{from = From} = Packet, Response) ->
|
||||||
Node = proplists:get_value(node, Response),
|
Node = proplists:get_value(node, Response),
|
||||||
Subscriber = proplists:get_value(subscriber_jid, Response),
|
Subscriber = proplists:get_value(subscriber_jid, Response),
|
||||||
Allow = proplists:get_value(allow, Response),
|
Allow = proplists:get_value(allow, Response),
|
||||||
@ -1519,13 +1521,13 @@ handle_authorization_response(Host, From, To, Packet, Response) ->
|
|||||||
end,
|
end,
|
||||||
case transaction(Host, Node, Action, sync_dirty) of
|
case transaction(Host, Node, Action, sync_dirty) of
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
ejabberd_router:route_error(To, From, Packet, Error);
|
ejabberd_router:route_error(Packet, Error);
|
||||||
{result, {_, _NewSubscription}} ->
|
{result, {_, _NewSubscription}} ->
|
||||||
%% XXX: notify about subscription state change, section 12.11
|
%% XXX: notify about subscription state change, section 12.11
|
||||||
ok;
|
ok;
|
||||||
_ ->
|
_ ->
|
||||||
Err = xmpp:err_internal_server_error(),
|
Err = xmpp:err_internal_server_error(),
|
||||||
ejabberd_router:route_error(To, From, Packet, Err)
|
ejabberd_router:route_error(Packet, Err)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec update_auth(binary(), binary(), _, _, jid() | error, boolean(), _) ->
|
-spec update_auth(binary(), binary(), _, _, jid() | error, boolean(), _) ->
|
||||||
@ -2231,7 +2233,8 @@ dispatch_items({FromU, FromS, FromR} = From, {ToU, ToS, ToR} = To,
|
|||||||
Stanza}
|
Stanza}
|
||||||
end;
|
end;
|
||||||
dispatch_items(From, To, _Node, Stanza) ->
|
dispatch_items(From, To, _Node, Stanza) ->
|
||||||
ejabberd_router:route(service_jid(From), jid:make(To), Stanza).
|
ejabberd_router:route(
|
||||||
|
xmpp:set_from_to(Stanza, service_jid(From), jid:make(To))).
|
||||||
|
|
||||||
%% @doc <p>Return the list of affiliations as an XMPP response.</p>
|
%% @doc <p>Return the list of affiliations as an XMPP response.</p>
|
||||||
-spec get_affiliations(host(), binary(), jid(), [binary()]) ->
|
-spec get_affiliations(host(), binary(), jid(), [binary()]) ->
|
||||||
@ -2603,12 +2606,14 @@ set_subscriptions(Host, Node, From, Entities) ->
|
|||||||
Owner = jid:tolower(jid:remove_resource(From)),
|
Owner = jid:tolower(jid:remove_resource(From)),
|
||||||
Notify = fun(#ps_subscription{jid = JID, type = Sub}) ->
|
Notify = fun(#ps_subscription{jid = JID, type = Sub}) ->
|
||||||
Stanza = #message{
|
Stanza = #message{
|
||||||
|
from = service_jid(Host),
|
||||||
|
to = JID,
|
||||||
sub_els = [#ps_event{
|
sub_els = [#ps_event{
|
||||||
subscription = #ps_subscription{
|
subscription = #ps_subscription{
|
||||||
jid = JID,
|
jid = JID,
|
||||||
type = Sub,
|
type = Sub,
|
||||||
node = Node}}]},
|
node = Node}}]},
|
||||||
ejabberd_router:route(service_jid(Host), JID, Stanza)
|
ejabberd_router:route(Stanza)
|
||||||
end,
|
end,
|
||||||
Action =
|
Action =
|
||||||
fun(#pubsub_node{type = Type, id = Nidx, owners = O}) ->
|
fun(#pubsub_node{type = Type, id = Nidx, owners = O}) ->
|
||||||
@ -3002,7 +3007,8 @@ broadcast_stanza(Host, _Node, _Nidx, _Type, NodeOptions, SubsByDepth, NotifyType
|
|||||||
add_shim_headers(Stanza, subid_shim(SubIDs))
|
add_shim_headers(Stanza, subid_shim(SubIDs))
|
||||||
end,
|
end,
|
||||||
lists:foreach(fun(To) ->
|
lists:foreach(fun(To) ->
|
||||||
ejabberd_router:route(From, jid:make(To), StanzaToSend)
|
ejabberd_router:route(
|
||||||
|
xmpp:set_from_to(StanzaToSend, From, jid:make(To)))
|
||||||
end, LJIDs)
|
end, LJIDs)
|
||||||
end, SubIDsByJID).
|
end, SubIDsByJID).
|
||||||
|
|
||||||
@ -3034,7 +3040,7 @@ c2s_handle_info(#{server := Server} = C2SState,
|
|||||||
true ->
|
true ->
|
||||||
To = jid:make(USR),
|
To = jid:make(USR),
|
||||||
NewPacket = xmpp:set_from_to(Packet, From, To),
|
NewPacket = xmpp:set_from_to(Packet, From, To),
|
||||||
ejabberd_router:route(From, To, NewPacket);
|
ejabberd_router:route(NewPacket);
|
||||||
false ->
|
false ->
|
||||||
ok
|
ok
|
||||||
end
|
end
|
||||||
@ -3049,7 +3055,7 @@ c2s_handle_info(#{server := Server} = C2SState,
|
|||||||
case lists:member(Feature, Features) of
|
case lists:member(Feature, Features) of
|
||||||
true ->
|
true ->
|
||||||
NewPacket = xmpp:set_from_to(Packet, From, To),
|
NewPacket = xmpp:set_from_to(Packet, From, To),
|
||||||
ejabberd_router:route(From, To, NewPacket);
|
ejabberd_router:route(NewPacket);
|
||||||
false ->
|
false ->
|
||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
|
@ -150,7 +150,7 @@ process_iq(#iq{type = set, lang = Lang, to = To, from = From,
|
|||||||
case From of
|
case From of
|
||||||
#jid{luser = LUser, lserver = Server} ->
|
#jid{luser = LUser, lserver = Server} ->
|
||||||
ResIQ = xmpp:make_iq_result(IQ),
|
ResIQ = xmpp:make_iq_result(IQ),
|
||||||
ejabberd_router:route(From, From, ResIQ),
|
ejabberd_router:route(xmpp:set_from_to(ResIQ, From, From)),
|
||||||
ejabberd_auth:remove_user(LUser, Server),
|
ejabberd_auth:remove_user(LUser, Server),
|
||||||
ignore;
|
ignore;
|
||||||
_ ->
|
_ ->
|
||||||
@ -380,8 +380,9 @@ send_welcome_message(JID) ->
|
|||||||
{<<"">>, <<"">>} -> ok;
|
{<<"">>, <<"">>} -> ok;
|
||||||
{Subj, Body} ->
|
{Subj, Body} ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(Host), JID,
|
#message{from = jid:make(Host),
|
||||||
#message{subject = xmpp:mk_text(Subj),
|
to = JID,
|
||||||
|
subject = xmpp:mk_text(Subj),
|
||||||
body = xmpp:mk_text(Body)});
|
body = xmpp:mk_text(Body)});
|
||||||
_ -> ok
|
_ -> ok
|
||||||
end.
|
end.
|
||||||
@ -406,8 +407,9 @@ send_registration_notifications(Mod, UJID, Source) ->
|
|||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(JID) ->
|
fun(JID) ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
jid:make(Host), JID,
|
#message{from = jid:make(Host),
|
||||||
#message{type = chat,
|
to = JID,
|
||||||
|
type = chat,
|
||||||
body = xmpp:mk_text(Body)})
|
body = xmpp:mk_text(Body)})
|
||||||
end, JIDs)
|
end, JIDs)
|
||||||
end.
|
end.
|
||||||
|
@ -451,7 +451,7 @@ push_item(User, Server, Resource, From, Item,
|
|||||||
id = <<"push", (randoms:get_string())/binary>>,
|
id = <<"push", (randoms:get_string())/binary>>,
|
||||||
sub_els = [#roster_query{ver = Ver,
|
sub_els = [#roster_query{ver = Ver,
|
||||||
items = [encode_item(Item)]}]},
|
items = [encode_item(Item)]}]},
|
||||||
ejabberd_router:route(From, To, xmpp:put_meta(ResIQ, roster_item, Item)).
|
ejabberd_router:route(xmpp:put_meta(ResIQ, roster_item, Item)).
|
||||||
|
|
||||||
push_item_version(Server, User, From, Item,
|
push_item_version(Server, User, From, Item,
|
||||||
RosterVersion) ->
|
RosterVersion) ->
|
||||||
@ -499,7 +499,7 @@ roster_change(#{user := U, server := S, resource := R,
|
|||||||
ok;
|
ok;
|
||||||
allow ->
|
allow ->
|
||||||
Pres = xmpp:set_from_to(LastPres, From, To),
|
Pres = xmpp:set_from_to(LastPres, From, To),
|
||||||
ejabberd_router:route(From, To, Pres)
|
ejabberd_router:route(Pres)
|
||||||
end,
|
end,
|
||||||
A = ?SETS:add_element(LIJID, PresA),
|
A = ?SETS:add_element(LIJID, PresA),
|
||||||
State1#{pres_a => A};
|
State1#{pres_a => A};
|
||||||
@ -511,7 +511,7 @@ roster_change(#{user := U, server := S, resource := R,
|
|||||||
deny ->
|
deny ->
|
||||||
ok;
|
ok;
|
||||||
allow ->
|
allow ->
|
||||||
ejabberd_router:route(From, To, PU)
|
ejabberd_router:route(PU)
|
||||||
end,
|
end,
|
||||||
A = ?SETS:del_element(LIJID, PresA),
|
A = ?SETS:del_element(LIJID, PresA),
|
||||||
State1#{pres_a => A};
|
State1#{pres_a => A};
|
||||||
@ -623,8 +623,10 @@ process_subscription(Direction, User, Server, JID1,
|
|||||||
case AutoReply of
|
case AutoReply of
|
||||||
none -> ok;
|
none -> ok;
|
||||||
_ ->
|
_ ->
|
||||||
ejabberd_router:route(jid:make(User, Server, <<"">>),
|
ejabberd_router:route(
|
||||||
JID1, #presence{type = AutoReply})
|
#presence{type = AutoReply,
|
||||||
|
from = jid:make(User, Server, <<"">>),
|
||||||
|
to = JID1})
|
||||||
end,
|
end,
|
||||||
case Push of
|
case Push of
|
||||||
{push, Item} ->
|
{push, Item} ->
|
||||||
@ -788,15 +790,17 @@ send_unsubscribing_presence(From, Item) ->
|
|||||||
_ -> false
|
_ -> false
|
||||||
end,
|
end,
|
||||||
if IsTo ->
|
if IsTo ->
|
||||||
ejabberd_router:route(jid:remove_resource(From),
|
ejabberd_router:route(
|
||||||
jid:make(Item#roster.jid),
|
#presence{type = unsubscribe,
|
||||||
#presence{type = unsubscribe});
|
from = jid:remove_resource(From),
|
||||||
|
to = jid:make(Item#roster.jid)});
|
||||||
true -> ok
|
true -> ok
|
||||||
end,
|
end,
|
||||||
if IsFrom ->
|
if IsFrom ->
|
||||||
ejabberd_router:route(jid:remove_resource(From),
|
ejabberd_router:route(
|
||||||
jid:make(Item#roster.jid),
|
#presence{type = unsubscribed,
|
||||||
#presence{type = unsubscribed});
|
from = jid:remove_resource(From),
|
||||||
|
to = jid:make(Item#roster.jid)});
|
||||||
true -> ok
|
true -> ok
|
||||||
end,
|
end,
|
||||||
ok.
|
ok.
|
||||||
@ -1046,7 +1050,7 @@ user_roster_parse_query(User, Server, Items, Query) ->
|
|||||||
user_roster_subscribe_jid(User, Server, JID) ->
|
user_roster_subscribe_jid(User, Server, JID) ->
|
||||||
out_subscription(User, Server, JID, subscribe),
|
out_subscription(User, Server, JID, subscribe),
|
||||||
UJID = jid:make(User, Server, <<"">>),
|
UJID = jid:make(User, Server, <<"">>),
|
||||||
ejabberd_router:route(UJID, JID, #presence{type = subscribe}).
|
ejabberd_router:route(#presence{from = UJID, to = JID, type = subscribe}).
|
||||||
|
|
||||||
user_roster_item_parse_query(User, Server, Items,
|
user_roster_item_parse_query(User, Server, Items,
|
||||||
Query) ->
|
Query) ->
|
||||||
@ -1061,8 +1065,9 @@ user_roster_item_parse_query(User, Server, Items,
|
|||||||
out_subscription(User, Server, JID1,
|
out_subscription(User, Server, JID1,
|
||||||
subscribed),
|
subscribed),
|
||||||
UJID = jid:make(User, Server, <<"">>),
|
UJID = jid:make(User, Server, <<"">>),
|
||||||
ejabberd_router:route(UJID, JID1,
|
ejabberd_router:route(
|
||||||
#presence{type = subscribed}),
|
#presence{from = UJID, to = JID1,
|
||||||
|
type = subscribed}),
|
||||||
throw(submitted);
|
throw(submitted);
|
||||||
false ->
|
false ->
|
||||||
case lists:keysearch(<<"remove",
|
case lists:keysearch(<<"remove",
|
||||||
|
@ -285,12 +285,12 @@ set_new_rosteritems(UserFrom, ServerFrom, UserTo,
|
|||||||
RIFrom.
|
RIFrom.
|
||||||
|
|
||||||
set_item(User, Server, Resource, Item) ->
|
set_item(User, Server, Resource, Item) ->
|
||||||
ResIQ = #iq{type = set, id = <<"push", (randoms:get_string())/binary>>,
|
ResIQ = #iq{from = jid:make(User, Server, Resource),
|
||||||
|
to = jid:make(Server),
|
||||||
|
type = set, id = <<"push", (randoms:get_string())/binary>>,
|
||||||
sub_els = [#roster_query{
|
sub_els = [#roster_query{
|
||||||
items = [mod_roster:encode_item(Item)]}]},
|
items = [mod_roster:encode_item(Item)]}]},
|
||||||
ejabberd_router:route(jid:make(User, Server, Resource),
|
ejabberd_router:route(ResIQ).
|
||||||
jid:make(Server),
|
|
||||||
ResIQ).
|
|
||||||
|
|
||||||
c2s_session_opened(#{jid := #jid{luser = LUser, lserver = LServer},
|
c2s_session_opened(#{jid := #jid{luser = LUser, lserver = LServer},
|
||||||
pres_f := PresF, pres_t := PresT} = State) ->
|
pres_f := PresF, pres_t := PresT} = State) ->
|
||||||
@ -727,7 +727,8 @@ push_item(User, Server, Item) ->
|
|||||||
items = [mod_roster:encode_item(Item)]}]},
|
items = [mod_roster:encode_item(Item)]}]},
|
||||||
lists:foreach(fun (Resource) ->
|
lists:foreach(fun (Resource) ->
|
||||||
JID = jid:make(User, Server, Resource),
|
JID = jid:make(User, Server, Resource),
|
||||||
ejabberd_router:route(jid:remove_resource(JID), JID, Stanza)
|
ejabberd_router:route(
|
||||||
|
xmpp:set_from_to(Stanza, jid:remove_resource(JID), JID))
|
||||||
end,
|
end,
|
||||||
ejabberd_sm:get_user_resources(User, Server)).
|
ejabberd_sm:get_user_resources(User, Server)).
|
||||||
|
|
||||||
|
@ -516,7 +516,8 @@ route_unacked_stanzas(#{mgmt_state := MgmtState,
|
|||||||
?DEBUG("Dropping presence stanza from ~s", [jid:to_string(From)]);
|
?DEBUG("Dropping presence stanza from ~s", [jid:to_string(From)]);
|
||||||
({_, _Time, #iq{} = El}) ->
|
({_, _Time, #iq{} = El}) ->
|
||||||
Txt = <<"User session terminated">>,
|
Txt = <<"User session terminated">>,
|
||||||
route_error(El, xmpp:err_service_unavailable(Txt, Lang));
|
ejabberd_router:route_error(
|
||||||
|
El, xmpp:err_service_unavailable(Txt, Lang));
|
||||||
({_, _Time, #message{from = From, meta = #{carbon_copy := true}}}) ->
|
({_, _Time, #message{from = From, meta = #{carbon_copy := true}}}) ->
|
||||||
%% XEP-0280 says: "When a receiving server attempts to deliver a
|
%% XEP-0280 says: "When a receiving server attempts to deliver a
|
||||||
%% forked message, and that message bounces with an error for
|
%% forked message, and that message bounces with an error for
|
||||||
@ -534,10 +535,11 @@ route_unacked_stanzas(#{mgmt_state := MgmtState,
|
|||||||
[jid:to_string(xmpp:get_from(Msg))]);
|
[jid:to_string(xmpp:get_from(Msg))]);
|
||||||
false when ResendOnTimeout ->
|
false when ResendOnTimeout ->
|
||||||
NewEl = add_resent_delay_info(State, Msg, Time),
|
NewEl = add_resent_delay_info(State, Msg, Time),
|
||||||
route(NewEl);
|
ejabberd_router:route(NewEl);
|
||||||
false ->
|
false ->
|
||||||
Txt = <<"User session terminated">>,
|
Txt = <<"User session terminated">>,
|
||||||
route_error(Msg, xmpp:err_service_unavailable(Txt, Lang))
|
ejabberd_router:route_error(
|
||||||
|
Msg, xmpp:err_service_unavailable(Txt, Lang))
|
||||||
end;
|
end;
|
||||||
({_, _Time, El}) ->
|
({_, _Time, El}) ->
|
||||||
%% Raw element of type 'error' resulting from a validation error
|
%% Raw element of type 'error' resulting from a validation error
|
||||||
@ -614,18 +616,6 @@ add_resent_delay_info(#{lserver := LServer}, El, Time)
|
|||||||
add_resent_delay_info(_State, El, _Time) ->
|
add_resent_delay_info(_State, El, _Time) ->
|
||||||
El.
|
El.
|
||||||
|
|
||||||
-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 send(state(), xmpp_element()) -> state().
|
-spec send(state(), xmpp_element()) -> state().
|
||||||
send(#{mod := Mod} = State, Pkt) ->
|
send(#{mod := Mod} = State, Pkt) ->
|
||||||
Mod:send(State, Pkt).
|
Mod:send(State, Pkt).
|
||||||
@ -684,8 +674,8 @@ cancel_ack_timer(State) ->
|
|||||||
|
|
||||||
-spec bounce_message_queue() -> ok.
|
-spec bounce_message_queue() -> ok.
|
||||||
bounce_message_queue() ->
|
bounce_message_queue() ->
|
||||||
receive {route, From, To, Pkt} ->
|
receive {route, Pkt} ->
|
||||||
ejabberd_router:route(From, To, Pkt),
|
ejabberd_router:route(Pkt),
|
||||||
bounce_message_queue()
|
bounce_message_queue()
|
||||||
after 0 ->
|
after 0 ->
|
||||||
ok
|
ok
|
||||||
|
@ -131,8 +131,8 @@ handle_cast(Cast, State) ->
|
|||||||
?WARNING_MSG("unexpected cast: ~p", [Cast]),
|
?WARNING_MSG("unexpected cast: ~p", [Cast]),
|
||||||
{noreply, State}.
|
{noreply, State}.
|
||||||
|
|
||||||
handle_info({route, From, To, Packet}, State) ->
|
handle_info({route, Packet}, State) ->
|
||||||
case catch do_route(From, To, Packet) of
|
case catch do_route(Packet) of
|
||||||
{'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]);
|
{'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]);
|
||||||
_ -> ok
|
_ -> ok
|
||||||
end,
|
end,
|
||||||
@ -160,11 +160,9 @@ terminate(_Reason, #state{host = MyHost, server_host = Host}) ->
|
|||||||
code_change(_OldVsn, State, _Extra) ->
|
code_change(_OldVsn, State, _Extra) ->
|
||||||
{ok, State}.
|
{ok, State}.
|
||||||
|
|
||||||
do_route(From, To, #xmlel{name = <<"iq">>} = El) ->
|
do_route(#iq{} = IQ) ->
|
||||||
ejabberd_router:process_iq(From, To, El);
|
ejabberd_router:process_iq(IQ);
|
||||||
do_route(From, To, #iq{} = IQ) ->
|
do_route(_) ->
|
||||||
ejabberd_router:process_iq(From, To, IQ);
|
|
||||||
do_route(_, _, _) ->
|
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
-spec get_sm_features({error, stanza_error()} | empty | {result, [binary()]},
|
-spec get_sm_features({error, stanza_error()} | empty | {result, [binary()]},
|
||||||
|
@ -146,7 +146,7 @@ send_messages(Config) ->
|
|||||||
end;
|
end;
|
||||||
({recv, #message{} = Msg}) ->
|
({recv, #message{} = Msg}) ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
JID, MyJID, Msg#message{from = JID, to = MyJID}),
|
Msg#message{from = JID, to = MyJID}),
|
||||||
ct:comment("Receiving message ~s", [xmpp:pp(Msg)]),
|
ct:comment("Receiving message ~s", [xmpp:pp(Msg)]),
|
||||||
#message{} = recv_message(Config)
|
#message{} = recv_message(Config)
|
||||||
end, message_iterator(Config)).
|
end, message_iterator(Config)).
|
||||||
|
@ -766,7 +766,8 @@ s2s_ping(Config) ->
|
|||||||
From = my_jid(Config),
|
From = my_jid(Config),
|
||||||
To = jid:make(?MNESIA_VHOST),
|
To = jid:make(?MNESIA_VHOST),
|
||||||
ID = randoms:get_string(),
|
ID = randoms:get_string(),
|
||||||
ejabberd_s2s:route(From, To, #iq{id = ID, type = get, sub_els = [#ping{}]}),
|
ejabberd_s2s:route(#iq{from = From, to = To, id = ID,
|
||||||
|
type = get, sub_els = [#ping{}]}),
|
||||||
#iq{type = result, id = ID, sub_els = []} = recv_iq(Config),
|
#iq{type = result, id = ID, sub_els = []} = recv_iq(Config),
|
||||||
disconnect(Config).
|
disconnect(Config).
|
||||||
|
|
||||||
|
@ -785,12 +785,12 @@ server_send_iqs(Config) ->
|
|||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(Type) ->
|
fun(Type) ->
|
||||||
ejabberd_router:route(
|
ejabberd_router:route(
|
||||||
ServerJID, MyJID, #iq{type = Type})
|
#iq{from = ServerJID, to = MyJID, type = Type})
|
||||||
end, [error, result]),
|
end, [error, result]),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(Type) ->
|
fun(Type) ->
|
||||||
ejabberd_local:route_iq(
|
ejabberd_local:route_iq(
|
||||||
ServerJID, MyJID, #iq{type = Type},
|
#iq{from = ServerJID, to = MyJID, type = Type},
|
||||||
fun(#iq{type = result, sub_els = []}) -> ok;
|
fun(#iq{type = result, sub_els = []}) -> ok;
|
||||||
(IQ) -> ct:fail({unexpected_iq_result, IQ})
|
(IQ) -> ct:fail({unexpected_iq_result, IQ})
|
||||||
end)
|
end)
|
||||||
|
@ -77,7 +77,7 @@ resume(Config) ->
|
|||||||
Txt = #text{data = <<"body">>},
|
Txt = #text{data = <<"body">>},
|
||||||
Msg = #message{from = ServerJID, to = MyJID, body = [Txt]},
|
Msg = #message{from = ServerJID, to = MyJID, body = [Txt]},
|
||||||
%% Route message. The message should be queued by the C2S process.
|
%% Route message. The message should be queued by the C2S process.
|
||||||
ejabberd_router:route(ServerJID, MyJID, Msg),
|
ejabberd_router:route(Msg),
|
||||||
send(Config, #sm_resume{previd = ID, h = 0, xmlns = ?NS_STREAM_MGMT_3}),
|
send(Config, #sm_resume{previd = ID, h = 0, xmlns = ?NS_STREAM_MGMT_3}),
|
||||||
#sm_resumed{previd = ID, h = 3} = recv(Config),
|
#sm_resumed{previd = ID, h = 3} = recv(Config),
|
||||||
#message{from = ServerJID, to = MyJID, body = [Txt]} = recv_message(Config),
|
#message{from = ServerJID, to = MyJID, body = [Txt]} = recv_message(Config),
|
||||||
|
Loading…
Reference in New Issue
Block a user