Mercurial > prosody-modules
diff 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 |
line wrap: on
line diff
--- a/mod_smacks/mod_smacks.lua Tue Jul 30 01:46:57 2019 +0200 +++ b/mod_smacks/mod_smacks.lua Tue Jul 30 02:07:13 2019 +0200 @@ -160,6 +160,10 @@ local function request_ack_if_needed(session, force, reason) local queue = session.outgoing_stanza_queue; if session.awaiting_ack == nil and not session.hibernating then + -- this check of last_queue_count prevents ack-loops if missbehaving clients report wrong + -- stanza counts. it is set when an <r> is really sent (e.g. inside timer), preventing any + -- further requests until the queue count changes (either by incoming acks or by adding + -- more stanzas) if (#queue > max_unacked_stanzas and session.last_queue_count ~= #queue) or force then session.log("debug", "Queuing <r> (in a moment) from %s - #queue=%d", reason, #queue); session.awaiting_ack = false; @@ -167,8 +171,9 @@ if not session.awaiting_ack and not session.hibernating then session.log("debug", "Sending <r> (inside timer, before send)"); (session.sends2s or session.send)(st.stanza("r", { xmlns = session.smacks })) + session.awaiting_ack = true; + session.last_queue_count = #queue; session.log("debug", "Sending <r> (inside timer, after send)"); - session.awaiting_ack = true; if not session.delayed_ack_timer then session.delayed_ack_timer = stoppable_timer(delayed_ack_timeout, function() delayed_ack_function(session); @@ -187,8 +192,6 @@ session.log("debug", "Calling delayed_ack_function directly (still waiting for ack)"); delayed_ack_function(session); end - - session.last_queue_count = #queue; end local function outgoing_stanza_filter(stanza, session) @@ -587,7 +590,6 @@ return false; -- Kick the session end session.log("debug", "Sending <r> (read timeout)"); - session.awaiting_ack = false; (session.sends2s or session.send)(st.stanza("r", { xmlns = session.smacks })); session.awaiting_ack = true; if not session.delayed_ack_timer then