4 -- This project is MIT/X11 licensed. Please see the |
4 -- This project is MIT/X11 licensed. Please see the |
5 -- COPYING file in the source package for more information. |
5 -- COPYING file in the source package for more information. |
6 -- |
6 -- |
7 |
7 |
8 local st = require "util.stanza"; |
8 local st = require "util.stanza"; |
|
9 local zlib = require "zlib"; |
9 local print = print |
10 local print = print |
10 |
11 |
11 local xmlns_compression_feature = "http://jabber.org/features/compress" |
12 local xmlns_compression_feature = "http://jabber.org/features/compress" |
12 local xmlns_compression_protocol = "http://jabber.org/protocol/compress" |
13 local xmlns_compression_protocol = "http://jabber.org/protocol/compress" |
13 local compression_stream_feature = st.stanza("compression", {xmlns=xmlns_compression_feature}):tag("method"):text("zlib"):up(); |
14 local compression_stream_feature = st.stanza("compression", {xmlns=xmlns_compression_feature}):tag("method"):text("zlib"):up(); |
14 |
15 |
15 |
16 |
16 module:add_event_hook("stream-features", |
17 module:add_event_hook("stream-features", |
17 function (session, features) |
18 function (session, features) |
18 features:add_child(compression_stream_feature); |
19 if not session.compressed then features:add_child(compression_stream_feature); end |
19 end |
20 end |
20 ); |
21 ); |
21 |
22 |
22 module:add_handler("c2s_unauthed", "compress", xmlns_compression_protocol, |
23 module:add_handler("c2s_unauthed", "compress", xmlns_compression_protocol, |
23 function(session, stanza) |
24 function(session, stanza) |
24 -- checking if the compression method is supported |
25 -- checking if the compression method is supported |
25 local method = stanza:child_with_name("method")[1]; |
26 local method = stanza:child_with_name("method")[1]; |
26 if method == "zlib" then |
27 if method == "zlib" then |
27 session.log("info", method.." compression selected."); |
28 session.log("info", method.." compression selected."); |
28 session.send(st.stanza("compressed", {xmlns=xmlns_compression_protocol})); |
29 session.send(st.stanza("compressed", {xmlns=xmlns_compression_protocol})); |
|
30 session:reset_stream(); |
|
31 |
|
32 -- create deflate and inflate streams |
|
33 local deflate_stream = zlib.deflate(9); |
|
34 local inflate_stream = zlib.inflate(); |
|
35 |
|
36 -- setup compression for session.w |
|
37 local old_send = session.send; |
|
38 |
|
39 session.send = function(t) |
|
40 local compressed, eof = deflate_stream(tostring(t), 'sync'); |
|
41 old_send(compressed); |
|
42 end; |
|
43 |
|
44 -- setup decompression for session.data |
|
45 local function setup_decompression(session) |
|
46 local old_data = session.data |
|
47 session.data = function(conn, data) |
|
48 local decompressed, eof = inflate_stream(data); |
|
49 old_data(conn, decompressed); |
|
50 end; |
|
51 end |
|
52 setup_decompression(session); |
|
53 |
|
54 local session_reset_stream = session.reset_stream; |
|
55 session.reset_stream = function(session) |
|
56 session_reset_stream(session); |
|
57 setup_decompression(session); |
|
58 return true; |
|
59 end; |
|
60 session.compressed = true; |
29 else |
61 else |
30 session.log("info", method.." compression selected. But we don't support it."); |
62 session.log("info", method.." compression selected. But we don't support it."); |
31 local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("unsupported-method"); |
63 local error_st = st.stanza("failure", {xmlns=xmlns_compression_protocol}):tag("unsupported-method"); |
32 session.send(error_st); |
64 session.send(error_st); |
33 end |
65 end |