Diff

mod_presence_dedup/mod_presence_dedup.lua @ 2155:f24b02e0d706

mod_presence_dedup: Attempt at saving bandwith by deduplicating presence stanzas
author Kim Alvefur <zash@zash.se>
date Sun, 03 Apr 2016 17:09:03 +0200
child 3445:19924a2c4a48
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_presence_dedup/mod_presence_dedup.lua	Sun Apr 03 17:09:03 2016 +0200
@@ -0,0 +1,44 @@
+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, stanza = event.origin, event.stanza;
+	session.presence_cache = cache.new(cache_size);
+	add_filter(session, "stanzas/out", dedup_presence, 90);
+end);