aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHolger Weiss <holger@zedat.fu-berlin.de>2016-07-23 01:08:05 +0200
committerHolger Weiss <holger@zedat.fu-berlin.de>2016-07-23 01:08:05 +0200
commit814b80c644fa425990dc63875e1da841d698b0fa (patch)
tree277041ddec51894c69741f6df070b6a50e3ca4c4 /src
parentSupport oauth password grant type (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd_sm.erl42
-rw-r--r--src/mod_admin_extra.erl19
-rw-r--r--src/mod_configure.erl36
3 files changed, 57 insertions, 40 deletions
diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl
index 8d94bc6aa..16e0f9114 100644
--- a/src/ejabberd_sm.erl
+++ b/src/ejabberd_sm.erl
@@ -270,25 +270,28 @@ get_session_pid(User, Server, Resource) ->
-spec set_offline_info(sid(), binary(), binary(), binary(), info()) -> ok.
-set_offline_info({Time, _Pid}, User, Server, Resource, Info) ->
- SID = {Time, undefined},
+set_offline_info(SID, User, Server, Resource, Info) ->
LUser = jid:nodeprep(User),
LServer = jid:nameprep(Server),
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(),
binary()) -> none | info().
get_offline_info(Time, User, Server, Resource) ->
- SID = {Time, undefined},
LUser = jid:nodeprep(User),
LServer = jid:nameprep(Server),
LResource = jid:resourceprep(Resource),
Mod = get_sm_backend(LServer),
case Mod:get_sessions(LUser, LServer, LResource) of
- [#session{sid = SID, info = Info}] ->
- Info;
+ [#session{sid = {Time, _}, info = Info}] ->
+ case proplists:get_bool(offline, Info) of
+ true ->
+ Info;
+ false ->
+ none
+ end;
_ ->
none
end.
@@ -425,11 +428,12 @@ set_session(SID, User, Server, Resource, Priority, Info) ->
-spec online([#session{}]) -> [#session{}].
online(Sessions) ->
- lists:filter(fun(#session{sid = {_, undefined}}) ->
- false;
- (_) ->
- true
- end, Sessions).
+ lists:filter(fun is_online/1, Sessions).
+
+-spec is_online(#session{}) -> boolean().
+
+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_existing_resources(LUser, LServer, LResource) ->
- SIDs = get_resource_sessions(LUser, LServer, LResource),
- if SIDs == [] -> ok;
+ Mod = get_sm_backend(LServer),
+ 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 ->
+ SIDs = [SID || #session{sid = SID} <- OnlineSs],
MaxSID = lists:max(SIDs),
- lists:foreach(fun ({_, undefined} = S) ->
- Mod = get_sm_backend(LServer),
- Mod:delete_session(LUser, LServer, LResource,
- S);
- ({_, Pid} = S) when S /= MaxSID ->
+ lists:foreach(fun ({_, Pid} = S) when S /= MaxSID ->
Pid ! replaced;
(_) -> ok
end,
diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl
index 8f6724281..2ad1cc28e 100644
--- a/src/mod_admin_extra.erl
+++ b/src/mod_admin_extra.erl
@@ -863,12 +863,15 @@ connected_users_vhost(Host) ->
%% Code copied from ejabberd_sm.erl and customized
dirty_get_sessions_list2() ->
- mnesia:dirty_select(
- session,
- [{#session{usr = '$1', sid = {'$2', '$3'}, priority = '$4', info = '$5',
- _ = '_'},
- [{is_pid, '$3'}],
- [['$1', {{'$2', '$3'}}, '$4', '$5']]}]).
+ Ss = mnesia:dirty_select(
+ session,
+ [{#session{usr = '$1', sid = '$2', priority = '$3', info = '$4',
+ _ = '_'},
+ [],
+ [['$1', '$2', '$3', '$4']]}]),
+ lists:filter(fun([_USR, _SID, _Priority, Info]) ->
+ not proplists:get_bool(offline, Info)
+ end, Ss).
%% Make string more print-friendly
stringize(String) ->
@@ -903,8 +906,8 @@ user_sessions_info(User, Host) ->
{'EXIT', _Reason} ->
[];
Ss ->
- lists:filter(fun(#session{sid = {_, Pid}}) ->
- is_pid(Pid)
+ lists:filter(fun(#session{info = Info}) ->
+ not proplists:get_bool(offline, Info)
end, Ss)
end,
lists:map(
diff --git a/src/mod_configure.erl b/src/mod_configure.erl
index 97c944842..d0e0166a4 100644
--- a/src/mod_configure.erl
+++ b/src/mod_configure.erl
@@ -1917,21 +1917,29 @@ set_form(From, Host, ?NS_ADMINL(<<"end-user-session">>),
Xmlelement = ?SERRT_POLICY_VIOLATION(Lang, <<"has been kicked">>),
case JID#jid.lresource of
<<>> ->
- SIDs = mnesia:dirty_select(session,
- [{#session{sid = {'$1', '$2'},
- usr = {LUser, LServer, '_'},
- _ = '_'},
- [{is_pid, '$2'}],
- [{{'$1', '$2'}}]}]),
- [Pid ! {kick, kicked_by_admin, Xmlelement} || {_, Pid} <- SIDs];
+ SIs = mnesia:dirty_select(session,
+ [{#session{usr = {LUser, LServer, '_'},
+ sid = '$1',
+ info = '$2',
+ _ = '_'},
+ [], [{{'$1', '$2'}}]}]),
+ Pids = [P || {{_, P}, Info} <- SIs,
+ not proplists:get_bool(offline, Info)],
+ lists:foreach(fun(Pid) ->
+ Pid ! {kick, kicked_by_admin, Xmlelement}
+ end, Pids);
R ->
- [{_, Pid}] = mnesia:dirty_select(session,
- [{#session{sid = {'$1', '$2'},
- usr = {LUser, LServer, R},
- _ = '_'},
- [{is_pid, '$2'}],
- [{{'$1', '$2'}}]}]),
- Pid ! {kick, kicked_by_admin, Xmlelement}
+ [{{_, Pid}, Info}] = mnesia:dirty_select(
+ session,
+ [{#session{usr = {LUser, LServer, R},
+ sid = '$1',
+ info = '$2',
+ _ = '_'},
+ [], [{{'$1', '$2'}}]}]),
+ case proplists:get_bool(offline, Info) of
+ true -> ok;
+ false -> Pid ! {kick, kicked_by_admin, Xmlelement}
+ end
end,
{result, []};
set_form(From, Host,