changeset 2491:5fbca7de2088

mod_smacks: Send out more ack requests where needed Under some circumstances it was possible that more than "max_unacked_stanzas" where left in the outgoing stanza queue without forcing an ack. This could happen, when more stanzas entered the queue while the last ack request was still unanswered. Now the test "#queue > max_unacked_stanzas" is done upon receiving an ack as well as when sending out stanzas, which fixes this bug.
author tmolitor <thilo@eightysoft.de>
date Sun, 12 Feb 2017 19:27:50 +0100
parents 85509650ba82
children 63fb612d6ec5 d300ae5dba87
files mod_smacks/mod_smacks.lua
diffstat 1 files changed, 23 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/mod_smacks/mod_smacks.lua	Fri Feb 10 22:50:45 2017 +0100
+++ b/mod_smacks/mod_smacks.lua	Sun Feb 12 19:27:50 2017 +0100
@@ -5,7 +5,7 @@
 -- Copyright (C) 2012-2015 Kim Alvefur
 -- Copyright (C) 2012 Thijs Alkemade
 -- Copyright (C) 2014 Florian Zeitz
--- Copyright (C) 2016 Thilo Molitor
+-- Copyright (C) 2016-2017 Thilo Molitor
 --
 -- This project is MIT/X11 licensed. Please see the
 -- COPYING file in the source package for more information.
@@ -80,6 +80,25 @@
 			end
 		end);
 
+local function request_ack_if_needed(session)
+	local queue = session.outgoing_stanza_queue;
+	if #queue > max_unacked_stanzas and session.awaiting_ack == nil then
+		session.log("debug", "Queuing <r> (in a moment)");
+		session.awaiting_ack = false;
+		session.awaiting_ack_timer = module:add_timer(1e-06, function ()
+			if not session.awaiting_ack then
+				session.log("debug", "Sending <r> (inside timer, before send)");
+				(session.sends2s or session.send)(st.stanza("r", { xmlns = session.smacks }))
+				session.log("debug", "Sending <r> (inside timer, after send)");
+				session.awaiting_ack = true;
+				session.delayed_ack_timer = module:add_timer(delayed_ack_timeout, function()
+					delayed_ack_function(session);
+				end);
+			end
+		end);
+	end
+end
+
 local function outgoing_stanza_filter(stanza, session)
 	local is_stanza = stanza.attr and not stanza.attr.xmlns and not stanza.name:find":";
 	if is_stanza and not stanza._cached then -- Stanza in default stream namespace
@@ -97,21 +116,7 @@
 			session.log("debug", "hibernating, stanza queued");
 			return nil;
 		end
-		if #queue > max_unacked_stanzas and session.awaiting_ack == nil then
-			session.log("debug", "Queuing <r> (in a moment)");
-			session.awaiting_ack = false;
-			session.awaiting_ack_timer = module:add_timer(1e-06, function ()
-				if not session.awaiting_ack then
-					session.log("debug", "Sending <r> (before send)");
-					(session.sends2s or session.send)(st.stanza("r", { xmlns = session.smacks }))
-					session.log("debug", "Sending <r> (after send)");
-					session.awaiting_ack = true;
-					session.delayed_ack_timer = module:add_timer(delayed_ack_timeout, function()
-						delayed_ack_function(session);
-					end);
-				end
-			end);
-		end
+		request_ack_if_needed(session);
 	end
 	return stanza;
 end
@@ -238,7 +243,7 @@
 		origin.delayed_ack_timer:stop();
 	end
 	-- Remove handled stanzas from outgoing_stanza_queue
-	--log("debug", "ACK: h=%s, last=%s", stanza.attr.h or "", origin.last_acknowledged_stanza or "");
+	log("debug", "ACK: h=%s, last=%s", stanza.attr.h or "", origin.last_acknowledged_stanza or "");
 	local h = tonumber(stanza.attr.h);
 	if not h then
 		origin:close{ condition = "invalid-xml"; text = "Missing or invalid 'h' attribute"; };
@@ -258,6 +263,7 @@
 	end
 	origin.log("debug", "#queue = %d", #queue);
 	origin.last_acknowledged_stanza = origin.last_acknowledged_stanza + handled_stanza_count;
+	request_ack_if_needed(origin)
 	return true;
 end
 module:hook_stanza(xmlns_sm2, "a", handle_a);