aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rebar.config2
-rw-r--r--src/ejabberd_bosh.erl38
-rw-r--r--src/ejabberd_c2s.erl21
-rw-r--r--src/ejabberd_http_ws.erl14
-rw-r--r--src/ejabberd_receiver.erl4
-rw-r--r--src/ejabberd_regexp.erl2
-rw-r--r--src/ejabberd_s2s.erl14
-rw-r--r--src/ejabberd_sql.erl30
-rw-r--r--src/eldap.erl30
-rw-r--r--src/gen_mod.erl17
-rw-r--r--src/mod_echo.erl41
-rw-r--r--src/mod_http_upload.erl20
-rw-r--r--src/mod_irc.erl62
-rw-r--r--src/mod_irc_connection.erl10
-rw-r--r--src/mod_mix.erl103
-rw-r--r--src/mod_muc.erl87
-rw-r--r--src/mod_muc_admin.erl20
-rw-r--r--src/mod_muc_log.erl2
-rw-r--r--src/mod_muc_mnesia.erl7
-rw-r--r--src/mod_muc_room.erl12
-rw-r--r--src/mod_proxy65.erl4
-rw-r--r--src/mod_proxy65_service.erl95
-rw-r--r--src/mod_proxy65_stream.erl10
-rw-r--r--src/mod_pubsub.erl141
-rw-r--r--src/mod_sip_proxy.erl7
-rw-r--r--src/mod_vcard.erl82
-rw-r--r--src/mod_vcard_ldap.erl7
-rw-r--r--test/ejabberd_SUITE.erl8
28 files changed, 495 insertions, 395 deletions
diff --git a/rebar.config b/rebar.config
index 160185511..b8a94611a 100644
--- a/rebar.config
+++ b/rebar.config
@@ -76,7 +76,7 @@
ezlib,
iconv]}}.
-{erl_first_files, ["src/ejabberd_config.erl", "src/gen_mod.erl", "src/mod_muc_room.erl"]}.
+{erl_first_files, ["src/ejabberd_config.erl", "src/gen_mod.erl", "src/mod_muc_room.erl", "src/mod_push.erl"]}.
{erl_opts, [nowarn_deprecated_function,
{i, "include"},
diff --git a/src/ejabberd_bosh.erl b/src/ejabberd_bosh.erl
index 0755067e7..1df6681ff 100644
--- a/src/ejabberd_bosh.erl
+++ b/src/ejabberd_bosh.erl
@@ -27,9 +27,7 @@
-protocol({xep, 124, '1.11'}).
-protocol({xep, 206, '1.4'}).
--define(GEN_FSM, p1_fsm).
-
--behaviour(?GEN_FSM).
+-behaviour(p1_fsm).
%% API
-export([start/2, start/3, start_link/3]).
@@ -137,18 +135,18 @@ start(#body{attrs = Attrs} = Body, IP, SID) ->
end.
start(StateName, State) ->
- (?GEN_FSM):start_link(?MODULE, [StateName, State],
+ p1_fsm:start_link(?MODULE, [StateName, State],
?FSMOPTS).
start_link(Body, IP, SID) ->
- (?GEN_FSM):start_link(?MODULE, [Body, IP, SID],
+ p1_fsm:start_link(?MODULE, [Body, IP, SID],
?FSMOPTS).
send({http_bind, FsmRef, IP}, Packet) ->
send_xml({http_bind, FsmRef, IP}, Packet).
send_xml({http_bind, FsmRef, _IP}, Packet) ->
- case catch (?GEN_FSM):sync_send_all_state_event(FsmRef,
+ case catch p1_fsm:sync_send_all_state_event(FsmRef,
{send_xml, Packet},
?SEND_TIMEOUT)
of
@@ -160,12 +158,12 @@ send_xml({http_bind, FsmRef, _IP}, Packet) ->
setopts({http_bind, FsmRef, _IP}, Opts) ->
case lists:member({active, once}, Opts) of
true ->
- (?GEN_FSM):send_all_state_event(FsmRef,
+ p1_fsm:send_all_state_event(FsmRef,
{activate, self()});
_ ->
case lists:member({active, false}, Opts) of
true ->
- case catch (?GEN_FSM):sync_send_all_state_event(FsmRef,
+ case catch p1_fsm:sync_send_all_state_event(FsmRef,
deactivate_socket)
of
{'EXIT', _} -> {error, einval};
@@ -181,7 +179,7 @@ custom_receiver({http_bind, FsmRef, _IP}) ->
{receiver, ?MODULE, FsmRef}.
become_controller(FsmRef, C2SPid) ->
- (?GEN_FSM):send_all_state_event(FsmRef,
+ p1_fsm:send_all_state_event(FsmRef,
{become_controller, C2SPid}).
change_controller({http_bind, FsmRef, _IP}, C2SPid) ->
@@ -190,14 +188,14 @@ change_controller({http_bind, FsmRef, _IP}, C2SPid) ->
reset_stream({http_bind, _FsmRef, _IP}) -> ok.
change_shaper({http_bind, FsmRef, _IP}, Shaper) ->
- (?GEN_FSM):send_all_state_event(FsmRef,
+ p1_fsm:send_all_state_event(FsmRef,
{change_shaper, Shaper}).
monitor({http_bind, FsmRef, _IP}) ->
erlang:monitor(process, FsmRef).
close({http_bind, FsmRef, _IP}) ->
- catch (?GEN_FSM):sync_send_all_state_event(FsmRef,
+ catch p1_fsm:sync_send_all_state_event(FsmRef,
close).
sockname(_Socket) -> {ok, {{0, 0, 0, 0}, 0}}.
@@ -269,7 +267,7 @@ process_request(Data, IP, Type) ->
end.
process_request(Pid, Req, _IP, Type) ->
- case catch (?GEN_FSM):sync_send_event(Pid, Req,
+ case catch p1_fsm:sync_send_event(Pid, Req,
infinity)
of
#body{} = Resp -> bosh_response(Resp, Type);
@@ -571,7 +569,7 @@ handle_sync_event({send_xml, El}, _From, StateName,
of
{{value, {TRef, From, Body}}, Q} ->
cancel_timer(TRef),
- (?GEN_FSM):send_event(self(), {Body, From}),
+ p1_fsm:send_event(self(), {Body, From}),
State1#state{shaped_receivers = Q};
_ -> State1
end,
@@ -598,7 +596,7 @@ handle_info({timeout, TRef, shaper_timeout}, StateName,
State) ->
case p1_queue:out(State#state.shaped_receivers) of
{{value, {TRef, From, Req}}, Q} ->
- (?GEN_FSM):send_event(self(), {Req, From}),
+ p1_fsm:send_event(self(), {Req, From}),
{next_state, StateName,
State#state{shaped_receivers = Q}};
{{value, _}, _} ->
@@ -630,7 +628,7 @@ terminate(_Reason, _StateName, State) ->
mod_bosh:close_session(State#state.sid),
case State#state.c2s_pid of
C2SPid when is_pid(C2SPid) ->
- (?GEN_FSM):send_event(C2SPid, closed);
+ p1_fsm:send_event(C2SPid, closed);
_ -> ok
end,
bounce_receivers(State, closed),
@@ -644,7 +642,7 @@ print_state(State) -> State.
route_els(#state{el_ibuf = Buf, c2s_pid = C2SPid} = State) ->
NewBuf = p1_queue:dropwhile(
fun(El) ->
- ?GEN_FSM:send_event(C2SPid, El),
+ p1_fsm:send_event(C2SPid, El),
true
end, Buf),
State#state{el_ibuf = NewBuf}.
@@ -653,7 +651,7 @@ route_els(State, Els) ->
case State#state.c2s_pid of
C2SPid when is_pid(C2SPid) ->
lists:foreach(fun (El) ->
- (?GEN_FSM):send_event(C2SPid, El)
+ p1_fsm:send_event(C2SPid, El)
end,
Els),
State;
@@ -676,7 +674,7 @@ reply(State, Body, RID, From) ->
case catch gb_trees:take_smallest(Receivers) of
{NextRID, {From1, Req}, Receivers1}
when NextRID == RID + 1 ->
- (?GEN_FSM):send_event(self(), {Req, From1}),
+ p1_fsm:send_event(self(), {Req, From1}),
State2#state{receivers = Receivers1};
_ -> State2#state{receivers = Receivers}
end.
@@ -715,7 +713,7 @@ do_reply(State, From, Body, RID) ->
?DEBUG("send reply:~n** RequestID: ~p~n** Reply: "
"~p~n** To: ~p~n** State: ~p",
[RID, Body, From, State]),
- (?GEN_FSM):reply(From, Body),
+ p1_fsm:reply(From, Body),
Responses = gb_trees:delete_any(RID,
State#state.responses),
Responses1 = case gb_trees:size(Responses) of
@@ -1053,7 +1051,7 @@ buf_out(Buf, I, Els) ->
end.
cancel_timer(TRef) when is_reference(TRef) ->
- (?GEN_FSM):cancel_timer(TRef);
+ p1_fsm:cancel_timer(TRef);
cancel_timer(_) -> false.
restart_timer(TRef, Timeout, Msg) ->
diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl
index 4b265d29d..a0be2e118 100644
--- a/src/ejabberd_c2s.erl
+++ b/src/ejabberd_c2s.erl
@@ -297,14 +297,19 @@ process_terminated(State, _Reason) ->
%%%===================================================================
%%% xmpp_stream_in callbacks
%%%===================================================================
-tls_options(#{lserver := LServer, tls_options := DefaultOpts}) ->
- TLSOpts1 = case ejabberd_config:get_option(
- {c2s_certfile, LServer},
- ejabberd_config:get_option(
- {domain_certfile, LServer})) of
- undefined -> DefaultOpts;
- CertFile -> lists:keystore(certfile, 1, DefaultOpts,
- {certfile, CertFile})
+tls_options(#{lserver := LServer, tls_options := DefaultOpts,
+ stream_encrypted := Encrypted}) ->
+ TLSOpts1 = case {Encrypted, proplists:get_value(certfile, DefaultOpts)} of
+ {true, CertFile} when CertFile /= undefined -> DefaultOpts;
+ {_, _} ->
+ case ejabberd_config:get_option(
+ {c2s_certfile, LServer},
+ ejabberd_config:get_option(
+ {domain_certfile, LServer})) of
+ undefined -> DefaultOpts;
+ CertFile -> lists:keystore(certfile, 1, DefaultOpts,
+ {certfile, CertFile})
+ end
end,
TLSOpts2 = case ejabberd_config:get_option(
{c2s_ciphers, LServer}) of
diff --git a/src/ejabberd_http_ws.erl b/src/ejabberd_http_ws.erl
index 2c44d6552..f9f7b07e9 100644
--- a/src/ejabberd_http_ws.erl
+++ b/src/ejabberd_http_ws.erl
@@ -28,7 +28,7 @@
-author('ecestari@process-one.net').
--behaviour(gen_fsm).
+-behaviour(p1_fsm).
-export([start/1, start_link/1, init/1, handle_event/3,
handle_sync_event/4, code_change/4, handle_info/3,
@@ -75,13 +75,13 @@
-export_type([ws_socket/0]).
start(WS) ->
- gen_fsm:start(?MODULE, [WS], ?FSMOPTS).
+ p1_fsm:start(?MODULE, [WS], ?FSMOPTS).
start_link(WS) ->
- gen_fsm:start_link(?MODULE, [WS], ?FSMOPTS).
+ p1_fsm:start_link(?MODULE, [WS], ?FSMOPTS).
send_xml({http_ws, FsmRef, _IP}, Packet) ->
- case catch gen_fsm:sync_send_all_state_event(FsmRef,
+ case catch p1_fsm:sync_send_all_state_event(FsmRef,
{send_xml, Packet},
15000)
of
@@ -93,7 +93,7 @@ send_xml({http_ws, FsmRef, _IP}, Packet) ->
setopts({http_ws, FsmRef, _IP}, Opts) ->
case lists:member({active, once}, Opts) of
true ->
- gen_fsm:send_all_state_event(FsmRef,
+ p1_fsm:send_all_state_event(FsmRef,
{activate, self()});
_ -> ok
end.
@@ -105,11 +105,11 @@ peername({http_ws, _FsmRef, IP}) -> {ok, IP}.
controlling_process(_Socket, _Pid) -> ok.
become_controller(FsmRef, C2SPid) ->
- gen_fsm:send_all_state_event(FsmRef,
+ p1_fsm:send_all_state_event(FsmRef,
{become_controller, C2SPid}).
close({http_ws, FsmRef, _IP}) ->
- catch gen_fsm:sync_send_all_state_event(FsmRef, close).
+ catch p1_fsm:sync_send_all_state_event(FsmRef, close).
socket_handoff(LocalPath, Request, Socket, SockMod, Buf, Opts) ->
ejabberd_websocket:socket_handoff(LocalPath, Request, Socket, SockMod,
diff --git a/src/ejabberd_receiver.erl b/src/ejabberd_receiver.erl
index 44c29680c..52077ac3c 100644
--- a/src/ejabberd_receiver.erl
+++ b/src/ejabberd_receiver.erl
@@ -234,7 +234,7 @@ terminate(_Reason,
State) ->
close_stream(XMLStreamState),
if C2SPid /= undefined ->
- gen_fsm:send_event(C2SPid, closed);
+ p1_fsm:send_event(C2SPid, closed);
true -> ok
end,
catch (State#state.sock_mod):close(State#state.socket),
@@ -272,7 +272,7 @@ process_data([Element | Els],
element(1, Element) == xmlstreamend ->
if C2SPid == undefined -> State;
true ->
- catch gen_fsm:send_event(C2SPid,
+ catch p1_fsm:send_event(C2SPid,
element_wrapper(Element)),
process_data(Els, State)
end;
diff --git a/src/ejabberd_regexp.erl b/src/ejabberd_regexp.erl
index b4ef7ac16..10f51aa47 100644
--- a/src/ejabberd_regexp.erl
+++ b/src/ejabberd_regexp.erl
@@ -25,7 +25,7 @@
-module(ejabberd_regexp).
--compile([export_all]).
+-export([exec/2, run/2, split/2, replace/3, greplace/3, sh_to_awk/1]).
exec({ReM, ReF, ReA}, {RgM, RgF, RgA}) ->
try apply(ReM, ReF, ReA) catch
diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl
index a0e9411cf..a614d8c4a 100644
--- a/src/ejabberd_s2s.erl
+++ b/src/ejabberd_s2s.erl
@@ -39,7 +39,7 @@
remove_connection/2, start_connection/2, start_connection/3,
dirty_get_connections/0, allow_host/2,
incoming_s2s_number/0, outgoing_s2s_number/0,
- stop_all_connections/0,
+ stop_s2s_connections/0,
clean_temporarily_blocked_table/0,
list_temporarily_blocked_hosts/0,
external_host_overloaded/1, is_temporarly_blocked/1,
@@ -558,10 +558,10 @@ get_commands_spec() ->
module = ?MODULE, function = outgoing_s2s_number,
args = [], result = {s2s_outgoing, integer}},
#ejabberd_commands{
- name = stop_all_connections, tags = [s2s],
- desc = "Stop all outgoing and incoming connections",
+ name = stop_s2s_connections, tags = [s2s],
+ desc = "Stop all s2s outgoing and incoming connections",
policy = admin,
- module = ?MODULE, function = stop_all_connections,
+ module = ?MODULE, function = stop_s2s_connections,
args = [], result = {res, rescode}}].
%% TODO Move those stats commands to ejabberd stats command ?
@@ -578,8 +578,8 @@ supervisor_count(Supervisor) ->
length(Result)
end.
--spec stop_all_connections() -> ok.
-stop_all_connections() ->
+-spec stop_s2s_connections() -> ok.
+stop_s2s_connections() ->
lists:foreach(
fun({_Id, Pid, _Type, _Module}) ->
supervisor:terminate_child(ejabberd_s2s_in_sup, Pid)
@@ -682,7 +682,7 @@ complete_s2s_info([Connection | T], Type, Result) ->
-spec get_s2s_state(pid()) -> [{status, open | closed | error} | {s2s_pid, pid()}].
get_s2s_state(S2sPid) ->
- Infos = case gen_fsm:sync_send_all_state_event(S2sPid,
+ Infos = case p1_fsm:sync_send_all_state_event(S2sPid,
get_state_infos)
of
{state_infos, Is} -> [{status, open} | Is];
diff --git a/src/ejabberd_sql.erl b/src/ejabberd_sql.erl
index 35d970291..cae41da6c 100644
--- a/src/ejabberd_sql.erl
+++ b/src/ejabberd_sql.erl
@@ -29,9 +29,7 @@
-author('alexey@process-one.net').
--define(GEN_FSM, p1_fsm).
-
--behaviour(?GEN_FSM).
+-behaviour(p1_fsm).
%% External exports
-export([start/1, start_link/2,
@@ -113,11 +111,11 @@
%%% API
%%%----------------------------------------------------------------------
start(Host) ->
- (?GEN_FSM):start(ejabberd_sql, [Host],
+ p1_fsm:start(ejabberd_sql, [Host],
fsm_limit_opts() ++ (?FSMOPTS)).
start_link(Host, StartInterval) ->
- (?GEN_FSM):start_link(ejabberd_sql,
+ p1_fsm:start_link(ejabberd_sql,
[Host, StartInterval],
fsm_limit_opts() ++ (?FSMOPTS)).
@@ -160,7 +158,7 @@ sql_call(Host, Msg) ->
case ejabberd_sql_sup:get_random_pid(Host) of
none -> {error, <<"Unknown Host">>};
Pid ->
- (?GEN_FSM):sync_send_event(Pid,{sql_cmd, Msg,
+ p1_fsm:sync_send_event(Pid,{sql_cmd, Msg,
p1_time_compat:monotonic_time(milli_seconds)},
query_timeout(Host))
end;
@@ -168,7 +166,7 @@ sql_call(Host, Msg) ->
end.
keep_alive(Host, PID) ->
- (?GEN_FSM):sync_send_event(PID,
+ p1_fsm:sync_send_event(PID,
{sql_cmd, {sql_query, ?KEEPALIVE_QUERY},
p1_time_compat:monotonic_time(milli_seconds)},
query_timeout(Host)).
@@ -280,7 +278,7 @@ init([Host, StartInterval]) ->
keep_alive, [Host, self()])
end,
[DBType | _] = db_opts(Host),
- (?GEN_FSM):send_event(self(), connect),
+ p1_fsm:send_event(self(), connect),
ejabberd_sql_sup:add_pid(Host, self()),
QueueType = case ejabberd_config:get_option({sql_queue_type, Host}) of
undefined ->
@@ -313,7 +311,7 @@ connecting(connect, #state{host = Host} = State) ->
PendingRequests =
p1_queue:dropwhile(
fun(Req) ->
- ?GEN_FSM:send_event(self(), Req),
+ p1_fsm:send_event(self(), Req),
true
end, State#state.pending_requests),
State1 = State#state{db_ref = Ref,
@@ -325,7 +323,7 @@ connecting(connect, #state{host = Host} = State) ->
"Retry after: ~p seconds",
[State#state.db_type, Reason,
State#state.start_interval div 1000]),
- (?GEN_FSM):send_event_after(State#state.start_interval,
+ p1_fsm:send_event_after(State#state.start_interval,
connect),
{next_state, connecting, State}
end;
@@ -337,7 +335,7 @@ connecting(Event, State) ->
connecting({sql_cmd, {sql_query, ?KEEPALIVE_QUERY},
_Timestamp},
From, State) ->
- (?GEN_FSM):reply(From,
+ p1_fsm:reply(From,
{error, <<"SQL connection failed">>}),
{next_state, connecting, State};
connecting({sql_cmd, Command, Timestamp} = Req, From,
@@ -350,7 +348,7 @@ connecting({sql_cmd, Command, Timestamp} = Req, From,
catch error:full ->
Q = p1_queue:dropwhile(
fun({sql_cmd, _, To, _Timestamp}) ->
- (?GEN_FSM):reply(
+ p1_fsm:reply(
To, {error, <<"SQL connection failed">>}),
true
end, State#state.pending_requests),
@@ -393,7 +391,7 @@ code_change(_OldVsn, StateName, State, _Extra) ->
%% monitoring the connection)
handle_info({'DOWN', _MonitorRef, process, _Pid, _Info},
_StateName, State) ->
- (?GEN_FSM):send_event(self(), connect),
+ p1_fsm:send_event(self(), connect),
{next_state, connecting, State};
handle_info(Info, StateName, State) ->
?WARNING_MSG("unexpected info in ~p: ~p",
@@ -734,16 +732,16 @@ sql_query_to_iolist(SQLQuery) ->
abort_on_driver_error({error, <<"query timed out">>} =
Reply,
From) ->
- (?GEN_FSM):reply(From, Reply),
+ p1_fsm:reply(From, Reply),
{stop, timeout, get(?STATE_KEY)};
abort_on_driver_error({error,
<<"Failed sending data on socket", _/binary>>} =
Reply,
From) ->
- (?GEN_FSM):reply(From, Reply),
+ p1_fsm:reply(From, Reply),
{stop, closed, get(?STATE_KEY)};
abort_on_driver_error(Reply, From) ->
- (?GEN_FSM):reply(From, Reply),
+ p1_fsm:reply(From, Reply),
{next_state, session_established, get(?STATE_KEY)}.
%% == pure ODBC code
diff --git a/src/eldap.erl b/src/eldap.erl
index f47550353..8e6b710b1 100644
--- a/src/eldap.erl
+++ b/src/eldap.erl
@@ -63,7 +63,7 @@
%%% active_bind - sent bind() request and waiting for response
%%%----------------------------------------------------------------------
--behaviour(gen_fsm).
+-behaviour(p1_fsm).
-include("ejabberd.hrl").
-include("logger.hrl").
@@ -148,7 +148,7 @@
start_link(Name) ->
Reg_name = misc:binary_to_atom(<<"eldap_",
Name/binary>>),
- gen_fsm:start_link({local, Reg_name}, ?MODULE, [], []).
+ p1_fsm:start_link({local, Reg_name}, ?MODULE, [], []).
-spec start_link(binary(), [binary()], inet:port_number(), binary(),
binary(), tlsopts()) -> any().
@@ -156,7 +156,7 @@ start_link(Name) ->
start_link(Name, Hosts, Port, Rootdn, Passwd, Opts) ->
Reg_name = misc:binary_to_atom(<<"eldap_",
Name/binary>>),
- gen_fsm:start_link({local, Reg_name}, ?MODULE,
+ p1_fsm:start_link({local, Reg_name}, ?MODULE,
[Hosts, Port, Rootdn, Passwd, Opts], []).
-spec get_status(handle()) -> any().
@@ -166,7 +166,7 @@ start_link(Name, Hosts, Port, Rootdn, Passwd, Opts) ->
%%% --------------------------------------------------------------------
get_status(Handle) ->
Handle1 = get_handle(Handle),
- gen_fsm:sync_send_all_state_event(Handle1, get_status).
+ p1_fsm:sync_send_all_state_event(Handle1, get_status).
%%% --------------------------------------------------------------------
%%% Shutdown connection (and process) asynchronous.
@@ -175,7 +175,7 @@ get_status(Handle) ->
close(Handle) ->
Handle1 = get_handle(Handle),
- gen_fsm:send_all_state_event(Handle1, close).
+ p1_fsm:send_all_state_event(Handle1, close).
%%% --------------------------------------------------------------------
%%% Add an entry. The entry field MUST NOT exist for the AddRequest
@@ -192,7 +192,7 @@ close(Handle) ->
%%% --------------------------------------------------------------------
add(Handle, Entry, Attributes) ->
Handle1 = get_handle(Handle),
- gen_fsm:sync_send_event(Handle1,
+ p1_fsm:sync_send_event(Handle1,
{add, Entry, add_attrs(Attributes)}, ?CALL_TIMEOUT).
%%% Do sanity check !
@@ -216,7 +216,7 @@ add_attrs(Attrs) ->
%%% --------------------------------------------------------------------
delete(Handle, Entry) ->
Handle1 = get_handle(Handle),
- gen_fsm:sync_send_event(Handle1, {delete, Entry},
+ p1_fsm:sync_send_event(Handle1, {delete, Entry},
?CALL_TIMEOUT).
%%% --------------------------------------------------------------------
@@ -234,7 +234,7 @@ delete(Handle, Entry) ->
modify(Handle, Object, Mods) ->
Handle1 = get_handle(Handle),
- gen_fsm:sync_send_event(Handle1, {modify, Object, Mods},
+ p1_fsm:sync_send_event(Handle1, {modify, Object, Mods},
?CALL_TIMEOUT).
%%%
@@ -274,7 +274,7 @@ m(Operation, Type, Values) ->
modify_dn(Handle, Entry, NewRDN, DelOldRDN, NewSup) ->
Handle1 = get_handle(Handle),
- gen_fsm:sync_send_event(Handle1,
+ p1_fsm:sync_send_event(Handle1,
{modify_dn, Entry, NewRDN, bool_p(DelOldRDN),
optional(NewSup)},
?CALL_TIMEOUT).
@@ -283,7 +283,7 @@ modify_dn(Handle, Entry, NewRDN, DelOldRDN, NewSup) ->
modify_passwd(Handle, DN, Passwd) ->
Handle1 = get_handle(Handle),
- gen_fsm:sync_send_event(Handle1,
+ p1_fsm:sync_send_event(Handle1,
{modify_passwd, DN, Passwd}, ?CALL_TIMEOUT).
%%% --------------------------------------------------------------------
@@ -298,7 +298,7 @@ modify_passwd(Handle, DN, Passwd) ->
bind(Handle, RootDN, Passwd) ->
Handle1 = get_handle(Handle),
- gen_fsm:sync_send_event(Handle1, {bind, RootDN, Passwd},
+ p1_fsm:sync_send_event(Handle1, {bind, RootDN, Passwd},
?CALL_TIMEOUT).
%%% Sanity checks !
@@ -356,7 +356,7 @@ search(Handle, L) when is_list(L) ->
call_search(Handle, A) ->
Handle1 = get_handle(Handle),
- gen_fsm:sync_send_event(Handle1, {search, A},
+ p1_fsm:sync_send_event(Handle1, {search, A},
?CALL_TIMEOUT).
-spec parse_search_args(search_args()) -> eldap_search().
@@ -637,7 +637,7 @@ active(Event, From, S) ->
%%----------------------------------------------------------------------
%% Func: handle_event/3
-%% Called when gen_fsm:send_all_state_event/2 is invoked.
+%% Called when p1_fsm:send_all_state_event/2 is invoked.
%% Returns: {next_state, NextStateName, NextStateData} |
%% {next_state, NextStateName, NextStateData, Timeout} |
%% {stop, Reason, NewStateData}
@@ -680,7 +680,7 @@ handle_info({Tag, _Socket, Data}, StateName, S)
case catch recvd_packet(Data, S) of
{response, Response, RequestType} ->
NewS = case Response of
- {reply, Reply, To, S1} -> gen_fsm:reply(To, Reply), S1;
+ {reply, Reply, To, S1} -> p1_fsm:reply(To, Reply), S1;
{ok, S1} -> S1
end,
if StateName == active_bind andalso
@@ -709,7 +709,7 @@ handle_info({timeout, Timer, {cmd_timeout, Id}},
StateName, S) ->
case cmd_timeout(Timer, Id, S) of
{reply, To, Reason, NewS} ->
- gen_fsm:reply(To, Reason),
+ p1_fsm:reply(To, Reason),
{next_state, StateName, NewS};
{error, _Reason} -> {next_state, StateName, S}
end;
diff --git a/src/gen_mod.erl b/src/gen_mod.erl
index 5bfa3b4d4..e17197dfb 100644
--- a/src/gen_mod.erl
+++ b/src/gen_mod.erl
@@ -34,7 +34,8 @@
stop_child/1, stop_child/2, config_reloaded/0]).
-export([start_module/2, start_module/3,
stop_module/2, stop_module_keep_config/2,
- get_opt/2, get_opt/3, get_opt_host/3, opt_type/1, is_equal_opt/4,
+ get_opt/2, get_opt/3, get_opt_host/3,
+ get_opt_hosts/3, opt_type/1, is_equal_opt/4,
get_module_opt/3, get_module_opt/4, get_module_opt_host/3,
loaded_modules/1, loaded_modules_with_opts/1,
get_hosts/2, get_module_proc/2, is_loaded/2, is_loaded_elsewhere/2,
@@ -441,6 +442,20 @@ get_opt_host(Host, Opts, Default) ->
Val = get_opt(host, Opts, Default),
ejabberd_regexp:greplace(Val, <<"@HOST@">>, Host).
+-spec get_opt_hosts(binary(), opts(), binary()) -> [binary()].
+
+get_opt_hosts(Host, Opts, Default) ->
+ Vals = case get_opt(host, Opts, undefined) of
+ undefined ->
+ case get_opt(hosts, Opts, []) of
+ [] -> [Default];
+ L -> L
+ end;
+ Val ->
+ [Val]
+ end,
+ [ejabberd_regexp:greplace(V, <<"@HOST@">>, Host) || V <- Vals].
+
-spec get_validators(binary(), module(), opts()) -> dict:dict() | undef.
get_validators(Host, Module, Opts) ->
try Module:mod_opt_type('') of
diff --git a/src/mod_echo.erl b/src/mod_echo.erl
index 861b1a0ef..79dd59962 100644
--- a/src/mod_echo.erl
+++ b/src/mod_echo.erl
@@ -43,7 +43,7 @@
-include("xmpp.hrl").
--record(state, {host = <<"">> :: binary()}).
+-record(state, {hosts = [] :: [binary()]}).
%%====================================================================
%% gen_mod API
@@ -62,7 +62,9 @@ depends(_Host, _Opts) ->
[].
mod_opt_type(host) -> fun iolist_to_binary/1;
-mod_opt_type(_) -> [host].
+mod_opt_type(hosts) ->
+ fun(L) -> lists:map(fun iolist_to_binary/1, L) end;
+mod_opt_type(_) -> [host, hosts].
%%====================================================================
%% gen_server callbacks
@@ -77,10 +79,13 @@ mod_opt_type(_) -> [host].
%%--------------------------------------------------------------------
init([Host, Opts]) ->
process_flag(trap_exit, true),
- MyHost = gen_mod:get_opt_host(Host, Opts,
+ Hosts = gen_mod:get_opt_hosts(Host, Opts,
<<"echo.@HOST@">>),
- ejabberd_router:register_route(MyHost, Host),
- {ok, #state{host = MyHost}}.
+ lists:foreach(
+ fun(H) ->
+ ejabberd_router:register_route(H, Host)
+ end, Hosts),
+ {ok, #state{hosts = Hosts}}.
%%--------------------------------------------------------------------
%% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} |
@@ -101,17 +106,19 @@ handle_call(stop, _From, State) ->
%% Description: Handling cast messages
%%--------------------------------------------------------------------
handle_cast({reload, Host, NewOpts, OldOpts}, State) ->
- NewMyHost = gen_mod:get_opt_host(Host, NewOpts,
- <<"echo.@HOST@">>),
- OldMyHost = gen_mod:get_opt_host(Host, OldOpts,
- <<"echo.@HOST@">>),
- if NewMyHost /= OldMyHost ->
- ejabberd_router:register_route(NewMyHost, Host),
- ejabberd_router:unregister_route(OldMyHost);
- true ->
- ok
- end,
- {noreply, State#state{host = NewMyHost}};
+ NewMyHosts = gen_mod:get_opt_hosts(Host, NewOpts,
+ <<"echo.@HOST@">>),
+ OldMyHosts = gen_mod:get_opt_hosts(Host, OldOpts,
+ <<"echo.@HOST@">>),
+ lists:foreach(
+ fun(H) ->
+ ejabberd_router:unregister_route(H)
+ end, OldMyHosts -- NewMyHosts),
+ lists:foreach(
+ fun(H) ->
+ ejabberd_router:register_route(H, Host)
+ end, NewMyHosts -- OldMyHosts),
+ {noreply, State#state{hosts = NewMyHosts}};
handle_cast(Msg, State) ->
?WARNING_MSG("unexpected cast: ~p", [Msg]),
{noreply, State}.
@@ -147,7 +154,7 @@ handle_info(_Info, State) -> {noreply, State}.
%% The return value is ignored.
%%--------------------------------------------------------------------
terminate(_Reason, State) ->
- ejabberd_router:unregister_route(State#state.host), ok.
+ lists:foreach(fun ejabberd_router:unregister_route/1, State#state.hosts).
%%--------------------------------------------------------------------
%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl
index c8cd300f4..6d981e9ec 100644
--- a/src/mod_http_upload.erl
+++ b/src/mod_http_upload.erl
@@ -94,7 +94,7 @@
-record(state,
{server_host :: binary(),
- host :: binary(),
+ hosts :: [binary()],
name :: binary(),
access :: atom(),
max_size :: pos_integer() | infinity,
@@ -151,6 +151,8 @@ stop(ServerHost) ->
mod_opt_type(host) ->
fun iolist_to_binary/1;
+mod_opt_type(hosts) ->
+ fun (L) -> lists:map(fun iolist_to_binary/1, L) end;
mod_opt_type(name) ->
fun iolist_to_binary/1;
mod_opt_type(access) ->
@@ -194,7 +196,7 @@ mod_opt_type(rm_on_unregister) ->
mod_opt_type(thumbnail) ->
fun(B) when is_boolean(B) -> B end;
mod_opt_type(_) ->
- [host, name, access, max_size, secret_length, jid_in_url, file_mode,
+ [host, hosts, name, access, max_size, secret_length, jid_in_url, file_mode,
dir_mode, docroot, put_url, get_url, service_url, custom_headers,
rm_on_unregister, thumbnail].
@@ -211,7 +213,7 @@ depends(_Host, _Opts) ->
init([ServerHost, Opts]) ->
process_flag(trap_exit, true),
- Host = gen_mod:get_opt_host(ServerHost, Opts, <<"upload.@HOST@">>),
+ Hosts = gen_mod:get_opt_hosts(ServerHost, Opts, <<"upload.@HOST@">>),
Name = gen_mod:get_opt(name, Opts, <<"HTTP File Upload">>),
Access = gen_mod:get_opt(access, Opts, local),
MaxSize = gen_mod:get_opt(max_size, Opts, 104857600),
@@ -244,8 +246,11 @@ init([ServerHost, Opts]) ->
false ->
ok
end,
- ejabberd_router:register_route(Host, ServerHost),
- {ok, #state{server_host = ServerHost, host = Host, name = Name,
+ lists:foreach(
+ fun(Host) ->
+ ejabberd_router:register_route(Host, ServerHost)
+ end, Hosts),
+ {ok, #state{server_host = ServerHost, hosts = Hosts, name = Name,
access = Access, max_size = MaxSize,
secret_length = SecretLength, jid_in_url = JIDinURL,
file_mode = FileMode, dir_mode = DirMode,
@@ -324,10 +329,9 @@ handle_info(Info, State) ->
-spec terminate(normal | shutdown | {shutdown, _} | _, state()) -> ok.
-terminate(Reason, #state{server_host = ServerHost, host = Host}) ->
+terminate(Reason, #state{server_host = ServerHost, hosts = Hosts}) ->
?DEBUG("Stopping HTTP upload process for ~s: ~p", [ServerHost, Reason]),
- ejabberd_router:unregister_route(Host),
- ok.
+ lists:foreach(fun ejabberd_router:unregister_route/1, Hosts).
-spec code_change({down, _} | _, state(), _) -> {ok, state()}.
diff --git a/src/mod_irc.erl b/src/mod_irc.erl
index fc85668e8..04687ea67 100644
--- a/src/mod_irc.erl
+++ b/src/mod_irc.erl
@@ -58,7 +58,7 @@
[<<"koi8-r">>, <<"iso8859-15">>, <<"iso8859-1">>, <<"iso8859-2">>,
<<"utf-8">>, <<"utf-8+latin-1">>]).
--record(state, {host = <<"">> :: binary(),
+-record(state, {hosts = [] :: [binary()],
server_host = <<"">> :: binary(),
access = all :: atom()}).
@@ -99,8 +99,7 @@ depends(_Host, _Opts) ->
init([Host, Opts]) ->
process_flag(trap_exit, true),
ejabberd:start_app(iconv),
- MyHost = gen_mod:get_opt_host(Host, Opts,
- <<"irc.@HOST@">>),
+ MyHosts = gen_mod:get_opt_hosts(Host, Opts, <<"irc.@HOST@">>),
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
Mod:init(Host, Opts),
Access = gen_mod:get_opt(access, Opts, all),
@@ -108,10 +107,13 @@ init([Host, Opts]) ->
[named_table, public,
{keypos, #irc_connection.jid_server_host}]),
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
- register_hooks(MyHost, IQDisc),
- ejabberd_router:register_route(MyHost, Host),
+ lists:foreach(
+ fun(MyHost) ->
+ register_hooks(MyHost, IQDisc),
+ ejabberd_router:register_route(MyHost, Host)
+ end, MyHosts),
{ok,
- #state{host = MyHost, server_host = Host,
+ #state{hosts = MyHosts, server_host = Host,
access = Access}}.
%%--------------------------------------------------------------------
@@ -133,8 +135,8 @@ handle_call(stop, _From, State) ->
%% Description: Handling cast messages
%%--------------------------------------------------------------------
handle_cast({reload, ServerHost, NewOpts, OldOpts}, State) ->
- NewHost = gen_mod:get_opt_host(ServerHost, NewOpts, <<"irc.@HOST@">>),
- OldHost = gen_mod:get_opt_host(ServerHost, OldOpts, <<"irc.@HOST@">>),
+ NewHosts = gen_mod:get_opt_hosts(ServerHost, NewOpts, <<"irc.@HOST@">>),
+ OldHosts = gen_mod:get_opt_hosts(ServerHost, OldOpts, <<"irc.@HOST@">>),
NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts, gen_iq_handler:iqdisc(ServerHost)),
OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts, gen_iq_handler:iqdisc(ServerHost)),
NewMod = gen_mod:db_mod(ServerHost, NewOpts, ?MODULE),
@@ -145,20 +147,26 @@ handle_cast({reload, ServerHost, NewOpts, OldOpts}, State) ->
true ->
ok
end,
- if (NewIQDisc /= OldIQDisc) or (NewHost /= OldHost) ->
- register_hooks(NewHost, NewIQDisc);
- true ->
- ok
- end,
- if NewHost /= OldHost ->
- ejabberd_router:register_route(NewHost, ServerHost),
- ejabberd_router:unregister_route(OldHost),
- unregister_hooks(OldHost);
+ if (NewIQDisc /= OldIQDisc) ->
+ lists:foreach(
+ fun(NewHost) ->
+ register_hooks(NewHost, NewIQDisc)
+ end, NewHosts -- (NewHosts -- OldHosts));
true ->
ok
end,
+ lists:foreach(
+ fun(NewHost) ->
+ ejabberd_router:register_route(NewHost, ServerHost),
+ register_hooks(NewHost, NewIQDisc)
+ end, NewHosts -- OldHosts),
+ lists:foreach(
+ fun(OldHost) ->
+ ejabberd_router:unregister_route(OldHost),
+ unregister_hooks(OldHost)
+ end, OldHosts -- NewHosts),
Access = gen_mod:get_opt(access, NewOpts, all),
- {noreply, State#state{host = NewHost, access = Access}};
+ {noreply, State#state{hosts = NewHosts, access = Access}};
handle_cast(Msg, State) ->
?WARNING_MSG("unexpected cast: ~p", [Msg]),
{noreply, State}.
@@ -170,9 +178,10 @@ handle_cast(Msg, State) ->
%% Description: Handling all non call/cast messages
%%--------------------------------------------------------------------
handle_info({route, Packet},
- #state{host = Host, server_host = ServerHost,
- access = Access} =
+ #state{server_host = ServerHost, access = Access} =
State) ->
+ To = xmpp:get_to(Packet),
+ Host = To#jid.lserver,
case catch do_route(Host, ServerHost, Access, Packet) of
{'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]);
_ -> ok
@@ -187,9 +196,12 @@ handle_info(_Info, State) -> {noreply, State}.
%% cleaning up. When it returns, the gen_server terminates with Reason.
%% The return value is ignored.
%%--------------------------------------------------------------------
-terminate(_Reason, #state{host = MyHost}) ->
- ejabberd_router:unregister_route(MyHost),
- unregister_hooks(MyHost).
+terminate(_Reason, #state{hosts = MyHosts}) ->
+ lists:foreach(
+ fun(MyHost) ->
+ ejabberd_router:unregister_route(MyHost),
+ unregister_hooks(MyHost)
+ end, MyHosts).
%%--------------------------------------------------------------------
%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
@@ -975,8 +987,10 @@ mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
mod_opt_type(default_encoding) ->
fun iolist_to_binary/1;
mod_opt_type(host) -> fun iolist_to_binary/1;
+mod_opt_type(hosts) ->
+ fun (L) -> lists:map(fun iolist_to_binary/1, L) end;
mod_opt_type(_) ->
- [access, db_type, default_encoding, host].
+ [access, db_type, default_encoding, host, hosts].
-spec extract_ident(stanza()) -> binary().
extract_ident(Packet) ->
diff --git a/src/mod_irc_connection.erl b/src/mod_irc_connection.erl
index 1e90c4005..b7b2f8e1d 100644
--- a/src/mod_irc_connection.erl
+++ b/src/mod_irc_connection.erl
@@ -27,7 +27,7 @@
-author('alexey@process-one.net').
--behaviour(gen_fsm).
+-behaviour(p1_fsm).
%% External exports
-export([start_link/12, start/13, route_chan/4,
@@ -91,7 +91,7 @@ start(From, Host, ServerHost, Server, Username,
start_link(From, Host, Server, Username, Encoding, Port,
Password, Ident, RemoteAddr, RealName, WebircPassword, Mod) ->
- gen_fsm:start_link(?MODULE,
+ p1_fsm:start_link(?MODULE,
[From, Host, Server, Username, Encoding, Port, Password,
Ident, RemoteAddr, RealName, WebircPassword, Mod],
?FSMOPTS).
@@ -109,7 +109,7 @@ start_link(From, Host, Server, Username, Encoding, Port,
%%----------------------------------------------------------------------
init([From, Host, Server, Username, Encoding, Port,
Password, Ident, RemoteAddr, RealName, WebircPassword, Mod]) ->
- gen_fsm:send_event(self(), init),
+ p1_fsm:send_event(self(), init),
{ok, open_socket,
#state{mod = Mod,
encoding = Encoding, port = Port, password = Password,
@@ -628,11 +628,11 @@ handle_info({tcp, _Socket, Data}, StateName,
StateData#state{inbuf = NewBuf}};
handle_info({tcp_closed, _Socket}, StateName,
StateData) ->
- gen_fsm:send_event(self(), closed),
+ p1_fsm:send_event(self(), closed),
{next_state, StateName, StateData};
handle_info({tcp_error, _Socket, _Reason}, StateName,
StateData) ->
- gen_fsm:send_event(self(), closed),
+ p1_fsm:send_event(self(), closed),
{next_state, StateName, StateData}.
%%----------------------------------------------------------------------
diff --git a/src/mod_mix.erl b/src/mod_mix.erl
index 4763447f3..90507665b 100644
--- a/src/mod_mix.erl
+++ b/src/mod_mix.erl
@@ -46,7 +46,7 @@
?NS_MIX_NODES_CONFIG]).
-record(state, {server_host :: binary(),
- host :: binary()}).
+ hosts :: [binary()]}).
%%%===================================================================
%%% API
@@ -124,36 +124,39 @@ process_iq(#iq{lang = Lang} = IQ) ->
%%%===================================================================
init([ServerHost, Opts]) ->
process_flag(trap_exit, true),
- Host = gen_mod:get_opt_host(ServerHost, Opts, <<"mix.@HOST@">>),
- IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
- ConfigTab = gen_mod:get_module_proc(Host, config),
- ets:new(ConfigTab, [named_table]),
- ets:insert(ConfigTab, {plugins, [<<"mix">>]}),
- ejabberd_hooks:add(disco_local_items, Host, ?MODULE, disco_items, 100),
- ejabberd_hooks:add(disco_local_features, Host, ?MODULE, disco_features, 100),
- ejabberd_hooks:add(disco_local_identity, Host, ?MODULE, disco_identity, 100),
- ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, disco_items, 100),
- ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, disco_features, 100),
- ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE, disco_identity, 100),
- ejabberd_hooks:add(disco_info, Host, ?MODULE, disco_info, 100),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host,
- ?NS_DISCO_ITEMS, mod_disco,
- process_local_iq_items, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host,
- ?NS_DISCO_INFO, mod_disco,
- process_local_iq_info, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
- ?NS_DISCO_ITEMS, mod_disco,
- process_local_iq_items, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
- ?NS_DISCO_INFO, mod_disco,
- process_local_iq_info, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
- ?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, ServerHost),
- {ok, #state{server_host = ServerHost, host = Host}}.
+ Hosts = gen_mod:get_opt_hosts(ServerHost, Opts, <<"mix.@HOST@">>),
+ IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(ServerHost)),
+ lists:foreach(
+ fun(Host) ->
+ ConfigTab = gen_mod:get_module_proc(Host, config),
+ ets:new(ConfigTab, [named_table]),
+ ets:insert(ConfigTab, {plugins, [<<"mix">>]}),
+ ejabberd_hooks:add(disco_local_items, Host, ?MODULE, disco_items, 100),
+ ejabberd_hooks:add(disco_local_features, Host, ?MODULE, disco_features, 100),
+ ejabberd_hooks:add(disco_local_identity, Host, ?MODULE, disco_identity, 100),
+ ejabberd_hooks:add(disco_sm_items, Host, ?MODULE, disco_items, 100),
+ ejabberd_hooks:add(disco_sm_features, Host, ?MODULE, disco_features, 100),
+ ejabberd_hooks:add(disco_sm_identity, Host, ?MODULE, disco_identity, 100),
+ ejabberd_hooks:add(disco_info, Host, ?MODULE, disco_info, 100),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host,
+ ?NS_DISCO_ITEMS, mod_disco,
+ process_local_iq_items, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host,
+ ?NS_DISCO_INFO, mod_disco,
+ process_local_iq_info, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
+ ?NS_DISCO_ITEMS, mod_disco,
+ process_local_iq_items, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
+ ?NS_DISCO_INFO, mod_disco,
+ process_local_iq_info, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_sm, Host,
+ ?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, ServerHost)
+ end, Hosts),
+ {ok, #state{server_host = ServerHost, hosts = Hosts}}.
handle_call(_Request, _From, State) ->
Reply = ok,
@@ -180,22 +183,24 @@ handle_info({route, Packet}, State) ->
handle_info(_Info, State) ->
{noreply, State}.
-terminate(_Reason, #state{host = Host}) ->
- ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, disco_items, 100),
- ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, disco_features, 100),
- ejabberd_hooks:delete(disco_local_identity, Host, ?MODULE, disco_identity, 100),
- ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, disco_items, 100),
- ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, disco_features, 100),
- ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE, disco_identity, 100),
- ejabberd_hooks:delete(disco_info, Host, ?MODULE, disco_info, 100),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO),
- gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_DISCO_ITEMS),
- gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_DISCO_INFO),
- gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PUBSUB),
- gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MIX_0),
- ejabberd_router:unregister_route(Host),
- ok.
+terminate(_Reason, #state{hosts = Hosts}) ->
+ lists:foreach(
+ fun(Host) ->
+ ejabberd_hooks:delete(disco_local_items, Host, ?MODULE, disco_items, 100),
+ ejabberd_hooks:delete(disco_local_features, Host, ?MODULE, disco_features, 100),
+ ejabberd_hooks:delete(disco_local_identity, Host, ?MODULE, disco_identity, 100),
+ ejabberd_hooks:delete(disco_sm_items, Host, ?MODULE, disco_items, 100),
+ ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, disco_features, 100),
+ ejabberd_hooks:delete(disco_sm_identity, Host, ?MODULE, disco_identity, 100),
+ ejabberd_hooks:delete(disco_info, Host, ?MODULE, disco_info, 100),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO),
+ gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_DISCO_ITEMS),
+ gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_DISCO_INFO),
+ gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_PUBSUB),
+ gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_MIX_0),
+ ejabberd_router:unregister_route(Host)
+ end, Hosts).
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
@@ -316,4 +321,6 @@ depends(_Host, _Opts) ->
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
mod_opt_type(host) -> fun iolist_to_binary/1;
-mod_opt_type(_) -> [host, iqdisc].
+mod_opt_type(hosts) ->
+ fun (L) -> lists:map(fun iolist_to_binary/1, L) end;
+mod_opt_type(_) -> [host, hosts, iqdisc].
diff --git a/src/mod_muc.erl b/src/mod_muc.erl
index 8b6d7b8b9..db101e4f6 100644
--- a/src/mod_muc.erl
+++ b/src/mod_muc.erl
@@ -75,7 +75,7 @@
-include("mod_muc.hrl").
-record(state,
- {host = <<"">> :: binary(),
+ {hosts = [] :: [binary()],
server_host = <<"">> :: binary(),
access = {none, none, none, none} :: {atom(), atom(), atom(), atom()},
history_size = 20 :: non_neg_integer(),
@@ -151,8 +151,9 @@ room_destroyed(Host, Room, Pid, ServerHost) ->
%% If Opts = default, the default room options are used.
%% Else use the passed options as defined in mod_muc_room.
create_room(Host, Name, From, Nick, Opts) ->
- Proc = gen_mod:get_module_proc(Host, ?MODULE),
- gen_server:call(Proc, {create, Name, From, Nick, Opts}).
+ ServerHost = ejabberd_router:host_of_route(Host),
+ Proc = gen_mod:get_module_proc(ServerHost, ?MODULE),
+ gen_server:call(Proc, {create, Name, Host, From, Nick, Opts}).
store_room(ServerHost, Host, Name, Opts) ->
LServer = jid:nameprep(ServerHost),
@@ -225,22 +226,26 @@ get_online_rooms_by_user(ServerHost, LUser, LServer) ->
init([Host, Opts]) ->
process_flag(trap_exit, true),
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
- #state{access = Access, host = MyHost,
+ #state{access = Access, hosts = MyHosts,
history_size = HistorySize, queue_type = QueueType,
room_shaper = RoomShaper} = State = init_state(Host, Opts),
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
RMod = gen_mod:ram_db_mod(Host, Opts, ?MODULE),
- Mod:init(Host, [{host, MyHost}|Opts]),
- RMod:init(Host, [{host, MyHost}|Opts]),
- register_iq_handlers(MyHost, IQDisc),
- ejabberd_router:register_route(MyHost, Host),
- load_permanent_rooms(MyHost, Host, Access, HistorySize, RoomShaper, QueueType),
+ Mod:init(Host, [{hosts, MyHosts}|Opts]),
+ RMod:init(Host, [{hosts, MyHosts}|Opts]),
+ lists:foreach(
+ fun(MyHost) ->
+ register_iq_handlers(MyHost, IQDisc),
+ ejabberd_router:register_route(MyHost, Host),
+ load_permanent_rooms(MyHost, Host, Access, HistorySize,
+ RoomShaper, QueueType)
+ end, MyHosts),
{ok, State}.
handle_call(stop, _From, State) ->
{stop, normal, ok, State};
-handle_call({create, Room, From, Nick, Opts}, _From,
- #state{host = Host, server_host = ServerHost,
+handle_call({create, Room, Host, From, Nick, Opts}, _From,
+ #state{server_host = ServerHost,
access = Access, default_room_opts = DefOpts,
history_size = HistorySize, queue_type = QueueType,
room_shaper = RoomShaper} = State) ->
@@ -259,49 +264,56 @@ handle_call({create, Room, From, Nick, Opts}, _From,
ejabberd_hooks:run(create_room, ServerHost, [ServerHost, Room, Host]),
{reply, ok, State}.
-handle_cast({reload, ServerHost, NewOpts, OldOpts}, #state{host = OldHost}) ->
+handle_cast({reload, ServerHost, NewOpts, OldOpts}, #state{hosts = OldHosts}) ->
NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts, gen_iq_handler:iqdisc(ServerHost)),
OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts, gen_iq_handler:iqdisc(ServerHost)),
NewMod = gen_mod:db_mod(ServerHost, NewOpts, ?MODULE),
NewRMod = gen_mod:ram_db_mod(ServerHost, NewOpts, ?MODULE),
OldMod = gen_mod:db_mod(ServerHost, OldOpts, ?MODULE),
OldRMod = gen_mod:ram_db_mod(ServerHost, OldOpts, ?MODULE),
- #state{host = NewHost} = NewState = init_state(ServerHost, NewOpts),
+ #state{hosts = NewHosts} = NewState = init_state(ServerHost, NewOpts),
if NewMod /= OldMod ->
- NewMod:init(ServerHost, [{host, NewHost}|NewOpts]);
+ NewMod:init(ServerHost, [{hosts, NewHosts}|NewOpts]);
true ->
ok
end,
if NewRMod /= OldRMod ->
- NewRMod:init(ServerHost, [{host, NewHost}|NewOpts]);
- true ->
- ok
- end,
- if (NewIQDisc /= OldIQDisc) or (NewHost /= OldHost) ->
- register_iq_handlers(NewHost, NewIQDisc);
+ NewRMod:init(ServerHost, [{hosts, NewHosts}|NewOpts]);
true ->
ok
end,
- if NewHost /= OldHost ->
- ejabberd_router:register_route(NewHost, ServerHost),
- ejabberd_router:unregister_route(OldHost),
- unregister_iq_handlers(OldHost);
+ if (NewIQDisc /= OldIQDisc) ->
+ lists:foreach(
+ fun(NewHost) ->
+ register_iq_handlers(NewHost, NewIQDisc)
+ end, NewHosts -- (NewHosts -- OldHosts));
true ->
ok
end,
+ lists:foreach(
+ fun(NewHost) ->
+ ejabberd_router:register_route(NewHost, ServerHost),
+ register_iq_handlers(NewHost, NewIQDisc)
+ end, NewHosts -- OldHosts),
+ lists:foreach(
+ fun(OldHost) ->
+ ejabberd_router:unregister_route(OldHost),
+ unregister_iq_handlers(OldHost)
+ end, OldHosts -- NewHosts),
{noreply, NewState};
handle_cast(Msg, State) ->
?WARNING_MSG("unexpected cast: ~p", [Msg]),
{noreply, State}.
handle_info({route, Packet},
- #state{host = Host, server_host = ServerHost,
+ #state{server_host = ServerHost,
access = Access, default_room_opts = DefRoomOpts,
history_size = HistorySize, queue_type = QueueType,
max_rooms_discoitems = MaxRoomsDiscoItems,
room_shaper = RoomShaper} = State) ->
From = xmpp:get_from(Packet),
To = xmpp:get_to(Packet),
+ Host = To#jid.lserver,
case catch do_route(Host, ServerHost, Access, HistorySize, RoomShaper,
From, To, Packet, DefRoomOpts, MaxRoomsDiscoItems,
QueueType) of
@@ -320,9 +332,12 @@ handle_info(Info, State) ->
?ERROR_MSG("unexpected info: ~p", [Info]),
{noreply, State}.
-terminate(_Reason, #state{host = MyHost}) ->
- ejabberd_router:unregister_route(MyHost),
- unregister_iq_handlers(MyHost).
+terminate(_Reason, #state{hosts = MyHosts}) ->
+ lists:foreach(
+ fun(MyHost) ->
+ ejabberd_router:unregister_route(MyHost),
+ unregister_iq_handlers(MyHost)
+ end, MyHosts).
code_change(_OldVsn, State, _Extra) -> {ok, State}.
@@ -330,8 +345,8 @@ code_change(_OldVsn, State, _Extra) -> {ok, State}.
%%% Internal functions
%%--------------------------------------------------------------------
init_state(Host, Opts) ->
- MyHost = gen_mod:get_opt_host(Host, Opts,
- <<"conference.@HOST@">>),
+ MyHosts = gen_mod:get_opt_hosts(Host, Opts,
+ <<"conference.@HOST@">>),
Access = gen_mod:get_opt(access, Opts, all),
AccessCreate = gen_mod:get_opt(access_create, Opts, all),
AccessAdmin = gen_mod:get_opt(access_admin, Opts, none),
@@ -342,7 +357,7 @@ init_state(Host, Opts) ->
QueueType = gen_mod:get_opt(queue_type, Opts,
ejabberd_config:default_queue_type(Host)),
RoomShaper = gen_mod:get_opt(room_shaper, Opts, none),
- #state{host = MyHost,
+ #state{hosts = MyHosts,
server_host = Host,
access = {Access, AccessCreate, AccessAdmin, AccessPersistent},
default_room_opts = DefRoomOpts,
@@ -668,7 +683,7 @@ iq_disco_items(_ServerHost, _Host, _From, Lang, _MaxRoomsDiscoItems, _Node, _RSM
{error, timeout | notfound}.
get_room_disco_item({Name, Host, Pid}, Query) ->
RoomJID = jid:make(Name, Host),
- try gen_fsm:sync_send_all_state_event(Pid, Query, 100) of
+ try p1_fsm:sync_send_all_state_event(Pid, Query, 100) of
{item, Desc} ->
{ok, #disco_item{jid = RoomJID, name = Desc}};
false ->
@@ -684,7 +699,7 @@ get_subscribed_rooms(ServerHost, Host, From) ->
BareFrom = jid:remove_resource(From),
lists:flatmap(
fun({Name, _, Pid}) ->
- case gen_fsm:sync_send_all_state_event(Pid, {is_subscribed, BareFrom}) of
+ case p1_fsm:sync_send_all_state_event(Pid, {is_subscribed, BareFrom}) of
true -> [jid:make(Name, Host)];
false -> []
end;
@@ -766,7 +781,7 @@ process_iq_register_set(ServerHost, Host, From,
broadcast_service_message(ServerHost, Host, Msg) ->
lists:foreach(
fun({_, _, Pid}) ->
- gen_fsm:send_all_state_event(
+ p1_fsm:send_all_state_event(
Pid, {service_message, Msg})
end, get_online_rooms(ServerHost, Host)).
@@ -851,6 +866,8 @@ mod_opt_type(ram_db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
mod_opt_type(history_size) ->
fun (I) when is_integer(I), I >= 0 -> I end;
mod_opt_type(host) -> fun iolist_to_binary/1;
+mod_opt_type(hosts) ->
+ fun (L) -> lists:map(fun iolist_to_binary/1, L) end;
mod_opt_type(max_room_desc) ->
fun (infinity) -> infinity;
(I) when is_integer(I), I > 0 -> I
@@ -944,7 +961,7 @@ mod_opt_type({default_room_options, presence_broadcast}) ->
end;
mod_opt_type(_) ->
[access, access_admin, access_create, access_persistent,
- db_type, ram_db_type, history_size, host,
+ db_type, ram_db_type, history_size, host, hosts,
max_room_desc, max_room_id, max_room_name,
max_rooms_discoitems, max_user_conferences, max_users,
max_users_admin_threshold, max_users_presence,
diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl
index 2d1e66ba5..332c83b55 100644
--- a/src/mod_muc_admin.erl
+++ b/src/mod_muc_admin.erl
@@ -597,7 +597,7 @@ muc_create_room(ServerHost, {Name, Host, _}, DefRoomOpts) ->
destroy_room(Name, Service) ->
case mod_muc:find_online_room(Name, Service) of
{ok, Pid} ->
- gen_fsm:send_all_state_event(Pid, destroy),
+ p1_fsm:send_all_state_event(Pid, destroy),
ok;
error ->
error
@@ -716,11 +716,11 @@ get_rooms(ServerHost) ->
end, Hosts).
get_room_config(Room_pid) ->
- {ok, R} = gen_fsm:sync_send_all_state_event(Room_pid, get_config),
+ {ok, R} = p1_fsm:sync_send_all_state_event(Room_pid, get_config),
R.
get_room_state(Room_pid) ->
- {ok, R} = gen_fsm:sync_send_all_state_event(Room_pid, get_state),
+ {ok, R} = p1_fsm:sync_send_all_state_event(Room_pid, get_state),
R.
%%---------------
@@ -786,7 +786,7 @@ find_serverhost(Host, ServerHosts) ->
ServerHost.
act_on_room(destroy, {N, H, Pid}, SH) ->
- gen_fsm:send_all_state_event(
+ p1_fsm:send_all_state_event(
Pid, {destroy, <<"Room destroyed by rooms_unused_destroy.">>}),
mod_muc:room_destroyed(H, N, Pid, SH),
mod_muc:forget_room(SH, H, N);
@@ -888,7 +888,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, _} = gen_fsm:sync_send_all_state_event(Pid, {change_config, Config2}),
+ {ok, _} = p1_fsm:sync_send_all_state_event(Pid, {change_config, Config2}),
ok
end.
@@ -983,7 +983,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} = gen_fsm:sync_send_all_state_event(Pid, get_state),
+ {ok, StateData} = p1_fsm:sync_send_all_state_event(Pid, get_state),
Affiliations = ?DICT:to_list(StateData#state.affiliations),
lists:map(
fun({{Uname, Domain, _Res}, {Aff, Reason}}) when is_atom(Aff)->
@@ -1012,7 +1012,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} = gen_fsm:sync_send_all_state_event(Pid, {process_item_change, {jid:decode(JID), affiliation, Affiliation, <<"">>}, undefined}),
+ {ok, StateData} = p1_fsm:sync_send_all_state_event(Pid, {process_item_change, {jid:decode(JID), affiliation, Affiliation, <<"">>}, undefined}),
mod_muc:store_room(StateData#state.server_host, StateData#state.host, StateData#state.room, make_opts(StateData)),
ok;
error ->
@@ -1035,7 +1035,7 @@ subscribe_room(User, Nick, Room, Nodes) ->
UserJID ->
case get_room_pid(Name, Host) of
Pid when is_pid(Pid) ->
- case gen_fsm:sync_send_all_state_event(
+ case p1_fsm:sync_send_all_state_event(
Pid,
{muc_subscribe, UserJID, Nick, NodeList}) of
{ok, SubscribedNodes} ->
@@ -1062,7 +1062,7 @@ unsubscribe_room(User, Room) ->
UserJID ->
case get_room_pid(Name, Host) of
Pid when is_pid(Pid) ->
- case gen_fsm:sync_send_all_state_event(
+ case p1_fsm:sync_send_all_state_event(
Pid,
{muc_unsubscribe, UserJID}) of
ok ->
@@ -1085,7 +1085,7 @@ unsubscribe_room(User, Room) ->
get_subscribers(Name, Host) ->
case get_room_pid(Name, Host) of
Pid when is_pid(Pid) ->
- {ok, JIDList} = gen_fsm:sync_send_all_state_event(Pid, get_subscribers),
+ {ok, JIDList} = p1_fsm:sync_send_all_state_event(Pid, get_subscribers),
[jid:encode(jid:remove_resource(J)) || J <- JIDList];
_ ->
throw({error, "The room does not exist"})
diff --git a/src/mod_muc_log.erl b/src/mod_muc_log.erl
index 3d4c87c0f..61101d1c2 100644
--- a/src/mod_muc_log.erl
+++ b/src/mod_muc_log.erl
@@ -1142,7 +1142,7 @@ get_room_state(RoomName, MucService) ->
-spec get_room_state(pid()) -> mod_muc_room:state().
get_room_state(RoomPid) ->
- {ok, R} = gen_fsm:sync_send_all_state_event(RoomPid,
+ {ok, R} = p1_fsm:sync_send_all_state_event(RoomPid,
get_state),
R.
diff --git a/src/mod_muc_mnesia.erl b/src/mod_muc_mnesia.erl
index 53f31cb9f..015c5ec43 100644
--- a/src/mod_muc_mnesia.erl
+++ b/src/mod_muc_mnesia.erl
@@ -296,7 +296,7 @@ import(_LServer, <<"muc_registered">>,
%%% gen_server callbacks
%%%===================================================================
init([Host, Opts]) ->
- MyHost = proplists:get_value(host, Opts),
+ MyHosts = proplists:get_value(hosts, Opts),
case gen_mod:db_mod(Host, Opts, mod_muc) of
?MODULE ->
ejabberd_mnesia:create(?MODULE, muc_room,
@@ -318,7 +318,10 @@ init([Host, Opts]) ->
{type, ordered_set},
{attributes, record_info(fields, muc_online_room)}]),
catch ets:new(muc_online_users, [bag, named_table, public, {keypos, 2}]),
- clean_table_from_bad_node(node(), MyHost),
+ lists:foreach(
+ fun(MyHost) ->
+ clean_table_from_bad_node(node(), MyHost)
+ end, MyHosts),
mnesia:subscribe(system);
_ ->
ok
diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl
index 31dbbbfa7..2a1ca6011 100644
--- a/src/mod_muc_room.erl
+++ b/src/mod_muc_room.erl
@@ -27,7 +27,7 @@
-author('alexey@process-one.net').
--behaviour(gen_fsm).
+-behaviour(p1_fsm).
%% External exports
-export([start_link/10,
@@ -94,23 +94,23 @@
%%%----------------------------------------------------------------------
start(Host, ServerHost, Access, Room, HistorySize, RoomShaper,
Creator, Nick, DefRoomOpts, QueueType) ->
- gen_fsm:start(?MODULE, [Host, ServerHost, Access, Room, HistorySize,
+ p1_fsm:start(?MODULE, [Host, ServerHost, Access, Room, HistorySize,
RoomShaper, Creator, Nick, DefRoomOpts, QueueType],
?FSMOPTS).
start(Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts, QueueType) ->
- gen_fsm:start(?MODULE, [Host, ServerHost, Access, Room, HistorySize,
+ p1_fsm:start(?MODULE, [Host, ServerHost, Access, Room, HistorySize,
RoomShaper, Opts, QueueType],
?FSMOPTS).
start_link(Host, ServerHost, Access, Room, HistorySize, RoomShaper,
Creator, Nick, DefRoomOpts, QueueType) ->
- gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, HistorySize,
+ p1_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, HistorySize,
RoomShaper, Creator, Nick, DefRoomOpts, QueueType],
?FSMOPTS).
start_link(Host, ServerHost, Access, Room, HistorySize, RoomShaper, Opts, QueueType) ->
- gen_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, HistorySize,
+ p1_fsm:start_link(?MODULE, [Host, ServerHost, Access, Room, HistorySize,
RoomShaper, Opts, QueueType],
?FSMOPTS).
@@ -703,7 +703,7 @@ terminate(Reason, _StateName, StateData) ->
-spec route(pid(), stanza()) -> ok.
route(Pid, Packet) ->
#jid{lresource = Nick} = xmpp:get_to(Packet),
- gen_fsm:send_event(Pid, {route, Nick, Packet}).
+ p1_fsm:send_event(Pid, {route, Nick, Packet}).
-spec process_groupchat_message(message(), state()) -> fsm_next().
process_groupchat_message(#message{from = From, lang = Lang} = Packet, StateData) ->
diff --git a/src/mod_proxy65.erl b/src/mod_proxy65.erl
index aee324960..671baef9a 100644
--- a/src/mod_proxy65.erl
+++ b/src/mod_proxy65.erl
@@ -112,6 +112,8 @@ depends(_Host, _Opts) ->
mod_opt_type(access) -> fun acl:access_rules_validator/1;
mod_opt_type(host) -> fun iolist_to_binary/1;
+mod_opt_type(hosts) ->
+ fun(L) -> lists:map(fun iolist_to_binary/1, L) end;
mod_opt_type(hostname) -> fun iolist_to_binary/1;
mod_opt_type(ip) ->
fun (S) ->
@@ -131,7 +133,7 @@ mod_opt_type(ram_db_type) ->
mod_opt_type(Opt) ->
case mod_proxy65_stream:listen_opt_type(Opt) of
Opts when is_list(Opts) ->
- [access, host, hostname, ip, name, port,
+ [access, host, hosts, hostname, ip, name, port,
max_connections, ram_db_type] ++ Opts;
Fun ->
Fun
diff --git a/src/mod_proxy65_service.erl b/src/mod_proxy65_service.erl
index b27f3bc20..aaece980a 100644
--- a/src/mod_proxy65_service.erl
+++ b/src/mod_proxy65_service.erl
@@ -43,7 +43,7 @@
-define(PROCNAME, ejabberd_mod_proxy65_service).
--record(state, {myhost = <<"">> :: binary()}).
+-record(state, {myhosts = [] :: [binary()]}).
%%%------------------------
%%% gen_server callbacks
@@ -61,24 +61,27 @@ reload(Host, NewOpts, OldOpts) ->
init([Host, Opts]) ->
process_flag(trap_exit, true),
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
- MyHost = gen_mod:get_opt_host(Host, Opts, <<"proxy.@HOST@">>),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO,
- ?MODULE, process_disco_info, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_ITEMS,
- ?MODULE, process_disco_items, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_VCARD,
- ?MODULE, process_vcard, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_BYTESTREAMS,
- ?MODULE, process_bytestreams, IQDisc),
- ejabberd_router:register_route(MyHost, Host),
- {ok, #state{myhost = MyHost}}.
+ MyHosts = gen_mod:get_opt_hosts(Host, Opts, <<"proxy.@HOST@">>),
+ lists:foreach(
+ fun(MyHost) ->
+ gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO,
+ ?MODULE, process_disco_info, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_ITEMS,
+ ?MODULE, process_disco_items, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_VCARD,
+ ?MODULE, process_vcard, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, MyHost, ?NS_BYTESTREAMS,
+ ?MODULE, process_bytestreams, IQDisc),
+ ejabberd_router:register_route(MyHost, Host)
+ end, MyHosts),
+ {ok, #state{myhosts = MyHosts}}.
-terminate(_Reason, #state{myhost = MyHost}) ->
- ejabberd_router:unregister_route(MyHost),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_ITEMS),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_VCARD),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_BYTESTREAMS).
+terminate(_Reason, #state{myhosts = MyHosts}) ->
+ lists:foreach(
+ fun(MyHost) ->
+ ejabberd_router:unregister_route(MyHost),
+ unregister_handlers(MyHost)
+ end, MyHosts).
handle_info({route, #iq{} = Packet}, State) ->
ejabberd_router:process_iq(Packet),
@@ -89,33 +92,29 @@ handle_call(_Request, _From, State) ->
{reply, ok, State}.
handle_cast({reload, ServerHost, NewOpts, OldOpts}, State) ->
- NewHost = gen_mod:get_opt_host(ServerHost, NewOpts, <<"proxy.@HOST@">>),
- OldHost = gen_mod:get_opt_host(ServerHost, OldOpts, <<"proxy.@HOST@">>),
+ NewHosts = gen_mod:get_opt_hosts(ServerHost, NewOpts, <<"proxy.@HOST@">>),
+ OldHosts = gen_mod:get_opt_hosts(ServerHost, OldOpts, <<"proxy.@HOST@">>),
NewIQDisc = gen_mod:get_opt(iqdisc, NewOpts, gen_iq_handler:iqdisc(ServerHost)),
OldIQDisc = gen_mod:get_opt(iqdisc, OldOpts, gen_iq_handler:iqdisc(ServerHost)),
- if (NewIQDisc /= OldIQDisc) or (NewHost /= OldHost) ->
- gen_iq_handler:add_iq_handler(ejabberd_local, NewHost, ?NS_DISCO_INFO,
- ?MODULE, process_disco_info, NewIQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, NewHost, ?NS_DISCO_ITEMS,
- ?MODULE, process_disco_items, NewIQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, NewHost, ?NS_VCARD,
- ?MODULE, process_vcard, NewIQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, NewHost, ?NS_BYTESTREAMS,
- ?MODULE, process_bytestreams, NewIQDisc);
- true ->
- ok
- end,
- if NewHost /= OldHost ->
- ejabberd_router:register_route(NewHost, ServerHost),
- ejabberd_router:unregister_route(OldHost),
- gen_iq_handler:remove_iq_handler(ejabberd_local, OldHost, ?NS_DISCO_INFO),
- gen_iq_handler:remove_iq_handler(ejabberd_local, OldHost, ?NS_DISCO_ITEMS),
- gen_iq_handler:remove_iq_handler(ejabberd_local, OldHost, ?NS_VCARD),
- gen_iq_handler:remove_iq_handler(ejabberd_local, OldHost, ?NS_BYTESTREAMS);
+ if (NewIQDisc /= OldIQDisc) ->
+ lists:foreach(
+ fun(NewHost) ->
+ register_handlers(NewHost, NewIQDisc)
+ end, NewHosts -- (NewHosts -- OldHosts));
true ->
ok
end,
- {noreply, State#state{myhost = NewHost}};
+ lists:foreach(
+ fun(NewHost) ->
+ ejabberd_router:register_route(NewHost, ServerHost),
+ register_handlers(NewHost, NewIQDisc)
+ end, NewHosts -- OldHosts),
+ lists:foreach(
+ fun(OldHost) ->
+ ejabberd_router:unregister_route(OldHost),
+ unregister_handlers(OldHost)
+ end, OldHosts -- NewHosts),
+ {noreply, State#state{myhosts = NewHosts}};
handle_cast(Msg, State) ->
?WARNING_MSG("unexpected cast: ~p", [Msg]),
{noreply, State}.
@@ -276,3 +275,19 @@ get_my_ip() ->
max_connections(ServerHost) ->
gen_mod:get_module_opt(ServerHost, mod_proxy65, max_connections, infinity).
+
+register_handlers(Host, IQDisc) ->
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO,
+ ?MODULE, process_disco_info, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS,
+ ?MODULE, process_disco_items, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VCARD,
+ ?MODULE, process_vcard, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_BYTESTREAMS,
+ ?MODULE, process_bytestreams, IQDisc).
+
+unregister_handlers(Host) ->
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_BYTESTREAMS).
diff --git a/src/mod_proxy65_stream.erl b/src/mod_proxy65_stream.erl
index 899b66727..1fa6ff804 100644
--- a/src/mod_proxy65_stream.erl
+++ b/src/mod_proxy65_stream.erl
@@ -26,7 +26,7 @@
-author('xram@jabber.ru').
--behaviour(gen_fsm).
+-behaviour(p1_fsm).
%% gen_fsm callbacks.
-export([init/1, handle_event/3, handle_sync_event/4,
@@ -75,7 +75,7 @@ start({gen_tcp, Socket}, Opts1) ->
[Socket, Host, Opts]).
start_link(Socket, Host, Opts) ->
- gen_fsm:start_link(?MODULE, [Socket, Host, Opts], []).
+ p1_fsm:start_link(?MODULE, [Socket, Host, Opts], []).
init([Socket, Host, Opts]) ->
process_flag(trap_exit, true),
@@ -106,9 +106,9 @@ socket_type() -> raw.
stop(StreamPid) -> StreamPid ! stop.
activate({P1, J1}, {P2, J2}) ->
- case catch {gen_fsm:sync_send_all_state_event(P1,
+ case catch {p1_fsm:sync_send_all_state_event(P1,
get_socket),
- gen_fsm:sync_send_all_state_event(P2, get_socket)}
+ p1_fsm:sync_send_all_state_event(P2, get_socket)}
of
{S1, S2} when is_port(S1), is_port(S2) ->
P1 ! {activate, P2, S2, J1, J2},
@@ -197,7 +197,7 @@ handle_info({tcp, _S, Data}, StateName, StateData)
when StateName /= wait_for_activation ->
erlang:cancel_timer(StateData#state.timer),
TRef = erlang:send_after(?WAIT_TIMEOUT, self(), stop),
- gen_fsm:send_event(self(), Data),
+ p1_fsm:send_event(self(), Data),
{next_state, StateName, StateData#state{timer = TRef}};
%% Activation message.
handle_info({activate, PeerPid, PeerSocket, IJid, TJid},
diff --git a/src/mod_pubsub.erl b/src/mod_pubsub.erl
index d682eb5f3..0ae68b24b 100644
--- a/src/mod_pubsub.erl
+++ b/src/mod_pubsub.erl
@@ -189,7 +189,7 @@
-record(state,
{
server_host,
- host,
+ hosts,
access,
pep_mapping = [],
ignore_pep_from_offline = true,
@@ -205,7 +205,7 @@
-type(state() ::
#state{
server_host :: binary(),
- host :: mod_pubsub:hostPubsub(),
+ hosts :: [mod_pubsub:hostPubsub()],
access :: atom(),
pep_mapping :: [{binary(), binary()}],
ignore_pep_from_offline :: boolean(),
@@ -243,42 +243,63 @@ stop(Host) ->
init([ServerHost, Opts]) ->
process_flag(trap_exit, true),
?DEBUG("pubsub init ~p ~p", [ServerHost, Opts]),
- Host = gen_mod:get_opt_host(ServerHost, Opts, <<"pubsub.@HOST@">>),
- ejabberd_router:register_route(Host, ServerHost),
+ Hosts = gen_mod:get_opt_hosts(ServerHost, Opts, <<"pubsub.@HOST@">>),
Access = gen_mod:get_opt(access_createnode, Opts, all),
PepOffline = gen_mod:get_opt(ignore_pep_from_offline, Opts, true),
- IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
+ IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(ServerHost)),
LastItemCache = gen_mod:get_opt(last_item_cache, Opts, false),
MaxItemsNode = gen_mod:get_opt(max_items_node, Opts, ?MAXITEMS),
MaxSubsNode = gen_mod:get_opt(max_subscriptions_node, Opts),
- case gen_mod:db_type(ServerHost, ?MODULE) of
- mnesia -> pubsub_index:init(Host, ServerHost, Opts);
- _ -> ok
- end,
- {Plugins, NodeTree, PepMapping} = init_plugins(Host, ServerHost, Opts),
- DefaultModule = plugin(Host, hd(Plugins)),
- BaseOptions = DefaultModule:options(),
- DefaultNodeCfg = filter_node_options(
- gen_mod:get_opt(default_node_config, Opts, []),
- BaseOptions),
ejabberd_mnesia:create(?MODULE, pubsub_last_item,
- [{ram_copies, [node()]},
- {attributes, record_info(fields, pubsub_last_item)}]),
- lists:foreach(
- fun(H) ->
- T = gen_mod:get_module_proc(H, config),
- ets:new(T, [set, named_table]),
- ets:insert(T, {nodetree, NodeTree}),
- ets:insert(T, {plugins, Plugins}),
- ets:insert(T, {last_item_cache, LastItemCache}),
- ets:insert(T, {max_items_node, MaxItemsNode}),
- ets:insert(T, {max_subscriptions_node, MaxSubsNode}),
- ets:insert(T, {default_node_config, DefaultNodeCfg}),
- ets:insert(T, {pep_mapping, PepMapping}),
- ets:insert(T, {ignore_pep_from_offline, PepOffline}),
- ets:insert(T, {host, Host}),
- ets:insert(T, {access, Access})
- end, [Host, ServerHost]),
+ [{ram_copies, [node()]},
+ {attributes, record_info(fields, pubsub_last_item)}]),
+ AllPlugins =
+ lists:flatmap(
+ fun(Host) ->
+ ejabberd_router:register_route(Host, ServerHost),
+ case gen_mod:db_type(ServerHost, ?MODULE) of
+ mnesia -> pubsub_index:init(Host, ServerHost, Opts);
+ _ -> ok
+ end,
+ {Plugins, NodeTree, PepMapping} = init_plugins(Host, ServerHost, Opts),
+ DefaultModule = plugin(Host, hd(Plugins)),
+ BaseOptions = DefaultModule:options(),
+ DefaultNodeCfg = filter_node_options(
+ gen_mod:get_opt(default_node_config, Opts, []),
+ BaseOptions),
+ lists:foreach(
+ fun(H) ->
+ T = gen_mod:get_module_proc(H, config),
+ try
+ ets:new(T, [set, named_table]),
+ ets:insert(T, {nodetree, NodeTree}),
+ ets:insert(T, {plugins, Plugins}),
+ ets:insert(T, {last_item_cache, LastItemCache}),
+ ets:insert(T, {max_items_node, MaxItemsNode}),
+ ets:insert(T, {max_subscriptions_node, MaxSubsNode}),
+ ets:insert(T, {default_node_config, DefaultNodeCfg}),
+ ets:insert(T, {pep_mapping, PepMapping}),
+ ets:insert(T, {ignore_pep_from_offline, PepOffline}),
+ ets:insert(T, {host, Host}),
+ ets:insert(T, {access, Access})
+ catch error:badarg when H == ServerHost ->
+ ok
+ end
+ end, [Host, ServerHost]),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO,
+ ?MODULE, process_disco_info, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS,
+ ?MODULE, process_disco_items, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_PUBSUB,
+ ?MODULE, process_pubsub, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_PUBSUB_OWNER,
+ ?MODULE, process_pubsub_owner, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VCARD,
+ ?MODULE, process_vcard, IQDisc),
+ gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_COMMANDS,
+ ?MODULE, process_commands, IQDisc),
+ Plugins
+ end, Hosts),
ejabberd_hooks:add(sm_remove_connection_hook, ServerHost,
?MODULE, on_user_offline, 75),
ejabberd_hooks:add(disco_local_identity, ServerHost,
@@ -297,19 +318,7 @@ init([ServerHost, Opts]) ->
?MODULE, remove_user, 50),
ejabberd_hooks:add(c2s_handle_info, ServerHost,
?MODULE, c2s_handle_info, 50),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO,
- ?MODULE, process_disco_info, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS,
- ?MODULE, process_disco_items, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_PUBSUB,
- ?MODULE, process_pubsub, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_PUBSUB_OWNER,
- ?MODULE, process_pubsub_owner, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_VCARD,
- ?MODULE, process_vcard, IQDisc),
- gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_COMMANDS,
- ?MODULE, process_commands, IQDisc),
- case lists:member(?PEPNODE, Plugins) of
+ case lists:member(?PEPNODE, AllPlugins) of
true ->
ejabberd_hooks:add(caps_add, ServerHost,
?MODULE, caps_add, 80),
@@ -328,20 +337,19 @@ init([ServerHost, Opts]) ->
false ->
ok
end,
- {_, State} = init_send_loop(ServerHost),
+ {_, State} = init_send_loop(ServerHost, Hosts),
{ok, State}.
-init_send_loop(ServerHost) ->
+init_send_loop(ServerHost, Hosts) ->
NodeTree = config(ServerHost, nodetree),
Plugins = config(ServerHost, plugins),
LastItemCache = config(ServerHost, last_item_cache),
MaxItemsNode = config(ServerHost, max_items_node),
PepMapping = config(ServerHost, pep_mapping),
PepOffline = config(ServerHost, ignore_pep_from_offline),
- Host = config(ServerHost, host),
Access = config(ServerHost, access),
DBType = gen_mod:db_type(ServerHost, ?MODULE),
- State = #state{host = Host, server_host = ServerHost,
+ State = #state{hosts = Hosts, server_host = ServerHost,
access = Access, pep_mapping = PepMapping,
ignore_pep_from_offline = PepOffline,
last_item_cache = LastItemCache,
@@ -419,7 +427,7 @@ get_subscribed(User, Server) ->
send_loop(State) ->
receive
{presence, JID, _Pid} ->
- Host = State#state.host,
+ Host = State#state.server_host,
ServerHost = State#state.server_host,
DBType = State#state.db_type,
LJID = jid:tolower(JID),
@@ -461,7 +469,7 @@ send_loop(State) ->
send_loop(State);
{presence, User, Server, Resources, JID} ->
spawn(fun() ->
- Host = State#state.host,
+ Host = State#state.server_host,
Owner = jid:remove_resource(jid:tolower(JID)),
lists:foreach(fun(#pubsub_node{nodeid = {_, Node}, type = Type, id = Nidx, options = Options}) ->
case match_option(Options, send_last_published_item, on_sub_and_presence) of
@@ -689,11 +697,7 @@ presence_probe(_From, _To, _Pid) ->
ok.
presence(ServerHost, Presence) ->
- {SendLoop, _} = case whereis(gen_mod:get_module_proc(ServerHost, ?LOOPNAME)) of
- undefined -> init_send_loop(ServerHost);
- Pid -> {Pid, undefined}
- end,
- SendLoop ! Presence,
+ gen_mod:get_module_proc(ServerHost, ?LOOPNAME) ! Presence,
ok.
%% -------
@@ -859,7 +863,7 @@ handle_info(_Info, State) ->
%%--------------------------------------------------------------------
%% @private
terminate(_Reason,
- #state{host = Host, server_host = ServerHost, nodetree = TreePlugin, plugins = Plugins}) ->
+ #state{hosts = Hosts, server_host = ServerHost, nodetree = TreePlugin, plugins = Plugins}) ->
case lists:member(?PEPNODE, Plugins) of
true ->
ejabberd_hooks:delete(caps_add, ServerHost,
@@ -897,20 +901,23 @@ terminate(_Reason,
?MODULE, remove_user, 50),
ejabberd_hooks:delete(c2s_handle_info, ServerHost,
?MODULE, c2s_handle_info, 50),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_PUBSUB),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_PUBSUB_OWNER),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD),
- gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_COMMANDS),
case whereis(gen_mod:get_module_proc(ServerHost, ?LOOPNAME)) of
undefined ->
?ERROR_MSG("~s process is dead, pubsub was broken", [?LOOPNAME]);
Pid ->
Pid ! stop
end,
- terminate_plugins(Host, ServerHost, Plugins, TreePlugin),
- ejabberd_router:unregister_route(Host).
+ lists:foreach(
+ fun(Host) ->
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_INFO),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_DISCO_ITEMS),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_PUBSUB),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_PUBSUB_OWNER),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_COMMANDS),
+ terminate_plugins(Host, ServerHost, Plugins, TreePlugin),
+ ejabberd_router:unregister_route(Host)
+ end, Hosts).
%%--------------------------------------------------------------------
%% Func: code_change(OldVsn, State, Extra) -> {ok, NewState}
@@ -3877,6 +3884,8 @@ export(Server) ->
mod_opt_type(access_createnode) -> fun acl:access_rules_validator/1;
mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
mod_opt_type(host) -> fun iolist_to_binary/1;
+mod_opt_type(hosts) ->
+ fun (L) -> lists:map(fun iolist_to_binary/1, L) end;
mod_opt_type(ignore_pep_from_offline) ->
fun (A) when is_boolean(A) -> A end;
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
@@ -3895,7 +3904,7 @@ mod_opt_type(pep_mapping) ->
mod_opt_type(plugins) ->
fun (A) when is_list(A) -> A end;
mod_opt_type(_) ->
- [access_createnode, db_type, host,
+ [access_createnode, db_type, host, hosts,
ignore_pep_from_offline, iqdisc, last_item_cache,
max_items_node, nodetree, pep_mapping, plugins,
max_subscriptions_node, default_node_config].
diff --git a/src/mod_sip_proxy.erl b/src/mod_sip_proxy.erl
index 19a02e8e4..25f035377 100644
--- a/src/mod_sip_proxy.erl
+++ b/src/mod_sip_proxy.erl
@@ -27,8 +27,7 @@
-ifndef(SIP).
-export([]).
-else.
--define(GEN_FSM, p1_fsm).
--behaviour(?GEN_FSM).
+-behaviour(p1_fsm).
%% API
-export([start/2, start_link/2, route/3, route/4]).
@@ -58,10 +57,10 @@ start(LServer, Opts) ->
supervisor:start_child(mod_sip_proxy_sup, [LServer, Opts]).
start_link(LServer, Opts) ->
- ?GEN_FSM:start_link(?MODULE, [LServer, Opts], []).
+ p1_fsm:start_link(?MODULE, [LServer, Opts], []).
route(SIPMsg, _SIPSock, TrID, Pid) ->
- ?GEN_FSM:send_event(Pid, {SIPMsg, TrID}).
+ p1_fsm:send_event(Pid, {SIPMsg, TrID}).
route(#sip{hdrs = Hdrs} = Req, LServer, Opts) ->
case proplists:get_bool(authenticated, Opts) of
diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl
index 495393f72..67d01a085 100644
--- a/src/mod_vcard.erl
+++ b/src/mod_vcard.erl
@@ -67,7 +67,7 @@
-optional_callbacks([use_cache/1, cache_nodes/1]).
--record(state, {host :: binary(), server_host :: binary()}).
+-record(state, {hosts :: [binary()], server_host :: binary()}).
%%====================================================================
%% gen_mod callbacks
@@ -95,37 +95,40 @@ init([Host, Opts]) ->
?NS_VCARD, ?MODULE, process_sm_iq, IQDisc),
ejabberd_hooks:add(disco_sm_features, Host, ?MODULE,
get_sm_features, 50),
- MyHost = gen_mod:get_opt_host(Host, Opts, <<"vjud.@HOST@">>),
+ MyHosts = gen_mod:get_opt_hosts(Host, Opts, <<"vjud.@HOST@">>),
Search = gen_mod:get_opt(search, Opts, false),
if Search ->
- ejabberd_hooks:add(
- disco_local_items, MyHost, ?MODULE, disco_items, 100),
- ejabberd_hooks:add(
- disco_local_features, MyHost, ?MODULE, disco_features, 100),
- ejabberd_hooks:add(
- disco_local_identity, MyHost, ?MODULE, disco_identity, 100),
- gen_iq_handler:add_iq_handler(
- ejabberd_local, MyHost, ?NS_SEARCH, ?MODULE, process_search, IQDisc),
- gen_iq_handler:add_iq_handler(
- ejabberd_local, MyHost, ?NS_VCARD, ?MODULE, process_vcard, IQDisc),
- gen_iq_handler:add_iq_handler(
- ejabberd_local, MyHost, ?NS_DISCO_ITEMS, mod_disco,
- process_local_iq_items, IQDisc),
- gen_iq_handler:add_iq_handler(
- ejabberd_local, MyHost, ?NS_DISCO_INFO, mod_disco,
- process_local_iq_info, IQDisc),
- case Mod:is_search_supported(Host) of
- false ->
- ?WARNING_MSG("vcard search functionality is "
- "not implemented for ~s backend",
- [gen_mod:db_type(Host, Opts, ?MODULE)]);
- true ->
- ejabberd_router:register_route(MyHost, Host)
- end;
+ lists:foreach(
+ fun(MyHost) ->
+ ejabberd_hooks:add(
+ disco_local_items, MyHost, ?MODULE, disco_items, 100),
+ ejabberd_hooks:add(
+ disco_local_features, MyHost, ?MODULE, disco_features, 100),
+ ejabberd_hooks:add(
+ disco_local_identity, MyHost, ?MODULE, disco_identity, 100),
+ gen_iq_handler:add_iq_handler(
+ ejabberd_local, MyHost, ?NS_SEARCH, ?MODULE, process_search, IQDisc),
+ gen_iq_handler:add_iq_handler(
+ ejabberd_local, MyHost, ?NS_VCARD, ?MODULE, process_vcard, IQDisc),
+ gen_iq_handler:add_iq_handler(
+ ejabberd_local, MyHost, ?NS_DISCO_ITEMS, mod_disco,
+ process_local_iq_items, IQDisc),
+ gen_iq_handler:add_iq_handler(
+ ejabberd_local, MyHost, ?NS_DISCO_INFO, mod_disco,
+ process_local_iq_info, IQDisc),
+ case Mod:is_search_supported(Host) of
+ false ->
+ ?WARNING_MSG("vcard search functionality is "
+ "not implemented for ~s backend",
+ [gen_mod:db_type(Host, Opts, ?MODULE)]);
+ true ->
+ ejabberd_router:register_route(MyHost, Host)
+ end
+ end, MyHosts);
true ->
ok
end,
- {ok, #state{host = MyHost, server_host = Host}}.
+ {ok, #state{hosts = MyHosts, server_host = Host}}.
handle_call(_Call, _From, State) ->
{noreply, State}.
@@ -144,21 +147,24 @@ handle_info(Info, State) ->
?WARNING_MSG("unexpected info: ~p", [Info]),
{noreply, State}.
-terminate(_Reason, #state{host = MyHost, server_host = Host}) ->
+terminate(_Reason, #state{hosts = MyHosts, server_host = Host}) ->
ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50),
gen_iq_handler:remove_iq_handler(ejabberd_local, Host, ?NS_VCARD),
gen_iq_handler:remove_iq_handler(ejabberd_sm, Host, ?NS_VCARD),
ejabberd_hooks:delete(disco_sm_features, Host, ?MODULE, get_sm_features, 50),
Mod = gen_mod:db_mod(Host, ?MODULE),
Mod:stop(Host),
- ejabberd_router:unregister_route(MyHost),
- ejabberd_hooks:delete(disco_local_items, MyHost, ?MODULE, disco_items, 100),
- ejabberd_hooks:delete(disco_local_features, MyHost, ?MODULE, disco_features, 100),
- ejabberd_hooks:delete(disco_local_identity, MyHost, ?MODULE, disco_identity, 100),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_SEARCH),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_VCARD),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_ITEMS),
- gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO).
+ lists:foreach(
+ fun(MyHost) ->
+ ejabberd_router:unregister_route(MyHost),
+ ejabberd_hooks:delete(disco_local_items, MyHost, ?MODULE, disco_items, 100),
+ ejabberd_hooks:delete(disco_local_features, MyHost, ?MODULE, disco_features, 100),
+ ejabberd_hooks:delete(disco_local_identity, MyHost, ?MODULE, disco_identity, 100),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_SEARCH),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_VCARD),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_ITEMS),
+ gen_iq_handler:remove_iq_handler(ejabberd_local, MyHost, ?NS_DISCO_INFO)
+ end, MyHosts).
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
@@ -527,6 +533,8 @@ mod_opt_type(allow_return_all) ->
fun (B) when is_boolean(B) -> B end;
mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
mod_opt_type(host) -> fun iolist_to_binary/1;
+mod_opt_type(hosts) ->
+ fun (L) -> lists:map(fun iolist_to_binary/1, L) end;
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
mod_opt_type(matches) ->
fun (infinity) -> infinity;
@@ -543,6 +551,6 @@ mod_opt_type(O) when O == cache_life_time; O == cache_size ->
mod_opt_type(O) when O == use_cache; O == cache_missed ->
fun (B) when is_boolean(B) -> B end;
mod_opt_type(_) ->
- [allow_return_all, db_type, host, iqdisc, matches,
+ [allow_return_all, db_type, host, hosts, iqdisc, matches,
search, search_all_hosts, cache_life_time, cache_size,
use_cache, cache_missed].
diff --git a/src/mod_vcard_ldap.erl b/src/mod_vcard_ldap.erl
index f1f076468..38c4747e6 100644
--- a/src/mod_vcard_ldap.erl
+++ b/src/mod_vcard_ldap.erl
@@ -47,7 +47,7 @@
-record(state,
{serverhost = <<"">> :: binary(),
- myhost = <<"">> :: binary(),
+ myhosts = [] :: [binary()],
eldap_id = <<"">> :: binary(),
search = false :: boolean(),
servers = [] :: [binary()],
@@ -351,8 +351,7 @@ default_search_reported() ->
{<<"Organization Unit">>, <<"ORGUNIT">>}].
parse_options(Host, Opts) ->
- MyHost = gen_mod:get_opt_host(Host, Opts,
- <<"vjud.@HOST@">>),
+ MyHosts = gen_mod:get_opt_hosts(Host, Opts, <<"vjud.@HOST@">>),
Search = gen_mod:get_opt(search, Opts, false),
Matches = gen_mod:get_opt(matches, Opts, 30),
Eldap_ID = misc:atom_to_binary(gen_mod:get_module_proc(Host, ?PROCNAME)),
@@ -394,7 +393,7 @@ parse_options(Host, Opts) ->
end,
SearchReported)
++ UIDAttrs),
- #state{serverhost = Host, myhost = MyHost,
+ #state{serverhost = Host, myhosts = MyHosts,
eldap_id = Eldap_ID, search = Search,
servers = Cfg#eldap_config.servers,
backups = Cfg#eldap_config.backups,
diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl
index 539d8dc33..97c56159a 100644
--- a/test/ejabberd_SUITE.erl
+++ b/test/ejabberd_SUITE.erl
@@ -750,25 +750,25 @@ test_component_send(Config) ->
disconnect(Config).
s2s_dialback(Config) ->
- ejabberd_s2s:stop_all_connections(),
+ ejabberd_s2s:stop_s2s_connections(),
ejabberd_config:add_option(s2s_use_starttls, false),
ejabberd_config:add_option(domain_certfile, "self-signed-cert.pem"),
s2s_ping(Config).
s2s_optional(Config) ->
- ejabberd_s2s:stop_all_connections(),
+ ejabberd_s2s:stop_s2s_connections(),
ejabberd_config:add_option(s2s_use_starttls, optional),
ejabberd_config:add_option(domain_certfile, "self-signed-cert.pem"),
s2s_ping(Config).
s2s_required(Config) ->
- ejabberd_s2s:stop_all_connections(),
+ ejabberd_s2s:stop_s2s_connections(),
ejabberd_config:add_option(s2s_use_starttls, required),
ejabberd_config:add_option(domain_certfile, "self-signed-cert.pem"),
s2s_ping(Config).
s2s_required_trusted(Config) ->
- ejabberd_s2s:stop_all_connections(),
+ ejabberd_s2s:stop_s2s_connections(),
ejabberd_config:add_option(s2s_use_starttls, required),
ejabberd_config:add_option(domain_certfile, "cert.pem"),
s2s_ping(Config).