mod_presence_dedup/mod_presence_dedup.lua
changeset 2159 f24b02e0d706
child 3449 19924a2c4a48
equal deleted inserted replaced
2158:ada71b81425a 2159:f24b02e0d706
       
     1 local st = require "util.stanza";
       
     2 local cache = require "util.cache";
       
     3 local add_filter = require "util.filters".add_filter;
       
     4 
       
     5 local cache_size = module:get_option_number("presence_dedup_cache_size", 100);
       
     6 
       
     7 -- stanza equality tests
       
     8 local function attr_eq(a, b)
       
     9 	if a == b then return true; end -- unlikely but not impossible
       
    10 	for k,v in pairs(a) do if b[k] ~= v then return false; end end
       
    11 	for k,v in pairs(b) do if a[k] ~= v then return false; end end
       
    12 	return true;
       
    13 end
       
    14 
       
    15 local function st_eq(a, b)
       
    16 	if a == b then return true; end
       
    17 	if type(b) ~= "table" then return false; end
       
    18 	if getmetatable(b) ~= st.stanza_mt then return false; end
       
    19 	if a.name ~= b.name then return false; end
       
    20 	if #a ~= #b then return false; end
       
    21 	if not attr_eq(a.attr, b.attr) then return false; end
       
    22 	for i = 1, #a do if not st_eq(a[i], b[i]) then return false; end end
       
    23 	return true;
       
    24 end
       
    25 
       
    26 local function dedup_presence(stanza, session)
       
    27 	if session.presence_cache and session.presence
       
    28 	and getmetatable(stanza) == st.stanza_mt and stanza.name == "presence"
       
    29 	and stanza.attr.xmlns == nil and stanza.attr.from then
       
    30 		local cached = session.presence_cache:get(stanza.attr.from);
       
    31 		if st_eq(stanza, cached) then
       
    32 			return nil;
       
    33 		else
       
    34 			session.presence_cache:set(stanza.attr.from, st.clone(stanza));
       
    35 		end
       
    36 	end
       
    37 	return stanza;
       
    38 end
       
    39 
       
    40 module:hook("presence/initial",	function (event)
       
    41 	local session, stanza = event.origin, event.stanza;
       
    42 	session.presence_cache = cache.new(cache_size);
       
    43 	add_filter(session, "stanzas/out", dedup_presence, 90);
       
    44 end);