mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
* src/mod_muc/mod_muc_room.erl: Added user_message_shaper and
room_shaper options * src/mod_muc/mod_muc.erl: Likewise SVN Revision: 906
This commit is contained in:
parent
4b63b03718
commit
722563ed94
@ -1,3 +1,9 @@
|
||||
2007-09-01 Alexey Shchepin <alexey@process-one.net>
|
||||
|
||||
* src/mod_muc/mod_muc_room.erl: Added user_message_shaper and
|
||||
room_shaper options
|
||||
* src/mod_muc/mod_muc.erl: Likewise
|
||||
|
||||
2007-08-31 Mickael Remond <mremond@process-one.net>
|
||||
|
||||
* doc/guide.tex: Minor examples improvement in LDAP
|
||||
|
@ -34,7 +34,12 @@
|
||||
-record(muc_online_room, {name_host, pid}).
|
||||
-record(muc_registered, {us_host, nick}).
|
||||
|
||||
-record(state, {host, server_host, access, history_size, default_room_opts}).
|
||||
-record(state, {host,
|
||||
server_host,
|
||||
access,
|
||||
history_size,
|
||||
default_room_opts,
|
||||
room_shaper}).
|
||||
|
||||
-define(PROCNAME, ejabberd_mod_muc).
|
||||
|
||||
@ -155,14 +160,18 @@ init([Host, Opts]) ->
|
||||
AccessPersistent = gen_mod:get_opt(access_persistent, Opts, all),
|
||||
HistorySize = gen_mod:get_opt(history_size, Opts, 20),
|
||||
DefRoomOpts = gen_mod:get_opt(default_room_options, Opts, []),
|
||||
RoomShaper = gen_mod:get_opt(room_shaper, Opts, none),
|
||||
ejabberd_router:register_route(MyHost),
|
||||
load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin, AccessPersistent},
|
||||
HistorySize),
|
||||
load_permanent_rooms(MyHost, Host,
|
||||
{Access, AccessCreate, AccessAdmin, AccessPersistent},
|
||||
HistorySize,
|
||||
RoomShaper),
|
||||
{ok, #state{host = MyHost,
|
||||
server_host = Host,
|
||||
access = {Access, AccessCreate, AccessAdmin, AccessPersistent},
|
||||
default_room_opts = DefRoomOpts,
|
||||
history_size = HistorySize}}.
|
||||
history_size = HistorySize,
|
||||
room_shaper = RoomShaper}}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
|
||||
@ -196,8 +205,10 @@ handle_info({route, From, To, Packet},
|
||||
server_host = ServerHost,
|
||||
access = Access,
|
||||
default_room_opts = DefRoomOpts,
|
||||
history_size = HistorySize} = State) ->
|
||||
case catch do_route(Host, ServerHost, Access, HistorySize, From, To, Packet, DefRoomOpts) of
|
||||
history_size = HistorySize,
|
||||
room_shaper = RoomShaper} = State) ->
|
||||
case catch do_route(Host, ServerHost, Access, HistorySize, RoomShaper,
|
||||
From, To, Packet, DefRoomOpts) of
|
||||
{'EXIT', Reason} ->
|
||||
?ERROR_MSG("~p", [Reason]);
|
||||
_ ->
|
||||
@ -255,11 +266,13 @@ stop_supervisor(Host) ->
|
||||
supervisor:terminate_child(ejabberd_sup, Proc),
|
||||
supervisor:delete_child(ejabberd_sup, Proc).
|
||||
|
||||
do_route(Host, ServerHost, Access, HistorySize, From, To, Packet, DefRoomOpts) ->
|
||||
do_route(Host, ServerHost, Access, HistorySize, RoomShaper,
|
||||
From, To, Packet, DefRoomOpts) ->
|
||||
{AccessRoute, _AccessCreate, _AccessAdmin, _AccessPersistent} = Access,
|
||||
case acl:match_rule(ServerHost, AccessRoute, From) of
|
||||
allow ->
|
||||
do_route1(Host, ServerHost, Access, HistorySize, From, To, Packet, DefRoomOpts);
|
||||
do_route1(Host, ServerHost, Access, HistorySize, RoomShaper,
|
||||
From, To, Packet, DefRoomOpts);
|
||||
_ ->
|
||||
{xmlelement, _Name, Attrs, _Els} = Packet,
|
||||
Lang = xml:get_attr_s("xml:lang", Attrs),
|
||||
@ -270,7 +283,8 @@ do_route(Host, ServerHost, Access, HistorySize, From, To, Packet, DefRoomOpts) -
|
||||
end.
|
||||
|
||||
|
||||
do_route1(Host, ServerHost, Access, HistorySize, From, To, Packet, DefRoomOpts) ->
|
||||
do_route1(Host, ServerHost, Access, HistorySize, RoomShaper,
|
||||
From, To, Packet, DefRoomOpts) ->
|
||||
{_AccessRoute, AccessCreate, AccessAdmin, _AccessPersistent} = Access,
|
||||
{Room, _, Nick} = jlib:jid_tolower(To),
|
||||
{xmlelement, Name, Attrs, _Els} = Packet,
|
||||
@ -395,7 +409,8 @@ do_route1(Host, ServerHost, Access, HistorySize, From, To, Packet, DefRoomOpts)
|
||||
?DEBUG("MUC: open new room '~s'~n", [Room]),
|
||||
{ok, Pid} = mod_muc_room:start(
|
||||
Host, ServerHost, Access,
|
||||
Room, HistorySize, From,
|
||||
Room, HistorySize,
|
||||
RoomShaper, From,
|
||||
Nick, DefRoomOpts),
|
||||
register_room(Host, Room, Pid),
|
||||
mod_muc_room:route(Pid, From, Nick, Packet),
|
||||
@ -425,7 +440,7 @@ do_route1(Host, ServerHost, Access, HistorySize, From, To, Packet, DefRoomOpts)
|
||||
|
||||
|
||||
|
||||
load_permanent_rooms(Host, ServerHost, Access, HistorySize) ->
|
||||
load_permanent_rooms(Host, ServerHost, Access, HistorySize, RoomShaper) ->
|
||||
case catch mnesia:dirty_select(
|
||||
muc_room, [{#muc_room{name_host = {'_', Host}, _ = '_'},
|
||||
[],
|
||||
@ -445,6 +460,7 @@ load_permanent_rooms(Host, ServerHost, Access, HistorySize) ->
|
||||
Access,
|
||||
Room,
|
||||
HistorySize,
|
||||
RoomShaper,
|
||||
R#muc_room.opts),
|
||||
register_room(Host, Room, Pid);
|
||||
_ ->
|
||||
|
@ -12,10 +12,10 @@
|
||||
|
||||
|
||||
%% External exports
|
||||
-export([start_link/8,
|
||||
start_link/6,
|
||||
start/8,
|
||||
start/6,
|
||||
-export([start_link/9,
|
||||
start_link/7,
|
||||
start/9,
|
||||
start/7,
|
||||
route/4]).
|
||||
|
||||
%% gen_fsm callbacks
|
||||
@ -64,6 +64,9 @@
|
||||
|
||||
-record(activity, {message_time = 0,
|
||||
presence_time = 0,
|
||||
message_shaper,
|
||||
presence_shaper,
|
||||
message,
|
||||
presence}).
|
||||
|
||||
-record(state, {room,
|
||||
@ -78,7 +81,9 @@
|
||||
subject = "",
|
||||
subject_author = "",
|
||||
just_created = false,
|
||||
activity = ?DICT:new()}).
|
||||
activity = ?DICT:new(),
|
||||
room_shaper,
|
||||
room_queue = queue:new()}).
|
||||
|
||||
|
||||
%-define(DBGFSM, true).
|
||||
@ -93,22 +98,28 @@
|
||||
%%%----------------------------------------------------------------------
|
||||
%%% API
|
||||
%%%----------------------------------------------------------------------
|
||||
start(Host, ServerHost, Access, Room, HistorySize, Creator, Nick, DefRoomOpts) ->
|
||||
start(Host, ServerHost, Access, Room, HistorySize, RoomShaper,
|
||||
Creator, Nick, DefRoomOpts) ->
|
||||
Supervisor = gen_mod:get_module_proc(ServerHost, ejabberd_mod_muc_sup),
|
||||
supervisor:start_child(
|
||||
Supervisor, [Host, ServerHost, Access, Room, HistorySize, Creator, Nick, DefRoomOpts]).
|
||||
Supervisor, [Host, ServerHost, Access, Room, HistorySize, RoomShaper,
|
||||
Creator, Nick, DefRoomOpts]).
|
||||
|
||||
start(Host, ServerHost, Access, Room, HistorySize, Opts) ->
|
||||
start(Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts) ->
|
||||
Supervisor = gen_mod:get_module_proc(ServerHost, ejabberd_mod_muc_sup),
|
||||
supervisor:start_child(
|
||||
Supervisor, [Host, ServerHost, Access, Room, HistorySize, Opts]).
|
||||
Supervisor, [Host, ServerHost, Access, Room, HistorySize, RoomShaper,
|
||||
Opts]).
|
||||
|
||||
start_link(Host, ServerHost, Access, Room, HistorySize, Creator, Nick, DefRoomOpts) ->
|
||||
gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, HistorySize, Creator, Nick, DefRoomOpts],
|
||||
start_link(Host, ServerHost, Access, Room, HistorySize, RoomShaper,
|
||||
Creator, Nick, DefRoomOpts) ->
|
||||
gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, HistorySize,
|
||||
RoomShaper, Creator, Nick, DefRoomOpts],
|
||||
?FSMOPTS).
|
||||
|
||||
start_link(Host, ServerHost, Access, Room, HistorySize, Opts) ->
|
||||
gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, HistorySize, Opts],
|
||||
start_link(Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts) ->
|
||||
gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, HistorySize,
|
||||
RoomShaper, Opts],
|
||||
?FSMOPTS).
|
||||
|
||||
%%%----------------------------------------------------------------------
|
||||
@ -122,7 +133,8 @@ start_link(Host, ServerHost, Access, Room, HistorySize, Opts) ->
|
||||
%% ignore |
|
||||
%% {stop, StopReason}
|
||||
%%----------------------------------------------------------------------
|
||||
init([Host, ServerHost, Access, Room, HistorySize, Creator, _Nick, DefRoomOpts]) ->
|
||||
init([Host, ServerHost, Access, Room, HistorySize, RoomShaper, Creator, _Nick, DefRoomOpts]) ->
|
||||
Shaper = shaper:new(RoomShaper),
|
||||
State = set_affiliation(Creator, owner,
|
||||
#state{host = Host,
|
||||
server_host = ServerHost,
|
||||
@ -130,16 +142,19 @@ init([Host, ServerHost, Access, Room, HistorySize, Creator, _Nick, DefRoomOpts])
|
||||
room = Room,
|
||||
history = lqueue_new(HistorySize),
|
||||
jid = jlib:make_jid(Room, Host, ""),
|
||||
just_created = true}),
|
||||
just_created = true,
|
||||
room_shaper = Shaper}),
|
||||
State1 = set_opts(DefRoomOpts, State),
|
||||
{ok, normal_state, State1};
|
||||
init([Host, ServerHost, Access, Room, HistorySize, Opts]) ->
|
||||
init([Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts]) ->
|
||||
Shaper = shaper:new(RoomShaper),
|
||||
State = set_opts(Opts, #state{host = Host,
|
||||
server_host = ServerHost,
|
||||
access = Access,
|
||||
room = Room,
|
||||
history = lqueue_new(HistorySize),
|
||||
jid = jlib:make_jid(Room, Host, "")}),
|
||||
jid = jlib:make_jid(Room, Host, ""),
|
||||
room_shaper = Shaper}),
|
||||
{ok, normal_state, State}.
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
@ -156,34 +171,90 @@ normal_state({route, From, "",
|
||||
true ->
|
||||
case xml:get_attr_s("type", Attrs) of
|
||||
"groupchat" ->
|
||||
Activity = case ?DICT:find(jlib:jid_tolower(From),
|
||||
StateData#state.activity) of
|
||||
{ok, A} -> A;
|
||||
error -> #activity{}
|
||||
end,
|
||||
Activity = get_user_activity(From, StateData),
|
||||
Now = now_to_usec(now()),
|
||||
MinMessageInterval =
|
||||
trunc(gen_mod:get_module_opt(
|
||||
StateData#state.server_host,
|
||||
mod_muc, min_message_interval, 0) * 1000000),
|
||||
Size = lists:flatlength(xml:element_to_string(Packet)),
|
||||
{MessageShaper, MessageShaperInterval} =
|
||||
shaper:update(Activity#activity.message_shaper, Size),
|
||||
if
|
||||
Now >= Activity#activity.message_time + MinMessageInterval ->
|
||||
NewActivity = Activity#activity{message_time = Now},
|
||||
Activity#activity.message /= undefined ->
|
||||
ErrText = "Traffic rate limit is exceeded",
|
||||
Err = jlib:make_error_reply(
|
||||
Packet, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)),
|
||||
ejabberd_router:route(
|
||||
StateData#state.jid,
|
||||
From, Err),
|
||||
{next_state, normal_state, StateData};
|
||||
Now >= Activity#activity.message_time + MinMessageInterval,
|
||||
MessageShaperInterval == 0 ->
|
||||
{RoomShaper, RoomShaperInterval} =
|
||||
shaper:update(StateData#state.room_shaper, Size),
|
||||
RoomQueueEmpty = queue:is_empty(
|
||||
StateData#state.room_queue),
|
||||
if
|
||||
RoomShaperInterval == 0,
|
||||
RoomQueueEmpty ->
|
||||
NewActivity = Activity#activity{
|
||||
message_time = Now,
|
||||
message_shaper = MessageShaper},
|
||||
StateData1 =
|
||||
StateData#state{
|
||||
activity = ?DICT:store(
|
||||
jlib:jid_tolower(From),
|
||||
NewActivity,
|
||||
StateData#state.activity),
|
||||
room_shaper = RoomShaper},
|
||||
process_groupchat_message(From, Packet, StateData1);
|
||||
true ->
|
||||
StateData1 =
|
||||
if
|
||||
RoomQueueEmpty ->
|
||||
erlang:send_after(
|
||||
RoomShaperInterval, self(),
|
||||
process_room_queue),
|
||||
StateData#state{
|
||||
room_shaper = RoomShaper};
|
||||
true ->
|
||||
StateData
|
||||
end,
|
||||
NewActivity = Activity#activity{
|
||||
message_time = Now,
|
||||
message_shaper = MessageShaper,
|
||||
message = Packet},
|
||||
RoomQueue = queue:in(
|
||||
{message, From},
|
||||
StateData#state.room_queue),
|
||||
StateData2 =
|
||||
StateData1#state{
|
||||
activity = ?DICT:store(
|
||||
jlib:jid_tolower(From),
|
||||
NewActivity,
|
||||
StateData#state.activity),
|
||||
room_queue = RoomQueue},
|
||||
{next_state, normal_state, StateData2}
|
||||
end;
|
||||
true ->
|
||||
MessageInterval =
|
||||
(Activity#activity.message_time +
|
||||
MinMessageInterval - Now) div 1000,
|
||||
Interval = lists:max([MessageInterval,
|
||||
MessageShaperInterval]),
|
||||
erlang:send_after(
|
||||
Interval, self(), {process_user_message, From}),
|
||||
NewActivity = Activity#activity{
|
||||
message = Packet,
|
||||
message_shaper = MessageShaper},
|
||||
StateData1 =
|
||||
StateData#state{
|
||||
activity = ?DICT:store(
|
||||
jlib:jid_tolower(From),
|
||||
NewActivity,
|
||||
StateData#state.activity)},
|
||||
process_groupchat_message(From, Packet, StateData1);
|
||||
true ->
|
||||
ErrText = "Message frequency is too high",
|
||||
Err = jlib:make_error_reply(
|
||||
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
||||
ejabberd_router:route(
|
||||
StateData#state.jid,
|
||||
From, Err),
|
||||
{next_state, normal_state, StateData}
|
||||
{next_state, normal_state, StateData1}
|
||||
end;
|
||||
"error" ->
|
||||
case is_user_online(From, StateData) of
|
||||
@ -321,11 +392,7 @@ normal_state({route, From, "",
|
||||
normal_state({route, From, Nick,
|
||||
{xmlelement, "presence", _Attrs, _Els} = Packet},
|
||||
StateData) ->
|
||||
Activity = case ?DICT:find(jlib:jid_tolower(From),
|
||||
StateData#state.activity) of
|
||||
{ok, A} -> A;
|
||||
error -> #activity{}
|
||||
end,
|
||||
Activity = get_user_activity(From, StateData),
|
||||
Now = now_to_usec(now()),
|
||||
MinPresenceInterval =
|
||||
trunc(gen_mod:get_module_opt(
|
||||
@ -348,7 +415,7 @@ normal_state({route, From, Nick,
|
||||
Interval = (Activity#activity.presence_time +
|
||||
MinPresenceInterval - Now) div 1000,
|
||||
erlang:send_after(
|
||||
Interval, self(), {process_presence, From});
|
||||
Interval, self(), {process_user_presence, From});
|
||||
true ->
|
||||
ok
|
||||
end,
|
||||
@ -562,7 +629,8 @@ handle_sync_event({get_disco_item, JID, Lang}, _From, StateName, StateData) ->
|
||||
_ ->
|
||||
translate:translate(Lang, "private, ")
|
||||
end,
|
||||
Len = length(?DICT:to_list(StateData#state.users)),
|
||||
Len = ?DICT:fold(fun(_, _, Acc) -> Acc + 1 end, 0,
|
||||
StateData#state.users),
|
||||
" (" ++ Desc ++ integer_to_list(Len) ++ ")";
|
||||
_ ->
|
||||
""
|
||||
@ -597,12 +665,8 @@ code_change(_OldVsn, StateName, StateData, _Extra) ->
|
||||
%% {next_state, NextStateName, NextStateData, Timeout} |
|
||||
%% {stop, Reason, NewStateData}
|
||||
%%----------------------------------------------------------------------
|
||||
handle_info({process_presence, From}, normal_state = _StateName, StateData) ->
|
||||
Activity = case ?DICT:find(jlib:jid_tolower(From),
|
||||
StateData#state.activity) of
|
||||
{ok, A} -> A;
|
||||
error -> #activity{}
|
||||
end,
|
||||
handle_info({process_user_presence, From}, normal_state = _StateName, StateData) ->
|
||||
Activity = get_user_activity(From, StateData),
|
||||
Now = now_to_usec(now()),
|
||||
{Nick, Packet} = Activity#activity.presence,
|
||||
NewActivity = Activity#activity{presence_time = Now,
|
||||
@ -614,6 +678,50 @@ handle_info({process_presence, From}, normal_state = _StateName, StateData) ->
|
||||
NewActivity,
|
||||
StateData#state.activity)},
|
||||
process_presence(From, Nick, Packet, StateData1);
|
||||
handle_info({process_user_message, From}, normal_state = _StateName, StateData) ->
|
||||
Activity = get_user_activity(From, StateData),
|
||||
Now = now_to_usec(now()),
|
||||
Packet = Activity#activity.message,
|
||||
NewActivity = Activity#activity{message_time = Now,
|
||||
message = undefined},
|
||||
StateData1 =
|
||||
StateData#state{
|
||||
activity = ?DICT:store(
|
||||
jlib:jid_tolower(From),
|
||||
NewActivity,
|
||||
StateData#state.activity)},
|
||||
process_groupchat_message(From, Packet, StateData1);
|
||||
handle_info(process_room_queue, normal_state = StateName, StateData) ->
|
||||
case queue:out(StateData#state.room_queue) of
|
||||
{{value, {message, From}}, RoomQueue} ->
|
||||
Activity = get_user_activity(From, StateData),
|
||||
Packet = Activity#activity.message,
|
||||
NewActivity = Activity#activity{message = undefined},
|
||||
StateData1 =
|
||||
StateData#state{
|
||||
activity = ?DICT:store(
|
||||
jlib:jid_tolower(From),
|
||||
NewActivity,
|
||||
StateData#state.activity),
|
||||
room_queue = RoomQueue},
|
||||
StateData2 = prepare_room_queue(StateData1),
|
||||
process_groupchat_message(From, Packet, StateData2);
|
||||
{{value, {presence, From}}, RoomQueue} ->
|
||||
Activity = get_user_activity(From, StateData),
|
||||
{Nick, Packet} = Activity#activity.presence,
|
||||
NewActivity = Activity#activity{presence = undefined},
|
||||
StateData1 =
|
||||
StateData#state{
|
||||
activity = ?DICT:store(
|
||||
jlib:jid_tolower(From),
|
||||
NewActivity,
|
||||
StateData#state.activity),
|
||||
room_queue = RoomQueue},
|
||||
StateData2 = prepare_room_queue(StateData1),
|
||||
process_presence(From, Nick, Packet, StateData2);
|
||||
{empty, _} ->
|
||||
{next_state, StateName, StateData}
|
||||
end;
|
||||
handle_info(_Info, StateName, StateData) ->
|
||||
{next_state, StateName, StateData}.
|
||||
|
||||
@ -637,82 +745,91 @@ route(Pid, From, ToNick, Packet) ->
|
||||
process_groupchat_message(From, {xmlelement, "message", Attrs, _Els} = Packet,
|
||||
StateData) ->
|
||||
Lang = xml:get_attr_s("xml:lang", Attrs),
|
||||
{ok, #user{nick = FromNick, role = Role}} =
|
||||
?DICT:find(jlib:jid_tolower(From),
|
||||
StateData#state.users),
|
||||
if
|
||||
(Role == moderator) or (Role == participant) ->
|
||||
{NewStateData1, IsAllowed} =
|
||||
case check_subject(Packet) of
|
||||
false ->
|
||||
{StateData, true};
|
||||
Subject ->
|
||||
case can_change_subject(Role,
|
||||
StateData) of
|
||||
true ->
|
||||
NSD =
|
||||
StateData#state{
|
||||
subject = Subject,
|
||||
subject_author =
|
||||
FromNick},
|
||||
case (NSD#state.config)#config.persistent of
|
||||
case is_user_online(From, StateData) of
|
||||
true ->
|
||||
{ok, #user{nick = FromNick, role = Role}} =
|
||||
?DICT:find(jlib:jid_tolower(From),
|
||||
StateData#state.users),
|
||||
if
|
||||
(Role == moderator) or (Role == participant) ->
|
||||
{NewStateData1, IsAllowed} =
|
||||
case check_subject(Packet) of
|
||||
false ->
|
||||
{StateData, true};
|
||||
Subject ->
|
||||
case can_change_subject(Role,
|
||||
StateData) of
|
||||
true ->
|
||||
mod_muc:store_room(
|
||||
NSD#state.host,
|
||||
NSD#state.room,
|
||||
make_opts(NSD));
|
||||
NSD =
|
||||
StateData#state{
|
||||
subject = Subject,
|
||||
subject_author =
|
||||
FromNick},
|
||||
case (NSD#state.config)#config.persistent of
|
||||
true ->
|
||||
mod_muc:store_room(
|
||||
NSD#state.host,
|
||||
NSD#state.room,
|
||||
make_opts(NSD));
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
{NSD, true};
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
{NSD, true};
|
||||
_ ->
|
||||
{StateData, false}
|
||||
end
|
||||
end,
|
||||
case IsAllowed of
|
||||
true ->
|
||||
lists:foreach(
|
||||
fun({_LJID, Info}) ->
|
||||
ejabberd_router:route(
|
||||
jlib:jid_replace_resource(
|
||||
StateData#state.jid,
|
||||
FromNick),
|
||||
Info#user.jid,
|
||||
Packet)
|
||||
end,
|
||||
?DICT:to_list(StateData#state.users)),
|
||||
NewStateData2 =
|
||||
add_message_to_history(FromNick,
|
||||
Packet,
|
||||
NewStateData1),
|
||||
{next_state, normal_state, NewStateData2};
|
||||
_ ->
|
||||
Err =
|
||||
case (StateData#state.config)#config.allow_change_subj of
|
||||
true ->
|
||||
?ERRT_FORBIDDEN(
|
||||
Lang,
|
||||
"Only moderators and participants "
|
||||
"are allowed to change subject in this room");
|
||||
_ ->
|
||||
?ERRT_FORBIDDEN(
|
||||
Lang,
|
||||
"Only moderators "
|
||||
"are allowed to change subject in this room")
|
||||
{StateData, false}
|
||||
end
|
||||
end,
|
||||
case IsAllowed of
|
||||
true ->
|
||||
lists:foreach(
|
||||
fun({_LJID, Info}) ->
|
||||
ejabberd_router:route(
|
||||
jlib:jid_replace_resource(
|
||||
StateData#state.jid,
|
||||
FromNick),
|
||||
Info#user.jid,
|
||||
Packet)
|
||||
end,
|
||||
?DICT:to_list(StateData#state.users)),
|
||||
NewStateData2 =
|
||||
add_message_to_history(FromNick,
|
||||
Packet,
|
||||
NewStateData1),
|
||||
{next_state, normal_state, NewStateData2};
|
||||
_ ->
|
||||
Err =
|
||||
case (StateData#state.config)#config.allow_change_subj of
|
||||
true ->
|
||||
?ERRT_FORBIDDEN(
|
||||
Lang,
|
||||
"Only moderators and participants "
|
||||
"are allowed to change subject in this room");
|
||||
_ ->
|
||||
?ERRT_FORBIDDEN(
|
||||
Lang,
|
||||
"Only moderators "
|
||||
"are allowed to change subject in this room")
|
||||
end,
|
||||
ejabberd_router:route(
|
||||
StateData#state.jid,
|
||||
From,
|
||||
jlib:make_error_reply(Packet, Err)),
|
||||
{next_state, normal_state, StateData}
|
||||
end;
|
||||
true ->
|
||||
ErrText = "Visitors are not allowed to send messages to all occupants",
|
||||
Err = jlib:make_error_reply(
|
||||
Packet, ?ERRT_FORBIDDEN(Lang, ErrText)),
|
||||
ejabberd_router:route(
|
||||
StateData#state.jid,
|
||||
From,
|
||||
jlib:make_error_reply(Packet, Err)),
|
||||
From, Err),
|
||||
{next_state, normal_state, StateData}
|
||||
end;
|
||||
true ->
|
||||
ErrText = "Visitors are not allowed to send messages to all occupants",
|
||||
false ->
|
||||
ErrText = "Only occupants are allowed to send messages to the conference",
|
||||
Err = jlib:make_error_reply(
|
||||
Packet, ?ERRT_FORBIDDEN(Lang, ErrText)),
|
||||
ejabberd_router:route(
|
||||
StateData#state.jid,
|
||||
From, Err),
|
||||
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
||||
ejabberd_router:route(StateData#state.jid, From, Err),
|
||||
{next_state, normal_state, StateData}
|
||||
end.
|
||||
|
||||
@ -1003,6 +1120,51 @@ get_max_users_admin_threshold(StateData) ->
|
||||
gen_mod:get_module_opt(StateData#state.server_host,
|
||||
mod_muc, max_users_admin_threshold, 5).
|
||||
|
||||
get_user_activity(JID, StateData) ->
|
||||
case ?DICT:find(jlib:jid_tolower(JID),
|
||||
StateData#state.activity) of
|
||||
{ok, A} -> A;
|
||||
error ->
|
||||
MessageShaper =
|
||||
shaper:new(gen_mod:get_module_opt(
|
||||
StateData#state.server_host,
|
||||
mod_muc, user_message_shaper, none)),
|
||||
PresenceShaper =
|
||||
shaper:new(gen_mod:get_module_opt(
|
||||
StateData#state.server_host,
|
||||
mod_muc, user_presence_shaper, none)),
|
||||
#activity{message_shaper = MessageShaper,
|
||||
presence_shaper = PresenceShaper}
|
||||
end.
|
||||
|
||||
prepare_room_queue(StateData) ->
|
||||
case queue:out(StateData#state.room_queue) of
|
||||
{{value, {message, From}}, _RoomQueue} ->
|
||||
Activity = get_user_activity(From, StateData),
|
||||
Packet = Activity#activity.message,
|
||||
Size = lists:flatlength(xml:element_to_string(Packet)),
|
||||
{RoomShaper, RoomShaperInterval} =
|
||||
shaper:update(StateData#state.room_shaper, Size),
|
||||
erlang:send_after(
|
||||
RoomShaperInterval, self(),
|
||||
process_room_queue),
|
||||
StateData#state{
|
||||
room_shaper = RoomShaper};
|
||||
{{value, {presence, From}}, _RoomQueue} ->
|
||||
Activity = get_user_activity(From, StateData),
|
||||
{_Nick, Packet} = Activity#activity.presence,
|
||||
Size = lists:flatlength(xml:element_to_string(Packet)),
|
||||
{RoomShaper, RoomShaperInterval} =
|
||||
shaper:update(StateData#state.room_shaper, Size),
|
||||
erlang:send_after(
|
||||
RoomShaperInterval, self(),
|
||||
process_room_queue),
|
||||
StateData#state{
|
||||
room_shaper = RoomShaper};
|
||||
{empty, _} ->
|
||||
StateData
|
||||
end.
|
||||
|
||||
|
||||
add_online_user(JID, Nick, Role, StateData) ->
|
||||
LJID = jlib:jid_tolower(JID),
|
||||
|
Loading…
Reference in New Issue
Block a user