diff --git a/src/ejabberd_local.erl b/src/ejabberd_local.erl index 292288a37..7c30f3b6c 100644 --- a/src/ejabberd_local.erl +++ b/src/ejabberd_local.erl @@ -178,6 +178,7 @@ bounce_resource_packet(From, To, Packet) -> init([]) -> lists:foreach(fun (Host) -> ejabberd_router:register_route(Host, + Host, {apply, ?MODULE, route}), ejabberd_hooks:add(local_send_to_resource_hook, Host, diff --git a/src/ejabberd_router.erl b/src/ejabberd_router.erl index da1bd3e0f..e29d6acfb 100644 --- a/src/ejabberd_router.erl +++ b/src/ejabberd_router.erl @@ -36,7 +36,9 @@ route_error/4, register_route/1, register_route/2, + register_route/3, register_routes/1, + host_of_route/1, unregister_route/1, unregister_routes/1, dirty_get_all_routes/0, @@ -55,7 +57,7 @@ -type local_hint() :: undefined | integer() | {apply, atom(), atom()}. --record(route, {domain, pid, local_hint}). +-record(route, {domain, server_host, pid, local_hint}). -record(state, {}). @@ -94,19 +96,29 @@ route_error(From, To, ErrPacket, OrigPacket) -> -spec register_route(binary()) -> term(). register_route(Domain) -> - register_route(Domain, undefined). + ?WARNING_MSG("~s:register_route/1 is deprected, " + "use ~s:register_route/2 instead", + [?MODULE, ?MODULE]), + register_route(Domain, ?MYNAME). --spec register_route(binary(), local_hint()) -> term(). +-spec register_route(binary(), binary()) -> term(). -register_route(Domain, LocalHint) -> - case jid:nameprep(Domain) of - error -> erlang:error({invalid_domain, Domain}); - LDomain -> +register_route(Domain, ServerHost) -> + register_route(Domain, ServerHost, undefined). + +-spec register_route(binary(), binary(), local_hint()) -> term(). + +register_route(Domain, ServerHost, LocalHint) -> + case {jid:nameprep(Domain), jid:nameprep(ServerHost)} of + {error, _} -> erlang:error({invalid_domain, Domain}); + {_, error} -> erlang:error({invalid_domain, ServerHost}); + {LDomain, LServerHost} -> Pid = self(), case get_component_number(LDomain) of undefined -> F = fun () -> mnesia:write(#route{domain = LDomain, pid = Pid, + server_host = LServerHost, local_hint = LocalHint}) end, mnesia:transaction(F); @@ -115,46 +127,42 @@ register_route(Domain, LocalHint) -> case mnesia:wread({route, LDomain}) of [] -> mnesia:write(#route{domain = LDomain, + server_host = LServerHost, pid = Pid, local_hint = 1}), - lists:foreach(fun (I) -> - mnesia:write(#route{domain - = - LDomain, - pid - = - undefined, - local_hint - = - I}) - end, - lists:seq(2, N)); + lists:foreach( + fun (I) -> + mnesia:write( + #route{domain = LDomain, + pid = undefined, + server_host = LServerHost, + local_hint = I}) + end, + lists:seq(2, N)); Rs -> - lists:any(fun (#route{pid = undefined, - local_hint = I} = - R) -> - mnesia:write(#route{domain = - LDomain, - pid = - Pid, - local_hint - = - I}), - mnesia:delete_object(R), - true; - (_) -> false - end, - Rs) + lists:any( + fun (#route{pid = undefined, + local_hint = I} = R) -> + mnesia:write( + #route{domain = LDomain, + pid = Pid, + server_host = LServerHost, + local_hint = I}), + mnesia:delete_object(R), + true; + (_) -> false + end, + Rs) end end, mnesia:transaction(F) end end. --spec register_routes([binary()]) -> ok. +-spec register_routes([{binary(), binary()}]) -> ok. register_routes(Domains) -> - lists:foreach(fun (Domain) -> register_route(Domain) + lists:foreach(fun ({Domain, ServerHost}) -> register_route(Domain, ServerHost) end, Domains). @@ -183,7 +191,9 @@ unregister_route(Domain) -> of [R] -> I = R#route.local_hint, + ServerHost = R#route.server_host, mnesia:write(#route{domain = LDomain, + server_host = ServerHost, pid = undefined, local_hint = I}), mnesia:delete_object(R); @@ -211,6 +221,20 @@ dirty_get_all_routes() -> dirty_get_all_domains() -> lists:usort(mnesia:dirty_all_keys(route)). +-spec host_of_route(binary()) -> binary(). + +host_of_route(Domain) -> + case jid:nameprep(Domain) of + error -> + erlang:error({invalid_domain, Domain}); + LDomain -> + case mnesia:dirty_read(route, LDomain) of + [#route{server_host = ServerHost}|_] -> + ServerHost; + [] -> + erlang:error({unregistered_route, Domain}) + end + end. %%==================================================================== %% gen_server callbacks @@ -283,8 +307,11 @@ handle_info({'DOWN', _Ref, _Type, Pid, _Info}, State) -> if is_integer(E#route.local_hint) -> LDomain = E#route.domain, I = E#route.local_hint, + ServerHost = E#route.server_host, mnesia:write(#route{domain = LDomain, + server_host = + ServerHost, pid = undefined, local_hint = @@ -394,12 +421,10 @@ get_component_number(LDomain) -> undefined). update_tables() -> - case catch mnesia:table_info(route, attributes) of - [domain, node, pid] -> mnesia:delete_table(route); - [domain, pid] -> mnesia:delete_table(route); - [domain, pid, local_hint] -> ok; - [domain, pid, local_hint|_] -> mnesia:delete_table(route); - {'EXIT', _} -> ok + try + mnesia:transform_table(route, ignore, record_info(fields, route)) + catch exit:{aborted, {no_exists, _}} -> + ok end, case lists:member(local_route, mnesia:system_info(tables)) diff --git a/src/ejabberd_service.erl b/src/ejabberd_service.erl index e5508a190..5caae6102 100644 --- a/src/ejabberd_service.erl +++ b/src/ejabberd_service.erl @@ -222,7 +222,7 @@ wait_for_handshake({xmlstreamelement, El}, StateData) -> send_text(StateData, <<"">>), lists:foreach( fun (H) -> - ejabberd_router:register_route(H), + ejabberd_router:register_route(H, ?MYNAME), ?INFO_MSG("Route registered for service ~p~n", [H]) end, dict:fetch_keys(StateData#state.host_opts)), diff --git a/src/mod_echo.erl b/src/mod_echo.erl index 8e7394cb4..7184ee4e7 100644 --- a/src/mod_echo.erl +++ b/src/mod_echo.erl @@ -86,7 +86,7 @@ stop(Host) -> init([Host, Opts]) -> MyHost = gen_mod:get_opt_host(Host, Opts, <<"echo.@HOST@">>), - ejabberd_router:register_route(MyHost), + ejabberd_router:register_route(MyHost, Host), {ok, #state{host = MyHost}}. %%-------------------------------------------------------------------- diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl index 5635102b2..6c029c437 100644 --- a/src/mod_http_upload.erl +++ b/src/mod_http_upload.erl @@ -306,7 +306,7 @@ init({ServerHost, Opts}) -> false -> ok end, - ejabberd_router:register_route(Host), + ejabberd_router:register_route(Host, ServerHost), {ok, #state{server_host = ServerHost, host = Host, name = Name, access = Access, max_size = MaxSize, secret_length = SecretLength, jid_in_url = JIDinURL, diff --git a/src/mod_irc.erl b/src/mod_irc.erl index b7300e28b..d5cd01353 100644 --- a/src/mod_irc.erl +++ b/src/mod_irc.erl @@ -133,7 +133,7 @@ init([Host, Opts]) -> catch ets:new(irc_connection, [named_table, public, {keypos, #irc_connection.jid_server_host}]), - ejabberd_router:register_route(MyHost), + ejabberd_router:register_route(MyHost, Host), {ok, #state{host = MyHost, server_host = Host, access = Access}}. diff --git a/src/mod_mix.erl b/src/mod_mix.erl index 8224ec78a..d8cf94ac3 100644 --- a/src/mod_mix.erl +++ b/src/mod_mix.erl @@ -168,7 +168,7 @@ init([ServerHost, Opts]) -> ?NS_PUBSUB, mod_pubsub, iq_sm, IQDisc), gen_iq_handler:add_iq_handler(ejabberd_sm, Host, ?NS_MIX_0, ?MODULE, process_iq, IQDisc), - ejabberd_router:register_route(Host), + ejabberd_router:register_route(Host, ServerHost), {ok, #state{server_host = ServerHost, host = Host}}. handle_call(_Request, _From, State) -> diff --git a/src/mod_muc.erl b/src/mod_muc.erl index de795fc0e..0d37a236e 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -373,7 +373,7 @@ init([Host, Opts]) -> RoomShaper = gen_mod:get_opt(room_shaper, Opts, fun(A) when is_atom(A) -> A end, none), - ejabberd_router:register_route(MyHost), + ejabberd_router:register_route(MyHost, Host), load_permanent_rooms(MyHost, Host, {Access, AccessCreate, AccessAdmin, AccessPersistent}, HistorySize, RoomShaper), diff --git a/src/mod_multicast.erl b/src/mod_multicast.erl index 5c662a868..0c6130482 100644 --- a/src/mod_multicast.erl +++ b/src/mod_multicast.erl @@ -151,7 +151,7 @@ init([LServerS, Opts]) -> try_start_loop(), create_pool(), ejabberd_router_multicast:register_route(LServerS), - ejabberd_router:register_route(LServiceS), + ejabberd_router:register_route(LServiceS, LServerS), {ok, #state{lservice = LServiceS, lserver = LServerS, access = Access, service_limits = SLimits}}. diff --git a/src/mod_proxy65_service.erl b/src/mod_proxy65_service.erl index 3fb86360a..8b4644ba8 100644 --- a/src/mod_proxy65_service.erl +++ b/src/mod_proxy65_service.erl @@ -63,7 +63,7 @@ start_link(Host, Opts) -> init([Host, Opts]) -> State = parse_options(Host, Opts), - ejabberd_router:register_route(State#state.myhost), + ejabberd_router:register_route(State#state.myhost, Host), {ok, State}. terminate(_Reason, #state{myhost = MyHost}) -> diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl index 8017e3e5d..5fa8a989b 100644 --- a/src/mod_pubsub.erl +++ b/src/mod_pubsub.erl @@ -241,6 +241,7 @@ stop(Host) -> init([ServerHost, Opts]) -> ?DEBUG("pubsub init ~p ~p", [ServerHost, Opts]), Host = gen_mod:get_opt_host(ServerHost, Opts, <<"pubsub.@HOST@">>), + ejabberd_router:register_route(Host, ServerHost), 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, @@ -309,7 +310,6 @@ init([ServerHost, Opts]) -> false -> ok end, - ejabberd_router:register_route(Host), pubsub_migrate:update_node_database(Host, ServerHost), pubsub_migrate:update_state_database(Host, ServerHost), pubsub_migrate:update_lastitem_database(Host, ServerHost), diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index 3652fb2af..256dc5de7 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -105,7 +105,7 @@ init(Host, ServerHost, Search) -> case Search of false -> loop(Host, ServerHost); _ -> - ejabberd_router:register_route(Host), + ejabberd_router:register_route(Host, ServerHost), loop(Host, ServerHost) end. diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl index 25239133c..98aaf9362 100644 --- a/src/mod_vcard_ldap.erl +++ b/src/mod_vcard_ldap.erl @@ -173,7 +173,7 @@ init([Host, Opts]) -> State#state.password, State#state.tls_options), case State#state.search of true -> - ejabberd_router:register_route(State#state.myhost); + ejabberd_router:register_route(State#state.myhost, Host); _ -> ok end, {ok, State}.