mix_pam: Add roster changes and keep track of SPIDs
This commit is contained in:
parent
53e53efa44
commit
e09f4ebcd3
@ -1,23 +1,58 @@
|
||||
if module:get_host() ~= "*" then
|
||||
local host = module:get_host()
|
||||
--[[
|
||||
if host ~= "*" then
|
||||
module:log("error", "mix_pam should be used on the user host!");
|
||||
end
|
||||
]]--
|
||||
|
||||
local jid = require("util.jid");
|
||||
local st = require("util.stanza");
|
||||
local rm_remove_from_roster = require("core.rostermanager").remove_from_roster;
|
||||
local rm_add_to_roster = require("core.rostermanager").add_to_roster;
|
||||
local rm_roster_push = require("core.rostermanager").roster_push;
|
||||
|
||||
-- Persistent storage
|
||||
local mix_pam = module:open_store("mix_pam", "keyval");
|
||||
|
||||
-- Runtime data
|
||||
local mix_hosts = {};
|
||||
local mix_spids = {}; -- user -> channel -> spid
|
||||
|
||||
-- Namespaceing
|
||||
local mix_pam_xmlns = "urn:xmpp:mix:pam:2";
|
||||
local mix_roster_xmlns = "urn:xmpp:mix:roster:0";
|
||||
|
||||
module:add_feature(mix_pam_xmlns);
|
||||
-- NOTE: To show that we archive messages
|
||||
-- module:add_feature(mix_pam_xmlns.."#archive");
|
||||
|
||||
function contains_key(table, key)
|
||||
-- Returns true if table contains the key key. Returns false
|
||||
-- otherwise.
|
||||
return table[key] ~= nil;
|
||||
end
|
||||
|
||||
function set_mix_spid(user, channel, spid)
|
||||
if mix_spids[user] ~= nil then
|
||||
mix_spids[user][channel] = spid;
|
||||
else
|
||||
mix_spids[user] = { [channel] = spid };
|
||||
end
|
||||
|
||||
mix_pam:set("spids", mix_spids);
|
||||
end
|
||||
function get_mix_spid(user, channel)
|
||||
return mix_spids[user][channel];
|
||||
end;
|
||||
function remove_mix_spid(user, channel)
|
||||
mix_spids[user][channel] = nil;
|
||||
if mix_spids[user][channel] == {} then
|
||||
mix_spids[user][channel] = nil;
|
||||
end
|
||||
|
||||
mix_pam:set("spids", mix_spids);
|
||||
end
|
||||
|
||||
function add_mix_host(host)
|
||||
if mix_hosts[host] ~= nil then
|
||||
mix_hosts[host] = mix_hosts[host] + 1;
|
||||
@ -26,6 +61,8 @@ function add_mix_host(host)
|
||||
module:log("debug", "Added %s as a new MIX host", host);
|
||||
mix_hosts[host] = 1;
|
||||
end
|
||||
|
||||
mix_pam:set("hosts", mix_hosts);
|
||||
end
|
||||
|
||||
function remove_mix_host(host)
|
||||
@ -41,6 +78,8 @@ function remove_mix_host(host)
|
||||
else
|
||||
module:log("debug", "Attempt to remove unknown MIX host");
|
||||
end
|
||||
|
||||
mix_pam:set("hosts", mix_hosts);
|
||||
end
|
||||
|
||||
function is_mix_host(host)
|
||||
@ -58,11 +97,28 @@ function module.load()
|
||||
if mix_hosts == nil then
|
||||
module:log("info", "No known MIX hosts loaded");
|
||||
mix_hosts = {};
|
||||
return;
|
||||
end
|
||||
for _, host in pairs(mix_hosts) do
|
||||
for host, _ in pairs(mix_hosts) do
|
||||
module:log("debug", "Known host: %s", host);
|
||||
end
|
||||
|
||||
mix_spids = mix_pam:get("spids");
|
||||
module:log("info", "Loaded known MIX SPIDs");
|
||||
|
||||
if mix_spids == nil then
|
||||
module:log("info", "No known MIX SPIDs loaded");
|
||||
mix_spids = {};
|
||||
end
|
||||
for user, channel_map in pairs(mix_spids) do
|
||||
module:log("debug", "-- %s", user);
|
||||
if channel_map[user] then
|
||||
for channel, spid in pairs(channel_map[user]) do
|
||||
module:log("debug", "%s -> %s", channel, spid);
|
||||
end
|
||||
else
|
||||
module:log("warn", "User mapping empty");
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local client_state_tracker = {}; -- [stanza ID] -> resource
|
||||
@ -117,7 +173,7 @@ function handle_client_join(event)
|
||||
local join_iq = st.iq({ type = "set", from = jid.bare(stanza.attr.from), to = client_join.attr.channel, id = stanza.attr.id, xmlns = "jabber:client" });
|
||||
join_iq:add_child(join);
|
||||
|
||||
add_state(stanza.attr.id, jid.resource(stanza.attr.from));
|
||||
add_state(stanza.attr.id, origin);
|
||||
|
||||
module:send(join_iq);
|
||||
return true;
|
||||
@ -144,7 +200,7 @@ function handle_client_leave(event)
|
||||
local leave_iq = st.iq({ type = "set", from = jid.bare(stanza.attr.from), to = client_leave.attr.channel, id = stanza.attr.id });
|
||||
leave_iq:add_child(leave);
|
||||
|
||||
add_state(stanza.attr.id, jid.resource(stanza.attr.from));
|
||||
add_state(stanza.attr.id, origin);
|
||||
|
||||
module:send(leave_iq);
|
||||
return true;
|
||||
@ -168,44 +224,66 @@ end);
|
||||
|
||||
function handle_mix_join(event)
|
||||
-- The MIX server responded
|
||||
-- TODO: Do stuff to the user's roster
|
||||
module:log("debug", "Received MIX-JOIN result");
|
||||
module:log("debug", "Adding %s as a new MIX host", jid.host(event.stanza.attr.from));
|
||||
add_mix_host(jid.host(event.stanza.attr.from));
|
||||
mix_pam:set("hosts", mix_hosts);
|
||||
|
||||
local stanza = event.stanza;
|
||||
local channel_jid = stanza:get_child("join", "urn:xmpp:mix:core:1").attr.id.."#"..stanza.attr.from;
|
||||
local resource = pop_state(stanza.attr.id);
|
||||
local spid = stanza:get_child("join", "urn:xmpp:mix:core:1").attr.id;
|
||||
local channel_jid = spid.."#"..stanza.attr.from;
|
||||
local origin = pop_state(stanza.attr.id);
|
||||
local resource = origin.resource;
|
||||
if resource == nil then
|
||||
module:log("error", "Got a MIX join result for a not-requested id %s. Maybe the MIX server changed the stanza ID?", stanza.attr.id);
|
||||
return false;
|
||||
end
|
||||
|
||||
-- Keep track of the SPID
|
||||
set_mix_spid(stanza.attr.to, stanza.attr.from, spid);
|
||||
|
||||
local client_join = st.iq({ type = "result", id = stanza.attr.id, from = jid.bare(stanza.attr.to), to = stanza.attr.to.."/"..resource })
|
||||
:tag("client-join", { xmlns = mix_pam_xmlns, jid = channel_jid });
|
||||
client_join:add_child(stanza:get_child("join", "urn:xmpp:mix:core:1"));
|
||||
module:send(client_join);
|
||||
|
||||
-- TODO: Error handling?
|
||||
rm_add_to_roster(origin, stanza.attr.from, {
|
||||
subscription = "both",
|
||||
groups = {},
|
||||
});
|
||||
rm_roster_push(jid.node(stanza.attr.to), host, stanza.attr.from);
|
||||
|
||||
return true;
|
||||
end
|
||||
|
||||
function handle_mix_leave(event)
|
||||
-- The MIX server responded
|
||||
-- TODO: Do stuff to the user's roster
|
||||
module:log("debug", "Received MIX-LEAVE result");
|
||||
remove_mix_host(jid.host(event.stanza.attr.from));
|
||||
mix_pam:set("hosts", mix_hosts);
|
||||
|
||||
local stanza = event.stanza;
|
||||
local resource = pop_state(stanza.attr.id);
|
||||
local origin = pop_state(stanza.attr.id);
|
||||
local resource = origin.resource;
|
||||
if resource == nil then
|
||||
module:log("error", "Got a MIX leave result for a not-requested id %s. Maybe the MIX server changed the stanza ID?", stanza.attr.id);
|
||||
return false;
|
||||
end
|
||||
|
||||
-- Keep track of the SPID
|
||||
set_mix_spid(stanza.attr.to, jid.bare(stanza.attr.from));
|
||||
|
||||
local client_leave = st.iq({ type = "result", id = stanza.attr.id, from = jid.bare(stanza.attr.to), to = stanza.attr.to.."/"..resource })
|
||||
:tag("client-leave", { xmlns = mix_pam_xmlns });
|
||||
client_leave:add_child(stanza:get_child("leave", "urn:xmpp:mix:core:1"));
|
||||
module:send(client_leave);
|
||||
|
||||
-- Remove from roster
|
||||
-- TODO: Error handling
|
||||
rm_remove_from_roster(origin, jid.bare(stanza.attr.from));
|
||||
rm_roster_push(jid.node(stanza.attr.to), host, jid.bare(stanza.attr.from));
|
||||
|
||||
return true;
|
||||
end
|
||||
|
||||
@ -238,6 +316,29 @@ module:hook("resource-unbind", function(event)
|
||||
module:log("debug", "Unbind of not recorded resource %s (%s)", resource, jid);
|
||||
end);
|
||||
|
||||
module:hook("roster-get", function(event)
|
||||
-- NOTE: Currently this requires a patch to make mod_roster emit
|
||||
-- the roster-get event
|
||||
local annotate = event.stanza
|
||||
:get_child("query", "jabber:iq:roster")
|
||||
:get_child("annotate", mix_roster_xmlns);
|
||||
if not annotate then return; end
|
||||
local reply, stanza = event.reply, event.stanza;
|
||||
|
||||
module:log("debug", "Annotated roster request received");
|
||||
|
||||
-- User requested the roster with an <annotate/>
|
||||
for item in event.reply:get_child("query", "jabber:iq:roster"):children() do
|
||||
if contains_key(mix_hosts, jid.host(item.attr.jid)) then
|
||||
local spid = get_mix_spid(jid.bare(stanza.attr.from), item.attr.jid);
|
||||
item:tag("channel", {
|
||||
xmlns = mix_roster_xmlns,
|
||||
["participant-id"] = spid,
|
||||
});
|
||||
end
|
||||
end
|
||||
end);
|
||||
|
||||
module:hook("message/bare", function(event)
|
||||
local stanza = event.stanza;
|
||||
local host = jid.host(stanza.attr.from);
|
||||
|
Loading…
Reference in New Issue
Block a user