# HG changeset patch # User tmolitor # Date 1486924070 -3600 # Node ID 5fbca7de208871926be291cc249fa99c831dd72f # Parent 85509650ba828a84b9245675bdba0d10ff5172df 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. diff -r 85509650ba82 -r 5fbca7de2088 mod_smacks/mod_smacks.lua --- 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 (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 (inside timer, before send)"); + (session.sends2s or session.send)(st.stanza("r", { xmlns = session.smacks })) + session.log("debug", "Sending (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 (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 (before send)"); - (session.sends2s or session.send)(st.stanza("r", { xmlns = session.smacks })) - session.log("debug", "Sending (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);