25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-24 16:23:40 +01:00

Don't expose internal FSM API of mod_muc_room

This commit is contained in:
Evgeny Khramtsov 2019-07-09 00:47:54 +03:00
parent cbe84eb50c
commit 9cbc0685db
4 changed files with 159 additions and 50 deletions

View File

@ -164,7 +164,7 @@ reload(ServerHost, NewOpts, OldOpts) ->
fun(Host) ->
lists:foreach(
fun({_, _, Pid}) when node(Pid) == node() ->
Pid ! config_reloaded;
mod_muc_room:config_reloaded(Pid);
(_) ->
ok
end, get_online_rooms(ServerHost, Host))
@ -271,7 +271,7 @@ shutdown_rooms(ServerHost, Hosts, RMod) ->
|| Host <- Hosts],
lists:flatmap(
fun({_, _, Pid}) when node(Pid) == node() ->
Pid ! shutdown,
mod_muc_room:shutdown(Pid),
[Pid];
(_) ->
[]
@ -840,13 +840,13 @@ iq_disco_items(ServerHost, Host, From, Lang, MaxRoomsDiscoItems, Node, RSM)
when Node == <<"">>; Node == <<"nonemptyrooms">>; Node == <<"emptyrooms">> ->
Count = count_online_rooms(ServerHost, Host),
Query = if Node == <<"">>, RSM == undefined, Count > MaxRoomsDiscoItems ->
{get_disco_item, only_non_empty, From, Lang};
{only_non_empty, From, Lang};
Node == <<"nonemptyrooms">> ->
{get_disco_item, only_non_empty, From, Lang};
{only_non_empty, From, Lang};
Node == <<"emptyrooms">> ->
{get_disco_item, 0, From, Lang};
{0, From, Lang};
true ->
{get_disco_item, all, From, Lang}
{all, From, Lang}
end,
MaxItems = case RSM of
undefined ->
@ -884,23 +884,16 @@ iq_disco_items(_ServerHost, _Host, _From, Lang, _MaxRoomsDiscoItems, _Node, _RSM
{error, xmpp:err_item_not_found(?T("Node not found"), Lang)}.
-spec get_room_disco_item({binary(), binary(), pid()},
term()) -> {ok, disco_item()} |
{error, timeout | notfound}.
get_room_disco_item({Name, Host, Pid},
{get_disco_item, Filter, JID, Lang}) ->
RoomJID = jid:make(Name, Host),
Timeout = 100,
Time = erlang:system_time(millisecond),
Query1 = {get_disco_item, Filter, JID, Lang, Time+Timeout},
try p1_fsm:sync_send_all_state_event(Pid, Query1, Timeout) of
{item, Desc} ->
{mod_muc_room:disco_item_filter(),
jid(), binary()}) -> {ok, disco_item()} |
{error, timeout | notfound}.
get_room_disco_item({Name, Host, Pid}, {Filter, JID, Lang}) ->
case mod_muc_room:get_disco_item(Pid, Filter, JID, Lang) of
{ok, Desc} ->
RoomJID = jid:make(Name, Host),
{ok, #disco_item{jid = RoomJID, name = Desc}};
false ->
{error, notfound}
catch _:{timeout, {p1_fsm, _, _}} ->
{error, timeout};
_:{_, {p1_fsm, _, _}} ->
{error, notfound}
{error, _} = Err ->
Err
end.
-spec get_subscribed_rooms(binary(), jid()) -> {ok, [{jid(), [binary()]}]} | {error, any()}.
@ -931,8 +924,7 @@ get_subscribed_rooms(ServerHost, Host, From) ->
[]
end;
({Name, _, Pid}) ->
case p1_fsm:sync_send_all_state_event(
Pid, {is_subscribed, BareFrom}) of
case mod_muc_room:is_subscribed(Pid, BareFrom) of
{true, Nodes} ->
[{jid:make(Name, Host), Nodes}];
false -> []
@ -1017,8 +1009,7 @@ process_iq_register_set(ServerHost, Host, From,
broadcast_service_message(ServerHost, Host, Msg) ->
lists:foreach(
fun({_, _, Pid}) ->
p1_fsm:send_all_state_event(
Pid, {service_message, Msg})
mod_muc_room:service_message(Pid, Msg)
end, get_online_rooms(ServerHost, Host)).
-spec get_online_rooms(binary(), binary()) -> [{binary(), binary(), pid()}].

View File

@ -673,8 +673,7 @@ muc_create_room(ServerHost, {Name, Host, _}, DefRoomOpts) ->
destroy_room(Name, Service) ->
case mod_muc:find_online_room(Name, Service) of
{ok, Pid} ->
p1_fsm:send_all_state_event(Pid, destroy),
ok;
mod_muc_room:destroy(Pid);
error ->
error
end.
@ -793,11 +792,11 @@ get_rooms(ServerHost) ->
end, Hosts).
get_room_config(Room_pid) ->
{ok, R} = p1_fsm:sync_send_all_state_event(Room_pid, get_config),
{ok, R} = mod_muc_room:get_config(Room_pid),
R.
get_room_state(Room_pid) ->
{ok, R} = p1_fsm:sync_send_all_state_event(Room_pid, get_state),
{ok, R} = mod_muc_room:get_state(Room_pid),
R.
%%---------------
@ -882,8 +881,7 @@ find_serverhost(Host, ServerHosts) ->
act_on_room(Method, destroy, {N, H, Pid}, SH) ->
Message = iolist_to_binary(io_lib:format(
<<"Room destroyed by rooms_~s_destroy.">>, [Method])),
p1_fsm:send_all_state_event(
Pid, {destroy, Message}),
mod_muc_room:destroy(Pid, Message),
mod_muc:room_destroyed(H, N, Pid, SH),
mod_muc:forget_room(SH, H, N);
@ -991,7 +989,7 @@ change_room_option(Name, Service, OptionString, ValueString) ->
{Option, Value} = format_room_option(OptionString, ValueString),
Config = get_room_config(Pid),
Config2 = change_option(Option, Value, Config),
{ok, _} = p1_fsm:sync_send_all_state_event(Pid, {change_config, Config2}),
{ok, _} = mod_muc_room:set_config(Pid, Config2),
ok
end.
@ -1093,7 +1091,7 @@ get_room_affiliations(Name, Service) ->
case mod_muc:find_online_room(Name, Service) of
{ok, Pid} ->
%% Get the PID of the online room, then request its state
{ok, StateData} = p1_fsm:sync_send_all_state_event(Pid, get_state),
{ok, StateData} = mod_muc_room:get_state(Pid),
Affiliations = maps:to_list(StateData#state.affiliations),
lists:map(
fun({{Uname, Domain, _Res}, {Aff, Reason}}) when is_atom(Aff)->
@ -1117,7 +1115,7 @@ get_room_affiliation(Name, Service, JID) ->
case mod_muc:find_online_room(Name, Service) of
{ok, Pid} ->
%% Get the PID of the online room, then request its state
{ok, StateData} = p1_fsm:sync_send_all_state_event(Pid, get_state),
{ok, StateData} = mod_muc_room:get_state(Pid),
UserJID = jid:decode(JID),
mod_muc_room:get_affiliation(UserJID, StateData);
error ->
@ -1141,7 +1139,7 @@ set_room_affiliation(Name, Service, JID, AffiliationString) ->
case mod_muc:find_online_room(Name, Service) of
{ok, Pid} ->
%% Get the PID for the online room so we can get the state of the room
{ok, StateData} = p1_fsm:sync_send_all_state_event(Pid, {process_item_change, {jid:decode(JID), affiliation, Affiliation, <<"">>}, undefined}),
{ok, StateData} = mod_muc_room:change_item(Pid, jid:decode(JID), affiliation, Affiliation, <<"">>),
mod_muc:store_room(StateData#state.server_host, StateData#state.host, StateData#state.room, make_opts(StateData)),
ok;
error ->
@ -1163,9 +1161,8 @@ subscribe_room(User, Nick, Room, Nodes) ->
UserJID = jid:replace_resource(UserJID1, <<"modmucadmin">>),
case get_room_pid(Name, Host) of
Pid when is_pid(Pid) ->
case p1_fsm:sync_send_all_state_event(
Pid,
{muc_subscribe, UserJID, Nick, NodeList}) of
case mod_muc_room:subscribe(
Pid, UserJID, Nick, NodeList) of
{ok, SubscribedNodes} ->
SubscribedNodes;
{error, Reason} ->
@ -1190,9 +1187,7 @@ unsubscribe_room(User, Room) ->
UserJID ->
case get_room_pid(Name, Host) of
Pid when is_pid(Pid) ->
case p1_fsm:sync_send_all_state_event(
Pid,
{muc_unsubscribe, UserJID}) of
case mod_muc_room:unsubscribe(Pid, UserJID) of
ok ->
ok;
{error, Reason} ->
@ -1213,7 +1208,7 @@ unsubscribe_room(User, Room) ->
get_subscribers(Name, Host) ->
case get_room_pid(Name, Host) of
Pid when is_pid(Pid) ->
{ok, JIDList} = p1_fsm:sync_send_all_state_event(Pid, get_subscribers),
{ok, JIDList} = mod_muc_room:get_subscribers(Pid),
[jid:encode(jid:remove_resource(J)) || J <- JIDList];
_ ->
throw({error, "The room does not exist"})

View File

@ -896,8 +896,9 @@ get_room_state(RoomName, MucService) ->
-spec get_room_state(pid()) -> {ok, mod_muc_room:state()} | error.
get_room_state(RoomPid) ->
try p1_fsm:sync_send_all_state_event(RoomPid, get_state)
catch _:_ -> error
case mod_muc_room:get_state(RoomPid) of
{ok, State} -> {ok, State};
{error, _} -> error
end.
get_proc_name(Host) ->

View File

@ -39,7 +39,21 @@
is_occupant_or_admin/2,
route/2,
expand_opts/1,
config_fields/0]).
config_fields/0,
destroy/1,
destroy/2,
shutdown/1,
get_config/1,
set_config/2,
get_state/1,
change_item/5,
config_reloaded/1,
subscribe/4,
unsubscribe/2,
is_subscribed/2,
get_subscribers/1,
service_message/2,
get_disco_item/4]).
%% gen_fsm callbacks
-export([init/1,
@ -77,8 +91,8 @@
-type fsm_stop() :: {stop, normal, state()}.
-type fsm_next() :: {next_state, normal_state, state()}.
-type fsm_transition() :: fsm_stop() | fsm_next().
-export_type([state/0]).
-type disco_item_filter() :: only_non_empty | all | non_neg_integer().
-export_type([state/0, disco_item_filter/0]).
-callback set_affiliation(binary(), binary(), binary(), jid(), affiliation(),
binary()) -> ok | {error, any()}.
@ -127,6 +141,114 @@ start_link(Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts, QueueT
RoomShaper, Opts, QueueType],
?FSMOPTS).
-spec destroy(pid()) -> ok.
destroy(Pid) ->
p1_fsm:send_all_state_event(Pid, destroy).
-spec destroy(pid(), binary()) -> ok.
destroy(Pid, Reason) ->
p1_fsm:send_all_state_event(Pid, {destroy, Reason}).
-spec shutdown(pid()) -> boolean().
shutdown(Pid) ->
ejabberd_cluster:send(Pid, shutdown).
-spec config_reloaded(pid()) -> boolean().
config_reloaded(Pid) ->
ejabberd_cluster:send(Pid, config_reloaded).
-spec get_config(pid()) -> {ok, config()} | {error, notfound | timeout}.
get_config(Pid) ->
try p1_fsm:sync_send_all_state_event(Pid, get_config)
catch _:{timeout, {p1_fsm, _, _}} ->
{error, timeout};
_:{_, {p1_fsm, _, _}} ->
{error, notfound}
end.
-spec set_config(pid(), config()) -> {ok, config()} | {error, notfound | timeout}.
set_config(Pid, Config) ->
try p1_fsm:sync_send_all_state_event(Pid, {change_config, Config})
catch _:{timeout, {p1_fsm, _, _}} ->
{error, timeout};
_:{_, {p1_fsm, _, _}} ->
{error, notfound}
end.
-spec change_item(pid(), jid(), affiliation | role, affiliation() | role(), binary()) ->
{ok, state()} | {error, notfound | timeout}.
change_item(Pid, JID, Type, AffiliationOrRole, Reason) ->
try p1_fsm:sync_send_all_state_event(
Pid, {process_item_change, {JID, Type, AffiliationOrRole, Reason}, undefined})
catch _:{timeout, {p1_fsm, _, _}} ->
{error, timeout};
_:{_, {p1_fsm, _, _}} ->
{error, notfound}
end.
-spec get_state(pid()) -> {ok, state()} | {error, notfound | timeout}.
get_state(Pid) ->
try p1_fsm:sync_send_all_state_event(Pid, get_state)
catch _:{timeout, {p1_fsm, _, _}} ->
{error, timeout};
_:{_, {p1_fsm, _, _}} ->
{error, notfound}
end.
-spec subscribe(pid(), jid(), binary(), [binary()]) -> {ok, [binary()]} | {error, binary()}.
subscribe(Pid, JID, Nick, Nodes) ->
try p1_fsm:sync_send_all_state_event(Pid, {muc_subscribe, JID, Nick, Nodes})
catch _:{timeout, {p1_fsm, _, _}} ->
{error, ?T("Request has timed out")};
_:{_, {p1_fsm, _, _}} ->
{error, ?T("Conference room does not exist")}
end.
-spec unsubscribe(pid(), jid()) -> ok | {error, binary()}.
unsubscribe(Pid, JID) ->
try p1_fsm:sync_send_all_state_event(Pid, {muc_unsubscribe, JID})
catch _:{timeout, {p1_fsm, _, _}} ->
{error, ?T("Request has timed out")};
_:{_, {p1_fsm, _, _}} ->
{error, ?T("Conference room does not exist")}
end.
-spec is_subscribed(pid(), jid()) -> {true, [binary()]} | false.
is_subscribed(Pid, JID) ->
try p1_fsm:sync_send_all_state_event(Pid, {is_subscribed, JID})
catch _:{_, {p1_fsm, _, _}} -> false
end.
-spec get_subscribers(pid()) -> {ok, [jid()]} | {error, notfound | timeout}.
get_subscribers(Pid) ->
try p1_fsm:sync_send_all_state_event(Pid, get_subscribers)
catch _:{timeout, {p1_fsm, _, _}} ->
{error, timeout};
_:{_, {p1_fsm, _, _}} ->
{error, notfound}
end.
-spec service_message(pid(), binary()) -> ok.
service_message(Pid, Text) ->
p1_fsm:send_all_state_event(Pid, {service_message, Text}).
-spec get_disco_item(pid(), disco_item_filter(), jid(), binary()) ->
{ok, binary()} | {error, notfound | timeout}.
get_disco_item(Pid, Filter, JID, Lang) ->
Timeout = 100,
Time = erlang:system_time(millisecond),
Query = {get_disco_item, Filter, JID, Lang, Time+Timeout},
try p1_fsm:sync_send_all_state_event(Pid, Query, Timeout) of
{item, Desc} ->
{ok, Desc};
false ->
{error, notfound}
catch _:{timeout, {p1_fsm, _, _}} ->
{error, timeout};
_:{_, {p1_fsm, _, _}} ->
{error, notfound}
end.
%%%----------------------------------------------------------------------
%%% Callback functions from gen_fsm
%%%----------------------------------------------------------------------
@ -593,7 +715,7 @@ handle_sync_event({muc_subscribe, From, Nick, Nodes}, _From,
NewConfig = (NewState#state.config)#config{
captcha_protected = CaptchaRequired,
password_protected = PasswordProtected},
{reply, {error, <<"Request is ignored">>},
{reply, {error, ?T("Request is ignored")},
NewState#state{config = NewConfig}};
{error, Err} ->
{reply, {error, get_error_text(Err)}, StateName, StateData}
@ -605,7 +727,7 @@ handle_sync_event({muc_unsubscribe, From}, _From, StateName, StateData) ->
{result, _, NewState} ->
{reply, ok, StateName, NewState};
{ignore, NewState} ->
{reply, {error, <<"Request is ignored">>}, NewState};
{reply, {error, ?T("Request is ignored")}, NewState};
{error, Err} ->
{reply, {error, get_error_text(Err)}, StateName, StateData}
end;