aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMickaël Rémond <mickael.remond@process-one.net>2006-05-21 16:34:32 +0000
committerMickaël Rémond <mickael.remond@process-one.net>2006-05-21 16:34:32 +0000
commit043c2ccf518e9ad928bdee48349ece56b7da5751 (patch)
tree099debfbf8f78e7406d6586c9e19c59f3756ee66 /src
parent* src/web/ejabberd_http_poll.erl: Timeout disconnection were not (diff)
* src/ejabberd_sm.erl: An option to limit the number of opened sessions
for a given user have been added. As a default, a given user can only log in 10 times with different resources. After that, new connections replace the older ones. * src/ejabberd.cfg.example: Likewise. * doc/guide.tex: Likewise. SVN Revision: 567
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd.cfg.example1
-rw-r--r--src/ejabberd_sm.erl86
2 files changed, 70 insertions, 17 deletions
diff --git a/src/ejabberd.cfg.example b/src/ejabberd.cfg.example
index 3a8fc9319..9b894de13 100644
--- a/src/ejabberd.cfg.example
+++ b/src/ejabberd.cfg.example
@@ -114,6 +114,7 @@
{listen,
[{5222, ejabberd_c2s, [{access, c2s}, {shaper, c2s_shaper},
{max_stanza_size, 65536},
+ {max_user_sessions, 10},
starttls, {certfile, "./ssl.pem"}]},
{5223, ejabberd_c2s, [{access, c2s},
{max_stanza_size, 65536},
diff --git a/src/ejabberd_sm.erl b/src/ejabberd_sm.erl
index c9ed39b18..4e82e5632 100644
--- a/src/ejabberd_sm.erl
+++ b/src/ejabberd_sm.erl
@@ -42,6 +42,9 @@
-record(session, {sid, usr, us, priority}).
-record(state, {}).
+%% default value for the maximum number of user connections
+-define(MAX_USER_SESSIONS, 10).
+
%%====================================================================
%% API
%%====================================================================
@@ -63,6 +66,7 @@ route(From, To, Packet) ->
open_session(SID, User, Server, Resource) ->
set_session(SID, User, Server, Resource, undefined),
+ check_for_sessions_to_replace(User, Server, Resource),
JID = jlib:make_jid(User, Server, Resource),
ejabberd_hooks:run(sm_register_connection_hook, JID#jid.lserver,
[SID, JID]).
@@ -177,6 +181,7 @@ init([]) ->
{"connected-users-number", "print a number of established sessions"},
{"user-resources user server", "print user's connected resources"}],
?MODULE, ctl_process),
+
{ok, #state{}}.
%%--------------------------------------------------------------------
@@ -270,23 +275,7 @@ set_session(SID, User, Server, Resource, Priority) ->
us = US,
priority = Priority})
end,
- mnesia:sync_dirty(F),
- SIDs = mnesia:dirty_select(
- session,
- [{#session{sid = '$1', usr = USR, _ = '_'}, [], ['$1']}]),
- if
- SIDs == [] ->
- ok;
- true ->
- MaxSID = lists:max(SIDs),
- lists:foreach(
- fun({_, Pid} = S) when S /= MaxSID ->
- Pid ! replaced;
- (_) ->
- ok
- end, SIDs)
- end.
-
+ mnesia:sync_dirty(F).
clean_table_from_bad_node(Node) ->
F = fun() ->
@@ -509,6 +498,69 @@ get_user_present_resources(LUser, LServer) ->
S <- clean_session_list(Ss), is_integer(S#session.priority)]
end.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% On new session, check if some existing connections need to be replace
+check_for_sessions_to_replace(User, Server, Resource) ->
+ LUser = jlib:nodeprep(User),
+ LServer = jlib:nameprep(Server),
+ LResource = jlib:resourceprep(Resource),
+
+ %% TODO: Depending on how this is executed, there could be an unneeded
+ %% replacement for max_sessions. We need to check this at some point.
+ check_existing_resources(LUser, LServer, LResource),
+ check_max_sessions(LUser, LServer).
+
+check_existing_resources(LUser, LServer, LResource) ->
+ USR = {LUser, LServer, LResource},
+ %% A connection exist with the same resource. We replace it:
+ SIDs = mnesia:dirty_select(
+ session,
+ [{#session{sid = '$1', usr = USR, _ = '_'}, [], ['$1']}]),
+ if
+ SIDs == [] -> ok;
+ true ->
+ MaxSID = lists:max(SIDs),
+ lists:foreach(
+ fun({_, Pid} = S) when S /= MaxSID ->
+ Pid ! replaced;
+ (_) -> ok
+ end, SIDs)
+ end.
+
+check_max_sessions(LUser, LServer) ->
+ %% If the max number of sessions for a given is reached, we replace the
+ %% first one
+ SIDs = mnesia:dirty_select(
+ session,
+ [{#session{sid = '$1', usr = {LUser, LServer, '_'}, _ = '_'}, [], ['$1']}]),
+ MaxSessions = get_max_user_sessions(),
+ if length(SIDs) =< MaxSessions -> ok;
+ true -> {_, Pid} = lists:min(SIDs),
+ Pid ! replaced
+ end.
+
+
+%% Get the user_max_session setting
+%% This option defines the max number of time a given users are allowed to
+%% log in
+%% This option is only used on c2s connections
+%% Defaults to 10
+%% Can be set to infinity
+get_max_user_sessions() ->
+ case ejabberd_config:get_local_option(listen) of
+ undefined -> ?MAX_USER_SESSIONS;
+ Listeners ->
+ case lists:keysearch(ejabberd_c2s, 2, Listeners) of
+ {value, {_Port, _Method, Opts}} ->
+ case lists:keysearch(max_user_sessions, 1, Opts) of
+ {value, {_, Max}} -> Max;
+ _ -> ?MAX_USER_SESSIONS
+ end;
+ _ -> ?MAX_USER_SESSIONS
+ end
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%