Software /
code /
prosody-modules
File
mod_client_proxy/mod_client_proxy.lua @ 5173:460f78654864
mod_muc_rtbl: also filter messages
This was a bit tricky because we don't want to run the JIDs
through SHA256 on each message. Took a while to come up with this
simple plan of just caching the SHA256 of the JIDs on the
occupants.
This will leave some dirt in the occupants after unloading the
module, but that should be ok; once they cycle the room, the
hashes will be gone.
This is direly needed, otherwise, there is a tight race between
the moderation activities and the actors joining the room.
author | Jonas Schäfer <jonas@wielicki.name> |
---|---|
date | Tue, 21 Feb 2023 21:37:27 +0100 |
parent | 3101:a14a573d43ff |
line wrap: on
line source
if module:get_host_type() ~= "component" then error("proxy_component should be loaded as component", 0); end local jid_split = require "util.jid".split; local jid_bare = require "util.jid".bare; local jid_prep = require "util.jid".prep; local st = require "util.stanza"; local array = require "util.array"; local target_address = module:get_option_string("target_address"); sessions = array{}; local sessions = sessions; local function handle_target_presence(stanza) local type = stanza.attr.type; module:log("debug", "received presence from destination: %s", type) local _, _, resource = jid_split(stanza.attr.from); if type == "error" then -- drop all known sessions for k in pairs(sessions) do sessions[k] = nil end module:log( "debug", "received error presence, dropping all target sessions", resource ) elseif type == "unavailable" then for k in pairs(sessions) do if sessions[k] == resource then sessions[k] = nil module:log( "debug", "dropped target session: %s", resource ) break end end elseif not type then -- available local found = false; for k in pairs(sessions) do if sessions[k] == resource then found = true; break end end if not found then module:log( "debug", "registered new target session: %s", resource ) sessions:push(resource) end end end local function handle_from_target(stanza) local type = stanza.attr.type module:log( "debug", "non-presence stanza from target: name = %s, type = %s", stanza.name, type ) if stanza.name == "iq" then if type == "error" or type == "result" then -- de-NAT message local _, _, denatted_to_unprepped = jid_split(stanza.attr.to); local denatted_to = jid_prep(denatted_to_unprepped); if not denatted_to then module:log( "debug", "cannot de-NAT stanza, invalid to: %s", denatted_to_unprepped ) return end local denatted_from = module:get_host(); module:log( "debug", "de-NAT-ed stanza: from: %s -> %s, to: %s -> %s", stanza.attr.from, denatted_from, stanza.attr.to, denatted_to ) stanza.attr.from = denatted_from stanza.attr.to = denatted_to module:send(stanza) else -- FIXME: we don’t support NATing outbund requests atm. module:send(st.error_reply(stanza, "cancel", "feature-not-implemented")) end elseif stanza.name == "message" then -- not implemented yet, we need a way to ensure that routing doesn’t -- break module:send(st.error_reply(stanza, "cancel", "feature-not-implemented")) end end local function handle_to_target(stanza) local type = stanza.attr.type; module:log( "debug", "stanza to target: name = %s, type = %s", stanza.name, type ) if stanza.name == "presence" then if type ~= "error" then module:send(st.error_reply(stanza, "cancel", "bad-request")) return end elseif stanza.name == "iq" then if type == "get" or type == "set" then if #sessions == 0 then -- no sessions available to send to module:log("debug", "no sessions to send to!") module:send(st.error_reply(stanza, "cancel", "service-unavailable")) return end -- find a target session local target_session = sessions:random() local target = target_address .. "/" .. target_session -- encode sender JID in resource local natted_from = module:get_host() .. "/" .. stanza.attr.from; module:log( "debug", "NAT-ed stanza: from: %s -> %s, to: %s -> %s", stanza.attr.from, natted_from, stanza.attr.to, target ) stanza.attr.from = natted_from stanza.attr.to = target module:send(stanza) end -- FIXME: handle and forward result/error correctly elseif stanza.name == "message" then -- not implemented yet, we need a way to ensure that routing doesn’t -- break module:send(st.error_reply(stanza, "cancel", "feature-not-implemented")) end end local function stanza_handler(event) local origin, stanza = event.origin, event.stanza module:log("debug", "received stanza from %s session", origin.type) local bare_from = jid_bare(stanza.attr.from); local _, _, to = jid_split(stanza.attr.to); if bare_from == target_address then -- from our target, to whom? if not to then -- directly to component if stanza.name == "presence" then handle_target_presence(stanza) else module:send(st.error_reply(stanza, "cancel", "bad-request")) return true end else -- to someone else handle_from_target(stanza) end else handle_to_target(stanza) end return true end module:hook("iq/bare", stanza_handler, -1); module:hook("message/bare", stanza_handler, -1); module:hook("presence/bare", stanza_handler, -1); module:hook("iq/full", stanza_handler, -1); module:hook("message/full", stanza_handler, -1); module:hook("presence/full", stanza_handler, -1); module:hook("iq/host", stanza_handler, -1); module:hook("message/host", stanza_handler, -1); module:hook("presence/host", stanza_handler, -1); module:log("debug", "loaded proxy on %s", module:get_host()) subscription_request = st.presence({ type = "subscribe", to = target_address, from = module:get_host()} ) module:send(subscription_request)