+2006-09-05 Mickael Remond <mickael.remond@process-one.net>
+
+ * src/mod_muc/mod_muc.erl: It is now possible to configure the MUC room
+ history feature. A new option has been added in ejabberd muc module
+ configuration (history_size) to define the size of the history. 0 is
+ used to disable the feature.
+ * src/mod_muc/mod_muc_room.erl: Likewise.
+ * doc/guide.tex: Likewise.
+
2006-09-05 Alexey Shchepin <alexey@sevcom.net>
* src/ejabberd_socket.erl: All XML socket operations moved here
value is <TT>none</TT>, which means that only the room creator can
administer his room). By sending a message to the service JID,
administrators can send service messages that will be displayed in every
- active room.
+ active room.<BR>
+<BR>
+<DT CLASS="dt-description"><B><TT>history_size</TT></B><DD CLASS="dd-description"> a small history of the
+ current discussion is send to users when they enter the room. This option make
+ it possible to define the number of history messages to keep and send to the
+ user joining the room. The value is a integer. Setting the value to <TT>0</TT>
+ disable the history feature and nothing is kept in memory. The default value
+ is <TT>20</TT>. This value is global and affects all MUC rooms on the server.
</DL>
Examples:
<UL CLASS="itemize"><LI CLASS="li-itemize">
sends a message such as “Tomorrow, the Jabber server will be moved
to new hardware. This will involve service breakdowns around 23:00 UMT.
We apologise for this inconvenience.” to <TT>conference.example.org</TT>,
- it will be displayed in all active rooms.
+ it will be displayed in all active rooms. In this example the history
+ feature is disabled.
<PRE CLASS="verbatim">
{acl, admins, {user, "admin", "example.org"}}.
...
...
{mod_muc, [{access, all},
{access_create, all},
- {access_admin, muc_admins}]},
+ {access_admin, muc_admins},
+ {history_size, 0}]},
...
]}.
</PRE><LI CLASS="li-itemize">In the second example the Multi-User Chat service is only accessible by
<TT>admin@example.org</TT> sends a message such as “Tomorrow, the Jabber
server will be moved to new hardware. This will involve service breakdowns
around 23:00 UMT. We apologise for this inconvenience.” to
- <TT>conference.example.org</TT>, it will be displayed in all active rooms.
+ <TT>conference.example.org</TT>, it will be displayed in all active rooms. No
+ <TT>history_size</TT> option is used, this means that the feature is enabled
+ and the default value of 20 history messages will be send to the users.
<PRE CLASS="verbatim">
{acl, paying_customers, {user, "customer1", "example.net"}}.
{acl, paying_customers, {user, "customer2", "example.com"}}.
administer his room). By sending a message to the service JID,
administrators can send service messages that will be displayed in every
active room.
+
+ \titem{history\_size} \ind{options!history\_size}a small history of the
+ current discussion is send to users when they enter the room. This option make
+ it possible to define the number of history messages to keep and send to the
+ user joining the room. The value is a integer. Setting the value to \term{0}
+ disable the history feature and nothing is kept in memory. The default value
+ is \term{20}. This value is global and affects all MUC rooms on the server.
\end{description}
Examples:
sends a message such as ``Tomorrow, the \Jabber{} server will be moved
to new hardware. This will involve service breakdowns around 23:00 UMT.
We apologise for this inconvenience.'' to \jid{conference.example.org},
- it will be displayed in all active rooms.
+ it will be displayed in all active rooms. In this example the history
+ feature is disabled.
\begin{verbatim}
{acl, admins, {user, "admin", "example.org"}}.
...
...
{mod_muc, [{access, all},
{access_create, all},
- {access_admin, muc_admins}]},
+ {access_admin, muc_admins},
+ {history_size, 0}]},
...
]}.
\end{verbatim}
\jid{admin@example.org} sends a message such as ``Tomorrow, the \Jabber{}
server will be moved to new hardware. This will involve service breakdowns
around 23:00 UMT. We apologise for this inconvenience.'' to
- \jid{conference.example.org}, it will be displayed in all active rooms.
+ \jid{conference.example.org}, it will be displayed in all active rooms. No
+ \term{history\_size} option is used, this means that the feature is enabled
+ and the default value of 20 history messages will be send to the users.
\begin{verbatim}
{acl, paying_customers, {user, "customer1", "example.net"}}.
{acl, paying_customers, {user, "customer2", "example.com"}}.
-record(muc_online_room, {name_host, pid}).
-record(muc_registered, {us_host, nick}).
--record(state, {host, server_host, access}).
+-record(state, {host, server_host, access, history_size}).
-define(PROCNAME, ejabberd_mod_muc).
Access = gen_mod:get_opt(access, Opts, all),
AccessCreate = gen_mod:get_opt(access_create, Opts, all),
AccessAdmin = gen_mod:get_opt(access_admin, Opts, none),
+ HistorySize = gen_mod:get_opt(history_size, Opts, 20),
catch ets:new(muc_online_room, [named_table,
public,
{keypos, #muc_online_room.name_host}]),
ejabberd_router:register_route(MyHost),
- load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin}),
+ load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin},
+ HistorySize),
{ok, #state{host = MyHost,
server_host = Host,
- access = {Access, AccessCreate, AccessAdmin}}}.
+ access = {Access, AccessCreate, AccessAdmin},
+ history_size = HistorySize}}.
%%--------------------------------------------------------------------
%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
handle_info({route, From, To, Packet},
#state{host = Host,
server_host = ServerHost,
- access = Access} = State) ->
- case catch do_route(Host, ServerHost, Access, From, To, Packet) of
+ access = Access,
+ history_size = HistorySize} = State) ->
+ case catch do_route(Host, ServerHost, Access, HistorySize, From, To, Packet) of
{'EXIT', Reason} ->
?ERROR_MSG("~p", [Reason]);
_ ->
supervisor:terminate_child(ejabberd_sup, Proc),
supervisor:delete_child(ejabberd_sup, Proc).
-do_route(Host, ServerHost, Access, From, To, Packet) ->
+do_route(Host, ServerHost, Access, HistorySize, From, To, Packet) ->
{AccessRoute, _AccessCreate, _AccessAdmin} = Access,
case acl:match_rule(ServerHost, AccessRoute, From) of
allow ->
- do_route1(Host, ServerHost, Access, From, To, Packet);
+ do_route1(Host, ServerHost, Access, HistorySize, From, To, Packet);
_ ->
{xmlelement, _Name, Attrs, _Els} = Packet,
Lang = xml:get_attr_s("xml:lang", Attrs),
end.
-do_route1(Host, ServerHost, Access, From, To, Packet) ->
+do_route1(Host, ServerHost, Access, HistorySize, From, To, Packet) ->
{_AccessRoute, AccessCreate, AccessAdmin} = Access,
{Room, _, Nick} = jlib:jid_tolower(To),
{xmlelement, Name, Attrs, _Els} = Packet,
?DEBUG("MUC: open new room '~s'~n", [Room]),
{ok, Pid} = mod_muc_room:start(
Host, ServerHost, Access,
- Room, From, Nick),
+ Room, HistorySize, From,
+ Nick),
ets:insert(
muc_online_room,
#muc_online_room{name_host = {Room, Host},
-load_permanent_rooms(Host, ServerHost, Access) ->
+load_permanent_rooms(Host, ServerHost, Access, HistorySize) ->
case catch mnesia:dirty_select(
muc_room, [{#muc_room{name_host = {'_', Host}, _ = '_'},
[],
ServerHost,
Access,
Room,
+ HistorySize,
R#muc_room.opts),
ets:insert(
muc_online_room,
%% External exports
--export([start_link/6,
- start_link/5,
+-export([start_link/7,
+ start_link/6,
+ start/7,
start/6,
- start/5,
route/4]).
%% gen_fsm callbacks
%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------
-start(Host, ServerHost, Access, Room, Creator, Nick) ->
+start(Host, ServerHost, Access, Room, HistorySize, Creator, Nick) ->
Supervisor = gen_mod:get_module_proc(ServerHost, ejabberd_mod_muc_sup),
supervisor:start_child(
- Supervisor, [Host, ServerHost, Access, Room, Creator, Nick]).
+ Supervisor, [Host, ServerHost, Access, Room, HistorySize, Creator, Nick]).
-start(Host, ServerHost, Access, Room, Opts) ->
+start(Host, ServerHost, Access, Room, HistorySize, Opts) ->
Supervisor = gen_mod:get_module_proc(ServerHost, ejabberd_mod_muc_sup),
supervisor:start_child(
- Supervisor, [Host, ServerHost, Access, Room, Opts]).
+ Supervisor, [Host, ServerHost, Access, Room, HistorySize, Opts]).
-start_link(Host, ServerHost, Access, Room, Creator, Nick) ->
- gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, Creator, Nick],
+start_link(Host, ServerHost, Access, Room, HistorySize, Creator, Nick) ->
+ gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, HistorySize, Creator, Nick],
?FSMOPTS).
-start_link(Host, ServerHost, Access, Room, Opts) ->
- gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, Opts],
+start_link(Host, ServerHost, Access, Room, HistorySize, Opts) ->
+ gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, HistorySize, Opts],
?FSMOPTS).
%%%----------------------------------------------------------------------
%% ignore |
%% {stop, StopReason}
%%----------------------------------------------------------------------
-init([Host, ServerHost, Access, Room, Creator, _Nick]) ->
+init([Host, ServerHost, Access, Room, HistorySize, Creator, _Nick]) ->
State = set_affiliation(Creator, owner,
#state{host = Host,
server_host = ServerHost,
access = Access,
room = Room,
+ history = lqueue_new(HistorySize),
jid = jlib:make_jid(Room, Host, ""),
just_created = true}),
{ok, normal_state, State};
-init([Host, ServerHost, Access, Room, Opts]) ->
+init([Host, ServerHost, Access, Room, HistorySize, Opts]) ->
State = set_opts(Opts, #state{host = Host,
server_host = ServerHost,
access = Access,
room = Room,
+ history = lqueue_new(HistorySize),
jid = jlib:make_jid(Room, Host, "")}),
{ok, normal_state, State}.
len = 0,
max = Max}.
-lqueue_in(Item, #lqueue{queue = Q1, len = Len, max = Max}) ->
+%% If the message queue limit is set to 0, do not store messages.
+lqueue_in(Item, LQ = #lqueue{max = 0}) ->
+ LQ;
+%% Otherwise, rotate messages in the queue store.
+lqueue_in(Item, LQ = #lqueue{queue = Q1, len = Len, max = Max}) ->
Q2 = queue:in(Item, Q1),
if
Len >= Max ->