comparison mod_smacks/mod_smacks.lua @ 3634:915e32d5a147

mod_smacks: fix bug for missbehaving clients sending multiple acks in a row Missbehaving clients, sending multiple acks in a row (I'm looking at you Monal!) triggered the ack-loop-prevention code added in 2017, leaving unacked stanzas in the queue. This fixes the bug while still preventing ack-loops.
author tmolitor <thilo@eightysoft.de>
date Tue, 30 Jul 2019 02:07:13 +0200
parents c2c851722a8a
children b2f32b3c6ec1
comparison
equal deleted inserted replaced
3633:6b0db0f2d57a 3634:915e32d5a147
158 end); 158 end);
159 159
160 local function request_ack_if_needed(session, force, reason) 160 local function request_ack_if_needed(session, force, reason)
161 local queue = session.outgoing_stanza_queue; 161 local queue = session.outgoing_stanza_queue;
162 if session.awaiting_ack == nil and not session.hibernating then 162 if session.awaiting_ack == nil and not session.hibernating then
163 -- this check of last_queue_count prevents ack-loops if missbehaving clients report wrong
164 -- stanza counts. it is set when an <r> is really sent (e.g. inside timer), preventing any
165 -- further requests until the queue count changes (either by incoming acks or by adding
166 -- more stanzas)
163 if (#queue > max_unacked_stanzas and session.last_queue_count ~= #queue) or force then 167 if (#queue > max_unacked_stanzas and session.last_queue_count ~= #queue) or force then
164 session.log("debug", "Queuing <r> (in a moment) from %s - #queue=%d", reason, #queue); 168 session.log("debug", "Queuing <r> (in a moment) from %s - #queue=%d", reason, #queue);
165 session.awaiting_ack = false; 169 session.awaiting_ack = false;
166 session.awaiting_ack_timer = stoppable_timer(1e-06, function () 170 session.awaiting_ack_timer = stoppable_timer(1e-06, function ()
167 if not session.awaiting_ack and not session.hibernating then 171 if not session.awaiting_ack and not session.hibernating then
168 session.log("debug", "Sending <r> (inside timer, before send)"); 172 session.log("debug", "Sending <r> (inside timer, before send)");
169 (session.sends2s or session.send)(st.stanza("r", { xmlns = session.smacks })) 173 (session.sends2s or session.send)(st.stanza("r", { xmlns = session.smacks }))
174 session.awaiting_ack = true;
175 session.last_queue_count = #queue;
170 session.log("debug", "Sending <r> (inside timer, after send)"); 176 session.log("debug", "Sending <r> (inside timer, after send)");
171 session.awaiting_ack = true;
172 if not session.delayed_ack_timer then 177 if not session.delayed_ack_timer then
173 session.delayed_ack_timer = stoppable_timer(delayed_ack_timeout, function() 178 session.delayed_ack_timer = stoppable_timer(delayed_ack_timeout, function()
174 delayed_ack_function(session); 179 delayed_ack_function(session);
175 end); 180 end);
176 end 181 end
185 -- would not trigger this event (again). 190 -- would not trigger this event (again).
186 if #queue > max_unacked_stanzas and session.awaiting_ack and session.delayed_ack_timer == nil then 191 if #queue > max_unacked_stanzas and session.awaiting_ack and session.delayed_ack_timer == nil then
187 session.log("debug", "Calling delayed_ack_function directly (still waiting for ack)"); 192 session.log("debug", "Calling delayed_ack_function directly (still waiting for ack)");
188 delayed_ack_function(session); 193 delayed_ack_function(session);
189 end 194 end
190
191 session.last_queue_count = #queue;
192 end 195 end
193 196
194 local function outgoing_stanza_filter(stanza, session) 197 local function outgoing_stanza_filter(stanza, session)
195 local is_stanza = stanza.attr and not stanza.attr.xmlns and not stanza.name:find":"; 198 local is_stanza = stanza.attr and not stanza.attr.xmlns and not stanza.name:find":";
196 if is_stanza and not stanza._cached then -- Stanza in default stream namespace 199 if is_stanza and not stanza._cached then -- Stanza in default stream namespace
585 session.delayed_ack_timer = nil; 588 session.delayed_ack_timer = nil;
586 end 589 end
587 return false; -- Kick the session 590 return false; -- Kick the session
588 end 591 end
589 session.log("debug", "Sending <r> (read timeout)"); 592 session.log("debug", "Sending <r> (read timeout)");
590 session.awaiting_ack = false;
591 (session.sends2s or session.send)(st.stanza("r", { xmlns = session.smacks })); 593 (session.sends2s or session.send)(st.stanza("r", { xmlns = session.smacks }));
592 session.awaiting_ack = true; 594 session.awaiting_ack = true;
593 if not session.delayed_ack_timer then 595 if not session.delayed_ack_timer then
594 session.delayed_ack_timer = stoppable_timer(delayed_ack_timeout, function() 596 session.delayed_ack_timer = stoppable_timer(delayed_ack_timeout, function()
595 delayed_ack_function(session); 597 delayed_ack_function(session);