view mod_presence_dedup/mod_presence_dedup.lua @ 4293:edde5905744a

mod_s2s_keepalive: Don't send whitespace keepalives before s2sin stream is open Could possibly result in whitespace before the XML and stream header, which isn't allowed by the parser. Don't think s2sout is affected, as the stream is opened early and doesn't have to wait for the other end. Thanks Ge0rG
author Kim Alvefur <zash@zash.se>
date Thu, 10 Dec 2020 11:57:03 +0100
parents 19924a2c4a48
children
line wrap: on
line source

local st = require "util.stanza";
local cache = require "util.cache";
local add_filter = require "util.filters".add_filter;

local cache_size = module:get_option_number("presence_dedup_cache_size", 100);

-- stanza equality tests
local function attr_eq(a, b)
	if a == b then return true; end -- unlikely but not impossible
	for k,v in pairs(a) do if b[k] ~= v then return false; end end
	for k,v in pairs(b) do if a[k] ~= v then return false; end end
	return true;
end

local function st_eq(a, b)
	if a == b then return true; end
	if type(b) ~= "table" then return false; end
	if getmetatable(b) ~= st.stanza_mt then return false; end
	if a.name ~= b.name then return false; end
	if #a ~= #b then return false; end
	if not attr_eq(a.attr, b.attr) then return false; end
	for i = 1, #a do if not st_eq(a[i], b[i]) then return false; end end
	return true;
end

local function dedup_presence(stanza, session)
	if session.presence_cache and session.presence
	and getmetatable(stanza) == st.stanza_mt and stanza.name == "presence"
	and stanza.attr.xmlns == nil and stanza.attr.from then
		local cached = session.presence_cache:get(stanza.attr.from);
		if st_eq(stanza, cached) then
			return nil;
		else
			session.presence_cache:set(stanza.attr.from, st.clone(stanza));
		end
	end
	return stanza;
end

module:hook("presence/initial",	function (event)
	local session = event.origin;
	session.presence_cache = cache.new(cache_size);
	add_filter(session, "stanzas/out", dedup_presence, 90);
end);