fix(visitors): Fixes s2s multiple connections.

We cannot use filters with s2s as not sending a stanza will result skipping existing connection and creating a new one.
This also clears some of the "No hosts[from_host] (please report)" errors, but there is still one (easy to repro is we disable the jicofo locking) on join we see a presence trying to be routed using the wrong from (virtual  tenant jid).
This commit is contained in:
damencho
2023-05-31 17:15:02 -05:00
committed by Дамян Минков
parent 0a84dbb302
commit 06e86a2f3e
4 changed files with 55 additions and 9 deletions

View File

@@ -20,6 +20,7 @@ local room_jid_match_rewrite = util.room_jid_match_rewrite;
local get_room_from_jid = util.get_room_from_jid;
local get_focus_occupant = util.get_focus_occupant;
local internal_room_jid_match_rewrite = util.internal_room_jid_match_rewrite;
local presence_check_status = util.presence_check_status;
-- this is the main virtual host of this vnode
local local_domain = module:get_option_string('muc_mapper_domain_base');
@@ -325,6 +326,8 @@ module:hook('muc-occupant-groupchat', function(event)
if occupant and occupant_host ~= main_domain then
local main_message = st.clone(stanza);
main_message.attr.to = jid.join(jid.node(room.jid), muc_domain_prefix..'.'..main_domain);
-- make sure we fix the from to be the real jid
main_message.attr.from = room_jid_match_rewrite(stanza.attr.from);
module:send(main_message);
end
stanza.attr.from = from; -- something prosody does internally
@@ -461,15 +464,24 @@ end
module:hook('iq/host', iq_from_main_handler, 10);
-- Filters presences (if detected) that are with destination the main prosody
function filter_stanza(stanza)
if not stanza.attr or not stanza.attr.to or stanza.name ~= 'presence' then
return stanza;
end
function filter_stanza(stanza, session)
if (stanza.name == 'presence' or stanza.name == 'message') and session.type ~= 'c2s' then
-- we clone it so we do not affect broadcast using same stanza, sending it to clients
local f_st = st.clone(stanza);
f_st.skipMapping = true;
return f_st;
elseif stanza.name == 'presence' and session.type == 'c2s' and jid.node(stanza.attr.to) == 'focus' then
local x = stanza:get_child('x', 'http://jabber.org/protocol/muc#user');
if presence_check_status(x, '110') then
return stanza; -- no filter
end
if jid.host(stanza.attr.to) == main_domain then
-- we want to filter presences to jicofo for the main participants
-- no point of having them, but if it is the one of the first to be sent
-- when first visitor is joining can produce the 'No hosts[from_host]' error as we
-- rewrite the from, but we need to not do it to be able to filter it later for the s2s
return nil; -- returning nil filters the stanza
end
return stanza; -- no filter
end
function filter_session(session)
@@ -478,3 +490,34 @@ function filter_session(session)
end
filters.add_filter_hook(filter_session);
function route_s2s_stanza(event)
local from_host, to_host, stanza = event.from_host, event.to_host, event.stanza;
if to_host ~= main_domain then
return; -- continue with hook listeners
end
if stanza.name == 'message' then
if jid.resource(stanza.to) then
-- there is no point of delivering messages to main participants individually
return true; -- drop it
end
return;
end
if stanza.name == 'presence' then
-- we want to leave only unavailable presences to go to main node
-- all other presences from jicofo or the main participants there is no point to go to the main node
-- they are anyway not handled
if stanza.attr.type ~= 'unavailable' then
return true; -- drop it
end
return;
end
end
-- routing to sessions in mod_s2s is -1 and -10, we want to hook before that to make sure to is correct
-- or if we want to filter that stanza
module:hook("route/remote", route_s2s_stanza, 10);

View File

@@ -17,6 +17,10 @@ local internal_room_jid_match_rewrite = util.internal_room_jid_match_rewrite;
-- We must filter stanzas in order to hook in to all incoming and outgoing messaging which skips the stanza routers
function filter_stanza(stanza)
if stanza.skipMapping then
return stanza;
end
if stanza.name == "message" or stanza.name == "iq" or stanza.name == "presence" then
-- module:log("debug", "Filtering stanza type %s to %s from %s",stanza.name,stanza.attr.to,stanza.attr.from);
if stanza.name == "iq" then

View File

@@ -115,8 +115,6 @@ function handle_jicofo_unlock(event)
-- and now let's handle all pre_join_queue events
for _, ev in room.pre_join_queue:items() do
-- we see wrong from on some stanzas when using tenants with visitor nodes
ev.stanza.attr.from = internal_room_jid_match_rewrite(ev.stanza.attr.from, ev.stanza)
module:log('info', 'Occupant processed from queue %s', ev.occupant.nick);
room:handle_normal_presence(ev.origin, ev.stanza);
end

View File

@@ -129,7 +129,8 @@ local function stanza_handler(event)
return;
end
if stanza.attr.type == 'result' and sent_iq_cache:get(stanza.attr.id) then
-- we receive error from vnode for our disconnect message as the room was already destroyed (all visitors left)
if (stanza.attr.type == 'result' or stanza.attr.type == 'error') and sent_iq_cache:get(stanza.attr.id) then
sent_iq_cache:set(stanza.attr.id, nil);
return true;
end