diff --git a/apps/ejabberd/include/mod_muc_light.hrl b/apps/ejabberd/include/mod_muc_light.hrl index 1798af08cee..19abf9e7e8a 100644 --- a/apps/ejabberd/include/mod_muc_light.hrl +++ b/apps/ejabberd/include/mod_muc_light.hrl @@ -15,7 +15,6 @@ -define(DEFAULT_MAX_OCCUPANTS, infinity). -define(DEFAULT_ROOMS_PER_PAGE, 10). -define(DEFAULT_ROOMS_IN_ROSTERS, false). --define(DEFAULT_HOST, <<"muclight.@HOST@">>). -type schema_value_type() :: binary | integer | float. -type schema_item() :: {FormFieldName :: binary(), OptionName :: atom(), diff --git a/apps/ejabberd/src/ejabberd_admin.erl b/apps/ejabberd/src/ejabberd_admin.erl index 96ad6625e4b..7f377423bac 100644 --- a/apps/ejabberd/src/ejabberd_admin.erl +++ b/apps/ejabberd/src/ejabberd_admin.erl @@ -283,9 +283,8 @@ status() -> send_service_message_all_mucs(Subject, AnnouncementText) -> Message = io_lib:format("~s~n~s", [Subject, AnnouncementText]), lists:foreach( - fun(ServerHost) -> - MUCHost = gen_mod:get_module_opt_host( - ServerHost, mod_muc, "conference.@HOST@"), + fun(Host) -> + MUCHost = gen_mod:get_module_opt_subhost(Host, mod_muc, mod_muc:default_host()), mod_muc:broadcast_service_message(MUCHost, Message) end, ?MYHOSTS). diff --git a/apps/ejabberd/src/ejabberd_app.erl b/apps/ejabberd/src/ejabberd_app.erl index b9314faf508..2604607cd17 100644 --- a/apps/ejabberd/src/ejabberd_app.erl +++ b/apps/ejabberd/src/ejabberd_app.erl @@ -51,6 +51,7 @@ start(normal, _Args) -> ejabberd_ctl:init(), ejabberd_commands:init(), mongoose_commands:init(), + mongoose_subhosts:init(), gen_mod:start(), ejabberd_config:start(), ejabberd_check:config(), @@ -80,6 +81,7 @@ start(_, _) -> prep_stop(State) -> ejabberd_listener:stop_listeners(), stop_modules(), + mongoose_subhosts:stop(), broadcast_c2s_shutdown(), timer:sleep(5000), mongoose_metrics:remove_all_metrics(), diff --git a/apps/ejabberd/src/ejabberd_receiver.erl b/apps/ejabberd/src/ejabberd_receiver.erl index 01c1f810c27..e49732ef09d 100644 --- a/apps/ejabberd/src/ejabberd_receiver.erl +++ b/apps/ejabberd/src/ejabberd_receiver.erl @@ -143,7 +143,7 @@ handle_call({starttls, TLSSocket}, _From, #state{parser = Parser} = State) -> NewState = State#state{socket = TLSSocket, sock_mod = fast_tls, parser = NewParser}, - case fast_tls:recv_data(TLSSocket, "") of + case fast_tls:recv_data(TLSSocket, <<"">>) of {ok, TLSData} -> {reply, ok, process_data(TLSData, NewState), ?HIBERNATE_TIMEOUT}; {error, _Reason} -> diff --git a/apps/ejabberd/src/gen_mod.erl b/apps/ejabberd/src/gen_mod.erl index bdb2bac4b09..73679186a93 100644 --- a/apps/ejabberd/src/gen_mod.erl +++ b/apps/ejabberd/src/gen_mod.erl @@ -27,24 +27,30 @@ -module(gen_mod). -author('alexey@process-one.net'). --export([start/0, +-export([ + % Modules start & stop + start/0, start_module/3, start_backend_module/2, start_backend_module/3, stop_module/2, stop_module_keep_config/2, reload_module/3, + % Get/set opts by host or from a list get_opt/2, get_opt/3, get_opt/4, - get_opt_host/3, set_opt/3, get_module_opt/4, - get_module_opt_host/3, set_module_opt/4, + get_opt_subhost/3, + get_module_opt_subhost/3, + % Get/set opts by subhost + get_module_opt_by_subhost/4, + set_module_opt_by_subhost/4, + loaded_modules/1, loaded_modules_with_opts/1, - get_hosts/2, get_module_proc/2, backend_code/3, is_loaded/2, @@ -52,7 +58,10 @@ -include("ejabberd.hrl"). --record(ejabberd_module, {module_host, opts}). +-record(ejabberd_module, { + module_host, % {module(), ejabberd:server()}, + opts % list() + }). %% -export([behaviour_info/1]). %% behaviour_info(callbacks) -> @@ -77,10 +86,8 @@ -spec start() -> 'ok'. start() -> - ets:new(ejabberd_modules, - [named_table, - public, - {keypos, #ejabberd_module.module_host}]), + ets:new(ejabberd_modules, [named_table, public, {keypos, #ejabberd_module.module_host}, + {read_concurrency, true}]), ok. @@ -90,9 +97,7 @@ start() -> start_module(Host, Module, Opts0) -> Opts = clear_opts(Module, Opts0), set_module_opts_mnesia(Host, Module, Opts), - ets:insert(ejabberd_modules, - #ejabberd_module{module_host = {Module, Host}, - opts = Opts}), + ets:insert(ejabberd_modules, #ejabberd_module{module_host = {Module, Host}, opts = Opts}), try Res = Module:start(Host, Opts), ?DEBUG("Module ~p started for ~p.", [Module, Host]), @@ -307,6 +312,14 @@ get_module_opt(Host, Module, Opt, Default) -> get_opt(Opt, Opts, Default) end. +-spec get_module_opt_by_subhost( + SubHost :: ejabberd:server(), + Module :: module(), + Opt :: term(), + Default :: term()) -> term(). +get_module_opt_by_subhost(SubHost, Module, Opt, Default) -> + {ok, Host} = mongoose_subhosts:get_host(SubHost), + get_module_opt(Host, Module, Opt, Default). %% @doc Non-atomic! You have been warned. -spec set_module_opt(ejabberd:server(), module(), _Opt, _Value) -> boolean(). @@ -322,18 +335,25 @@ set_module_opt(Host, Module, Opt, Value) -> {#ejabberd_module.opts, Updated}) end. - --spec get_module_opt_host(ejabberd:server(), module(), _) -> ejabberd:server(). -get_module_opt_host(Host, Module, Default) -> - Val = get_module_opt(Host, Module, host, Default), - re:replace(Val, "@HOST@", Host, [global, {return, binary}]). +-spec set_module_opt_by_subhost( + SubHost :: ejabberd:server(), + Module :: module(), + Opt :: term(), + Value :: term()) -> boolean(). +set_module_opt_by_subhost(SubHost, Module, Opt, Value) -> + {ok, Host} = mongoose_subhosts:get_host(SubHost), + set_module_opt(Host, Module, Opt, Value). --spec get_opt_host(ejabberd:server(), list(), _) -> ejabberd:server(). -get_opt_host(Host, Opts, Default) -> +-spec get_opt_subhost(ejabberd:server(), list(), list() | binary()) -> ejabberd:server(). +get_opt_subhost(Host, Opts, Default) -> Val = get_opt(host, Opts, Default), re:replace(Val, "@HOST@", Host, [global, {return, binary}]). +-spec get_module_opt_subhost(ejabberd:server(), module(), list() | binary()) -> ejabberd:server(). +get_module_opt_subhost(Host, Module, Default) -> + Subject = get_module_opt(Host, Module, host, Default), + re:replace(Subject, "@HOST@", Host, [global, {return, binary}]). -spec loaded_modules(ejabberd:server()) -> [module()]. loaded_modules(Host) -> @@ -381,20 +401,6 @@ del_module_mnesia(Host, Module) -> ejabberd_config:add_local_option({modules, Host}, OtherModules) end. -get_hosts(Opts, Prefix) -> - case catch gen_mod:get_opt(hosts, Opts) of - {'EXIT', _Error1} -> - case catch gen_mod:get_opt(host, Opts) of - {'EXIT', _Error2} -> - [Prefix ++ Host || Host <- ?MYHOSTS]; - Host -> - [Host] - end; - Hosts -> - Hosts - end. - - -spec get_module_proc(binary() | string(), module()) -> atom(). get_module_proc(Host, Base) when is_binary(Host) -> get_module_proc(binary_to_list(Host), Base); diff --git a/apps/ejabberd/src/mod_mam_muc.erl b/apps/ejabberd/src/mod_mam_muc.erl index b1c44bb8d00..de780429c06 100644 --- a/apps/ejabberd/src/mod_mam_muc.erl +++ b/apps/ejabberd/src/mod_mam_muc.erl @@ -49,8 +49,6 @@ room_process_mam_iq/3, forget_room/2]). --export([server_host/1]). - %% private -export([archive_message/8]). -export([lookup_messages/13]). @@ -140,30 +138,27 @@ max_result_limit() -> 50. %% API -spec delete_archive(ejabberd:server(), ejabberd:user()) -> 'ok'. -delete_archive(Server, User) - when is_binary(Server), is_binary(User) -> - ?DEBUG("Remove user ~p from ~p.", [User, Server]), - ArcJID = jid:make(User, Server, <<>>), - Host = server_host(ArcJID), +delete_archive(SubHost, RoomName) when is_binary(SubHost), is_binary(RoomName) -> + ?DEBUG("Remove room ~p from ~p.", [RoomName, SubHost]), + ArcJID = jid:make(RoomName, SubHost, <<>>), + {ok, Host} = mongoose_subhosts:get_host(SubHost), ArcID = archive_id_int(Host, ArcJID), remove_archive(Host, ArcID, ArcJID), ok. -spec archive_size(ejabberd:server(), ejabberd:user()) -> integer(). -archive_size(Server, User) - when is_binary(Server), is_binary(User) -> - ArcJID = jid:make(User, Server, <<>>), - Host = server_host(ArcJID), +archive_size(SubHost, RoomName) when is_binary(SubHost), is_binary(RoomName) -> + ArcJID = jid:make(RoomName, SubHost, <<>>), + {ok, Host} = mongoose_subhosts:get_host(SubHost), ArcID = archive_id_int(Host, ArcJID), archive_size(Host, ArcID, ArcJID). -spec archive_id(ejabberd:server(), ejabberd:user()) -> integer(). -archive_id(Server, User) - when is_binary(Server), is_binary(User) -> - ArcJID = jid:make(User, Server, <<>>), - Host = server_host(ArcJID), +archive_id(SubHost, RoomName) when is_binary(SubHost), is_binary(RoomName) -> + ArcJID = jid:make(RoomName, SubHost, <<>>), + {ok, Host} = mongoose_subhosts:get_host(SubHost), archive_id_int(Host, ArcJID). %% ---------------------------------------------------------------------- @@ -171,73 +166,40 @@ archive_id(Server, User) %% Starting and stopping functions for MUC archives -spec start(Host :: ejabberd:server(), Opts :: list()) -> any(). -start(ServerHost, Opts) -> +start(Host, Opts) -> ?DEBUG("mod_mam_muc starting", []), compile_params_module(Opts), %% MUC host. - Host = gen_mod:get_opt_host(ServerHost, Opts, <<"conference.@HOST@">>), - start_host_mapping(Host, ServerHost), + MUCHost = gen_mod:get_opt_subhost(Host, Opts, mod_muc:default_host()), IQDisc = gen_mod:get_opt(iqdisc, Opts, parallel), %% Type - mod_disco:register_feature(Host, ?NS_MAM), - mod_disco:register_feature(Host, ?NS_MAM_03), - mod_disco:register_feature(Host, ?NS_MAM_04), - gen_iq_handler:add_iq_handler(mod_muc_iq, Host, ?NS_MAM, + mod_disco:register_feature(MUCHost, ?NS_MAM), + mod_disco:register_feature(MUCHost, ?NS_MAM_03), + mod_disco:register_feature(MUCHost, ?NS_MAM_04), + gen_iq_handler:add_iq_handler(mod_muc_iq, MUCHost, ?NS_MAM, ?MODULE, room_process_mam_iq, IQDisc), - gen_iq_handler:add_iq_handler(mod_muc_iq, Host, ?NS_MAM_03, + gen_iq_handler:add_iq_handler(mod_muc_iq, MUCHost, ?NS_MAM_03, ?MODULE, room_process_mam_iq, IQDisc), - gen_iq_handler:add_iq_handler(mod_muc_iq, Host, ?NS_MAM_04, + gen_iq_handler:add_iq_handler(mod_muc_iq, MUCHost, ?NS_MAM_04, ?MODULE, room_process_mam_iq, IQDisc), - ejabberd_hooks:add(filter_room_packet, Host, ?MODULE, + ejabberd_hooks:add(filter_room_packet, MUCHost, ?MODULE, filter_room_packet, 90), - ejabberd_hooks:add(forget_room, Host, ?MODULE, forget_room, 90), + ejabberd_hooks:add(forget_room, MUCHost, ?MODULE, forget_room, 90), ok. -spec stop(Host :: ejabberd:server()) -> any(). -stop(ServerHost) -> - %% MUC host. - Host = gen_mod:get_module_opt_host( - ServerHost, ?MODULE, <<"conference.@HOST@">>), +stop(Host) -> + MUCHost = gen_mod:get_module_opt_subhost(Host, mod_mam_muc, mod_muc:default_host()), ?DEBUG("mod_mam stopping", []), - ejabberd_hooks:delete(filter_room_packet, Host, ?MODULE, filter_room_packet, 90), - ejabberd_hooks:delete(forget_room, Host, ?MODULE, forget_room, 90), - gen_iq_handler:remove_iq_handler(mod_muc_iq, Host, ?NS_MAM), - gen_iq_handler:remove_iq_handler(mod_muc_iq, Host, ?NS_MAM_03), - gen_iq_handler:remove_iq_handler(mod_muc_iq, Host, ?NS_MAM_04), - mod_disco:unregister_feature(Host, ?NS_MAM), - mod_disco:unregister_feature(Host, ?NS_MAM_03), - mod_disco:unregister_feature(Host, ?NS_MAM_04), - stop_host_mapping(Host, ServerHost), + ejabberd_hooks:delete(filter_room_packet, MUCHost, ?MODULE, filter_room_packet, 90), + ejabberd_hooks:delete(forget_room, MUCHost, ?MODULE, forget_room, 90), + gen_iq_handler:remove_iq_handler(mod_muc_iq, MUCHost, ?NS_MAM), + gen_iq_handler:remove_iq_handler(mod_muc_iq, MUCHost, ?NS_MAM_03), + gen_iq_handler:remove_iq_handler(mod_muc_iq, MUCHost, ?NS_MAM_04), + mod_disco:unregister_feature(MUCHost, ?NS_MAM), + mod_disco:unregister_feature(MUCHost, ?NS_MAM_03), + mod_disco:unregister_feature(MUCHost, ?NS_MAM_04), ok. -%% ---------------------------------------------------------------------- -%% Host to ServerHost mapping - --record(mam_host, {host :: ejabberd:server(), - server_host :: ejabberd:server()}). - --spec start_host_mapping(ejabberd:server(), ejabberd:server()) -> any(). -start_host_mapping(Host, ServerHost) -> - mnesia:create_table(mam_host, - [{ram_copies, [node()]}, - {type, set}, - {attributes, record_info(fields, mam_host)}]), - mnesia:add_table_copy(mam_host, node(), ram_copies), - mnesia:dirty_write(#mam_host{host = Host, server_host = ServerHost}). - - --spec stop_host_mapping(ejabberd:server(), ejabberd:server()) -> any(). -stop_host_mapping(Host, ServerHost) -> - mnesia:dirty_delete_object( - #mam_host{host = Host, server_host = ServerHost}). - - --spec server_host(ejabberd:jid()) -> ejabberd:server(). -server_host(#jid{lserver=Host}) -> - server_host_1(Host, mnesia:dirty_read(mam_host, Host)). - -server_host_1(_Host, [#mam_host{ server_host = ServerHost }]) -> - ServerHost. - %% ---------------------------------------------------------------------- %% hooks and handlers for MUC @@ -263,7 +225,7 @@ filter_room_packet(Packet, EventData) -> FromJID :: ejabberd:jid(), RoomJID :: ejabberd:jid(), Role :: mod_muc:role(), Affiliation :: mod_muc:affiliation()) -> packet(). archive_room_packet(Packet, FromNick, FromJID=#jid{}, RoomJID=#jid{}, Role, Affiliation) -> - Host = server_host(RoomJID), + {ok, Host} = mongoose_subhosts:get_host(RoomJID#jid.lserver), ArcID = archive_id_int(Host, RoomJID), %% Occupant JID SrcJID = jid:replace_resource(RoomJID, FromNick), @@ -445,7 +407,7 @@ handle_set_prefs(ArcJID=#jid{}, {DefaultMode, AlwaysJIDs, NeverJIDs} = parse_prefs(PrefsEl), ?DEBUG("Parsed data~n\tDefaultMode ~p~n\tAlwaysJIDs ~p~n\tNeverJIDS ~p~n", [DefaultMode, AlwaysJIDs, NeverJIDs]), - Host = server_host(ArcJID), + {ok, Host} = mongoose_subhosts:get_host(ArcJID#jid.lserver), ArcID = archive_id_int(Host, ArcJID), Res = set_prefs(Host, ArcID, ArcJID, DefaultMode, AlwaysJIDs, NeverJIDs), handle_set_prefs_result(Res, DefaultMode, AlwaysJIDs, NeverJIDs, IQ). @@ -461,7 +423,7 @@ handle_set_prefs_result({error, Reason}, -spec handle_get_prefs(ejabberd:jid(), ejabberd:iq()) -> ejabberd:iq() | {error, any(), ejabberd:iq()}. handle_get_prefs(ArcJID=#jid{}, IQ=#iq{}) -> - Host = server_host(ArcJID), + {ok, Host} = mongoose_subhosts:get_host(ArcJID#jid.lserver), ArcID = archive_id_int(Host, ArcJID), Res = get_prefs(Host, ArcID, ArcJID, always), handle_get_prefs_result(Res, IQ). @@ -482,7 +444,7 @@ handle_lookup_messages( ArcJID=#jid{}, IQ=#iq{xmlns = MamNs, sub_el = QueryEl}) -> Now = mod_mam_utils:now_to_microseconds(now()), - Host = server_host(ArcJID), + {ok, Host} = mongoose_subhosts:get_host(ArcJID#jid.lserver), ArcID = archive_id_int(Host, ArcJID), QueryID = xml:get_tag_attr_s(<<"queryid">>, QueryEl), %% Filtering by date. @@ -537,7 +499,7 @@ handle_set_message_form( ArcJID=#jid{}, IQ=#iq{xmlns=MamNs, sub_el = QueryEl}) -> Now = mod_mam_utils:now_to_microseconds(now()), - Host = server_host(ArcJID), + {ok, Host} = mongoose_subhosts:get_host(ArcJID#jid.lserver), ArcID = archive_id_int(Host, ArcJID), QueryID = xml:get_tag_attr_s(<<"queryid">>, QueryEl), %% Filtering by date. @@ -623,7 +585,7 @@ handle_get_message_form(_From=#jid{}, _ArcJID=#jid{}, IQ=#iq{}) -> handle_purge_multiple_messages(ArcJID=#jid{}, IQ=#iq{sub_el = PurgeEl}) -> Now = mod_mam_utils:now_to_microseconds(now()), - Host = server_host(ArcJID), + {ok, Host} = mongoose_subhosts:get_host(ArcJID#jid.lserver), ArcID = archive_id_int(Host, ArcJID), %% Filtering by date. %% Start :: integer() | undefined @@ -643,7 +605,7 @@ handle_purge_multiple_messages(ArcJID=#jid{}, handle_purge_single_message(ArcJID=#jid{}, IQ=#iq{sub_el = PurgeEl}) -> Now = mod_mam_utils:now_to_microseconds(now()), - Host = server_host(ArcJID), + {ok, Host} = mongoose_subhosts:get_host(ArcJID#jid.lserver), ArcID = archive_id_int(Host, ArcJID), BExtMessID = xml:get_tag_attr_s(<<"id">>, PurgeEl), MessID = mod_mam_utils:external_binary_to_mess_id(BExtMessID), diff --git a/apps/ejabberd/src/mod_muc.erl b/apps/ejabberd/src/mod_muc.erl index d874cb97a41..f9b8e1b9ddf 100644 --- a/apps/ejabberd/src/mod_muc.erl +++ b/apps/ejabberd/src/mod_muc.erl @@ -42,7 +42,8 @@ process_iq_disco_items/4, broadcast_service_message/2, can_use_nick/3, - room_jid_to_pid/1]). + room_jid_to_pid/1, + default_host/0]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, @@ -283,7 +284,7 @@ init([Host, Opts]) -> mnesia:add_table_copy(muc_room, node(), disc_copies), mnesia:add_table_copy(muc_registered, node(), disc_copies), catch ets:new(muc_online_users, [bag, named_table, public, {keypos, 2}]), - MyHost = gen_mod:get_opt_host(Host, Opts, <<"conference.@HOST@">>), + MyHost = gen_mod:get_opt_subhost(Host, Opts, default_host()), update_tables(MyHost), clean_table_from_bad_node(node(), MyHost), mnesia:add_table_index(muc_registered, nick), @@ -319,6 +320,7 @@ init([Host, Opts]) -> mod_muc:route({From, To, Packet}, State) end, ejabberd_router:register_route(MyHost, {apply_fun, F}), + mongoose_subhosts:register(Host, MyHost), load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin, AccessPersistent}, @@ -447,6 +449,7 @@ stop_if_hibernated_for_specified_time(Pid, Now, Timeout, {hibernated, LastHibern %% The return value is ignored. %%-------------------------------------------------------------------- terminate(_Reason, State) -> + mongoose_subhosts:unregister(State#state.host), ejabberd_router:unregister_route(State#state.host), ok. @@ -776,8 +779,10 @@ room_jid_to_pid(#jid{luser=RoomName, lserver=MucService}) -> {error, not_found} end. +-spec default_host() -> binary(). +default_host() -> <<"conference.@HOST@">>. --spec iq_disco_info(ejabberd:lang()) -> [jlib:xmlel(),...]. +-spec iq_disco_info(ejabberd:lang()) -> [jlib:xmlel(), ...]. iq_disco_info(Lang) -> [#xmlel{name = <<"identity">>, attrs = [{<<"category">>, <<"conference">>}, diff --git a/apps/ejabberd/src/mod_muc_commands.erl b/apps/ejabberd/src/mod_muc_commands.erl index 03d7fc93c01..0b80b5f35ce 100644 --- a/apps/ejabberd/src/mod_muc_commands.erl +++ b/apps/ejabberd/src/mod_muc_commands.erl @@ -111,7 +111,7 @@ create_instant_room(Host, Name, Owner, Nick) -> %% the HTTP API, they will certainly recieve stanzas as a %% consequence, even if their client(s) did not initiate this. OwnerJID = jid:binary_to_bare(Owner), - MUCHost = gen_mod:get_module_opt_host(Host, mod_muc, <<"muc.@HOST@">>), + MUCHost = gen_mod:get_module_opt_subhost(Host, mod_muc, mod_muc:default_host()), UserRoomJID = jid:make(Name, MUCHost, Nick), BareRoomJID = jid:make(Name, MUCHost, <<"">>), %% Send presence to create a room. @@ -172,7 +172,7 @@ kick_user_from_room(Host, Name, Nick) -> %%-------------------------------------------------------------------- room_address(Name, Host) -> - MUCHost = gen_mod:get_module_opt_host(Host, mod_muc, <<"muc.@HOST@">>), + MUCHost = gen_mod:get_module_opt_subhost(Host, mod_muc, mod_muc:default_host()), <>. iq(Type, Sender, Recipient, Children) diff --git a/apps/ejabberd/src/mod_muc_light.erl b/apps/ejabberd/src/mod_muc_light.erl index 34fd322348f..01f14b2defa 100644 --- a/apps/ejabberd/src/mod_muc_light.erl +++ b/apps/ejabberd/src/mod_muc_light.erl @@ -47,9 +47,8 @@ -behaviour(gen_mod). %% API --export([standard_config_schema/0, standard_default_config/0]). +-export([standard_config_schema/0, standard_default_config/0, default_host/0]). -export([config_schema/1, default_config/1]). --export([get_opt/3, set_opt/3]). %% gen_mod callbacks -export([start/2, stop/1]). @@ -79,8 +78,6 @@ -include("mod_muc_light.hrl"). -include("mod_roster.hrl"). --define(CONFIG_TAB, muc_light_config). - %%==================================================================== %% API %%==================================================================== @@ -91,24 +88,17 @@ standard_config_schema() -> ["roomname", "subject"]. -spec standard_default_config() -> [{K :: string(), V :: string()}]. standard_default_config() -> [{"roomname", "Untitled"}, {"subject", ""}]. +-spec default_host() -> binary(). +default_host() -> + <<"muclight.@HOST@">>. + -spec default_config(MUCServer :: ejabberd:lserver()) -> config(). -default_config(MUCServer) -> get_opt(MUCServer, default_config, []). +default_config(MUCServer) -> + gen_mod:get_module_opt_by_subhost(MUCServer, ?MODULE, default_config, []). -spec config_schema(MUCServer :: ejabberd:lserver()) -> config_schema(). -config_schema(MUCServer) -> get_opt(MUCServer, config_schema, undefined). - --spec get_opt(MUCServer :: ejabberd:lserver(), OptName :: atom(), Default :: any()) -> any(). -get_opt(MUCServer, OptName, Default) -> - [{_, Opts}] = ets:lookup(?CONFIG_TAB, MUCServer), - case lists:keyfind(OptName, 1, Opts) of - false -> Default; - {_, Val} -> Val - end. - --spec set_opt(MUCServer :: ejabberd:lserver(), OptName :: atom(), Value :: any()) -> any(). -set_opt(MUCServer, OptName, Value) -> - [{_, Opts}] = ets:lookup(?CONFIG_TAB, MUCServer), - ets:insert(?CONFIG_TAB, {MUCServer, lists:keystore(OptName, 1, Opts, {OptName, Value})}). +config_schema(MUCServer) -> + gen_mod:get_module_opt_by_subhost(MUCServer, ?MODULE, config_schema, undefined). %%==================================================================== %% gen_mod callbacks @@ -140,49 +130,39 @@ start(Host, Opts) -> end, gen_mod:start_backend_module(mod_muc_light_codec, [{backend, Codec}], []), - MyDomain = gen_mod:get_opt_host(Host, Opts, ?DEFAULT_HOST), - mod_muc_light_db_backend:start(Host, MyDomain), - ejabberd_router:register_route(MyDomain, {apply, ?MODULE, route}), + MUCHost = gen_mod:get_opt_subhost(Host, Opts, default_host()), + mod_muc_light_db_backend:start(Host, MUCHost), + mongoose_subhosts:register(Host, MUCHost), + ejabberd_router:register_route(MUCHost, {apply, ?MODULE, route}), - ejabberd_hooks:add(is_muc_room_owner, MyDomain, ?MODULE, is_room_owner, 50), - ejabberd_hooks:add(muc_room_pid, MyDomain, ?MODULE, muc_room_pid, 50), - ejabberd_hooks:add(can_access_room, MyDomain, ?MODULE, can_access_room, 50), - - EjdSupPid = whereis(ejabberd_sup), - HeirOpt = case self() =:= EjdSupPid of - true -> []; - false -> [{heir, EjdSupPid, testing}] % for dynamic start from tests - end, - catch ets:new(?CONFIG_TAB, [set, public, named_table, {read_concurrency, true} | HeirOpt]), - ets:insert(?CONFIG_TAB, {MyDomain, Opts}), + ejabberd_hooks:add(is_muc_room_owner, MUCHost, ?MODULE, is_room_owner, 50), + ejabberd_hooks:add(muc_room_pid, MUCHost, ?MODULE, muc_room_pid, 50), + ejabberd_hooks:add(can_access_room, MUCHost, ?MODULE, can_access_room, 50), %% Prepare config schema ConfigSchema = mod_muc_light_utils:make_config_schema( gen_mod:get_opt(config_schema, Opts, standard_config_schema())), - set_opt(MyDomain, config_schema, ConfigSchema), + gen_mod:set_module_opt(Host, ?MODULE, config_schema, ConfigSchema), %% Prepare default config DefaultConfig = mod_muc_light_utils:make_default_config( gen_mod:get_opt(default_config, Opts, standard_default_config()), ConfigSchema), - set_opt(MyDomain, default_config, DefaultConfig), - - set_opt(MyDomain, main_host, Host), + gen_mod:set_module_opt(Host, ?MODULE, default_config, DefaultConfig), ok. -spec stop(Host :: ejabberd:server()) -> ok. stop(Host) -> - MyDomain = gen_mod:get_module_opt_host(Host, ?MODULE, ?DEFAULT_HOST), - ejabberd_router:unregister_route(MyDomain), - - ets:delete(?CONFIG_TAB, MyDomain), + MUCHost = gen_mod:get_module_opt_subhost(Host, ?MODULE, default_host()), + ejabberd_router:unregister_route(MUCHost), + mongoose_subhosts:unregister(MUCHost), - mod_muc_light_db_backend:stop(Host, MyDomain), + mod_muc_light_db_backend:stop(Host, MUCHost), - ejabberd_hooks:delete(is_muc_room_owner, MyDomain, ?MODULE, is_room_owner, 50), - ejabberd_hooks:delete(muc_room_pid, MyDomain, ?MODULE, muc_room_pid, 50), - ejabberd_hooks:delete(can_access_room, MyDomain, ?MODULE, can_access_room, 50), + ejabberd_hooks:delete(is_muc_room_owner, MUCHost, ?MODULE, is_room_owner, 50), + ejabberd_hooks:delete(muc_room_pid, MUCHost, ?MODULE, muc_room_pid, 50), + ejabberd_hooks:delete(can_access_room, MUCHost, ?MODULE, can_access_room, 50), ejabberd_hooks:delete(roster_get, Host, ?MODULE, add_rooms_to_roster, 50), ejabberd_hooks:delete(privacy_iq_get, Host, ?MODULE, process_iq_get, 1), @@ -219,7 +199,7 @@ process_packet(From, To, {ok, {get, #disco_items{} = DI}}, OrigPacket) -> handle_disco_items_get(From, To, DI, OrigPacket); process_packet(From, To, {ok, {_, #blocking{}} = Blocking}, OrigPacket) -> RouteFun = fun ejabberd_router:route/3, - case get_opt(To#jid.lserver, blocking, ?DEFAULT_BLOCKING) of + case gen_mod:get_module_opt_by_subhost(To#jid.lserver, ?MODULE, blocking, ?DEFAULT_BLOCKING) of true -> case handle_blocking(From, To, Blocking) of ok -> @@ -267,13 +247,14 @@ prevent_service_unavailable(_From, _To, Packet) -> -spec get_muc_service(Acc :: {result, [jlib:xmlel()]}, From :: ejabberd:jid(), To :: ejabberd:jid(), NS :: binary(), ejabberd:lang()) -> {result, [jlib:xmlel()]}. get_muc_service({result, Nodes}, _From, #jid{lserver = LServer} = _To, <<"">>, _Lang) -> - XMLNS = case get_opt(LServer, legacy_mode, ?DEFAULT_LEGACY_MODE) of + XMLNS = case gen_mod:get_module_opt_by_subhost( + LServer, ?MODULE, legacy_mode, ?DEFAULT_LEGACY_MODE) of true -> ?NS_MUC; false -> ?NS_MUC_LIGHT end, - Host = gen_mod:get_module_opt_host(LServer, ?MODULE, ?DEFAULT_HOST), + SubHost = gen_mod:get_module_opt_subhost(LServer, ?MODULE, default_host()), Item = [#xmlel{name = <<"item">>, - attrs = [{<<"jid">>, Host}, + attrs = [{<<"jid">>, SubHost}, {<<"node">>, XMLNS}]}], {result, [Item | Nodes]}; get_muc_service(Acc, _From, _To, _Node, _Lang) -> @@ -314,9 +295,9 @@ add_rooms_to_roster(Acc, UserUS) -> IQ :: ejabberd:iq(), ActiveList :: binary()) -> {stop, {result, [jlib:xmlel()]}} | {error, jlib:xmlel()}. process_iq_get(_Acc, #jid{ lserver = FromS } = From, To, #iq{} = IQ, _ActiveList) -> - MUCHost = gen_mod:get_module_opt_host(FromS, ?MODULE, ?DEFAULT_HOST), + MUCHost = gen_mod:get_module_opt_subhost(FromS, ?MODULE, default_host()), case {mod_muc_light_codec_backend:decode(From, To, IQ), - get_opt(MUCHost, blocking, ?DEFAULT_BLOCKING)} of + gen_mod:get_module_opt_by_subhost(MUCHost, ?MODULE, blocking, ?DEFAULT_BLOCKING)} of {{ok, {get, #blocking{} = Blocking}}, true} -> Items = mod_muc_light_db_backend:get_blocking(jid:to_lus(From), MUCHost), mod_muc_light_codec_backend:encode( @@ -334,9 +315,9 @@ process_iq_get(_Acc, #jid{ lserver = FromS } = From, To, #iq{} = IQ, _ActiveList To :: ejabberd:jid(), IQ :: ejabberd:iq()) -> {stop, {result, [jlib:xmlel()]}} | {error, jlib:xmlel()}. process_iq_set(_Acc, #jid{ lserver = FromS } = From, To, #iq{} = IQ) -> - MUCHost = gen_mod:get_module_opt_host(FromS, ?MODULE, ?DEFAULT_HOST), + MUCHost = gen_mod:get_module_opt_subhost(FromS, ?MODULE, default_host()), case {mod_muc_light_codec_backend:decode(From, To, IQ), - get_opt(MUCHost, blocking, ?DEFAULT_BLOCKING)} of + gen_mod:get_module_opt_by_subhost(MUCHost, ?MODULE, blocking, ?DEFAULT_BLOCKING)} of {{ok, {set, #blocking{ items = Items }} = Blocking}, true} -> RouteFun = fun(_, _, Packet) -> put(encode_res, Packet) end, ConditionFun = fun({_, _, {WhoU, WhoS}}) -> WhoU =:= <<>> orelse WhoS =:= <<>> end, @@ -390,13 +371,13 @@ create_room(From, FromUS, To, Create0, OrigPacket) -> case try_to_create_room(FromUS, To, Create0) of {ok, FinalRoomUS, Details} -> mod_muc_light_codec_backend:encode({set, Details, To#jid.luser == <<>>}, From, - FinalRoomUS, fun ejabberd_router:route/3); + FinalRoomUS, fun ejabberd_router:route/3); {error, exists} -> mod_muc_light_codec_backend:encode_error({error, conflict}, From, To, OrigPacket, - fun ejabberd_router:route/3); + fun ejabberd_router:route/3); {error, bad_request} -> mod_muc_light_codec_backend:encode_error({error, bad_request}, From, To, OrigPacket, - fun ejabberd_router:route/3); + fun ejabberd_router:route/3); {error, Error} -> ErrorText = io_lib:format("~s:~p", tuple_to_list(Error)), mod_muc_light_codec_backend:encode_error( @@ -411,7 +392,8 @@ try_to_create_room(CreatorUS, RoomJID, #create{raw_config = RawConfig} = Creatio {_RoomU, RoomS} = RoomUS = jid:to_lus(RoomJID), InitialAffUsers = mod_muc_light_utils:filter_out_prevented( CreatorUS, RoomUS, CreationCfg#create.aff_users), - MaxOccupants = get_opt(RoomJID#jid.lserver, max_occupants, ?DEFAULT_MAX_OCCUPANTS), + MaxOccupants = gen_mod:get_module_opt_by_subhost( + RoomJID#jid.lserver, ?MODULE, max_occupants, ?DEFAULT_MAX_OCCUPANTS), case {mod_muc_light_utils:process_raw_config( RawConfig, default_config(RoomS), config_schema(RoomS)), process_create_aff_users_if_valid(RoomS, CreatorUS, InitialAffUsers)} of @@ -440,7 +422,8 @@ process_create_aff_users_if_valid(MUCServer, Creator, AffUsers) -> ({_, Aff}) -> Aff =:= none end, AffUsers) of false -> process_create_aff_users( - Creator, AffUsers, get_opt(MUCServer, equal_occupants, ?DEFAULT_EQUAL_OCCUPANTS)); + Creator, AffUsers, gen_mod:get_module_opt_by_subhost( + MUCServer, ?MODULE, equal_occupants, ?DEFAULT_EQUAL_OCCUPANTS)); true -> {error, bad_request} end. @@ -464,7 +447,7 @@ handle_disco_info_get(From, To, DiscoInfo) -> fun ejabberd_router:route/3). -spec handle_disco_items_get(From :: jid(), To :: jid(), DiscoItems :: op_disco_items(), - OrigPacket :: jlib:xmlel()) -> ok. + OrigPacket :: jlib:xmlel()) -> ok. handle_disco_items_get(From, To, DiscoItems0, OrigPacket) -> case catch mod_muc_light_db_backend:get_user_rooms(jid:to_lus(From), To#jid.lserver) of {error, Error} -> @@ -473,8 +456,9 @@ handle_disco_items_get(From, To, DiscoItems0, OrigPacket) -> {error, internal_server_error}, From, To, OrigPacket, fun ejabberd_router:route/3); Rooms -> RoomsInfo = get_rooms_info(lists:sort(Rooms)), - RoomsPerPage = get_opt(To#jid.lserver, rooms_per_page, ?DEFAULT_ROOMS_PER_PAGE), RouteFun = fun ejabberd_router:route/3, + RoomsPerPage = gen_mod:get_module_opt_by_subhost( + To#jid.lserver, ?MODULE, rooms_per_page, ?DEFAULT_ROOMS_PER_PAGE), case apply_rsm(RoomsInfo, length(RoomsInfo), page_service_limit(DiscoItems0#disco_items.rsm, RoomsPerPage)) of {ok, RoomsInfoSlice, RSMOut} -> @@ -569,7 +553,7 @@ find_room_pos(_, [], _) -> {error, item_not_found}. handle_blocking(From, To, {get, #blocking{} = Blocking}) -> BlockingItems = mod_muc_light_db_backend:get_blocking(jid:to_lus(From), To#jid.lserver), mod_muc_light_codec_backend:encode({get, Blocking#blocking{ items = BlockingItems }}, - From, jid:to_lus(To), fun ejabberd_router:route/3); + From, jid:to_lus(To), fun ejabberd_router:route/3); handle_blocking(From, To, {set, #blocking{ items = Items }} = BlockingReq) -> case lists:any(fun({_, _, {WhoU, WhoS}}) -> WhoU =:= <<>> orelse WhoS =:= <<>> end, Items) of true -> @@ -604,7 +588,7 @@ bcast_removed_user(UserJID, aff_users = AffUsersChanged }, mod_muc_light_codec_backend:encode({set, Affiliations, OldAffUsers, NewAffUsers}, - UserJID, RoomUS, fun ejabberd_router:route/3), + UserJID, RoomUS, fun ejabberd_router:route/3), bcast_removed_user(UserJID, RAffected, Version, ID); bcast_removed_user(UserJID, [{RoomUS, Error} | RAffected], Version, ID) -> ?ERROR_MSG("user=~p, room=~p, remove_user_error=~p", [UserJID, RoomUS, Error]), diff --git a/apps/ejabberd/src/mod_muc_light_codec_legacy.erl b/apps/ejabberd/src/mod_muc_light_codec_legacy.erl index c776ec26a1d..9f1955da966 100644 --- a/apps/ejabberd/src/mod_muc_light_codec_legacy.erl +++ b/apps/ejabberd/src/mod_muc_light_codec_legacy.erl @@ -273,7 +273,8 @@ encode_meta({set, #affiliations{} = Affs, OldAffUsers, NewAffUsers}, Affs#affiliations.aff_users, HandleFun), {iq_reply, Affs#affiliations.id}; encode_meta({get, #blocking{} = Blocking}, SenderBareJID, _SenderJID, _HandleFun) -> - MUCHost = gen_mod:get_module_opt_host(SenderBareJID#jid.lserver, mod_muc_light, ?DEFAULT_HOST), + MUCHost = gen_mod:get_module_opt_subhost( + SenderBareJID#jid.lserver, mod_muc_light, mod_muc_light:default_host()), BlockingEls = [ blocking_to_el(BlockingItem, MUCHost) || BlockingItem <- Blocking#blocking.items ], Blocklist = #xmlel{ name = <<"list">>, attrs = [{<<"name">>, ?NS_MUC_LIGHT}], diff --git a/apps/ejabberd/src/mod_muc_light_commands.erl b/apps/ejabberd/src/mod_muc_light_commands.erl index deb81299beb..1c2641dfcf3 100644 --- a/apps/ejabberd/src/mod_muc_light_commands.erl +++ b/apps/ejabberd/src/mod_muc_light_commands.erl @@ -108,8 +108,8 @@ commands() -> create_unique_room(Domain, RoomName, Creator, Subject) -> C = jid:to_lus(jid:from_binary(Creator)), - MUCLightDomain = gen_mod:get_module_opt_host(Domain, mod_muc_light, - <<"muclight.@HOST@">>), + MUCLightDomain = gen_mod:get_module_opt_subhost( + Domain, mod_muc_light, mod_muc_light:default_host()), MUCService = jid:make(<<>>, MUCLightDomain, <<>>), Config = make_room_config(RoomName, Subject), case mod_muc_light:try_to_create_room(C, MUCService, Config) of @@ -130,8 +130,8 @@ invite_to_room(Domain, RoomName, Sender, Recipient0) -> change_affiliation(Domain, RoomID, Sender, Recipient0, Affiliation) -> Recipient1 = jid:binary_to_bare(Recipient0), - MUCLightDomain = gen_mod:get_module_opt_host(Domain, mod_muc_light, - <<"muclight.@HOST@">>), + MUCLightDomain = gen_mod:get_module_opt_subhost(Domain, mod_muc_light, + mod_muc_light:default_host()), R = jid:make(RoomID, MUCLightDomain, <<>>), S = jid:binary_to_bare(Sender), Changes = query(?NS_MUC_LIGHT_AFFILIATIONS, diff --git a/apps/ejabberd/src/mod_muc_light_db_odbc.erl b/apps/ejabberd/src/mod_muc_light_db_odbc.erl index 89844883639..87ad90bea47 100644 --- a/apps/ejabberd/src/mod_muc_light_db_odbc.erl +++ b/apps/ejabberd/src/mod_muc_light_db_odbc.erl @@ -498,5 +498,6 @@ update_room_version_transaction({RoomU, RoomS}, Version) -> main_host({_, RoomS}) -> main_host(RoomS); main_host(MUCServer) -> - mod_muc_light:get_opt(MUCServer, main_host, <<>>). + {ok, MainHost} = mongoose_subhosts:get_host(MUCServer), + MainHost. diff --git a/apps/ejabberd/src/mod_muc_light_room.erl b/apps/ejabberd/src/mod_muc_light_room.erl index 8ecae0350af..e18a4b19294 100644 --- a/apps/ejabberd/src/mod_muc_light_room.erl +++ b/apps/ejabberd/src/mod_muc_light_room.erl @@ -63,7 +63,8 @@ maybe_forget(_, _) -> NewAffUsers :: aff_users()) -> ok | {error, occupant_limit_exceeded}. participant_limit_check({_, MUCServer} = _RoomUS, NewAffUsers) -> - MaxOccupants = mod_muc_light:get_opt(MUCServer, max_occupants, ?DEFAULT_MAX_OCCUPANTS), + MaxOccupants = gen_mod:get_module_opt_by_subhost( + MUCServer, mod_muc_light, max_occupants, ?DEFAULT_MAX_OCCUPANTS), case length(NewAffUsers) > MaxOccupants of true -> {error, occupant_limit_exceeded}; false -> ok @@ -113,8 +114,8 @@ process_request({get, #info{} = InfoReq}, _From, _UserUS, {_, RoomS} = RoomUS, _ raw_config = RawConfig }}; process_request({set, #config{} = ConfigReq}, _From, _UserUS, {_, MUCServer} = RoomUS, {_, UserAff}, AffUsers) -> - AllCanConfigure = mod_muc_light:get_opt( - MUCServer, all_can_configure, ?DEFAULT_ALL_CAN_CONFIGURE), + AllCanConfigure = gen_mod:get_module_opt_by_subhost( + MUCServer, mod_muc_light, all_can_configure, ?DEFAULT_ALL_CAN_CONFIGURE), process_config_set(ConfigReq, RoomUS, UserAff, AffUsers, AllCanConfigure); process_request({set, #affiliations{} = AffReq}, _From, UserUS, {_, MUCServer} = RoomUS, {_, UserAff}, AffUsers) -> @@ -128,8 +129,8 @@ process_request({set, #affiliations{} = AffReq}, _From, UserUS, {_, MUCServer} = {ok, mod_muc_light_utils:filter_out_prevented( UserUS, RoomUS, AffReq#affiliations.aff_users)}; member -> - AllCanInvite = mod_muc_light:get_opt( - MUCServer, all_can_invite, ?DEFAULT_ALL_CAN_INVITE), + AllCanInvite = gen_mod:get_module_opt_by_subhost( + MUCServer, mod_muc_light, all_can_invite, ?DEFAULT_ALL_CAN_INVITE), validate_aff_changes_by_member( AffReq#affiliations.aff_users, [], UserUS, OwnerUS, RoomUS, AllCanInvite) end, diff --git a/apps/ejabberd/src/mod_muc_light_utils.erl b/apps/ejabberd/src/mod_muc_light_utils.erl index 1fcde324c4f..478d662ee66 100644 --- a/apps/ejabberd/src/mod_muc_light_utils.erl +++ b/apps/ejabberd/src/mod_muc_light_utils.erl @@ -140,22 +140,21 @@ bin_ts() -> boolean(). room_limit_reached(UserUS, RoomS) -> room_limit_reached( - UserUS, RoomS, mod_muc_light:get_opt(RoomS, rooms_per_user, ?DEFAULT_ROOMS_PER_USER)). + UserUS, RoomS, gen_mod:get_module_opt_by_subhost( + RoomS, mod_muc_light, rooms_per_user, ?DEFAULT_ROOMS_PER_USER)). -spec filter_out_prevented(FromUS :: ejabberd:simple_bare_jid(), RoomUS :: ejabberd:simple_bare_jid(), AffUsers :: aff_users()) -> aff_users(). filter_out_prevented(FromUS, {RoomU, MUCServer} = RoomUS, AffUsers) -> - RoomsPerUser = mod_muc_light:get_opt(MUCServer, rooms_per_user, ?DEFAULT_ROOMS_PER_USER), - BlockingQuery = case mod_muc_light:get_opt(MUCServer, blocking, ?DEFAULT_BLOCKING) of - true -> - [{user, FromUS} - | if - RoomU == <<>> -> []; - true -> [{room, RoomUS}] - end]; - false -> - undefined + RoomsPerUser = gen_mod:get_module_opt_by_subhost( + MUCServer, mod_muc_light, rooms_per_user, ?DEFAULT_ROOMS_PER_USER), + BlockingEnabled = gen_mod:get_module_opt_by_subhost(MUCServer, mod_muc_light, + blocking, ?DEFAULT_BLOCKING), + BlockingQuery = case {BlockingEnabled, RoomU} of + {true, <<>>} -> [{user, FromUS}]; + {true, _} -> [{user, FromUS}, {room, RoomUS}]; + {false, _} -> undefined end, case BlockingQuery == undefined andalso RoomsPerUser == infinity of true -> AffUsers; diff --git a/apps/ejabberd/src/mod_pubsub.erl b/apps/ejabberd/src/mod_pubsub.erl index 5e2d1a972ee..752e9d4c541 100644 --- a/apps/ejabberd/src/mod_pubsub.erl +++ b/apps/ejabberd/src/mod_pubsub.erl @@ -91,6 +91,7 @@ -export([start_link/2, start/2, stop/1, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). +-export([default_host/0]). -export([send_loop/1]). @@ -235,6 +236,10 @@ stop(Host) -> ok = supervisor:terminate_child(ejabberd_sup, Proc), ok = supervisor:delete_child(ejabberd_sup, Proc). +-spec default_host() -> binary(). +default_host() -> + <<"pubsub.@HOST@">>. + %%==================================================================== %% gen_server callbacks %%==================================================================== @@ -252,7 +257,7 @@ stop(Host) -> init([ServerHost, Opts]) -> ?DEBUG("pubsub init ~p ~p", [ServerHost, Opts]), - Host = gen_mod:get_opt_host(ServerHost, Opts, <<"pubsub.@HOST@">>), + Host = gen_mod:get_opt_subhost(ServerHost, Opts, default_host()), Access = gen_mod:get_opt(access_createnode, Opts, fun(A) when is_atom(A) -> A end, all), PepOffline = gen_mod:get_opt(ignore_pep_from_offline, Opts, diff --git a/apps/ejabberd/src/mod_vcard.erl b/apps/ejabberd/src/mod_vcard.erl index 092e2370fc3..372c95c836e 100644 --- a/apps/ejabberd/src/mod_vcard.erl +++ b/apps/ejabberd/src/mod_vcard.erl @@ -64,6 +64,7 @@ -export([default_search_fields/0]). -export([get_results_limit/1]). -export([get_default_reported_fields/1]). +-export([default_host/0]). -export([config_change/4]). @@ -143,6 +144,10 @@ get_results_limit(LServer) -> ?JUD_MATCHES end. +-spec default_host() -> binary(). +default_host() -> + <<"vjud.@HOST@">>. + %%-------------------------------------------------------------------- %% gen_mod callbacks %%-------------------------------------------------------------------- @@ -172,10 +177,10 @@ init([VHost, Opts]) -> || {Hook, M, F, Prio} <- hook_handlers() ], IQDisc = gen_mod:get_opt(iqdisc, Opts, one_queue), gen_iq_handler:add_iq_handler(ejabberd_sm, VHost, ?NS_VCARD, - ?MODULE,process_sm_iq, IQDisc), + ?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_host(VHost, Opts, "vjud.@HOST@"), + ?MODULE, process_local_iq, IQDisc), + DirectoryHost = gen_mod:get_opt_subhost(VHost, Opts, default_host()), Search = gen_mod:get_opt(search, Opts, true), case Search of true -> diff --git a/apps/ejabberd/src/mod_vcard_ldap.erl b/apps/ejabberd/src/mod_vcard_ldap.erl index 7f036c3e464..ab714c48b49 100644 --- a/apps/ejabberd/src/mod_vcard_ldap.erl +++ b/apps/ejabberd/src/mod_vcard_ldap.erl @@ -457,12 +457,11 @@ map_vcard_attr(VCardName, Attributes, Pattern, UD) -> process_pattern(Str, {User, Domain}, AttrValues) -> eldap_filter:do_sub(Str, - [{<<"%u">>, User}, {<<"%d">>, Domain}] ++ - [{<<"%s">>, V, 1} || V <- AttrValues]). + [{<<"%u">>, User}, {<<"%d">>, Domain}] ++ + [{<<"%s">>, V, 1} || V <- AttrValues]). parse_options(Host, Opts) -> - MyHost = gen_mod:get_opt_host(Host, Opts, - <<"vjud.@HOST@">>), + MyHost = gen_mod:get_opt_subhost(Host, Opts, mod_vcard:default_host()), Matches = eldap_utils:get_mod_opt(matches, Opts, fun(infinity) -> 0; (I) when is_integer(I), I>0 -> I diff --git a/apps/ejabberd/src/mongoose_client_api_rooms.erl b/apps/ejabberd/src/mongoose_client_api_rooms.erl index 73058988e2d..c0c96ba06f3 100644 --- a/apps/ejabberd/src/mongoose_client_api_rooms.erl +++ b/apps/ejabberd/src/mongoose_client_api_rooms.erl @@ -127,7 +127,7 @@ user_to_json({UserServer, Role}) -> role => Role}. muc_light_domain(Server) -> - gen_mod:get_module_opt_host(Server, mod_muc_light, <<"muclight.@HOST@">>). + gen_mod:get_module_opt_subhost(Server, mod_muc_light, mod_muc_light:default_host()). determine_role(US, Users) -> case lists:keyfind(US, 1, Users) of diff --git a/apps/ejabberd/src/mongoose_subhosts.erl b/apps/ejabberd/src/mongoose_subhosts.erl new file mode 100644 index 00000000000..e3102671491 --- /dev/null +++ b/apps/ejabberd/src/mongoose_subhosts.erl @@ -0,0 +1,65 @@ +%%%---------------------------------------------------------------------- +%%% File : mongoose_subhosts.erl +%%% Author : Piotr Nosek +%%% Purpose : SubHost->Host register +%%% Created : 9 Dec 2016 +%%%---------------------------------------------------------------------- + +-module(mongoose_subhosts). + +-include("ejabberd.hrl"). + +-export([ + init/0, + stop/0, + + 'register'/2, + 'unregister'/1, + get_host/1 + ]). + +-record(subhost_mapping, { + subhost :: ejabberd:server(), + host :: ejabberd:server() + }). + +-define(TAB, subhost_mappings). + +%%--------------------------------------------------------------- +%% Init & teardown +%%--------------------------------------------------------------- + +-spec init() -> ok. +init() -> + ets:new( + ?TAB, [named_table, public, {read_concurrency, true}, {keypos, #subhost_mapping.subhost}]), + ok. + +-spec stop() -> ok. +stop() -> + ets:delete(?TAB), + ok. + +%%--------------------------------------------------------------- +%% API +%%--------------------------------------------------------------- + +-spec 'register'(Host :: ejabberd:server(), SubHost :: ejabberd:server()) -> + ok | {error, exists}. +register(Host, SubHost) -> + case ets:insert_new(?TAB, #subhost_mapping{ subhost = SubHost, host = Host }) of + true -> ok; + false -> {error, exists} + end. + +-spec 'unregister'(SubHost :: ejabberd:server()) -> true. +unregister(SubHost) -> + ets:delete(?TAB, SubHost). + +-spec get_host(SubHost :: ejabberd:server()) -> {ok, ejabberd:server()} | undefined. +get_host(SubHost) -> + case ets:lookup(?TAB, SubHost) of + [#subhost_mapping{ host = Host }] -> {ok, Host}; + [] -> undefined + end. + diff --git a/apps/ejabberd/test/muc_light_SUITE.erl b/apps/ejabberd/test/muc_light_SUITE.erl index 9fc1962bb3f..1b33fb0c551 100644 --- a/apps/ejabberd/test/muc_light_SUITE.erl +++ b/apps/ejabberd/test/muc_light_SUITE.erl @@ -33,6 +33,13 @@ groups() -> {codec, [sequence], [codec_calls]} ]. +init_per_suite(Config) -> + Config. + +end_per_suite(Config) -> + exit(whereis(ejabberd_sup), kill), + Config. + init_per_group(rsm_disco, Config) -> application:start(stringprep), Config; @@ -51,6 +58,8 @@ init_per_testcase(codec_calls, Config) -> ejabberd_hooks:start_link(), ejabberd_router:start_link(), mim_ct_sup:start_link(ejabberd_sup), + mongoose_subhosts:init(), + gen_mod:start(), mod_muc_light:start(?DOMAIN, []), ets:new(testcalls, [named_table]), ets:insert(testcalls, {hooks, 0}), @@ -62,7 +71,7 @@ init_per_testcase(_, Config) -> end_per_testcase(codec_calls, Config) -> mod_muc_light:stop(?DOMAIN), mnesia:stop(), - exit(whereis(ejabberd_sup), kill), + mongoose_subhosts:stop(), Config; end_per_testcase(_, Config) -> Config. diff --git a/rel/reltool_vars/node1_vars.config b/rel/reltool_vars/node1_vars.config index 46bd5e4cd04..9affb648ed1 100644 --- a/rel/reltool_vars/node1_vars.config +++ b/rel/reltool_vars/node1_vars.config @@ -37,7 +37,7 @@ {mod_roster, "{mod_roster, []},"}. {mod_vcard, "{mod_vcard, [ %{matches, 1},\n" "%{search, true},\n" - "%{host, directory.@HOST@}\n" + "{host, \"vjud.@HOST@\"}\n" "]},"}. {cowboy_port, 5280}. {cowboy_port_secure, 5285}. diff --git a/rel/reltool_vars/node2_vars.config b/rel/reltool_vars/node2_vars.config index 20489c94bab..20f39fcfd90 100644 --- a/rel/reltool_vars/node2_vars.config +++ b/rel/reltool_vars/node2_vars.config @@ -19,7 +19,7 @@ {mod_roster, "{mod_roster, []},"}. {mod_vcard, "{mod_vcard, [ %{matches, 1},\n" "%{search, true},\n" - "%{host, directory.@HOST@}\n" + "{host, \"vjud.@HOST@\"}\n" "]},"}. {http_api_old_endpoint, "{5289, \"127.0.0.1\"}"}. {http_api_endpoint, "{8090, \"127.0.0.1\"}"}. diff --git a/rel/reltool_vars/node3_vars.config b/rel/reltool_vars/node3_vars.config index bd0dce74305..f7bd215722f 100644 --- a/rel/reltool_vars/node3_vars.config +++ b/rel/reltool_vars/node3_vars.config @@ -21,7 +21,7 @@ {http_api_endpoint, "{5296, \"127.0.0.1\"}"}. {mod_vcard, "{mod_vcard, [ %{matches, 1},\n" "%{search, true},\n" - "%{host, directory.@HOST@}\n" + "{host, \"vjud.@HOST@\"}\n" "]},"}. {s2s_use_starttls, "{s2s_use_starttls, optional}."}. {s2s_certfile, "{s2s_certfile, \"priv/ssl/fake_server.pem\"}."}. diff --git a/rel/vars.config.in b/rel/vars.config.in index d182421a895..c476d5bf7db 100644 --- a/rel/vars.config.in +++ b/rel/vars.config.in @@ -29,7 +29,7 @@ "%{ldap_search_operator, 'or'}, %% either 'or' or 'and'\n" "%{ldap_binary_search_fields, [<<\"PHOTO\">>]},\n" "%% list of binary search fields (as in vcard after mapping)\n" - "%{host, directory.@HOST@}\n" + "{host, \"vjud.@HOST@\"}\n" "]},"}. {sm_backend, "{mnesia, []}"}. diff --git a/test/ejabberd_tests/test.config b/test/ejabberd_tests/test.config index 323a89c675e..3af130f4dd0 100644 --- a/test/ejabberd_tests/test.config +++ b/test/ejabberd_tests/test.config @@ -179,7 +179,7 @@ {mod_privacy, "{mod_privacy, [{backend, odbc}]},"}, {mod_private, "{mod_private, [{backend, odbc}]},"}, {mod_offline, "{mod_offline, [{backend, odbc}]},"}, - {mod_vcard, "{mod_vcard, [{backend, odbc}]},"}, + {mod_vcard, "{mod_vcard, [{backend, odbc}, {host, \"vjud.@HOST@\"}]},"}, {mod_roster, "{mod_roster, [{backend, odbc}]},"}]}, {odbc_pgsql_mnesia, [{sm_backend, "{mnesia, []}"}, @@ -190,7 +190,7 @@ {mod_privacy, "{mod_privacy, [{backend, odbc}]},"}, {mod_private, "{mod_private, [{backend, odbc}]},"}, {mod_offline, "{mod_offline, [{backend, odbc}]},"}, - {mod_vcard, "{mod_vcard, [{backend, odbc}]},"}, + {mod_vcard, "{mod_vcard, [{backend, odbc}, {host, \"vjud.@HOST@\"}]},"}, {mod_roster, "{mod_roster, [{backend, odbc}]},"}]}, {mysql_mnesia, [{sm_backend, "{mnesia, []}"}, @@ -200,7 +200,7 @@ {mod_privacy, "{mod_privacy, [{backend, odbc}]},"}, {mod_private, "{mod_private, [{backend, mysql}]},"}, {mod_offline, "{mod_offline, [{backend, odbc}]},"}, - {mod_vcard, "{mod_vcard, [{backend, odbc}]},"}, + {mod_vcard, "{mod_vcard, [{backend, odbc}, {host, \"vjud.@HOST@\"}]},"}, {mod_roster, "{mod_roster, [{backend, odbc}]},"}]}, {mysql_redis, [{sm_backend, "{redis, [{pool_size, 3}, {worker_config, [{host, \"localhost\"}, {port, 6379}]}]}"}, @@ -210,7 +210,7 @@ {mod_privacy, "{mod_privacy, [{backend, odbc}]},"}, {mod_private, "{mod_private, [{backend, mysql}]},"}, {mod_offline, "{mod_offline, [{backend, odbc}]},"}, - {mod_vcard, "{mod_vcard, [{backend, odbc}]},"}, + {mod_vcard, "{mod_vcard, [{backend, odbc}, {host, \"vjud.@HOST@\"}]},"}, {mod_roster, "{mod_roster, [{backend, odbc}]},"}]}, {external_mnesia, [{sm_backend, "{mnesia, []}"}, @@ -225,7 +225,7 @@ "{ldap_base, \"ou=Users,dc=esl,dc=com\"}.\n" "{ldap_filter, \"(objectClass=inetOrgPerson)\"}.\n" }, - {mod_vcard,"{mod_vcard, [{backend, ldap},\n" + {mod_vcard,"{mod_vcard, [{backend, ldap}, {host, \"vjud.@HOST@\"},\n" "{ldap_filter,\"(objectClass=inetOrgPerson)\"},\n" "{ldap_base, \"ou=Users,dc=esl,dc=com\"}\n" "]},"} @@ -237,7 +237,7 @@ {riak_server, "{riak_server, [{pool_size, 5}, {address, \"127.0.0.1\"},{port, 8087}]}."}, {mod_roster, "{mod_roster, [{backend, riak}]},"}, {mod_private, "{mod_private, [{backend, riak}]},"}, - {mod_vcard, "{mod_vcard, [{backend, riak}]},"}, + {mod_vcard, "{mod_vcard, [{backend, riak}, {host, \"vjud.@HOST@\"}]},"}, {mod_offline, "{mod_offline, [{backend, riak}]},"}, {mod_last, "{mod_last, [{backend, riak}]},"}, {mod_privacy, "{mod_privacy, [{backend, riak}]},"} diff --git a/test/ejabberd_tests/tests/mam_SUITE.erl b/test/ejabberd_tests/tests/mam_SUITE.erl index c44863b8e53..fff1cc521d8 100644 --- a/test/ejabberd_tests/tests/mam_SUITE.erl +++ b/test/ejabberd_tests/tests/mam_SUITE.erl @@ -513,7 +513,7 @@ init_modules(C, muc_light, Config) -> dynamic_modules:start(host(), mod_muc_light, [{host, binary_to_list(muc_light_host())}]), Config1 = init_modules(C, muc_all, Config), %% Init more modules! stop_module(host(), mod_mam_muc), - init_module(host(), mod_mam_muc, [{host, binary_to_list(muc_light_host())}]), + init_module(host(), mod_mam_muc, [{host, "muclight.@HOST@"}]), Config1; init_modules(ca, muc_all, Config) -> @@ -645,8 +645,9 @@ init_modules(odbc_mnesia_cache, _, Config) -> Config. end_modules(C, muc_light, Config) -> + end_modules(C, generic, Config), dynamic_modules:stop(host(), mod_muc_light), - end_modules(C, generic, Config); + Config; end_modules(_, _, Config) -> [stop_module(host(), M) || M <- mam_modules()], Config. diff --git a/test/ejabberd_tests/tests/muc_SUITE.erl b/test/ejabberd_tests/tests/muc_SUITE.erl index 284729c5efb..0de888db0fe 100644 --- a/test/ejabberd_tests/tests/muc_SUITE.erl +++ b/test/ejabberd_tests/tests/muc_SUITE.erl @@ -260,8 +260,8 @@ init_per_suite(Config) -> escalus:init_per_suite(Config). end_per_suite(Config) -> - escalus_fresh:clean(), unload_muc(), + escalus_fresh:clean(), escalus:end_per_suite(Config). init_per_group(moderator, Config) -> diff --git a/test/ejabberd_tests/tests/muc_light_SUITE.erl b/test/ejabberd_tests/tests/muc_light_SUITE.erl index 73df0e4963e..e11fd0c1a54 100644 --- a/test/ejabberd_tests/tests/muc_light_SUITE.erl +++ b/test/ejabberd_tests/tests/muc_light_SUITE.erl @@ -1186,7 +1186,7 @@ set_custom_config(RawSchema, RawDefaultConfig) -> -spec set_mod_config(K :: atom(), V :: any()) -> ok. set_mod_config(K, V) -> - true = rpc(mod_muc_light, set_opt, [?MUCHOST, K, V]). + true = rpc(gen_mod, set_module_opt_by_subhost, [?MUCHOST, mod_muc_light, K, V]). -spec ns_muc_light_affiliations() -> binary(). ns_muc_light_affiliations() -> diff --git a/test/ejabberd_tests/tests/muc_light_legacy_SUITE.erl b/test/ejabberd_tests/tests/muc_light_legacy_SUITE.erl index 324f168af40..36bb4f7b5dd 100644 --- a/test/ejabberd_tests/tests/muc_light_legacy_SUITE.erl +++ b/test/ejabberd_tests/tests/muc_light_legacy_SUITE.erl @@ -853,5 +853,5 @@ set_default_mod_config() -> -spec set_mod_config(K :: atom(), V :: any()) -> ok. set_mod_config(K, V) -> - true = rpc(mod_muc_light, set_opt, [?MUCHOST, K, V]). + true = rpc(gen_mod, set_module_opt_by_subhost, [?MUCHOST, mod_muc_light, K, V]). diff --git a/test/ejabberd_tests/tests/pep_SUITE.erl b/test/ejabberd_tests/tests/pep_SUITE.erl index ce94df98555..204c7bc0b30 100644 --- a/test/ejabberd_tests/tests/pep_SUITE.erl +++ b/test/ejabberd_tests/tests/pep_SUITE.erl @@ -135,9 +135,10 @@ send_caps_after_login_test(Config) -> required_modules() -> [{mod_caps, []}, {mod_pubsub, [ - {plugins,[<<"dag">>,<<"pep">>]}, - {nodetree,<<"dag">>}, - {pep_mapping,[]} + {plugins, [<<"dag">>, <<"pep">>]}, + {nodetree, <<"dag">>}, + {pep_mapping, []}, + {host, "pubsub.@HOST@"} ]}]. send_initial_presence_with_caps(User) -> diff --git a/test/ejabberd_tests/tests/pubsub_SUITE.erl b/test/ejabberd_tests/tests/pubsub_SUITE.erl index a78fc67986d..38faf4f17d6 100644 --- a/test/ejabberd_tests/tests/pubsub_SUITE.erl +++ b/test/ejabberd_tests/tests/pubsub_SUITE.erl @@ -931,6 +931,7 @@ disable_delivery_test(Config) -> required_modules() -> [{mod_pubsub, [ - {plugins,[<<"dag">>]}, - {nodetree,<<"dag">>} + {plugins, [<<"dag">>]}, + {nodetree, <<"dag">>}, + {host, "pubsub.@HOST@"} ]}]. diff --git a/test/ejabberd_tests/tests/rest_SUITE.erl b/test/ejabberd_tests/tests/rest_SUITE.erl index 713d19d70fd..46bdae504f5 100644 --- a/test/ejabberd_tests/tests/rest_SUITE.erl +++ b/test/ejabberd_tests/tests/rest_SUITE.erl @@ -88,7 +88,7 @@ init_per_suite(Config) -> end_per_suite(Config) -> escalus_fresh:clean(), - rest_helper:maybe_disable_mam(proplists:get_value(mam_enabled, Config), host()), + rest_helper:maybe_disable_mam(mam_helper:backend(), host()), escalus:end_per_suite(Config). init_per_group(_GroupName, Config) -> diff --git a/test/ejabberd_tests/tests/rest_client_SUITE.erl b/test/ejabberd_tests/tests/rest_client_SUITE.erl index 50f2e800f7a..393a95c5ffd 100644 --- a/test/ejabberd_tests/tests/rest_client_SUITE.erl +++ b/test/ejabberd_tests/tests/rest_client_SUITE.erl @@ -37,7 +37,7 @@ init_per_suite(C) -> end_per_suite(Config) -> escalus_fresh:clean(), Host = ct:get_config({hosts, mim, domain}), - rest_helper:maybe_disable_mam(proplists:get_value(mam_enabled, Config), Host), + rest_helper:maybe_disable_mam(mam_helper:backend(), Host), dynamic_modules:stop(Host, mod_muc_light), escalus:end_per_suite(Config). diff --git a/test/ejabberd_tests/tests/vcard_simple_SUITE.erl b/test/ejabberd_tests/tests/vcard_simple_SUITE.erl index 5e8927bff2a..4b19f164629 100644 --- a/test/ejabberd_tests/tests/vcard_simple_SUITE.erl +++ b/test/ejabberd_tests/tests/vcard_simple_SUITE.erl @@ -454,7 +454,7 @@ configure_ldap_vcards(Config) -> CurrentConfigs = escalus_ejabberd:rpc(gen_mod, loaded_modules_with_opts, [Domain]), {mod_vcard, CurrentVcardConfig} = lists:keyfind(mod_vcard, 1, CurrentConfigs), dynamic_modules:stop(Domain, mod_vcard), - Cfg = [{backend,ldap}, + Cfg = [{backend,ldap}, {host, "vjud.@HOST@"}, {ldap_filter,"(objectClass=inetOrgPerson)"}, {ldap_base,"ou=Users,dc=esl,dc=com"}, {ldap_search_fields, [{"Full Name","cn"},{"User","uid"}]},