1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
-- Copyright (C) 2016-2018 Kim Alvefur
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
module:depends"csi"
local jid = require "util.jid";
local st = require "util.stanza";
local dt = require "util.datetime";
local new_queue = require "util.queue".new;
local function new_pump(output, ...)
-- luacheck: ignore 212/self
local q = new_queue(...);
local flush = true;
function q:pause()
flush = false;
end
function q:resume()
flush = true;
return q:flush();
end
local push = q.push;
function q:push(item)
local ok = push(self, item);
if not ok then
q:flush();
output(item, self);
elseif flush then
return q:flush();
end
return true;
end
function q:flush()
local item = self:pop();
while item do
output(item, self);
item = self:pop();
end
return true;
end
return q;
end
local queue_size = module:get_option_number("csi_queue_size", 256);
module:hook("csi-is-stanza-important", function (event)
local stanza = event.stanza;
if not st.is_stanza(stanza) then
return true;
end
local st_name = stanza.name;
if not st_name then return false; end
local st_type = stanza.attr.type;
if st_name == "presence" then
if st_type == nil or st_type == "unavailable" then
return false;
end
return true;
elseif st_name == "message" then
if st_type == "headline" then
return false;
end
if stanza:get_child("sent", "urn:xmpp:carbons:2") then
return true;
end
local forwarded = stanza:find("{urn:xmpp:carbons:2}received/{urn:xmpp:forward:0}/{jabber:client}message");
if forwarded then
stanza = forwarded;
end
if stanza:get_child("body") then
return true;
end
if stanza:get_child("subject") then
return true;
end
if stanza:get_child("encryption", "urn:xmpp:eme:0") then
return true;
end
return false;
end
return true;
end, -1);
local function with_timestamp(stanza, from)
if st.is_stanza(stanza) and stanza.attr.xmlns == nil and stanza.name ~= "iq" then
stanza = st.clone(stanza);
stanza:add_direct_child(st.stanza("delay", {xmlns = "urn:xmpp:delay", from = from, stamp = dt.datetime()}));
end
return stanza;
end
module:hook("csi-client-inactive", function (event)
local session = event.origin;
if session.conn and session.conn and session.conn.pause_writes then
session.conn:pause_writes();
elseif session.pump then
session.pump:pause();
else
local bare_jid = jid.join(session.username, session.host);
local send = session.send;
session._orig_send = send;
local pump = new_pump(session.send, queue_size);
pump:pause();
session.pump = pump;
function session.send(stanza)
if session.state == "active" or module:fire_event("csi-is-stanza-important", { stanza = stanza, session = session }) then
pump:flush();
send(stanza);
else
pump:push(with_timestamp(stanza, bare_jid));
end
return true;
end
end
end);
module:hook("csi-client-active", function (event)
local session = event.origin;
if session.pump then
session.pump:resume();
elseif session.conn and session.conn and session.conn.resume_writes then
session.conn:resume_writes();
end
end);
|