From fd8e5ffce7b5e0f54d51d965f76cef8354c53ba5 Mon Sep 17 00:00:00 2001 From: Evgeny Khramtsov Date: Sat, 6 Jul 2019 12:30:57 +0300 Subject: [PATCH] Avoid routing packets through a single process --- src/mod_mix.erl | 10 ++++++++++ src/mod_muc.erl | 14 ++++++++------ src/mod_proxy65_service.erl | 22 ++++++++++++++++++---- src/mod_pubsub.erl | 28 ++++++++++++++++------------ src/mod_vcard.erl | 19 +++++++++++++------ 5 files changed, 65 insertions(+), 28 deletions(-) diff --git a/src/mod_mix.erl b/src/mod_mix.erl index 042b7dfef..6b768b702 100644 --- a/src/mod_mix.erl +++ b/src/mod_mix.erl @@ -43,6 +43,7 @@ -include("xmpp.hrl"). -include("logger.hrl"). -include("translate.hrl"). +-include("ejabberd_stacktrace.hrl"). -callback init(binary(), gen_mod:opts()) -> ok | {error, db_failure}. -callback set_channel(binary(), binary(), binary(), @@ -275,6 +276,15 @@ handle_cast(Request, State) -> ?WARNING_MSG("Unexpected cast: ~p", [Request]), {noreply, State}. +handle_info({route, Packet}, State) -> + try route(Packet) + catch ?EX_RULE(Class, Reason, St) -> + StackTrace = ?EX_STACK(St), + ?ERROR_MSG("Failed to route packet:~n~s~n** ~s", + [xmpp:pp(Packet), + misc:format_exception(2, Class, Reason, StackTrace)]) + end, + {noreply, State}; handle_info(Info, State) -> ?WARNING_MSG("Unexpected info: ~p", [Info]), {noreply, State}. diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 6f6330d2c..34b8a7ba1 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -393,10 +393,11 @@ handle_call({create, Room, Host, From, Nick, Opts}, _From, handle_cast({route_to_room, Packet}, #state{server_host = ServerHost} = State) -> try route_to_room(Packet, ServerHost) - catch ?EX_RULE(E, R, St) -> + catch ?EX_RULE(Class, Reason, St) -> StackTrace = ?EX_STACK(St), - ?ERROR_MSG("Failed to route packet:~n~s~nReason = ~p", - [xmpp:pp(Packet), {E, {R, StackTrace}}]) + ?ERROR_MSG("Failed to route packet:~n~s~n** ~s", + [xmpp:pp(Packet), + misc:format_exception(2, Class, Reason, StackTrace)]) end, {noreply, State}; handle_cast({room_destroyed, {Room, Host}, Pid}, State) -> @@ -420,10 +421,11 @@ handle_info({route, Packet}, State) -> %% where mod_muc is not loaded. Such configuration %% is *highly* discouraged try route(Packet, State#state.server_host) - catch ?EX_RULE(E, R, St) -> + catch ?EX_RULE(Class, Reason, St) -> StackTrace = ?EX_STACK(St), - ?ERROR_MSG("Failed to route packet:~n~s~nReason = ~p", - [xmpp:pp(Packet), {E, {R, StackTrace}}]) + ?ERROR_MSG("Failed to route packet:~n~s~n** ~s", + [xmpp:pp(Packet), + misc:format_exception(2, Class, Reason, StackTrace)]) end, {noreply, State}; handle_info({room_destroyed, {Room, Host}, Pid}, State) -> diff --git a/src/mod_proxy65_service.erl b/src/mod_proxy65_service.erl index a27dcc11c..468c2e8c7 100644 --- a/src/mod_proxy65_service.erl +++ b/src/mod_proxy65_service.erl @@ -35,11 +35,12 @@ -export([start_link/2, reload/3, add_listener/2, process_disco_info/1, process_disco_items/1, process_vcard/1, process_bytestreams/1, - delete_listener/1]). + delete_listener/1, route/1]). -include("logger.hrl"). -include("xmpp.hrl"). -include("translate.hrl"). +-include("ejabberd_stacktrace.hrl"). -define(PROCNAME, ejabberd_mod_proxy65_service). @@ -71,7 +72,8 @@ init([Host, Opts]) -> ?MODULE, process_vcard), gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_BYTESTREAMS, ?MODULE, process_bytestreams), - ejabberd_router:register_route(MyHost, Host) + ejabberd_router:register_route( + MyHost, Host, {apply, ?MODULE, route}) end, MyHosts), {ok, #state{myhosts = MyHosts}}. @@ -82,8 +84,14 @@ terminate(_Reason, #state{myhosts = MyHosts}) -> unregister_handlers(MyHost) end, MyHosts). -handle_info({route, #iq{} = Packet}, State) -> - ejabberd_router:process_iq(Packet), +handle_info({route, Packet}, State) -> + try route(Packet) + catch ?EX_RULE(Class, Reason, St) -> + StackTrace = ?EX_STACK(St), + ?ERROR_MSG("Failed to route packet:~n~s~n** ~s", + [xmpp:pp(Packet), + misc:format_exception(2, Class, Reason, StackTrace)]) + end, {noreply, State}; handle_info(_Info, State) -> {noreply, State}. @@ -110,6 +118,12 @@ handle_cast(Msg, State) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. +-spec route(stanza()) -> ok. +route(#iq{} = IQ) -> + ejabberd_router:process_iq(IQ); +route(_) -> + ok. + %%%------------------------ %%% Listener management %%%------------------------ diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 87b5a10a4..706edc419 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -44,6 +44,7 @@ -include("pubsub.hrl"). -include("mod_roster.hrl"). -include("translate.hrl"). +-include("ejabberd_stacktrace.hrl"). -define(STDTREE, <<"tree">>). -define(STDNODE, <<"flat">>). @@ -92,6 +93,8 @@ handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, depends/2, mod_opt_type/1, mod_options/1]). +-export([route/1]). + %%==================================================================== %% API %%==================================================================== @@ -254,7 +257,8 @@ init([ServerHost, Opts]) -> lists:flatmap( fun(Host) -> DBMod:init(Host, ServerHost, Opts), - ejabberd_router:register_route(Host, ServerHost), + ejabberd_router:register_route( + Host, ServerHost, {apply, ?MODULE, route}), {Plugins, NodeTree, PepMapping} = init_plugins(Host, ServerHost, Opts), DefaultModule = plugin(Host, hd(Plugins)), DefaultNodeCfg = merge_config( @@ -727,15 +731,13 @@ handle_cast(_Msg, State) -> {noreply, State}. %% Description: Handling all non call/cast messages %%-------------------------------------------------------------------- %% @private -handle_info({route, #iq{to = To} = IQ}, - State) when To#jid.lresource == <<"">> -> - ejabberd_router:process_iq(IQ), - {noreply, State}; handle_info({route, Packet}, State) -> - To = xmpp:get_to(Packet), - case catch do_route(To#jid.lserver, Packet) of - {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); - _ -> ok + try route(Packet) + catch ?EX_RULE(Class, Reason, St) -> + StackTrace = ?EX_STACK(St), + ?ERROR_MSG("Failed to route packet:~n~s~n** ~s", + [xmpp:pp(Packet), + misc:format_exception(2, Class, Reason, StackTrace)]) end, {noreply, State}; handle_info(_Info, State) -> @@ -892,8 +894,10 @@ process_commands(#iq{type = get, lang = Lang} = IQ) -> Txt = ?T("Value 'get' of 'type' attribute is not allowed"), xmpp:make_error(IQ, xmpp:err_not_allowed(Txt, Lang)). --spec do_route(binary(), stanza()) -> ok. -do_route(Host, Packet) -> +-spec route(stanza()) -> ok. +route(#iq{to = To} = IQ) when To#jid.lresource == <<"">> -> + ejabberd_router:process_iq(IQ); +route(Packet) -> To = xmpp:get_to(Packet), case To of #jid{luser = <<>>, lresource = <<>>} -> @@ -906,7 +910,7 @@ do_route(Host, Packet) -> ejabberd_router:route_error(Packet, Err); AuthResponse -> handle_authorization_response( - Host, Packet, AuthResponse) + To#jid.lserver, Packet, AuthResponse) end; _ -> Err = xmpp:err_service_unavailable(), diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index 0474f644c..b7be42a13 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -41,11 +41,13 @@ vcard_iq_set/1, mod_opt_type/1, set_vcard/3, make_vcard_search/4]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). +-export([route/1]). -include("logger.hrl"). -include("xmpp.hrl"). -include("mod_vcard.hrl"). -include("translate.hrl"). +-include("ejabberd_stacktrace.hrl"). -define(VCARD_CACHE, vcard_cache). @@ -121,7 +123,8 @@ init([Host, Opts]) -> "not implemented for ~s backend", [mod_vcard_opt:db_type(Opts)]); true -> - ejabberd_router:register_route(MyHost, Host) + ejabberd_router:register_route( + MyHost, Host, {apply, ?MODULE, route}) end end, MyHosts); true -> @@ -137,9 +140,12 @@ handle_cast(Cast, State) -> {noreply, State}. handle_info({route, Packet}, State) -> - case catch do_route(Packet) of - {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]); - _ -> ok + try route(Packet) + catch ?EX_RULE(Class, Reason, St) -> + StackTrace = ?EX_STACK(St), + ?ERROR_MSG("Failed to route packet:~n~s~n** ~s", + [xmpp:pp(Packet), + misc:format_exception(2, Class, Reason, StackTrace)]) end, {noreply, State}; handle_info(Info, State) -> @@ -169,9 +175,10 @@ terminate(_Reason, #state{hosts = MyHosts, server_host = Host}) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. -do_route(#iq{} = IQ) -> +-spec route(stanza()) -> ok. +route(#iq{} = IQ) -> ejabberd_router:process_iq(IQ); -do_route(_) -> +route(_) -> ok. -spec get_sm_features({error, stanza_error()} | empty | {result, [binary()]},