New option for mod_offline: access_max_user_messages.
The old option user_max_messages is no longer supported.
SVN Revision: 2162
online again. Thus it is very similar to how email works. Note that
<TT>ejabberdctl</TT> has a command to delete expired messages
(see section <A HREF="#ejabberdctl">4.1</A>).</P><DL CLASS="description"><DT CLASS="dt-description">
-<B><TT>user_max_messages</TT></B></DT><DD CLASS="dd-description">This option
-is use to set a max number of offline messages per user (quota). Its
-value can be either <TT>infinity</TT> or a strictly positive
-integer. The default value is <TT>infinity</TT>.
-</DD></DL><P> <A NAME="modprivacy"></A> </P><!--TOC subsection <TT>mod_privacy</TT>-->
+<B><TT>access_max_user_messages</TT></B></DT><DD CLASS="dd-description">
+This option defines which access rule will be enforced to limit
+the maximum number of offline messages that a user can have (quota).
+When a user has too many offline messages, any new messages that he receive are discarded,
+and a resource-constraint error is returned to the sender.
+The default value is <TT>max_user_offline_messages</TT>.
+Then you can define an access rule with a syntax similar to
+<TT>max_user_sessions</TT> (see <A HREF="#configmaxsessions">3.1.5</A>).
+</DD></DL><P>This example allows power users to have as much as 5000 offline messages,
+administrators up to 2000,
+and all the other users up to 100.
+</P><PRE CLASS="verbatim">{acl, admin, {user, "admin1", "localhost"}}.
+{acl, admin, {user, "admin2", "example.org"}}.
+{acl, poweruser, {user, "bob", "example.org"}}.
+{acl, poweruser, {user, "jane", "example.org"}}.
+
+{access, max_user_offline_messages, [ {5000, poweruser}, {2000, admin}, {100, all} ]}.
+
+{modules,
+ [
+ ...
+ {mod_offline, [ {access_max_user_messages, max_user_offline_messages} ]},
+ ...
+ ]}.
+</PRE><P> <A NAME="modprivacy"></A> </P><!--TOC subsection <TT>mod_privacy</TT>-->
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc48">3.3.11</A>  <A HREF="#modprivacy"><TT>mod_privacy</TT></A></H3><!--SEC END --><P> <A NAME="modprivacy"></A>
</P><P>This module implements Blocking Communication (also known as Privacy Rules)
as defined in section 10 from XMPP IM. If end users have support for it in
</DD><DT CLASS="dt-description"><B><TT>access_createnode</TT></B></DT><DD CLASS="dd-description">
This option restricts which users are allowed to create pubsub nodes using
-ACL and ACCESS. The default value is <TT>pubsub_createnode</TT>. </DD><DT CLASS="dt-description"><B><TT>plugins</TT></B></DT><DD CLASS="dd-description"> To specify which pubsub node plugins to use. If not defined, the default
+ACL and ACCESS. The default value is <TT>pubsub_createnode</TT>. </DD><DT CLASS="dt-description"><B><TT>plugins</TT></B></DT><DD CLASS="dd-description">
+To specify which pubsub node plugins to use. If not defined, the default
pubsub plugin is always used.
-</DD><DT CLASS="dt-description"><B><TT>nodetree</TT></B></DT><DD CLASS="dd-description"> To specify which nodetree to use. If not defined, the default pubsub
-nodetree is used. Nodetrees are default and virtual. Only one nodetree can be used
+</DD><DT CLASS="dt-description"><B><TT>nodetree</TT></B></DT><DD CLASS="dd-description">
+To specify which nodetree to use. If not defined, the default pubsub
+nodetree is used. Only one nodetree can be used per host,
and is shared by all node plugins.
-</DD></DL><P>Example:
+</DD><DT CLASS="dt-description"><B><TT>pep_sendlast_offline</TT></B></DT><DD CLASS="dd-description">
+To specify whether or not we should get last published PEP items
+from users in our roster which are offline when we connect. Value is true or false.
+If not defined, pubsub assumes false so we only get last items of online contacts.
+</DD><DT CLASS="dt-description"><B><TT>last_item_cache</TT></B></DT><DD CLASS="dd-description">
+To specify whether or not pubsub should cache last items. Value is true
+or false. If not defined, pubsub do not cache last items. On systems with not so many nodes,
+caching last items speeds up pubsub and allows to raise user connection rate. The cost is memory
+usage, as every item is stored in memory.
+</DD><DT CLASS="dt-description"><B><TT>pep_mapping</TT></B></DT><DD CLASS="dd-description">
+This allow to define a Key-Value list to choose defined node plugins on given PEP namespace.
+The following example will use node_tune instead of node_pep for every PEP node with tune namespace:
+<PRE CLASS="verbatim"> {mod_pubsub, [{pep_mapping, [{"http://jabber.org/protocol/tune", "tune"}]}]}
+</PRE></DD></DL><P>Example:
</P><PRE CLASS="verbatim">{modules,
[
...
(see section~\ref{ejabberdctl}).
\begin{description}
- \titem{user\_max\_messages}\ind{options!user\_max\_messages}This option
- is use to set a max number of offline messages per user (quota). Its
- value can be either \term{infinity} or a strictly positive
- integer. The default value is \term{infinity}.
+ \titem{access\_max\_user\_messages}\ind{options!access\_max\_user\_messages}
+ This option defines which access rule will be enforced to limit
+ the maximum number of offline messages that a user can have (quota).
+ When a user has too many offline messages, any new messages that he receive are discarded,
+ and a resource-constraint error is returned to the sender.
+ The default value is \term{max\_user\_offline\_messages}.
+ Then you can define an access rule with a syntax similar to
+ \term{max\_user\_sessions} (see \ref{configmaxsessions}).
\end{description}
+This example allows power users to have as much as 5000 offline messages,
+administrators up to 2000,
+and all the other users up to 100.
+\begin{verbatim}
+{acl, admin, {user, "admin1", "localhost"}}.
+{acl, admin, {user, "admin2", "example.org"}}.
+{acl, poweruser, {user, "bob", "example.org"}}.
+{acl, poweruser, {user, "jane", "example.org"}}.
+
+{access, max_user_offline_messages, [ {5000, poweruser}, {2000, admin}, {100, all} ]}.
+
+{modules,
+ [
+ ...
+ {mod_offline, [ {access_max_user_messages, max_user_offline_messages} ]},
+ ...
+ ]}.
+\end{verbatim}
+
\makesubsection{modprivacy}{\modprivacy{}}
\ind{modules!\modprivacy{}}\ind{Blocking Communication}\ind{Privacy Rules}\ind{protocols!RFC 3921: XMPP IM}
%% Maximum number of simultaneous sessions allowed for a single user:
{access, max_user_sessions, [{10, all}]}.
+%% Maximum number of offline messages that users can have:
+{access, max_user_offline_messages, [{5000, admin}, {100, all}]},
+
%% This rule allows access only for local users:
{access, local, [{allow, local}]}.
{access_admin, muc_admin}
]},
%%{mod_muc_log,[]},
- {mod_offline, []},
+ {mod_offline, [{access_max_user_messages, max_user_offline_messages}]},
{mod_privacy, []},
{mod_private, []},
%%{mod_proxy65,[]},
-behaviour(gen_mod).
-export([start/2,
- init/1,
+ loop/1,
stop/1,
store_packet/3,
resend_offline_messages/2,
-define(PROCNAME, ejabberd_offline).
-define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000).
+%% default value for the maximum number of user messages
+-define(MAX_USER_MESSAGES, infinity).
+
start(Host, Opts) ->
mnesia:create_table(offline_msg,
[{disc_only_copies, [node()]},
?MODULE, webadmin_user, 50),
ejabberd_hooks:add(webadmin_user_parse_query, Host,
?MODULE, webadmin_user_parse_query, 50),
- MaxOfflineMsgs = gen_mod:get_opt(user_max_messages, Opts, infinity),
+ AccessMaxOfflineMsgs = gen_mod:get_opt(access_max_user_messages, Opts, max_user_offline_messages),
register(gen_mod:get_module_proc(Host, ?PROCNAME),
- spawn(?MODULE, init, [MaxOfflineMsgs])).
-
-%% MaxOfflineMsgs is either infinity of integer > 0
-init(infinity) ->
- loop(infinity);
-init(MaxOfflineMsgs)
- when is_integer(MaxOfflineMsgs), MaxOfflineMsgs > 0 ->
- loop(MaxOfflineMsgs).
+ spawn(?MODULE, loop, [AccessMaxOfflineMsgs])).
-loop(MaxOfflineMsgs) ->
+loop(AccessMaxOfflineMsgs) ->
receive
#offline_msg{us=US} = Msg ->
Msgs = receive_all(US, [Msg]),
Len = length(Msgs),
+ {User, Host} = US,
+ MaxOfflineMsgs = get_max_user_messages(AccessMaxOfflineMsgs,
+ User, Host),
F = fun() ->
%% Only count messages if needed:
Count = if MaxOfflineMsgs =/= infinity ->
end
end,
mnesia:transaction(F),
- loop(MaxOfflineMsgs);
+ loop(AccessMaxOfflineMsgs);
_ ->
- loop(MaxOfflineMsgs)
+ loop(AccessMaxOfflineMsgs)
+ end.
+
+%% Function copied from ejabberd_sm.erl:
+get_max_user_messages(AccessRule, LUser, Host) ->
+ case acl:match_rule(
+ Host, AccessRule, jlib:make_jid(LUser, Host, "")) of
+ Max when is_integer(Max) -> Max;
+ infinity -> infinity;
+ _ -> ?MAX_USER_MESSAGES
end.
receive_all(US, Msgs) ->
-export([count_offline_messages/2]).
-export([start/2,
- init/2,
+ loop/2,
stop/1,
store_packet/3,
pop_offline_messages/3,
-define(PROCNAME, ejabberd_offline).
-define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000).
+%% default value for the maximum number of user messages
+-define(MAX_USER_MESSAGES, infinity).
+
start(Host, Opts) ->
ejabberd_hooks:add(offline_message_hook, Host,
?MODULE, store_packet, 50),
?MODULE, webadmin_user, 50),
ejabberd_hooks:add(webadmin_user_parse_query, Host,
?MODULE, webadmin_user_parse_query, 50),
- MaxOfflineMsgs = gen_mod:get_opt(user_max_messages, Opts, infinity),
+ AccessMaxOfflineMsgs = gen_mod:get_opt(access_max_user_messages, Opts, max_user_offline_messages),
register(gen_mod:get_module_proc(Host, ?PROCNAME),
- spawn(?MODULE, init, [Host, MaxOfflineMsgs])).
-
-%% MaxOfflineMsgs is either infinity of integer > 0
-init(Host, infinity) ->
- loop(Host, infinity);
-init(Host, MaxOfflineMsgs)
- when is_integer(MaxOfflineMsgs), MaxOfflineMsgs > 0 ->
- loop(Host, MaxOfflineMsgs).
+ spawn(?MODULE, loop, [Host, AccessMaxOfflineMsgs])).
-loop(Host, MaxOfflineMsgs) ->
+loop(Host, AccessMaxOfflineMsgs) ->
receive
#offline_msg{user = User} = Msg ->
Msgs = receive_all(User, [Msg]),
Len = length(Msgs),
+ MaxOfflineMsgs = get_max_user_messages(AccessMaxOfflineMsgs,
+ User, Host),
%% Only count existing messages if needed:
Count = if MaxOfflineMsgs =/= infinity ->
ok
end
end,
- loop(Host, MaxOfflineMsgs);
+ loop(Host, AccessMaxOfflineMsgs);
_ ->
- loop(Host, MaxOfflineMsgs)
+ loop(Host, AccessMaxOfflineMsgs)
+ end.
+
+%% Function copied from ejabberd_sm.erl:
+get_max_user_messages(AccessRule, LUser, Host) ->
+ case acl:match_rule(
+ Host, AccessRule, jlib:make_jid(LUser, Host, "")) of
+ Max when is_integer(Max) -> Max;
+ infinity -> infinity;
+ _ -> ?MAX_USER_MESSAGES
end.
receive_all(Username, Msgs) ->