Skip to content

Commit

Permalink
Merge pull request #3152 from esl/cleaning-up-subdomains-management
Browse files Browse the repository at this point in the history
Cleaning up subdomains management
  • Loading branch information
chrzaszcz authored Jun 10, 2021
2 parents f8bb90b + f00e0dc commit b094384
Show file tree
Hide file tree
Showing 17 changed files with 110 additions and 154 deletions.
2 changes: 1 addition & 1 deletion big_tests/tests/mam_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,7 @@ rdbms_simple_opts() ->

init_modules_for_muc_light(BackendType, Config) ->
dynamic_modules:restart(host_type(), mod_muc_light, [{host, subhost_pattern(muc_light_helper:muc_host_pattern())}]),
Config1 = init_modules(BackendType, muc_all, [{muc_domain, muc_helper:muc_host_pattern()} | Config]),
Config1 = init_modules(BackendType, muc_all, [{muc_domain, muc_light_helper:muc_host_pattern()} | Config]),
init_modules(BackendType, pm, [{archive_groupchats, false} | Config1]).

end_modules(C, muc_light, Config) ->
Expand Down
2 changes: 1 addition & 1 deletion big_tests/tests/mam_send_message_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ end_per_group(_Groupname, Config) ->
ok.

group_to_modules(send_message) ->
MH = subhost_pattern(muc_light_helper:muc_host()),
MH = subhost_pattern(muc_light_helper:muc_host_pattern()),
[{mod_mam_meta, [{backend, rdbms}, {pm, []}, {muc, [{host, MH}]},
{send_message, mam_send_message_example}]},
{mod_muc_light, []},
Expand Down
3 changes: 1 addition & 2 deletions big_tests/tests/muc_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
[muc_host/0,
load_muc/0,
unload_muc/0,
muc_host/0,
start_room/5,
generate_rpc_jid/1,
destroy_room/1,
Expand Down Expand Up @@ -383,7 +382,7 @@ init_per_group(hibernation, Config) ->
dynamic_modules:restart(host_type(), mod_mam_muc_rdbms_arch, [muc]),
dynamic_modules:restart(host_type(), mod_mam_rdbms_prefs, [muc]),
dynamic_modules:restart(host_type(), mod_mam_rdbms_user, [pm, muc]),
HostPattern = subhost_pattern("muc.@HOST@"),
HostPattern = subhost_pattern(muc_helper:muc_host_pattern()),
dynamic_modules:restart(host_type(), mod_mam_muc, [{host, HostPattern}]);
_ ->
ok
Expand Down
12 changes: 1 addition & 11 deletions src/domain/mongoose_domain_api.erl
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,7 @@ get_domain_host_type(Domain) ->
-spec get_subdomain_host_type(domain()) ->
{ok, host_type()} | {error, not_found}.
get_subdomain_host_type(Subdomain) ->
case mongoose_subdomain_core:get_host_type(Subdomain) of
{error, not_found} ->
case mongoose_subhosts:get_host(Subdomain) of
{ok, Domain} ->
get_domain_host_type(Domain);
undefined ->
{error, not_found}
end;
{ok, HostType} ->
{ok, HostType}
end.
mongoose_subdomain_core:get_host_type(Subdomain).

%% Subdomain should be nameprepped using `jid:nameprep'
-spec get_subdomain_info(domain()) ->
Expand Down
2 changes: 0 additions & 2 deletions src/ejabberd_app.erl
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ start(normal, _Args) ->
ejabberd_ctl:init(),
ejabberd_commands:init(),
mongoose_commands:init(),
mongoose_subhosts:init(),
mongoose_service:start(),
gen_mod:start(),
ejabberd_config:start(),
Expand Down Expand Up @@ -88,7 +87,6 @@ prep_stop(State) ->
ejabberd_listener:stop_listeners(),
stop_modules(),
stop_services(),
mongoose_subhosts:stop(),
broadcast_c2s_shutdown(),
lists:foreach(fun mongoose_users:stop/1, ?ALL_HOST_TYPES),
mongoose_wpool:stop(),
Expand Down
19 changes: 14 additions & 5 deletions src/ejabberd_router.erl
Original file line number Diff line number Diff line change
Expand Up @@ -238,12 +238,21 @@ do_register_component({LDomain, _}, Handler, Node, IsHidden) ->
%% @doc Check if the component/route is already registered somewhere; ok means it is not, so we are
%% ok to proceed, anything else means the domain/node pair is already serviced.
%% true and false are there because that's how orelse works.
-spec check_component(binary(), Node :: node()) -> ok | true | false.
-spec check_component(binary(), Node :: node()) -> ok | error.
check_component(LDomain, Node) ->
check_component_route(LDomain)
case check_dynamic_domains(LDomain)
orelse check_component_route(LDomain)
orelse check_component_local(LDomain, Node)
orelse check_component_global(LDomain, Node).
orelse check_component_global(LDomain, Node) of
true -> error;
false -> ok
end.

check_dynamic_domains(LDomain)->
case mongoose_domain_api:get_host_type(LDomain) of
{error, not_found} -> false;
{ok, _} -> true
end.

check_component_route(LDomain) ->
%% check that route for this domain is not already registered
Expand All @@ -268,9 +277,9 @@ check_component_global(LDomain, Node) ->
%% check that there is no component registered globally for this node
case get_global_component(LDomain, Node) of
undefined ->
ok;
false;
_ ->
false
true
end.

get_global_component([], _) ->
Expand Down
41 changes: 26 additions & 15 deletions src/http_upload/mod_http_upload.erl
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,11 @@
start(Host, Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue),
SubHost = subhost(Host),
mongoose_subhosts:register(Host, SubHost),
ejabberd_router:register_route(SubHost, mongoose_packet_handler:new(ejabberd_local)),
%% TODO: Conversion of this module is not done, it doesn't support dynamic
%% domains yet. Only subdomain registration is done properly.
SubdomainPattern = subdomain_pattern(Host),
PacketHandler = mongoose_packet_handler:new(ejabberd_local),
mongoose_domain_api:register_subdomain(Host, SubdomainPattern, PacketHandler),
ejabberd_hooks:add(disco_local_items, Host, ?MODULE, disco_local_items, 90),
gen_iq_handler:add_iq_handler(ejabberd_local, SubHost, ?NS_HTTP_UPLOAD_030,
?MODULE, process_iq, IQDisc),
Expand All @@ -69,8 +72,8 @@ stop(Host) ->
ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, disco_local_items, 90),
gen_iq_handler:remove_iq_handler(ejabberd_local, SubHost, ?NS_HTTP_UPLOAD_030),
gen_iq_handler:remove_iq_handler(ejabberd_local, SubHost, ?NS_DISCO_INFO),
ejabberd_router:unregister_route(SubHost),
mongoose_subhosts:unregister(SubHost).
SubdomainPattern = subdomain_pattern(Host),
mongoose_domain_api:unregister_subdomain(Host, SubdomainPattern).


-spec process_iq(From :: jid:jid(), To :: jid:jid(), Acc :: mongoose_acc:t(),
Expand All @@ -80,15 +83,15 @@ process_iq(_From, _To, Acc, IQ = #iq{type = set, lang = Lang, sub_el = SubEl}) -
Error = mongoose_xmpp_errors:not_allowed(Lang, <<"IQ set is not allowed for HTTP upload">>),
{Acc, IQ#iq{type = error, sub_el = [SubEl, Error]}};
process_iq(_From, _To = #jid{lserver = SubHost}, Acc, IQ = #iq{type = get, sub_el = Request}) ->
{ok, Host} = mongoose_subhosts:get_host(SubHost),
{ok, HostType} = mongoose_domain_api:get_subdomain_host_type(SubHost),
Res = case parse_request(Request) of
{Filename, Size, ContentType} ->
MaxFileSize = max_file_size(Host),
MaxFileSize = max_file_size(HostType),
case MaxFileSize =:= undefined orelse Size =< MaxFileSize of
true ->
UTCDateTime = calendar:universal_time(),
Token = generate_token(Host),
Opts = module_opts(Host),
Token = generate_token(HostType),
Opts = module_opts(HostType),

{PutUrl, GetUrl, Headers} =
mod_http_upload_backend:create_slot(UTCDateTime, Token, Filename,
Expand Down Expand Up @@ -193,20 +196,28 @@ disco_identity(Lang) ->

-spec disco_info(jid:lserver()) -> [exml:element()].
disco_info(SubHost) ->
{ok, Host} = mongoose_subhosts:get_host(SubHost),
case max_file_size(Host) of
{ok, HostType} = mongoose_domain_api:get_subdomain_host_type(SubHost),
case max_file_size(HostType) of
undefined ->
[];
MaxFileSize ->
MaxFileSizeBin = integer_to_binary(MaxFileSize),
[get_disco_info_form(MaxFileSizeBin)]
end.

-spec subhost(Host :: jid:server()) -> binary().
subhost(Host) ->
DefaultSubhost = mongoose_subdomain_utils:make_subdomain_pattern(?DEFAULT_SUBHOST),
gen_mod:get_module_opt_subhost(Host, ?MODULE, DefaultSubhost).

-spec subhost(mongooseim:host_type()) -> mongooseim:domain_name().
subhost(HostType) ->
%% TODO: this works only for statically configured hosts, when HostType =:= Domain.
DefaultSubdomainPattern =
mongoose_subdomain_utils:make_subdomain_pattern(?DEFAULT_SUBHOST),
gen_mod:get_module_opt_subhost(HostType, ?MODULE, DefaultSubdomainPattern).

-spec subdomain_pattern(mongooseim:host_type()) ->
mongoose_subdomain_utils:subdomain_pattern().
subdomain_pattern(HostType) ->
DefaultSubdomainPattern =
mongoose_subdomain_utils:make_subdomain_pattern(?DEFAULT_SUBHOST),
gen_mod:get_module_opt(HostType, ?MODULE, host, DefaultSubdomainPattern).

-spec my_disco_name(ejabberd:lang()) -> binary().
my_disco_name(Lang) ->
Expand Down
35 changes: 24 additions & 11 deletions src/mam/mod_mam_muc.erl
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
%% ejabberd room handlers
-export([add_local_features/5,
filter_room_packet/3,
room_process_mam_iq/4,
room_process_mam_iq/5,
forget_room/4]).

%% gdpr callback
Expand Down Expand Up @@ -232,10 +232,12 @@ archive_room_packet(HostType, Packet, FromNick, FromJID=#jid{},
%% to the user on their bare JID (i.e. `From.luser'),
%% while a MUC service might allow MAM queries to be sent to the room's bare JID
%% (i.e `To.luser').
-spec room_process_mam_iq(From :: jid:jid(), To :: jid:jid(), Acc :: mongoose_acc:t(),
IQ :: jlib:iq()) -> {mongoose_acc:t(), jlib:iq() | ignore}.
room_process_mam_iq(From, To, Acc, IQ) ->
HostType = mod_muc_light_utils:acc_to_host_type(Acc),
-spec room_process_mam_iq(Acc :: mongoose_acc:t(),
From :: jid:jid(),
To :: jid:jid(),
IQ :: jlib:iq(),
Extra :: map()) -> {mongoose_acc:t(), jlib:iq() | ignore}.
room_process_mam_iq(Acc, From, To, IQ, #{host_type := HostType}) ->
mod_mam_utils:maybe_log_deprecation(IQ),
Action = mam_iq:action(IQ),
MucAction = action_to_muc_action(Action),
Expand Down Expand Up @@ -616,15 +618,26 @@ hooks(HostType) ->

add_iq_handlers(HostType, Opts) ->
IQDisc = gen_mod:get_opt(iqdisc, Opts, parallel),
gen_iq_handler:add_iq_handler(mod_muc_iq, HostType, ?NS_MAM_04,
?MODULE, room_process_mam_iq, IQDisc),
gen_iq_handler:add_iq_handler(mod_muc_iq, HostType, ?NS_MAM_06,
?MODULE, room_process_mam_iq, IQDisc),
MUCSubdomainPattern = gen_mod:get_module_opt(HostType, ?MODULE, host,
mod_muc:default_host()),

gen_iq_handler:add_iq_handler_for_subdomain(HostType, MUCSubdomainPattern,
?NS_MAM_04, mod_muc_iq,
fun ?MODULE:room_process_mam_iq/5,
#{}, IQDisc),
gen_iq_handler:add_iq_handler_for_subdomain(HostType, MUCSubdomainPattern,
?NS_MAM_06, mod_muc_iq,
fun ?MODULE:room_process_mam_iq/5,
#{}, IQDisc),
ok.

remove_iq_handlers(HostType) ->
gen_iq_handler:remove_iq_handler(mod_muc_iq, HostType, ?NS_MAM_04),
gen_iq_handler:remove_iq_handler(mod_muc_iq, HostType, ?NS_MAM_06),
MUCSubdomainPattern = gen_mod:get_module_opt(HostType, ?MODULE, host,
mod_muc:default_host()),
gen_iq_handler:remove_iq_handler_for_subdomain(HostType, MUCSubdomainPattern,
?NS_MAM_04, mod_muc_iq),
gen_iq_handler:remove_iq_handler_for_subdomain(HostType, MUCSubdomainPattern,
?NS_MAM_06, mod_muc_iq),
ok.

ensure_metrics(HostType) ->
Expand Down
29 changes: 14 additions & 15 deletions src/mod_muc_iq.erl
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,24 @@ start_link() ->

%% @doc Handle custom IQ.
%% Called from mod_muc_room.
-spec process_iq(mongooseim:host_type(), jid:jid(), jid:jid(), mongoose_acc:t(),
-spec process_iq(jid:lserver(), jid:jid(), jid:jid(), mongoose_acc:t(),
jlib:iq()) -> mongoose_acc:t() | {mongoose_acc:t(), error}.
process_iq(HostType, From, RoomJID, Acc, IQ = #iq{xmlns = XMLNS}) ->
case ets:lookup(tbl_name(), {XMLNS, HostType}) of
process_iq(MucHost, From, RoomJID, Acc, IQ = #iq{xmlns = XMLNS}) ->
case ets:lookup(tbl_name(), {XMLNS, MucHost}) of
[{_, IQHandler}] ->
gen_iq_component:handle(IQHandler, Acc, From, RoomJID, IQ);
[] -> {Acc, error}
end.

-spec register_iq_handler(mongooseim:host_type(), binary(), mongoose_iq_handler:t()) -> ok.
register_iq_handler(HostType, XMLNS, IQHandler) ->
-spec register_iq_handler(jid:lserver(), binary(), mongoose_iq_handler:t()) -> ok.
register_iq_handler(MucHost, XMLNS, IQHandler) ->
gen_server:cast(srv_name(),
{register_iq_handler, HostType, XMLNS, IQHandler}).
{register_iq_handler, MucHost, XMLNS, IQHandler}).

-spec unregister_iq_handler(mongooseim:host_type(), binary()) -> ok.
unregister_iq_handler(HostType, XMLNS) ->
-spec unregister_iq_handler(jid:lserver(), binary()) -> ok.
unregister_iq_handler(MucHost, XMLNS) ->
gen_server:cast(srv_name(),
{unregister_iq_handler, HostType, XMLNS}).
{unregister_iq_handler, MucHost, XMLNS}).

-spec sync() -> ok.
sync() ->
Expand All @@ -72,14 +72,14 @@ handle_call(sync, _From, State) ->
handle_call(_Request, _From, State) ->
{reply, ok, State}.

handle_cast({register_iq_handler, HostType, XMLNS, IQHandler}, State) ->
ets:insert(tbl_name(), {{XMLNS, HostType}, IQHandler}),
handle_cast({register_iq_handler, MucHost, XMLNS, IQHandler}, State) ->
ets:insert(tbl_name(), {{XMLNS, MucHost}, IQHandler}),
{noreply, State};
handle_cast({unregister_iq_handler, HostType, XMLNS}, State) ->
case ets:lookup(tbl_name(), {XMLNS, HostType}) of
handle_cast({unregister_iq_handler, MucHost, XMLNS}, State) ->
case ets:lookup(tbl_name(), {XMLNS, MucHost}) of
[{_, IQHandler}] ->
gen_iq_component:stop_iq_handler(IQHandler),
ets:delete(tbl_name(), {XMLNS, HostType});
ets:delete(tbl_name(), {XMLNS, MucHost});
_ ->
ok
end,
Expand All @@ -95,4 +95,3 @@ terminate(_Reason, _State) ->

code_change(_OldVsn, State, _Extra) ->
{ok, State}.

6 changes: 3 additions & 3 deletions src/mod_muc_room.erl
Original file line number Diff line number Diff line change
Expand Up @@ -4581,11 +4581,11 @@ route_iq(Acc, #routed_iq{iq = #iq{type = Type, xmlns = ?NS_DISCO_ITEMS, lang = L
Res = process_iq_disco_items(From, Type, Lang, StateData),
do_route_iq(Acc, Res, Routed, StateData);
route_iq(Acc, #routed_iq{iq = IQ = #iq{}, packet = Packet, from = From},
#state{host_type = HostType, jid = RoomJID} = StateData) ->
#state{host = Host, host_type = HostType, jid = RoomJID} = StateData) ->
%% Custom IQ, addressed to this room's JID.
case mod_muc_iq:process_iq(HostType, From, RoomJID, Acc, IQ) of
case mod_muc_iq:process_iq(Host, From, RoomJID, Acc, IQ) of
{Acc1, error} ->
?LOG_WARNING(#{what => muc_process_iq_failed, acc => Acc,
?LOG_WARNING(#{what => muc_process_iq_failed, acc => Acc, server => Host,
host_type => HostType, room_jid => RoomJID}),
E = mongoose_xmpp_errors:feature_not_implemented(
<<"en">>, <<"From mod_muc_room">>),
Expand Down
20 changes: 11 additions & 9 deletions src/mod_vcard.erl
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,8 @@

-define(PROCNAME, ejabberd_mod_vcard).

-record(state, {search :: boolean(),
host :: binary(),
directory_host :: binary()
}).
-record(state, {search :: boolean(),
host :: binary()}).

-type error() :: error | {error, any()}.

Expand Down Expand Up @@ -323,22 +321,26 @@ init([VHost, Opts]) ->
?MODULE, process_sm_iq, IQDisc),
gen_iq_handler:add_iq_handler(ejabberd_local, VHost, ?NS_VCARD,
?MODULE, process_local_iq, IQDisc),
DirectoryHost = gen_mod:get_opt_subhost(VHost, Opts, default_host()),
DirectoryHost = gen_mod:get_opt(host, Opts, default_host()),

Search = gen_mod:get_opt(search, Opts, true),
case Search of
true ->
ejabberd_router:register_route(
DirectoryHost, mongoose_packet_handler:new(?MODULE, #{pid => self()}));
%% TODO: Conversion of this module is not done, it doesn't support dynamic
%% domains yet. Only subdomain registration is done properly.
PacketHandler = mongoose_packet_handler:new(?MODULE, #{pid => self()}),
mongoose_domain_api:register_subdomain(VHost, DirectoryHost, PacketHandler);
_ ->
ok
end,
{ok, #state{host = VHost, search = Search, directory_host = DirectoryHost}}.
{ok, #state{host = VHost, search = Search}}.

terminate(_Reason, State) ->
VHost = State#state.host,
case State#state.search of
true ->
ejabberd_router:unregister_route(State#state.directory_host);
DirectoryHost = gen_mod:get_module_opt(VHost, ?MODULE, host, default_host()),
mongoose_domain_api:unregister_subdomain(VHost, DirectoryHost);
_ ->
ok
end,
Expand Down
Loading

0 comments on commit b094384

Please sign in to comment.