mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-08 15:42:29 +01:00
Implement MUC rooms load distribution (TECH-1351).
Configuration example: {domain_balancing, "conference.domain.com", broadcast}. NOTE: both ejabberd_router and mod_muc use the option.
This commit is contained in:
parent
d6e81ac06b
commit
c9a712a16a
@ -115,7 +115,7 @@ room_destroyed(Host, Room, Pid, ServerHost) ->
|
|||||||
create_room(Host, Name, From, Nick, Opts) ->
|
create_room(Host, Name, From, Nick, Opts) ->
|
||||||
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
Proc = gen_mod:get_module_proc(Host, ?PROCNAME),
|
||||||
RoomHost = gen_mod:get_module_opt_host(Host, ?MODULE, "conference.@HOST@"),
|
RoomHost = gen_mod:get_module_opt_host(Host, ?MODULE, "conference.@HOST@"),
|
||||||
Node = ejabberd_cluster:get_node({Name, RoomHost}),
|
Node = get_node({Name, RoomHost}),
|
||||||
gen_server:call({Proc, Node}, {create, Name, From, Nick, Opts}).
|
gen_server:call({Proc, Node}, {create, Name, From, Nick, Opts}).
|
||||||
|
|
||||||
store_room(Host, Name, Opts) ->
|
store_room(Host, Name, Opts) ->
|
||||||
@ -177,7 +177,7 @@ migrate(_Node, _UpOrDown, After) ->
|
|||||||
['$$']}]),
|
['$$']}]),
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun([NameHost, Pid]) ->
|
fun([NameHost, Pid]) ->
|
||||||
case ejabberd_cluster:get_node(NameHost) of
|
case get_node(NameHost) of
|
||||||
Node when Node /= node() ->
|
Node when Node /= node() ->
|
||||||
mod_muc_room:migrate(Pid, Node, random:uniform(After));
|
mod_muc_room:migrate(Pid, Node, random:uniform(After));
|
||||||
_ ->
|
_ ->
|
||||||
@ -198,7 +198,7 @@ copy_rooms('$end_of_table') ->
|
|||||||
copy_rooms(Key) ->
|
copy_rooms(Key) ->
|
||||||
case mnesia:dirty_read(muc_online_room, Key) of
|
case mnesia:dirty_read(muc_online_room, Key) of
|
||||||
[#muc_online_room{name_host = NameHost} = Room] ->
|
[#muc_online_room{name_host = NameHost} = Room] ->
|
||||||
case ejabberd_cluster:get_node_new(NameHost) of
|
case get_node_new(NameHost) of
|
||||||
Node when node() /= Node ->
|
Node when node() /= Node ->
|
||||||
rpc:cast(Node, mnesia, dirty_write, [Room]);
|
rpc:cast(Node, mnesia, dirty_write, [Room]);
|
||||||
_ ->
|
_ ->
|
||||||
@ -315,7 +315,7 @@ handle_info({route, From, To, Packet},
|
|||||||
history_size = HistorySize,
|
history_size = HistorySize,
|
||||||
room_shaper = RoomShaper} = State) ->
|
room_shaper = RoomShaper} = State) ->
|
||||||
{U, S, _} = jlib:jid_tolower(To),
|
{U, S, _} = jlib:jid_tolower(To),
|
||||||
case ejabberd_cluster:get_node({U, S}) of
|
case get_node({U, S}) of
|
||||||
Node when Node == node() ->
|
Node when Node == node() ->
|
||||||
case catch do_route(Host, ServerHost, Access, HistorySize,
|
case catch do_route(Host, ServerHost, Access, HistorySize,
|
||||||
RoomShaper, From, To, Packet, DefRoomOpts) of
|
RoomShaper, From, To, Packet, DefRoomOpts) of
|
||||||
@ -335,7 +335,7 @@ handle_info({room_destroyed, RoomHost, Pid}, State) ->
|
|||||||
pid = Pid})
|
pid = Pid})
|
||||||
end,
|
end,
|
||||||
mnesia:async_dirty(F),
|
mnesia:async_dirty(F),
|
||||||
case ejabberd_cluster:get_node_new(RoomHost) of
|
case get_node_new(RoomHost) of
|
||||||
Node when Node /= node() ->
|
Node when Node /= node() ->
|
||||||
rpc:cast(Node, mnesia, dirty_delete_object,
|
rpc:cast(Node, mnesia, dirty_delete_object,
|
||||||
[#muc_online_room{name_host = RoomHost,
|
[#muc_online_room{name_host = RoomHost,
|
||||||
@ -603,19 +603,26 @@ load_permanent_rooms(Host, ServerHost, Access, HistorySize, RoomShaper) ->
|
|||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun(R) ->
|
fun(R) ->
|
||||||
{Room, Host} = R#muc_room.name_host,
|
{Room, Host} = R#muc_room.name_host,
|
||||||
case ejabberd_cluster:get_node({Room, Host}) of
|
case get_node({Room, Host}) of
|
||||||
Node when Node == node() ->
|
Node when Node == node() ->
|
||||||
case mnesia:dirty_read(muc_online_room, {Room, Host}) of
|
case mnesia:dirty_read(muc_online_room, {Room, Host}) of
|
||||||
[] ->
|
[] ->
|
||||||
{ok, Pid} = mod_muc_room:start(
|
case get_room_state_if_broadcasted(
|
||||||
Host,
|
{Room, Host}) of
|
||||||
ServerHost,
|
{ok, RoomState} ->
|
||||||
Access,
|
mod_muc_room:start(
|
||||||
Room,
|
normal_state, RoomState);
|
||||||
HistorySize,
|
error ->
|
||||||
RoomShaper,
|
{ok, Pid} = mod_muc_room:start(
|
||||||
R#muc_room.opts),
|
Host,
|
||||||
register_room(Host, Room, Pid);
|
ServerHost,
|
||||||
|
Access,
|
||||||
|
Room,
|
||||||
|
HistorySize,
|
||||||
|
RoomShaper,
|
||||||
|
R#muc_room.opts),
|
||||||
|
register_room(Host, Room, Pid)
|
||||||
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
ok
|
ok
|
||||||
end;
|
end;
|
||||||
@ -628,18 +635,24 @@ load_permanent_rooms(Host, ServerHost, Access, HistorySize, RoomShaper) ->
|
|||||||
start_new_room(Host, ServerHost, Access, Room,
|
start_new_room(Host, ServerHost, Access, Room,
|
||||||
HistorySize, RoomShaper, From,
|
HistorySize, RoomShaper, From,
|
||||||
Nick, DefRoomOpts) ->
|
Nick, DefRoomOpts) ->
|
||||||
case mnesia:dirty_read(muc_room, {Room, Host}) of
|
case get_room_state_if_broadcasted({Room, Host}) of
|
||||||
[] ->
|
{ok, RoomState} ->
|
||||||
?DEBUG("MUC: open new room '~s'~n", [Room]),
|
?DEBUG("MUC: restore room '~s' from other node~n", [Room]),
|
||||||
mod_muc_room:start(Host, ServerHost, Access,
|
mod_muc_room:start(normal_state, RoomState);
|
||||||
Room, HistorySize,
|
error ->
|
||||||
RoomShaper, From,
|
case mnesia:dirty_read(muc_room, {Room, Host}) of
|
||||||
Nick, DefRoomOpts);
|
[] ->
|
||||||
[#muc_room{opts = Opts}|_] ->
|
?DEBUG("MUC: open new room '~s'~n", [Room]),
|
||||||
?DEBUG("MUC: restore room '~s'~n", [Room]),
|
mod_muc_room:start(Host, ServerHost, Access,
|
||||||
mod_muc_room:start(Host, ServerHost, Access,
|
Room, HistorySize,
|
||||||
Room, HistorySize,
|
RoomShaper, From,
|
||||||
RoomShaper, Opts)
|
Nick, DefRoomOpts);
|
||||||
|
[#muc_room{opts = Opts}|_] ->
|
||||||
|
?DEBUG("MUC: restore room '~s'~n", [Room]),
|
||||||
|
mod_muc_room:start(Host, ServerHost, Access,
|
||||||
|
Room, HistorySize,
|
||||||
|
RoomShaper, Opts)
|
||||||
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
register_room(Host, Room, Pid) ->
|
register_room(Host, Room, Pid) ->
|
||||||
@ -648,7 +661,7 @@ register_room(Host, Room, Pid) ->
|
|||||||
pid = Pid})
|
pid = Pid})
|
||||||
end,
|
end,
|
||||||
mnesia:async_dirty(F),
|
mnesia:async_dirty(F),
|
||||||
case ejabberd_cluster:get_node_new({Room, Host}) of
|
case get_node_new({Room, Host}) of
|
||||||
Node when Node /= node() ->
|
Node when Node /= node() ->
|
||||||
%% New node has just been added. But we may miss MUC records
|
%% New node has just been added. But we may miss MUC records
|
||||||
%% copy procedure, so we copy the MUC record manually just
|
%% copy procedure, so we copy the MUC record manually just
|
||||||
@ -656,7 +669,7 @@ register_room(Host, Room, Pid) ->
|
|||||||
rpc:cast(Node, mnesia, dirty_write,
|
rpc:cast(Node, mnesia, dirty_write,
|
||||||
[#muc_online_room{name_host = {Room, Host},
|
[#muc_online_room{name_host = {Room, Host},
|
||||||
pid = Pid}]),
|
pid = Pid}]),
|
||||||
case ejabberd_cluster:get_node({Room, Host}) of
|
case get_node({Room, Host}) of
|
||||||
Node when node() /= Node ->
|
Node when node() /= Node ->
|
||||||
%% Migration to new node has completed, and seems like
|
%% Migration to new node has completed, and seems like
|
||||||
%% we missed it, so we migrate the MUC room pid manually.
|
%% we missed it, so we migrate the MUC room pid manually.
|
||||||
@ -934,7 +947,7 @@ get_vh_rooms_all_nodes(Host) ->
|
|||||||
_ ->
|
_ ->
|
||||||
Acc
|
Acc
|
||||||
end
|
end
|
||||||
end, [], ejabberd_cluster:get_nodes()),
|
end, [], get_nodes(Host)),
|
||||||
lists:ukeysort(#muc_online_room.name_host, Rooms).
|
lists:ukeysort(#muc_online_room.name_host, Rooms).
|
||||||
|
|
||||||
get_vh_rooms(Host) ->
|
get_vh_rooms(Host) ->
|
||||||
@ -1038,3 +1051,67 @@ update_muc_registered_table(Host) ->
|
|||||||
?INFO_MSG("Recreating muc_registered table", []),
|
?INFO_MSG("Recreating muc_registered table", []),
|
||||||
mnesia:transform_table(muc_registered, ignore, Fields)
|
mnesia:transform_table(muc_registered, ignore, Fields)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
is_broadcasted(RoomHost) ->
|
||||||
|
case ejabberd_config:get_local_option({domain_balancing, RoomHost}) of
|
||||||
|
broadcast ->
|
||||||
|
true;
|
||||||
|
_ ->
|
||||||
|
false
|
||||||
|
end.
|
||||||
|
|
||||||
|
get_node({_, RoomHost} = Key) ->
|
||||||
|
case is_broadcasted(RoomHost) of
|
||||||
|
true ->
|
||||||
|
node();
|
||||||
|
false ->
|
||||||
|
ejabberd_cluster:get_node(Key)
|
||||||
|
end;
|
||||||
|
get_node(RoomHost) ->
|
||||||
|
get_node({"", RoomHost}).
|
||||||
|
|
||||||
|
get_node_new({_, RoomHost} = Key) ->
|
||||||
|
case is_broadcasted(RoomHost) of
|
||||||
|
true ->
|
||||||
|
node();
|
||||||
|
false ->
|
||||||
|
ejabberd_cluster:get_node_new(Key)
|
||||||
|
end;
|
||||||
|
get_node_new(RoomHost) ->
|
||||||
|
get_node_new({"", RoomHost}).
|
||||||
|
|
||||||
|
get_nodes(RoomHost) ->
|
||||||
|
case is_broadcasted(RoomHost) of
|
||||||
|
true ->
|
||||||
|
[node()];
|
||||||
|
false ->
|
||||||
|
ejabberd_cluster:get_nodes()
|
||||||
|
end.
|
||||||
|
|
||||||
|
get_room_state_if_broadcasted({Room, Host}) ->
|
||||||
|
case is_broadcasted(Host) of
|
||||||
|
true ->
|
||||||
|
lists:foldl(
|
||||||
|
fun(_, {ok, StateData}) ->
|
||||||
|
{ok, StateData};
|
||||||
|
(Node, _) when Node /= node() ->
|
||||||
|
case catch rpc:call(
|
||||||
|
Node, mnesia, dirty_read,
|
||||||
|
[muc_online_room, {Room, Host}], 5000) of
|
||||||
|
[#muc_online_room{pid = Pid}] ->
|
||||||
|
case catch gen_fsm:sync_send_all_state_event(
|
||||||
|
Pid, get_state, 5000) of
|
||||||
|
{ok, StateData} ->
|
||||||
|
{ok, StateData};
|
||||||
|
_ ->
|
||||||
|
error
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
error
|
||||||
|
end;
|
||||||
|
(_, Acc) ->
|
||||||
|
Acc
|
||||||
|
end, error, ejabberd_cluster:get_nodes());
|
||||||
|
false ->
|
||||||
|
error
|
||||||
|
end.
|
||||||
|
@ -187,7 +187,7 @@ normal_state({route, From, "",
|
|||||||
ErrText = "Traffic rate limit is exceeded",
|
ErrText = "Traffic rate limit is exceeded",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)),
|
Packet, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
From, Err),
|
From, Err),
|
||||||
{next_state, normal_state, StateData};
|
{next_state, normal_state, StateData};
|
||||||
@ -268,7 +268,7 @@ normal_state({route, From, "",
|
|||||||
ErrText = "It is not allowed to send private messages to the conference",
|
ErrText = "It is not allowed to send private messages to the conference",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
From, Err),
|
From, Err),
|
||||||
{next_state, normal_state, StateData};
|
{next_state, normal_state, StateData};
|
||||||
@ -277,7 +277,7 @@ normal_state({route, From, "",
|
|||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, Error),
|
Packet, Error),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
From, Err),
|
From, Err),
|
||||||
{next_state, normal_state, StateData};
|
{next_state, normal_state, StateData};
|
||||||
@ -313,7 +313,7 @@ normal_state({route, From, "",
|
|||||||
ErrText = "Improper message type",
|
ErrText = "Improper message type",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
From, Err),
|
From, Err),
|
||||||
{next_state, normal_state, StateData}
|
{next_state, normal_state, StateData}
|
||||||
@ -364,7 +364,7 @@ normal_state({route, From, "",
|
|||||||
sub_el = [SubEl, Error]},
|
sub_el = [SubEl, Error]},
|
||||||
StateData}
|
StateData}
|
||||||
end,
|
end,
|
||||||
ejabberd_router:route(StateData#state.jid,
|
route_stanza(StateData#state.jid,
|
||||||
From,
|
From,
|
||||||
jlib:iq_to_xml(IQRes)),
|
jlib:iq_to_xml(IQRes)),
|
||||||
case NewStateData of
|
case NewStateData of
|
||||||
@ -378,7 +378,7 @@ normal_state({route, From, "",
|
|||||||
_ ->
|
_ ->
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERR_FEATURE_NOT_IMPLEMENTED),
|
Packet, ?ERR_FEATURE_NOT_IMPLEMENTED),
|
||||||
ejabberd_router:route(StateData#state.jid, From, Err),
|
route_stanza(StateData#state.jid, From, Err),
|
||||||
{next_state, normal_state, StateData}
|
{next_state, normal_state, StateData}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -437,7 +437,7 @@ normal_state({route, From, ToNick,
|
|||||||
"messages of type \"groupchat\"",
|
"messages of type \"groupchat\"",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_BAD_REQUEST(Lang, ErrText)),
|
Packet, ?ERRT_BAD_REQUEST(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
ToNick),
|
ToNick),
|
||||||
@ -455,7 +455,7 @@ normal_state({route, From, ToNick,
|
|||||||
ErrText = "Recipient is not in the conference room",
|
ErrText = "Recipient is not in the conference room",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)),
|
Packet, ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
ToNick),
|
ToNick),
|
||||||
@ -465,13 +465,13 @@ normal_state({route, From, ToNick,
|
|||||||
?DICT:find(jlib:jid_tolower(From),
|
?DICT:find(jlib:jid_tolower(From),
|
||||||
StateData#state.users),
|
StateData#state.users),
|
||||||
FromNickJID = jlib:jid_replace_resource(StateData#state.jid, FromNick),
|
FromNickJID = jlib:jid_replace_resource(StateData#state.jid, FromNick),
|
||||||
[ejabberd_router:route(FromNickJID, ToJID, Packet) || ToJID <- ToJIDs]
|
[route_stanza(FromNickJID, ToJID, Packet) || ToJID <- ToJIDs]
|
||||||
end;
|
end;
|
||||||
true ->
|
true ->
|
||||||
ErrText = "It is not allowed to send private messages",
|
ErrText = "It is not allowed to send private messages",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_FORBIDDEN(Lang, ErrText)),
|
Packet, ?ERRT_FORBIDDEN(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
ToNick),
|
ToNick),
|
||||||
@ -482,7 +482,7 @@ normal_state({route, From, ToNick,
|
|||||||
ErrText = "Only occupants are allowed to send messages to the conference",
|
ErrText = "Only occupants are allowed to send messages to the conference",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
ToNick),
|
ToNick),
|
||||||
@ -491,7 +491,7 @@ normal_state({route, From, ToNick,
|
|||||||
ErrText = "It is not allowed to send private messages",
|
ErrText = "It is not allowed to send private messages",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_FORBIDDEN(Lang, ErrText)),
|
Packet, ?ERRT_FORBIDDEN(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
ToNick),
|
ToNick),
|
||||||
@ -517,7 +517,7 @@ normal_state({route, From, ToNick,
|
|||||||
ErrText = "Recipient is not in the conference room",
|
ErrText = "Recipient is not in the conference room",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)),
|
Packet, ?ERRT_ITEM_NOT_FOUND(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid, ToNick),
|
StateData#state.jid, ToNick),
|
||||||
From, Err)
|
From, Err)
|
||||||
@ -528,7 +528,7 @@ normal_state({route, From, ToNick,
|
|||||||
StateData#state.users),
|
StateData#state.users),
|
||||||
{ToJID2, Packet2} = handle_iq_vcard(FromFull, ToJID,
|
{ToJID2, Packet2} = handle_iq_vcard(FromFull, ToJID,
|
||||||
StanzaId, NewId,Packet),
|
StanzaId, NewId,Packet),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(StateData#state.jid, FromNick),
|
jlib:jid_replace_resource(StateData#state.jid, FromNick),
|
||||||
ToJID2, Packet2)
|
ToJID2, Packet2)
|
||||||
end;
|
end;
|
||||||
@ -540,7 +540,7 @@ normal_state({route, From, ToNick,
|
|||||||
ErrText = "Only occupants are allowed to send queries to the conference",
|
ErrText = "Only occupants are allowed to send queries to the conference",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(StateData#state.jid, ToNick),
|
jlib:jid_replace_resource(StateData#state.jid, ToNick),
|
||||||
From, Err)
|
From, Err)
|
||||||
end;
|
end;
|
||||||
@ -552,7 +552,7 @@ normal_state({route, From, ToNick,
|
|||||||
ErrText = "Queries to the conference members are not allowed in this room",
|
ErrText = "Queries to the conference members are not allowed in this room",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_NOT_ALLOWED(Lang, ErrText)),
|
Packet, ?ERRT_NOT_ALLOWED(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(StateData#state.jid, ToNick),
|
jlib:jid_replace_resource(StateData#state.jid, ToNick),
|
||||||
From, Err)
|
From, Err)
|
||||||
end
|
end
|
||||||
@ -576,7 +576,7 @@ handle_event({service_message, Msg}, _StateName, StateData) ->
|
|||||||
[{xmlelement, "body", [], [{xmlcdata, Msg}]}]},
|
[{xmlelement, "body", [], [{xmlcdata, Msg}]}]},
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({_LJID, Info}) ->
|
fun({_LJID, Info}) ->
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
Info#user.jid,
|
Info#user.jid,
|
||||||
MessagePkt)
|
MessagePkt)
|
||||||
@ -718,7 +718,7 @@ handle_info({captcha_failed, From}, normal_state, StateData) ->
|
|||||||
Robots = ?DICT:erase(From, StateData#state.robots),
|
Robots = ?DICT:erase(From, StateData#state.robots),
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERR_NOT_AUTHORIZED),
|
Packet, ?ERR_NOT_AUTHORIZED),
|
||||||
ejabberd_router:route( % TODO: s/Nick/""/
|
route_stanza( % TODO: s/Nick/""/
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid, Nick),
|
StateData#state.jid, Nick),
|
||||||
From, Err),
|
From, Err),
|
||||||
@ -769,7 +769,7 @@ terminate(Reason, _StateName, StateData) ->
|
|||||||
Nick = Info#user.nick,
|
Nick = Info#user.nick,
|
||||||
case Reason of
|
case Reason of
|
||||||
shutdown ->
|
shutdown ->
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
||||||
Info#user.jid,
|
Info#user.jid,
|
||||||
Packet);
|
Packet);
|
||||||
@ -830,7 +830,7 @@ process_groupchat_message(From, {xmlelement, "message", Attrs, _Els} = Packet,
|
|||||||
true ->
|
true ->
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
fun({_LJID, Info}) ->
|
fun({_LJID, Info}) ->
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
FromNick),
|
FromNick),
|
||||||
@ -858,7 +858,7 @@ process_groupchat_message(From, {xmlelement, "message", Attrs, _Els} = Packet,
|
|||||||
"Only moderators "
|
"Only moderators "
|
||||||
"are allowed to change the subject in this room")
|
"are allowed to change the subject in this room")
|
||||||
end,
|
end,
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
From,
|
From,
|
||||||
jlib:make_error_reply(Packet, Err)),
|
jlib:make_error_reply(Packet, Err)),
|
||||||
@ -868,7 +868,7 @@ process_groupchat_message(From, {xmlelement, "message", Attrs, _Els} = Packet,
|
|||||||
ErrText = "Visitors are not allowed to send messages to all occupants",
|
ErrText = "Visitors are not allowed to send messages to all occupants",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_FORBIDDEN(Lang, ErrText)),
|
Packet, ?ERRT_FORBIDDEN(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
From, Err),
|
From, Err),
|
||||||
{next_state, normal_state, StateData}
|
{next_state, normal_state, StateData}
|
||||||
@ -877,7 +877,7 @@ process_groupchat_message(From, {xmlelement, "message", Attrs, _Els} = Packet,
|
|||||||
ErrText = "Only occupants are allowed to send messages to the conference",
|
ErrText = "Only occupants are allowed to send messages to the conference",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
||||||
ejabberd_router:route(StateData#state.jid, From, Err),
|
route_stanza(StateData#state.jid, From, Err),
|
||||||
{next_state, normal_state, StateData}
|
{next_state, normal_state, StateData}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -961,7 +961,7 @@ process_presence(From, Nick, {xmlelement, "presence", Attrs, _Els} = Packet,
|
|||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet,
|
Packet,
|
||||||
?ERRT_NOT_ALLOWED(Lang, ErrText)),
|
?ERRT_NOT_ALLOWED(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
% TODO: s/Nick/""/
|
% TODO: s/Nick/""/
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
@ -974,7 +974,7 @@ process_presence(From, Nick, {xmlelement, "presence", Attrs, _Els} = Packet,
|
|||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet,
|
Packet,
|
||||||
?ERRT_CONFLICT(Lang, ErrText)),
|
?ERRT_CONFLICT(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
Nick), % TODO: s/Nick/""/
|
Nick), % TODO: s/Nick/""/
|
||||||
@ -985,7 +985,7 @@ process_presence(From, Nick, {xmlelement, "presence", Attrs, _Els} = Packet,
|
|||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet,
|
Packet,
|
||||||
?ERRT_CONFLICT(Lang, ErrText)),
|
?ERRT_CONFLICT(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
% TODO: s/Nick/""/
|
% TODO: s/Nick/""/
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
@ -1680,7 +1680,7 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) ->
|
|||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet,
|
Packet,
|
||||||
?ERR_SERVICE_UNAVAILABLE),
|
?ERR_SERVICE_UNAVAILABLE),
|
||||||
ejabberd_router:route( % TODO: s/Nick/""/
|
route_stanza( % TODO: s/Nick/""/
|
||||||
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
||||||
From, Err),
|
From, Err),
|
||||||
StateData;
|
StateData;
|
||||||
@ -1695,14 +1695,14 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) ->
|
|||||||
ErrText = "Membership is required to enter this room",
|
ErrText = "Membership is required to enter this room",
|
||||||
?ERRT_REGISTRATION_REQUIRED(Lang, ErrText)
|
?ERRT_REGISTRATION_REQUIRED(Lang, ErrText)
|
||||||
end),
|
end),
|
||||||
ejabberd_router:route( % TODO: s/Nick/""/
|
route_stanza( % TODO: s/Nick/""/
|
||||||
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
||||||
From, Err),
|
From, Err),
|
||||||
StateData;
|
StateData;
|
||||||
{_, true, _, _} ->
|
{_, true, _, _} ->
|
||||||
ErrText = "That nickname is already in use by another occupant",
|
ErrText = "That nickname is already in use by another occupant",
|
||||||
Err = jlib:make_error_reply(Packet, ?ERRT_CONFLICT(Lang, ErrText)),
|
Err = jlib:make_error_reply(Packet, ?ERRT_CONFLICT(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
% TODO: s/Nick/""/
|
% TODO: s/Nick/""/
|
||||||
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
||||||
From, Err),
|
From, Err),
|
||||||
@ -1710,7 +1710,7 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) ->
|
|||||||
{_, _, false, _} ->
|
{_, _, false, _} ->
|
||||||
ErrText = "That nickname is registered by another person",
|
ErrText = "That nickname is registered by another person",
|
||||||
Err = jlib:make_error_reply(Packet, ?ERRT_CONFLICT(Lang, ErrText)),
|
Err = jlib:make_error_reply(Packet, ?ERRT_CONFLICT(Lang, ErrText)),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
% TODO: s/Nick/""/
|
% TODO: s/Nick/""/
|
||||||
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
||||||
From, Err),
|
From, Err),
|
||||||
@ -1731,7 +1731,7 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) ->
|
|||||||
"This room is not anonymous")}]},
|
"This room is not anonymous")}]},
|
||||||
{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
|
{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
|
||||||
[{xmlelement, "status", [{"code", "100"}], []}]}]},
|
[{xmlelement, "status", [{"code", "100"}], []}]}]},
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
From, WPacket);
|
From, WPacket);
|
||||||
true ->
|
true ->
|
||||||
@ -1757,7 +1757,7 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) ->
|
|||||||
ErrText = "A password is required to enter this room",
|
ErrText = "A password is required to enter this room",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_NOT_AUTHORIZED(Lang, ErrText)),
|
Packet, ?ERRT_NOT_AUTHORIZED(Lang, ErrText)),
|
||||||
ejabberd_router:route( % TODO: s/Nick/""/
|
route_stanza( % TODO: s/Nick/""/
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid, Nick),
|
StateData#state.jid, Nick),
|
||||||
From, Err),
|
From, Err),
|
||||||
@ -1773,13 +1773,13 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) ->
|
|||||||
MsgPkt = {xmlelement, "message", [{"id", ID}], CaptchaEls},
|
MsgPkt = {xmlelement, "message", [{"id", ID}], CaptchaEls},
|
||||||
Robots = ?DICT:store(From,
|
Robots = ?DICT:store(From,
|
||||||
{Nick, Packet}, StateData#state.robots),
|
{Nick, Packet}, StateData#state.robots),
|
||||||
ejabberd_router:route(RoomJID, From, MsgPkt),
|
route_stanza(RoomJID, From, MsgPkt),
|
||||||
StateData#state{robots = Robots};
|
StateData#state{robots = Robots};
|
||||||
{error, limit} ->
|
{error, limit} ->
|
||||||
ErrText = "Too many CAPTCHA requests",
|
ErrText = "Too many CAPTCHA requests",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)),
|
Packet, ?ERRT_RESOURCE_CONSTRAINT(Lang, ErrText)),
|
||||||
ejabberd_router:route( % TODO: s/Nick/""/
|
route_stanza( % TODO: s/Nick/""/
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid, Nick),
|
StateData#state.jid, Nick),
|
||||||
From, Err),
|
From, Err),
|
||||||
@ -1788,7 +1788,7 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) ->
|
|||||||
ErrText = "Unable to generate a captcha",
|
ErrText = "Unable to generate a captcha",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_INTERNAL_SERVER_ERROR(Lang, ErrText)),
|
Packet, ?ERRT_INTERNAL_SERVER_ERROR(Lang, ErrText)),
|
||||||
ejabberd_router:route( % TODO: s/Nick/""/
|
route_stanza( % TODO: s/Nick/""/
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid, Nick),
|
StateData#state.jid, Nick),
|
||||||
From, Err),
|
From, Err),
|
||||||
@ -1798,7 +1798,7 @@ add_new_user(From, Nick, {xmlelement, _, Attrs, Els} = Packet, StateData) ->
|
|||||||
ErrText = "Incorrect password",
|
ErrText = "Incorrect password",
|
||||||
Err = jlib:make_error_reply(
|
Err = jlib:make_error_reply(
|
||||||
Packet, ?ERRT_NOT_AUTHORIZED(Lang, ErrText)),
|
Packet, ?ERRT_NOT_AUTHORIZED(Lang, ErrText)),
|
||||||
ejabberd_router:route( % TODO: s/Nick/""/
|
route_stanza( % TODO: s/Nick/""/
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid, Nick),
|
StateData#state.jid, Nick),
|
||||||
From, Err),
|
From, Err),
|
||||||
@ -2074,7 +2074,7 @@ send_new_presence(NJID, Reason, StateData) ->
|
|||||||
Presence,
|
Presence,
|
||||||
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
|
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
|
||||||
[{xmlelement, "item", ItemAttrs, ItemEls} | Status3]}]),
|
[{xmlelement, "item", ItemAttrs, ItemEls} | Status3]}]),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
||||||
Info#user.jid,
|
Info#user.jid,
|
||||||
Packet)
|
Packet)
|
||||||
@ -2116,7 +2116,7 @@ send_existing_presences(ToJID, StateData) ->
|
|||||||
Presence,
|
Presence,
|
||||||
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
|
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
|
||||||
[{xmlelement, "item", ItemAttrs, []}]}]),
|
[{xmlelement, "item", ItemAttrs, []}]}]),
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(
|
jlib:jid_replace_resource(
|
||||||
StateData#state.jid, FromNick),
|
StateData#state.jid, FromNick),
|
||||||
RealToJID,
|
RealToJID,
|
||||||
@ -2214,7 +2214,7 @@ send_nick_changing(JID, OldNick, StateData,
|
|||||||
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
|
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
|
||||||
[{xmlelement, "item", ItemAttrs2, []}]}]),
|
[{xmlelement, "item", ItemAttrs2, []}]}]),
|
||||||
if SendOldUnavailable ->
|
if SendOldUnavailable ->
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(StateData#state.jid, OldNick),
|
jlib:jid_replace_resource(StateData#state.jid, OldNick),
|
||||||
Info#user.jid,
|
Info#user.jid,
|
||||||
Packet1);
|
Packet1);
|
||||||
@ -2222,7 +2222,7 @@ send_nick_changing(JID, OldNick, StateData,
|
|||||||
ok
|
ok
|
||||||
end,
|
end,
|
||||||
if SendNewAvailable ->
|
if SendNewAvailable ->
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
||||||
Info#user.jid,
|
Info#user.jid,
|
||||||
Packet2);
|
Packet2);
|
||||||
@ -2294,7 +2294,7 @@ add_message_to_history(FromNick, FromJID, Packet, StateData) ->
|
|||||||
send_history(JID, Shift, StateData) ->
|
send_history(JID, Shift, StateData) ->
|
||||||
lists:foldl(
|
lists:foldl(
|
||||||
fun({Nick, Packet, HaveSubject, _TimeStamp, _Size}, B) ->
|
fun({Nick, Packet, HaveSubject, _TimeStamp, _Size}, B) ->
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
||||||
JID,
|
JID,
|
||||||
Packet),
|
Packet),
|
||||||
@ -2316,7 +2316,7 @@ send_subject(JID, Lang, StateData) ->
|
|||||||
translate:translate(Lang,
|
translate:translate(Lang,
|
||||||
" has set the subject to: ") ++
|
" has set the subject to: ") ++
|
||||||
Subject}]}]},
|
Subject}]}]},
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
StateData#state.jid,
|
StateData#state.jid,
|
||||||
JID,
|
JID,
|
||||||
Packet)
|
Packet)
|
||||||
@ -2903,7 +2903,7 @@ send_kickban_presence1(UJID, Reason, Code, Affiliation, StateData) ->
|
|||||||
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
|
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
|
||||||
[{xmlelement, "item", ItemAttrs, ItemEls},
|
[{xmlelement, "item", ItemAttrs, ItemEls},
|
||||||
{xmlelement, "status", [{"code", Code}], []}]}]},
|
{xmlelement, "status", [{"code", Code}], []}]}]},
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
||||||
Info#user.jid,
|
Info#user.jid,
|
||||||
Packet)
|
Packet)
|
||||||
@ -3527,7 +3527,7 @@ destroy_room(DEl, StateData) ->
|
|||||||
Packet = {xmlelement, "presence", [{"type", "unavailable"}],
|
Packet = {xmlelement, "presence", [{"type", "unavailable"}],
|
||||||
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
|
[{xmlelement, "x", [{"xmlns", ?NS_MUC_USER}],
|
||||||
[{xmlelement, "item", ItemAttrs, []}, DEl]}]},
|
[{xmlelement, "item", ItemAttrs, []}, DEl]}]},
|
||||||
ejabberd_router:route(
|
route_stanza(
|
||||||
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
jlib:jid_replace_resource(StateData#state.jid, Nick),
|
||||||
Info#user.jid,
|
Info#user.jid,
|
||||||
Packet)
|
Packet)
|
||||||
@ -3769,7 +3769,7 @@ check_invitation(From, Els, Lang, StateData) ->
|
|||||||
""})}],
|
""})}],
|
||||||
[{xmlcdata, Reason}]},
|
[{xmlcdata, Reason}]},
|
||||||
Body]},
|
Body]},
|
||||||
ejabberd_router:route(StateData#state.jid, JID, Msg),
|
route_stanza(StateData#state.jid, JID, Msg),
|
||||||
JID
|
JID
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@ -3807,7 +3807,7 @@ send_decline_invitation({Packet, XEl, DEl, ToJID}, RoomJID, FromJID) ->
|
|||||||
DEl2 = {xmlelement, "decline", DAttrs3, DEls},
|
DEl2 = {xmlelement, "decline", DAttrs3, DEls},
|
||||||
XEl2 = replace_subelement(XEl, DEl2),
|
XEl2 = replace_subelement(XEl, DEl2),
|
||||||
Packet2 = replace_subelement(Packet, XEl2),
|
Packet2 = replace_subelement(Packet, XEl2),
|
||||||
ejabberd_router:route(RoomJID, ToJID, Packet2).
|
route_stanza(RoomJID, ToJID, Packet2).
|
||||||
|
|
||||||
%% Given an element and a new subelement,
|
%% Given an element and a new subelement,
|
||||||
%% replace the instance of the subelement in element with the new subelement.
|
%% replace the instance of the subelement in element with the new subelement.
|
||||||
@ -3819,7 +3819,7 @@ replace_subelement({xmlelement, Name, Attrs, SubEls}, NewSubEl) ->
|
|||||||
send_error_only_occupants(Packet, Lang, RoomJID, From) ->
|
send_error_only_occupants(Packet, Lang, RoomJID, From) ->
|
||||||
ErrText = "Only occupants are allowed to send messages to the conference",
|
ErrText = "Only occupants are allowed to send messages to the conference",
|
||||||
Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
Err = jlib:make_error_reply(Packet, ?ERRT_NOT_ACCEPTABLE(Lang, ErrText)),
|
||||||
ejabberd_router:route(RoomJID, From, Err).
|
route_stanza(RoomJID, From, Err).
|
||||||
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
@ -3877,3 +3877,12 @@ tab_count_user(JID) ->
|
|||||||
|
|
||||||
element_size(El) ->
|
element_size(El) ->
|
||||||
size(xml:element_to_binary(El)).
|
size(xml:element_to_binary(El)).
|
||||||
|
|
||||||
|
route_stanza(From, To, El) ->
|
||||||
|
#jid{luser = LUser, lserver = LServer} = To,
|
||||||
|
case ejabberd_cluster:get_node({LUser, LServer}) of
|
||||||
|
Node when Node == node() ->
|
||||||
|
ejabberd_router:route(From, To, El);
|
||||||
|
_ ->
|
||||||
|
ok
|
||||||
|
end.
|
||||||
|
Loading…
Reference in New Issue
Block a user