mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-28 16:34:13 +01:00
Don't lose carbons on presence change or session resumption
This commit is contained in:
parent
f02f44ad3f
commit
6cd8d1025c
@ -708,13 +708,11 @@ process_presence_out(#{lserver := LServer, jid := JID,
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
-spec process_self_presence(state(), presence()) -> state().
|
-spec process_self_presence(state(), presence()) -> state().
|
||||||
process_self_presence(#{ip := IP, conn := Conn, lserver := LServer,
|
process_self_presence(#{lserver := LServer, sid := SID,
|
||||||
auth_module := AuthMod, sid := SID,
|
|
||||||
user := U, server := S, resource := R} = State,
|
user := U, server := S, resource := R} = State,
|
||||||
#presence{type = unavailable} = Pres) ->
|
#presence{type = unavailable} = Pres) ->
|
||||||
Status = xmpp:get_text(Pres#presence.status),
|
Status = xmpp:get_text(Pres#presence.status),
|
||||||
Info = [{ip, IP}, {conn, Conn}, {auth_module, AuthMod}],
|
ejabberd_sm:unset_presence(SID, U, S, R, Status),
|
||||||
ejabberd_sm:unset_presence(SID, U, S, R, Status, Info),
|
|
||||||
{Pres1, State1} = ejabberd_hooks:run_fold(
|
{Pres1, State1} = ejabberd_hooks:run_fold(
|
||||||
c2s_self_presence, LServer, {Pres, State}, []),
|
c2s_self_presence, LServer, {Pres, State}, []),
|
||||||
State2 = broadcast_presence_unavailable(State1, Pres1),
|
State2 = broadcast_presence_unavailable(State1, Pres1),
|
||||||
@ -732,13 +730,11 @@ process_self_presence(#{lserver := LServer} = State,
|
|||||||
process_self_presence(State, _Pres) ->
|
process_self_presence(State, _Pres) ->
|
||||||
State.
|
State.
|
||||||
|
|
||||||
-spec update_priority(state(), presence()) -> ok.
|
-spec update_priority(state(), presence()) -> ok | {error, notfound}.
|
||||||
update_priority(#{ip := IP, conn := Conn, auth_module := AuthMod,
|
update_priority(#{sid := SID, user := U, server := S, resource := R},
|
||||||
sid := SID, user := U, server := S, resource := R},
|
|
||||||
Pres) ->
|
Pres) ->
|
||||||
Priority = get_priority_from_presence(Pres),
|
Priority = get_priority_from_presence(Pres),
|
||||||
Info = [{ip, IP}, {conn, Conn}, {auth_module, AuthMod}],
|
ejabberd_sm:set_presence(SID, U, S, R, Priority, Pres).
|
||||||
ejabberd_sm:set_presence(SID, U, S, R, Priority, Pres, Info).
|
|
||||||
|
|
||||||
-spec broadcast_presence_unavailable(state(), presence()) -> state().
|
-spec broadcast_presence_unavailable(state(), presence()) -> state().
|
||||||
broadcast_presence_unavailable(#{jid := JID, pres_a := PresA} = State, Pres) ->
|
broadcast_presence_unavailable(#{jid := JID, pres_a := PresA} = State, Pres) ->
|
||||||
|
@ -47,8 +47,8 @@
|
|||||||
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,
|
||||||
set_presence/7,
|
set_presence/6,
|
||||||
unset_presence/6,
|
unset_presence/5,
|
||||||
close_session_unset_presence/5,
|
close_session_unset_presence/5,
|
||||||
dirty_get_sessions_list/0,
|
dirty_get_sessions_list/0,
|
||||||
dirty_get_my_sessions_list/0,
|
dirty_get_my_sessions_list/0,
|
||||||
@ -307,26 +307,48 @@ del_user_info(User, Server, Resource, Key) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
-spec set_presence(sid(), binary(), binary(), binary(),
|
-spec set_presence(sid(), binary(), binary(), binary(),
|
||||||
prio(), presence(), info()) -> ok.
|
prio(), presence()) -> ok | {error, notfound}.
|
||||||
|
|
||||||
set_presence(SID, User, Server, Resource, Priority,
|
set_presence(SID, User, Server, Resource, Priority, Presence) ->
|
||||||
Presence, Info) ->
|
LUser = jid:nodeprep(User),
|
||||||
set_session(SID, User, Server, Resource, Priority,
|
LServer = jid:nameprep(Server),
|
||||||
Info),
|
LResource = jid:resourceprep(Resource),
|
||||||
|
Mod = get_sm_backend(LServer),
|
||||||
|
case get_sessions(Mod, LUser, LServer, LResource) of
|
||||||
|
[] -> {error, notfound};
|
||||||
|
Ss ->
|
||||||
|
case lists:keyfind(SID, 1, Ss) of
|
||||||
|
#session{info = Info} ->
|
||||||
|
set_session(SID, User, Server, Resource, Priority, Info),
|
||||||
ejabberd_hooks:run(set_presence_hook,
|
ejabberd_hooks:run(set_presence_hook,
|
||||||
jid:nameprep(Server),
|
LServer,
|
||||||
[User, Server, Resource, Presence]).
|
[User, Server, Resource, Presence]);
|
||||||
|
false ->
|
||||||
|
{error, notfound}
|
||||||
|
end
|
||||||
|
end.
|
||||||
|
|
||||||
-spec unset_presence(sid(), binary(), binary(),
|
-spec unset_presence(sid(), binary(), binary(),
|
||||||
binary(), binary(), info()) -> ok.
|
binary(), binary()) -> ok | {error, notfound}.
|
||||||
|
|
||||||
unset_presence(SID, User, Server, Resource, Status,
|
unset_presence(SID, User, Server, Resource, Status) ->
|
||||||
Info) ->
|
LUser = jid:nodeprep(User),
|
||||||
set_session(SID, User, Server, Resource, undefined,
|
LServer = jid:nameprep(Server),
|
||||||
Info),
|
LResource = jid:resourceprep(Resource),
|
||||||
|
Mod = get_sm_backend(LServer),
|
||||||
|
case get_sessions(Mod, LUser, LServer, LResource) of
|
||||||
|
[] -> {error, notfound};
|
||||||
|
Ss ->
|
||||||
|
case lists:keyfind(SID, 1, Ss) of
|
||||||
|
#session{info = Info} ->
|
||||||
|
set_session(SID, User, Server, Resource, undefined, Info),
|
||||||
ejabberd_hooks:run(unset_presence_hook,
|
ejabberd_hooks:run(unset_presence_hook,
|
||||||
jid:nameprep(Server),
|
LServer,
|
||||||
[User, Server, Resource, Status]).
|
[User, Server, Resource, Status]);
|
||||||
|
false ->
|
||||||
|
{error, notfound}
|
||||||
|
end
|
||||||
|
end.
|
||||||
|
|
||||||
-spec close_session_unset_presence(sid(), binary(), binary(),
|
-spec close_session_unset_presence(sid(), binary(), binary(),
|
||||||
binary(), binary()) -> ok.
|
binary(), binary()) -> ok.
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
iq_handler/1, disco_features/5,
|
iq_handler/1, disco_features/5,
|
||||||
is_carbon_copy/1, mod_opt_type/1, depends/2,
|
is_carbon_copy/1, mod_opt_type/1, depends/2,
|
||||||
mod_options/1]).
|
mod_options/1]).
|
||||||
|
-export([c2s_copy_session/2, c2s_session_opened/1, c2s_session_resumed/1]).
|
||||||
%% For debugging purposes
|
%% For debugging purposes
|
||||||
-export([list/2]).
|
-export([list/2]).
|
||||||
|
|
||||||
@ -45,6 +46,7 @@
|
|||||||
-include("xmpp.hrl").
|
-include("xmpp.hrl").
|
||||||
|
|
||||||
-type direction() :: sent | received.
|
-type direction() :: sent | received.
|
||||||
|
-type c2s_state() :: ejabberd_c2s:state().
|
||||||
|
|
||||||
-spec is_carbon_copy(stanza()) -> boolean().
|
-spec is_carbon_copy(stanza()) -> boolean().
|
||||||
is_carbon_copy(#message{meta = #{carbon_copy := true}}) ->
|
is_carbon_copy(#message{meta = #{carbon_copy := true}}) ->
|
||||||
@ -57,6 +59,9 @@ start(Host, _Opts) ->
|
|||||||
%% why priority 89: to define clearly that we must run BEFORE mod_logdb hook (90)
|
%% why priority 89: to define clearly that we must run BEFORE mod_logdb hook (90)
|
||||||
ejabberd_hooks:add(user_send_packet,Host, ?MODULE, user_send_packet, 89),
|
ejabberd_hooks:add(user_send_packet,Host, ?MODULE, user_send_packet, 89),
|
||||||
ejabberd_hooks:add(user_receive_packet,Host, ?MODULE, user_receive_packet, 89),
|
ejabberd_hooks:add(user_receive_packet,Host, ?MODULE, user_receive_packet, 89),
|
||||||
|
ejabberd_hooks:add(c2s_copy_session, Host, ?MODULE, c2s_copy_session, 50),
|
||||||
|
ejabberd_hooks:add(c2s_session_resumed, Host, ?MODULE, c2s_session_resumed, 50),
|
||||||
|
ejabberd_hooks:add(c2s_session_opened, Host, ?MODULE, c2s_session_opened, 50),
|
||||||
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_2, ?MODULE, iq_handler).
|
gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_CARBONS_2, ?MODULE, iq_handler).
|
||||||
|
|
||||||
stop(Host) ->
|
stop(Host) ->
|
||||||
@ -64,7 +69,10 @@ stop(Host) ->
|
|||||||
ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, disco_features, 50),
|
ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, disco_features, 50),
|
||||||
%% why priority 89: to define clearly that we must run BEFORE mod_logdb hook (90)
|
%% why priority 89: to define clearly that we must run BEFORE mod_logdb hook (90)
|
||||||
ejabberd_hooks:delete(user_send_packet,Host, ?MODULE, user_send_packet, 89),
|
ejabberd_hooks:delete(user_send_packet,Host, ?MODULE, user_send_packet, 89),
|
||||||
ejabberd_hooks:delete(user_receive_packet,Host, ?MODULE, user_receive_packet, 89).
|
ejabberd_hooks:delete(user_receive_packet,Host, ?MODULE, user_receive_packet, 89),
|
||||||
|
ejabberd_hooks:delete(c2s_copy_session, Host, ?MODULE, c2s_copy_session, 50),
|
||||||
|
ejabberd_hooks:delete(c2s_session_resumed, Host, ?MODULE, c2s_session_resumed, 50),
|
||||||
|
ejabberd_hooks:delete(c2s_session_opened, Host, ?MODULE, c2s_session_opened, 50).
|
||||||
|
|
||||||
reload(_Host, _NewOpts, _OldOpts) ->
|
reload(_Host, _NewOpts, _OldOpts) ->
|
||||||
ok.
|
ok.
|
||||||
@ -123,6 +131,29 @@ user_receive_packet({Packet, #{jid := JID} = C2SState}) ->
|
|||||||
Pkt -> {Pkt, C2SState}
|
Pkt -> {Pkt, C2SState}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
-spec c2s_copy_session(c2s_state(), c2s_state()) -> c2s_state().
|
||||||
|
c2s_copy_session(State, #{user := U, server := S, resource := R}) ->
|
||||||
|
case ejabberd_sm:get_user_info(U, S, R) of
|
||||||
|
offline -> State;
|
||||||
|
Info ->
|
||||||
|
case lists:keyfind(carboncopy, 1, Info) of
|
||||||
|
{_, CC} -> State#{carboncopy => CC};
|
||||||
|
false -> State
|
||||||
|
end
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec c2s_session_resumed(c2s_state()) -> c2s_state().
|
||||||
|
c2s_session_resumed(#{user := U, server := S, resource := R,
|
||||||
|
carboncopy := CC} = State) ->
|
||||||
|
ejabberd_sm:set_user_info(U, S, R, carboncopy, CC),
|
||||||
|
maps:remove(carboncopy, State);
|
||||||
|
c2s_session_resumed(State) ->
|
||||||
|
State.
|
||||||
|
|
||||||
|
-spec c2s_session_opened(c2s_state()) -> c2s_state().
|
||||||
|
c2s_session_opened(State) ->
|
||||||
|
maps:remove(carboncopy, State).
|
||||||
|
|
||||||
% Modified from original version:
|
% Modified from original version:
|
||||||
% - registered to the user_send_packet hook, to be called only once even for multicast
|
% - registered to the user_send_packet hook, to be called only once even for multicast
|
||||||
% - do not support "private" message mode, and do not modify the original packet in any way
|
% - do not support "private" message mode, and do not modify the original packet in any way
|
||||||
|
Loading…
Reference in New Issue
Block a user