Skip to content

Commit

Permalink
Remove the "focus" external component, use client_proxy instead. (#8381)
Browse files Browse the repository at this point in the history
* feat: Add mod_client_proxy and mod_roster_command.

Taken from prosody-modules 4317:456b9f608fcf with the
mod_roster_command patch applied.

* feat: Use mod_client_proxy to proxy to jicofo.
  • Loading branch information
bgrozev authored Jan 11, 2021
1 parent 6ebe2c2 commit b6f7f8f
Show file tree
Hide file tree
Showing 5 changed files with 432 additions and 2 deletions.
15 changes: 15 additions & 0 deletions debian/jitsi-meet-prosody.postinst
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,21 @@ case "$1" in
echo -e " admins = { \"$JICOFO_AUTH_USER@auth.$JVB_HOSTNAME\", \"jvb@auth.$JVB_HOSTNAME\" }" >> $PROSODY_HOST_CONFIG
fi

# Convert the old focus component config to the new one.
# Old:
# Component "focus.jitmeet.example.com"
# component_secret = "focusSecret"
# New:
# Component "focus.jitmeet.example.com" "client_proxy"
# target_address = "focus@auth.jitmeet.example.com"
if grep -q "Component \"focus.$JVB_HOSTNAME\"" $PROSODY_HOST_CONFIG && ! grep "Component \"focus.$JVB_HOSTNAME\" \"client_proxy\"" $PROSODY_HOST_CONFIG ;then
sed -i -e "s/Component \"focus.$JVB_HOSTNAME\"/Component \"focus.$JVB_HOSTNAME\" \"client_proxy\"\n target_address = \"$JICOFO_AUTH_USER@auth.$JVB_HOSTNAME\"/" $PROSODY_HOST_CONFIG
PROSODY_CONFIG_PRESENT="false"
fi

# Make sure the focus@auth user's roster includes the proxy component (this is idempotent)
prosodyctl mod_roster_command subscribe focus.$JVB_HOSTNAME $JICOFO_AUTH_USER@auth.$JVB_HOSTNAME

if [ ! -f /var/lib/prosody/$JVB_HOSTNAME.crt ]; then
# prosodyctl takes care for the permissions
# echo for using all default values
Expand Down
5 changes: 3 additions & 2 deletions doc/debian/jitsi-meet-prosody/prosody.cfg.lua-jvb.example
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ Component "internal.auth.jitmeet.example.com" "muc"
VirtualHost "auth.jitmeet.example.com"
authentication = "internal_plain"

Component "focus.jitmeet.example.com"
component_secret = "focusSecret"
-- Proxy to jicofo's user JID, so that it doesn't have to register as a component.
Component "focus.jitmeet.example.com" "client_proxy"
target_address = "focusUser@auth.jitmeet.example.com"

Component "speakerstats.jitmeet.example.com" "speakerstats_component"
muc_component = "conference.jitmeet.example.com"
Expand Down
202 changes: 202 additions & 0 deletions resources/prosody-plugins/mod_client_proxy.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
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)
Loading

0 comments on commit b6f7f8f

Please sign in to comment.