diff options
-rw-r--r-- | plugins/mod_compression.lua | 195 | ||||
-rw-r--r-- | util/cache.lua | 12 | ||||
-rw-r--r-- | util/iterators.lua | 33 |
3 files changed, 36 insertions, 204 deletions
diff --git a/plugins/mod_compression.lua b/plugins/mod_compression.lua index d49e3880..17be2ef2 100644 --- a/plugins/mod_compression.lua +++ b/plugins/mod_compression.lua @@ -1,198 +1,9 @@ -- Prosody IM --- Copyright (C) 2009-2012 Tobias Markmann +-- Copyright (C) 2016 Matthew Wild -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- -local st = require "util.stanza"; -local zlib = require "zlib"; -local pcall = pcall; -local tostring = tostring; - -local xmlns_compression_feature = "http://jabber.org/features/compress" -local xmlns_compression_protocol = "http://jabber.org/protocol/compress" -local xmlns_stream = "http://etherx.jabber.org/streams"; -local compression_stream_feature = st.stanza("compression", {xmlns=xmlns_compression_feature}):tag("method"):text("zlib"):up(); -local add_filter = require "util.filters".add_filter; - -local compression_level = module:get_option_number("compression_level", 7); - -if not compression_level or compression_level < 1 or compression_level > 9 then - module:log("warn", "Invalid compression level in config: %s", tostring(compression_level)); - module:log("warn", "Module loading aborted. Compression won't be available."); - return; -end - -module:hook("stream-features", function(event) - local origin, features = event.origin, event.features; - if not origin.compressed and origin.type == "c2s" then - features:add_child(compression_stream_feature); - end -end); - -module:hook("s2s-stream-features", function(event) - local origin, features = event.origin, event.features; - if not origin.compressed and origin.type == "s2sin" then - features:add_child(compression_stream_feature); - end -end); - --- Hook to activate compression if remote server supports it. -module:hook_stanza(xmlns_stream, "features", - function (session, stanza) - if not session.compressed and session.type == "s2sout" then - -- does remote server support compression? - local comp_st = stanza:get_child("compression", xmlns_compression_feature); - if comp_st then - -- do we support the mechanism - for a in comp_st:childtags("method") do - local algorithm = a:get_text(); - if algorithm == "zlib" then - session.sends2s(st.stanza("compress", {xmlns=xmlns_compression_protocol}):tag("method"):text("zlib")) - session.log("debug", "Enabled compression using zlib.") - return true; - end - end - session.log("debug", "Remote server supports no compression algorithm we support.") - end - end - end -, 250); - - --- returns either nil or a fully functional ready to use inflate stream -local function get_deflate_stream(session) - local status, deflate_stream = pcall(zlib.deflate, compression_level); - if status == false then - local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("setup-failed"); - (session.sends2s or session.send)(error_st); - session.log("error", "Failed to create zlib.deflate filter."); - module:log("error", "%s", tostring(deflate_stream)); - return - end - return deflate_stream -end - --- returns either nil or a fully functional ready to use inflate stream -local function get_inflate_stream(session) - local status, inflate_stream = pcall(zlib.inflate); - if status == false then - local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("setup-failed"); - (session.sends2s or session.send)(error_st); - session.log("error", "Failed to create zlib.inflate filter."); - module:log("error", "%s", tostring(inflate_stream)); - return - end - return inflate_stream -end - --- setup compression for a stream -local function setup_compression(session, deflate_stream) - add_filter(session, "bytes/out", function(t) - local status, compressed, eof = pcall(deflate_stream, tostring(t), 'sync'); - if status == false then - module:log("warn", "%s", tostring(compressed)); - session:close({ - condition = "undefined-condition"; - text = compressed; - extra = st.stanza("failure", {xmlns="http://jabber.org/protocol/compress"}):tag("processing-failed"); - }); - return; - end - return compressed; - end); -end - --- setup decompression for a stream -local function setup_decompression(session, inflate_stream) - add_filter(session, "bytes/in", function(data) - local status, decompressed, eof = pcall(inflate_stream, data); - if status == false then - module:log("warn", "%s", tostring(decompressed)); - session:close({ - condition = "undefined-condition"; - text = decompressed; - extra = st.stanza("failure", {xmlns="http://jabber.org/protocol/compress"}):tag("processing-failed"); - }); - return; - end - return decompressed; - end); -end - -module:hook("stanza/http://jabber.org/protocol/compress:compressed", function(event) - local session = event.origin; - - if session.type == "s2sout" then - session.log("debug", "Activating compression...") - -- create deflate and inflate streams - local deflate_stream = get_deflate_stream(session); - if not deflate_stream then return true; end - - local inflate_stream = get_inflate_stream(session); - if not inflate_stream then return true; end - - -- setup compression for session.w - setup_compression(session, deflate_stream); - - -- setup decompression for session.data - setup_decompression(session, inflate_stream); - session:reset_stream(); - session:open_stream(session.from_host, session.to_host); - session.compressed = true; - return true; - end -end); - -module:hook("stanza/http://jabber.org/protocol/compress:failure", function(event) - local err = event.stanza:get_child(); - (event.origin.log or module._log)("warn", "Compression setup failed (%s)", err and err.name or "unknown reason"); - return true; -end); - -module:hook("stanza/http://jabber.org/protocol/compress:compress", function(event) - local session, stanza = event.origin, event.stanza; - - if session.type == "c2s" or session.type == "s2sin" then - -- fail if we are already compressed - if session.compressed then - local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("setup-failed"); - (session.sends2s or session.send)(error_st); - session.log("debug", "Client tried to establish another compression layer."); - return true; - end - - -- checking if the compression method is supported - local method = stanza:get_child_text("method"); - if method == "zlib" then - session.log("debug", "zlib compression enabled."); - - -- create deflate and inflate streams - local deflate_stream = get_deflate_stream(session); - if not deflate_stream then return true; end - - local inflate_stream = get_inflate_stream(session); - if not inflate_stream then return true; end - - (session.sends2s or session.send)(st.stanza("compressed", {xmlns=xmlns_compression_protocol})); - session:reset_stream(); - - -- setup compression for session.w - setup_compression(session, deflate_stream); - - -- setup decompression for session.data - setup_decompression(session, inflate_stream); - - session.compressed = true; - elseif method then - session.log("debug", "%s compression selected, but we don't support it.", tostring(method)); - local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("unsupported-method"); - (session.sends2s or session.send)(error_st); - else - (session.sends2s or session.send)(st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("setup-failed")); - end - return true; - end -end); - +-- COMPAT w/ pre-0.10 configs +error("mod_compression has been removed in Prosody 0.10+. Please see https://prosody.im/doc/modules/mod_compression for more information."); diff --git a/util/cache.lua b/util/cache.lua index 074916cd..54f3e10b 100644 --- a/util/cache.lua +++ b/util/cache.lua @@ -88,6 +88,18 @@ function cache_methods:items() end end +function cache_methods:values() + local m = self._head; + return function () + if not m then + return; + end + local v = m.value; + m = m.next; + return v; + end +end + function cache_methods:count() return self._count; end diff --git a/util/iterators.lua b/util/iterators.lua index e553229e..bd150ff2 100644 --- a/util/iterators.lua +++ b/util/iterators.lua @@ -23,18 +23,18 @@ function it.reverse(f, s, var) while true do local ret = { f(s, var) }; var = ret[1]; - if var == nil then break; end + if var == nil then break; end t_insert(results, 1, ret); end -- Then return our reverse one local i,max = 0, #results; return function (_results) - if i<max then - i = i + 1; - return unpack(_results[i]); - end - end, results; + if i<max then + i = i + 1; + return unpack(_results[i]); + end + end, results; end -- Iterate only over keys in a table @@ -54,6 +54,15 @@ function it.values(t) end, t; end +-- Iterate over the n:th return value +function it.select(n, f, s, var) + return function (_s) + local ret = pack(f(_s, var)); + var = ret[1]; + return ret[n]; + end, s, var; +end + -- Given an iterator, iterate only over unique items function it.unique(f, s, var) local set = {}; @@ -62,8 +71,8 @@ function it.unique(f, s, var) while true do local ret = pack(f(s, var)); var = ret[1]; - if var == nil then break; end - if not set[var] then + if var == nil then break; end + if not set[var] then set[var] = true; return unpack(ret, 1, ret.n); end @@ -77,7 +86,7 @@ function it.count(f, s, var) while true do var = f(s, var); - if var == nil then break; end + if var == nil then break; end x = x + 1; end @@ -110,7 +119,7 @@ function it.tail(n, f, s, var) while true do local ret = pack(f(s, var)); var = ret[1]; - if var == nil then break; end + if var == nil then break; end results[(count%n)+1] = ret; count = count + 1; end @@ -157,7 +166,7 @@ function it.to_array(f, s, var) local t = {}; while true do var = f(s, var); - if var == nil then break; end + if var == nil then break; end t_insert(t, var); end return t; @@ -169,7 +178,7 @@ function it.to_table(f, s, var) local t, var2 = {}; while true do var, var2 = f(s, var); - if var == nil then break; end + if var == nil then break; end t[var] = var2; end return t; |