mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-28 16:34:13 +01:00
Preserve PID for offline sessions
Don't set the PID to 'undefined' when a session goes offline, as this looses the information which node created the session table entry. Fixes #1196.
This commit is contained in:
parent
4332dddbc4
commit
814b80c644
@ -1,9 +1,9 @@
|
|||||||
-ifndef(EJABBERD_SM_HRL).
|
-ifndef(EJABBERD_SM_HRL).
|
||||||
-define(EJABBERD_SM_HRL, true).
|
-define(EJABBERD_SM_HRL, true).
|
||||||
|
|
||||||
-record(session, {sid, usr, us, priority, info}).
|
-record(session, {sid, usr, us, priority, info = []}).
|
||||||
-record(session_counter, {vhost, count}).
|
-record(session_counter, {vhost, count}).
|
||||||
-type sid() :: {erlang:timestamp(), pid()} | {erlang:timestamp(), undefined}.
|
-type sid() :: {erlang:timestamp(), pid()}.
|
||||||
-type ip() :: {inet:ip_address(), inet:port_number()} | undefined.
|
-type ip() :: {inet:ip_address(), inet:port_number()} | undefined.
|
||||||
-type info() :: [{conn, atom()} | {ip, ip()} | {node, atom()}
|
-type info() :: [{conn, atom()} | {ip, ip()} | {node, atom()}
|
||||||
| {oor, boolean()} | {auth_module, atom()}
|
| {oor, boolean()} | {auth_module, atom()}
|
||||||
|
@ -270,25 +270,28 @@ get_session_pid(User, Server, Resource) ->
|
|||||||
|
|
||||||
-spec set_offline_info(sid(), binary(), binary(), binary(), info()) -> ok.
|
-spec set_offline_info(sid(), binary(), binary(), binary(), info()) -> ok.
|
||||||
|
|
||||||
set_offline_info({Time, _Pid}, User, Server, Resource, Info) ->
|
set_offline_info(SID, User, Server, Resource, Info) ->
|
||||||
SID = {Time, undefined},
|
|
||||||
LUser = jid:nodeprep(User),
|
LUser = jid:nodeprep(User),
|
||||||
LServer = jid:nameprep(Server),
|
LServer = jid:nameprep(Server),
|
||||||
LResource = jid:resourceprep(Resource),
|
LResource = jid:resourceprep(Resource),
|
||||||
set_session(SID, LUser, LServer, LResource, undefined, Info).
|
set_session(SID, LUser, LServer, LResource, undefined, [offline | Info]).
|
||||||
|
|
||||||
-spec get_offline_info(erlang:timestamp(), binary(), binary(),
|
-spec get_offline_info(erlang:timestamp(), binary(), binary(),
|
||||||
binary()) -> none | info().
|
binary()) -> none | info().
|
||||||
|
|
||||||
get_offline_info(Time, User, Server, Resource) ->
|
get_offline_info(Time, User, Server, Resource) ->
|
||||||
SID = {Time, undefined},
|
|
||||||
LUser = jid:nodeprep(User),
|
LUser = jid:nodeprep(User),
|
||||||
LServer = jid:nameprep(Server),
|
LServer = jid:nameprep(Server),
|
||||||
LResource = jid:resourceprep(Resource),
|
LResource = jid:resourceprep(Resource),
|
||||||
Mod = get_sm_backend(LServer),
|
Mod = get_sm_backend(LServer),
|
||||||
case Mod:get_sessions(LUser, LServer, LResource) of
|
case Mod:get_sessions(LUser, LServer, LResource) of
|
||||||
[#session{sid = SID, info = Info}] ->
|
[#session{sid = {Time, _}, info = Info}] ->
|
||||||
Info;
|
case proplists:get_bool(offline, Info) of
|
||||||
|
true ->
|
||||||
|
Info;
|
||||||
|
false ->
|
||||||
|
none
|
||||||
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
none
|
none
|
||||||
end.
|
end.
|
||||||
@ -425,11 +428,12 @@ set_session(SID, User, Server, Resource, Priority, Info) ->
|
|||||||
-spec online([#session{}]) -> [#session{}].
|
-spec online([#session{}]) -> [#session{}].
|
||||||
|
|
||||||
online(Sessions) ->
|
online(Sessions) ->
|
||||||
lists:filter(fun(#session{sid = {_, undefined}}) ->
|
lists:filter(fun is_online/1, Sessions).
|
||||||
false;
|
|
||||||
(_) ->
|
-spec is_online(#session{}) -> boolean().
|
||||||
true
|
|
||||||
end, Sessions).
|
is_online(#session{info = Info}) ->
|
||||||
|
not proplists:get_bool(offline, Info).
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
@ -678,15 +682,17 @@ check_for_sessions_to_replace(User, Server, Resource) ->
|
|||||||
check_max_sessions(LUser, LServer).
|
check_max_sessions(LUser, LServer).
|
||||||
|
|
||||||
check_existing_resources(LUser, LServer, LResource) ->
|
check_existing_resources(LUser, LServer, LResource) ->
|
||||||
SIDs = get_resource_sessions(LUser, LServer, LResource),
|
Mod = get_sm_backend(LServer),
|
||||||
if SIDs == [] -> ok;
|
Ss = Mod:get_sessions(LUser, LServer, LResource),
|
||||||
|
{OnlineSs, OfflineSs} = lists:partition(fun is_online/1, Ss),
|
||||||
|
lists:foreach(fun(#session{sid = S}) ->
|
||||||
|
Mod:delete_session(LUser, LServer, LResource, S)
|
||||||
|
end, OfflineSs),
|
||||||
|
if OnlineSs == [] -> ok;
|
||||||
true ->
|
true ->
|
||||||
|
SIDs = [SID || #session{sid = SID} <- OnlineSs],
|
||||||
MaxSID = lists:max(SIDs),
|
MaxSID = lists:max(SIDs),
|
||||||
lists:foreach(fun ({_, undefined} = S) ->
|
lists:foreach(fun ({_, Pid} = S) when S /= MaxSID ->
|
||||||
Mod = get_sm_backend(LServer),
|
|
||||||
Mod:delete_session(LUser, LServer, LResource,
|
|
||||||
S);
|
|
||||||
({_, Pid} = S) when S /= MaxSID ->
|
|
||||||
Pid ! replaced;
|
Pid ! replaced;
|
||||||
(_) -> ok
|
(_) -> ok
|
||||||
end,
|
end,
|
||||||
|
@ -863,12 +863,15 @@ connected_users_vhost(Host) ->
|
|||||||
|
|
||||||
%% Code copied from ejabberd_sm.erl and customized
|
%% Code copied from ejabberd_sm.erl and customized
|
||||||
dirty_get_sessions_list2() ->
|
dirty_get_sessions_list2() ->
|
||||||
mnesia:dirty_select(
|
Ss = mnesia:dirty_select(
|
||||||
session,
|
session,
|
||||||
[{#session{usr = '$1', sid = {'$2', '$3'}, priority = '$4', info = '$5',
|
[{#session{usr = '$1', sid = '$2', priority = '$3', info = '$4',
|
||||||
_ = '_'},
|
_ = '_'},
|
||||||
[{is_pid, '$3'}],
|
[],
|
||||||
[['$1', {{'$2', '$3'}}, '$4', '$5']]}]).
|
[['$1', '$2', '$3', '$4']]}]),
|
||||||
|
lists:filter(fun([_USR, _SID, _Priority, Info]) ->
|
||||||
|
not proplists:get_bool(offline, Info)
|
||||||
|
end, Ss).
|
||||||
|
|
||||||
%% Make string more print-friendly
|
%% Make string more print-friendly
|
||||||
stringize(String) ->
|
stringize(String) ->
|
||||||
@ -903,8 +906,8 @@ user_sessions_info(User, Host) ->
|
|||||||
{'EXIT', _Reason} ->
|
{'EXIT', _Reason} ->
|
||||||
[];
|
[];
|
||||||
Ss ->
|
Ss ->
|
||||||
lists:filter(fun(#session{sid = {_, Pid}}) ->
|
lists:filter(fun(#session{info = Info}) ->
|
||||||
is_pid(Pid)
|
not proplists:get_bool(offline, Info)
|
||||||
end, Ss)
|
end, Ss)
|
||||||
end,
|
end,
|
||||||
lists:map(
|
lists:map(
|
||||||
|
@ -1917,21 +1917,29 @@ set_form(From, Host, ?NS_ADMINL(<<"end-user-session">>),
|
|||||||
Xmlelement = ?SERRT_POLICY_VIOLATION(Lang, <<"has been kicked">>),
|
Xmlelement = ?SERRT_POLICY_VIOLATION(Lang, <<"has been kicked">>),
|
||||||
case JID#jid.lresource of
|
case JID#jid.lresource of
|
||||||
<<>> ->
|
<<>> ->
|
||||||
SIDs = mnesia:dirty_select(session,
|
SIs = mnesia:dirty_select(session,
|
||||||
[{#session{sid = {'$1', '$2'},
|
[{#session{usr = {LUser, LServer, '_'},
|
||||||
usr = {LUser, LServer, '_'},
|
sid = '$1',
|
||||||
_ = '_'},
|
info = '$2',
|
||||||
[{is_pid, '$2'}],
|
_ = '_'},
|
||||||
[{{'$1', '$2'}}]}]),
|
[], [{{'$1', '$2'}}]}]),
|
||||||
[Pid ! {kick, kicked_by_admin, Xmlelement} || {_, Pid} <- SIDs];
|
Pids = [P || {{_, P}, Info} <- SIs,
|
||||||
|
not proplists:get_bool(offline, Info)],
|
||||||
|
lists:foreach(fun(Pid) ->
|
||||||
|
Pid ! {kick, kicked_by_admin, Xmlelement}
|
||||||
|
end, Pids);
|
||||||
R ->
|
R ->
|
||||||
[{_, Pid}] = mnesia:dirty_select(session,
|
[{{_, Pid}, Info}] = mnesia:dirty_select(
|
||||||
[{#session{sid = {'$1', '$2'},
|
session,
|
||||||
usr = {LUser, LServer, R},
|
[{#session{usr = {LUser, LServer, R},
|
||||||
_ = '_'},
|
sid = '$1',
|
||||||
[{is_pid, '$2'}],
|
info = '$2',
|
||||||
[{{'$1', '$2'}}]}]),
|
_ = '_'},
|
||||||
Pid ! {kick, kicked_by_admin, Xmlelement}
|
[], [{{'$1', '$2'}}]}]),
|
||||||
|
case proplists:get_bool(offline, Info) of
|
||||||
|
true -> ok;
|
||||||
|
false -> Pid ! {kick, kicked_by_admin, Xmlelement}
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
{result, []};
|
{result, []};
|
||||||
set_form(From, Host,
|
set_form(From, Host,
|
||||||
|
Loading…
Reference in New Issue
Block a user