diff options
Diffstat (limited to 'src/ejabberd_sm.erl')
-rw-r--r-- | src/ejabberd_sm.erl | 106 |
1 files changed, 50 insertions, 56 deletions
diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl index 0c01496ef..83647054c 100644 --- a/src/ejabberd_sm.erl +++ b/src/ejabberd_sm.erl @@ -37,14 +37,14 @@ %% API -export([start/0, start_link/0, + route/1, route/2, - route/3, - process_iq/3, + process_iq/1, open_session/5, open_session/6, close_session/4, check_in_subscription/6, - bounce_offline_message/4, + bounce_offline_message/2, disconnect_removed_user/2, get_user_resources/2, get_user_present_resources/2, @@ -126,14 +126,12 @@ route(To, Term) -> ok end. --spec route(jid(), jid(), stanza()) -> ok. - -route(From, To, Packet) -> - case catch do_route(From, To, Packet) of - {'EXIT', Reason} -> - ?ERROR_MSG("~p~nwhen processing: ~p", - [Reason, {From, To, Packet}]); - _ -> ok +-spec route(stanza()) -> ok. +route(Packet) -> + try do_route(Packet), ok + catch E:R -> + ?ERROR_MSG("failed to route packet:~n~s~nReason = ~p", + [xmpp:pp(Packet), {E, {R, erlang:get_stacktrace()}}]) end. -spec open_session(sid(), binary(), binary(), binary(), prio(), info()) -> ok. @@ -174,15 +172,15 @@ check_in_subscription(Acc, User, Server, _JID, _Type, _Reason) -> false -> {stop, false} end. --spec bounce_offline_message(bounce | any(), jid(), jid(), message()) -> stop. +-spec bounce_offline_message(bounce | any(), message()) -> stop. -bounce_offline_message(bounce = Acc, From, To, Packet) -> +bounce_offline_message(bounce = Acc, Packet) -> Lang = xmpp:get_lang(Packet), Txt = <<"User session not found">>, Err = xmpp:err_service_unavailable(Txt, Lang), - ejabberd_router:route_error(To, From, Packet, Err), + ejabberd_router:route_error(Packet, Err), {stop, Acc}; -bounce_offline_message(Acc, _From, _To, _Packet) -> +bounce_offline_message(Acc, _Packet) -> Acc. -spec disconnect_removed_user(binary(), binary()) -> ok. @@ -427,14 +425,8 @@ handle_cast({unregister_iq_handler, Host, XMLNS}, {noreply, State}; handle_cast(_Msg, State) -> {noreply, State}. -handle_info({route, From, To, Packet}, State) -> - case catch do_route(From, To, Packet) of - {'EXIT', Reason} -> - ?ERROR_MSG("~p~nwhen processing: ~p", - [Reason, {From, To, Packet}]); - _ -> - ok - end, +handle_info({route, Packet}, State) -> + route(Packet), {noreply, State}; handle_info(Info, State) -> ?WARNING_MSG("unexpected info: ~p", [Info]), @@ -505,8 +497,8 @@ do_route(To, Term) -> Pid ! Term end. --spec do_route(jid(), jid(), stanza()) -> any(). -do_route(From, To, #presence{type = T, status = Status} = Packet) +-spec do_route(stanza()) -> any(). +do_route(#presence{from = From, to = To, type = T, status = Status} = Packet) when T == subscribe; T == subscribed; T == unsubscribe; T == unsubscribed -> ?DEBUG("processing subscription:~n~s", [xmpp:pp(Packet)]), #jid{user = User, server = Server, @@ -514,7 +506,7 @@ do_route(From, To, #presence{type = T, status = Status} = Packet) Reason = if T == subscribe -> xmpp:get_text(Status); true -> <<"">> end, - case is_privacy_allow(From, To, Packet) andalso + case is_privacy_allow(Packet) andalso ejabberd_hooks:run_fold( roster_in_subscription, LServer, false, @@ -525,37 +517,39 @@ do_route(From, To, #presence{type = T, status = Status} = Packet) fun(#session{sid = SID, usr = {_, _, R}, priority = Prio}) when is_integer(Prio) -> Pid = element(2, SID), + Packet1 = Packet#presence{to = jid:replace_resource(To, R)}, ?DEBUG("sending to process ~p:~n~s", - [Pid, xmpp:pp(Packet)]), - Pid ! {route, From, jid:replace_resource(To, R), Packet}; + [Pid, xmpp:pp(Packet1)]), + Pid ! {route, Packet1}; (_) -> ok end, online(Mod:get_sessions(LUser, LServer))); false -> ok end; -do_route(From, #jid{lresource = <<"">>} = To, #presence{} = Packet) -> +do_route(#presence{to = #jid{lresource = <<"">>} = To} = Packet) -> ?DEBUG("processing presence to bare JID:~n~s", [xmpp:pp(Packet)]), {LUser, LServer, _} = jid:tolower(To), lists:foreach( fun({_, R}) -> - do_route(From, jid:replace_resource(To, R), Packet) + do_route(Packet#presence{to = jid:replace_resource(To, R)}) end, get_user_present_resources(LUser, LServer)); -do_route(From, #jid{lresource = <<"">>} = To, #message{type = T} = Packet) -> +do_route(#message{to = #jid{lresource = <<"">>}, type = T} = Packet) -> ?DEBUG("processing message to bare JID:~n~s", [xmpp:pp(Packet)]), if T == chat; T == headline; T == normal; T == groupchat -> - route_message(From, To, Packet, T); + route_message(Packet); true -> Lang = xmpp:get_lang(Packet), ErrTxt = <<"User session not found">>, Err = xmpp:err_service_unavailable(ErrTxt, Lang), - ejabberd_router:route_error(To, From, Packet, Err) + ejabberd_router:route_error(Packet, Err) end; -do_route(From, #jid{lresource = <<"">>} = To, #iq{} = Packet) -> +do_route(#iq{to = #jid{lresource = <<"">>}} = Packet) -> ?DEBUG("processing IQ to bare JID:~n~s", [xmpp:pp(Packet)]), - process_iq(From, To, Packet); -do_route(From, To, Packet) -> + process_iq(Packet); +do_route(Packet) -> ?DEBUG("processing packet to full JID:~n~s", [xmpp:pp(Packet)]), + To = xmpp:get_to(Packet), {LUser, LServer, LResource} = jid:tolower(To), Mod = get_sm_backend(LServer), case online(Mod:get_sessions(LUser, LServer, LResource)) of @@ -563,7 +557,7 @@ do_route(From, To, Packet) -> case Packet of #message{type = T} when T == chat; T == normal; T == headline; T == groupchat -> - route_message(From, To, Packet, T); + route_message(Packet); #presence{} -> ?DEBUG("dropping presence to unavalable resource:~n~s", [xmpp:pp(Packet)]); @@ -571,28 +565,29 @@ do_route(From, To, Packet) -> Lang = xmpp:get_lang(Packet), ErrTxt = <<"User session not found">>, Err = xmpp:err_service_unavailable(ErrTxt, Lang), - ejabberd_router:route_error(To, From, Packet, Err) + ejabberd_router:route_error(Packet, Err) end; Ss -> Session = lists:max(Ss), Pid = element(2, Session#session.sid), ?DEBUG("sending to process ~p:~n~s", [Pid, xmpp:pp(Packet)]), - Pid ! {route, From, To, Packet} + Pid ! {route, Packet} end. %% The default list applies to the user as a whole, %% and is processed if there is no active list set %% for the target session/resource to which a stanza is addressed, %% or if there are no current sessions for the user. --spec is_privacy_allow(jid(), jid(), stanza()) -> boolean(). -is_privacy_allow(From, To, Packet) -> +-spec is_privacy_allow(stanza()) -> boolean(). +is_privacy_allow(Packet) -> + To = xmpp:get_to(Packet), LServer = To#jid.server, allow == ejabberd_hooks:run_fold( privacy_check_packet, LServer, allow, - [To, xmpp:set_from_to(Packet, From, To), in]). + [To, Packet, in]). --spec route_message(jid(), jid(), message(), message_type()) -> any(). -route_message(From, To, Packet, Type) -> +-spec route_message(message()) -> any(). +route_message(#message{to = To, type = Type} = Packet) -> LUser = To#jid.luser, LServer = To#jid.lserver, PrioRes = get_user_present_resources(LUser, LServer), @@ -616,7 +611,7 @@ route_message(From, To, Packet, Type) -> LResource, LMaxRes, P, MaxPrio), - Pid ! {route, From, To, Packet1} + Pid ! {route, Packet1} end; %% Ignore other priority: ({_Prio, _Res}) -> ok @@ -624,14 +619,14 @@ route_message(From, To, Packet, Type) -> PrioRes); _ -> case ejabberd_auth:is_user_exists(LUser, LServer) andalso - is_privacy_allow(From, To, Packet) of + is_privacy_allow(Packet) of true -> ejabberd_hooks:run_fold(offline_message_hook, LServer, bounce, - [From, To, Packet]); + [Packet]); false -> Err = xmpp:err_service_unavailable(), - ejabberd_router:route_error(To, From, Packet, Err) + ejabberd_router:route_error(Packet, Err) end end. @@ -737,29 +732,28 @@ get_max_user_sessions(LUser, Host) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec process_iq(jid(), jid(), iq()) -> any(). -process_iq(From, To, #iq{type = T, lang = Lang, sub_els = [El]} = Packet) +-spec process_iq(iq()) -> any(). +process_iq(#iq{to = To, type = T, lang = Lang, sub_els = [El]} = Packet) when T == get; T == set -> XMLNS = xmpp:get_ns(El), Host = To#jid.lserver, case ets:lookup(sm_iqtable, {Host, XMLNS}) of [{_, Module, Function, Opts}] -> - gen_iq_handler:handle(Host, Module, Function, Opts, - From, To, Packet); + gen_iq_handler:handle(Host, Module, Function, Opts, Packet); [] -> Txt = <<"No module is handling this query">>, Err = xmpp:err_service_unavailable(Txt, Lang), - ejabberd_router:route_error(To, From, Packet, Err) + ejabberd_router:route_error(Packet, Err) end; -process_iq(From, To, #iq{type = T, lang = Lang, sub_els = SubEls} = Packet) +process_iq(#iq{type = T, lang = Lang, sub_els = SubEls} = Packet) when T == get; T == set -> Txt = case SubEls of [] -> <<"No child elements found">>; _ -> <<"Too many child elements">> end, Err = xmpp:err_bad_request(Txt, Lang), - ejabberd_router:route_error(To, From, Packet, Err); -process_iq(_From, _To, #iq{}) -> + ejabberd_router:route_error(Packet, Err); +process_iq(#iq{}) -> ok. -spec force_update_presence({binary(), binary()}) -> ok. |