diff options
author | Mickaël Rémond <mickael.remond@process-one.net> | 2006-05-21 16:34:32 +0000 |
---|---|---|
committer | Mickaël Rémond <mickael.remond@process-one.net> | 2006-05-21 16:34:32 +0000 |
commit | 043c2ccf518e9ad928bdee48349ece56b7da5751 (patch) | |
tree | 099debfbf8f78e7406d6586c9e19c59f3756ee66 /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.example | 1 | ||||
-rw-r--r-- | src/ejabberd_sm.erl | 86 |
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. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |