Skip rate limit for login, capability negotiation
authorShane Synan <digitalcircuit36939@gmail.com>
Wed, 7 Sep 2016 05:35:48 +0000 (00:35 -0500)
committerManuel Nickschas <sputnick@quassel-irc.org>
Tue, 13 Sep 2016 22:17:08 +0000 (00:17 +0200)
Disable message rate limit during nick registration and capability
negotiation (Network::Initializing).  Once network initialization
is complete (Network::Initialized), re-apply configured rate limits.

Helps fix connection timeouts during login on servers with SASL
enabled, multiple capabilities negotiated, and a strict 10s login
time.

Add flag 'forceUnlimited' to updateRateLimiting() which temporarily
overrides user preferences to skip all rate limiting.  User
preferences can be applied afterwards by calling updateRateLimiting()
without setting 'forceUnlimited'.

Resolves GH-236.

src/core/corenetwork.cpp
src/core/corenetwork.h

index 6f2c285..383d4c0 100644 (file)
@@ -542,8 +542,13 @@ void CoreNetwork::socketInitialized()
 
     socket.setSocketOption(QAbstractSocket::KeepAliveOption, true);
 
-    // Update the TokenBucket with specified rate-limiting settings
-    updateRateLimiting();
+    // Update the TokenBucket, force-enabling unlimited message rates for initial registration and
+    // capability negotiation.  networkInitialized() will call updateRateLimiting() without the
+    // force flag to apply user preferences.  When making changes, ensure that this still happens!
+    // As Quassel waits for CAP ACK/NAK and AUTHENTICATE replies, this shouldn't ever fill the IRC
+    // server receive queue and cause a kill.  "Shouldn't" being the operative word; the real world
+    // is a scary place.
+    updateRateLimiting(true);
     // Fill up the token bucket as we're connecting from scratch
     resetTokenBucket();
 
@@ -640,6 +645,10 @@ void CoreNetwork::networkInitialized()
     _disconnectExpected = false;
     _quitRequested = false;
 
+    // Update the TokenBucket with specified rate-limiting settings, removing the force-unlimited
+    // flag used for initial registration and capability negotiation.
+    updateRateLimiting();
+
     if (useAutoReconnect()) {
         // reset counter
         _autoReconnectCount = unlimitedReconnectRetries() ? -1 : autoReconnectRetries();
@@ -931,12 +940,12 @@ void CoreNetwork::setPingInterval(int interval)
 
 /******** Custom Rate Limiting ********/
 
-void CoreNetwork::updateRateLimiting()
+void CoreNetwork::updateRateLimiting(const bool forceUnlimited)
 {
     // Always reset the delay and token bucket (safe-guard against accidentally starting the timer)
 
-    if (useCustomMessageRate()) {
-        // Custom message rates enabled.  Let's go for it!
+    if (useCustomMessageRate() || forceUnlimited) {
+        // Custom message rates enabled, or chosen by means of forcing unlimited.  Let's go for it!
 
         _messageDelay = messageRateDelay();
 
@@ -958,8 +967,9 @@ void CoreNetwork::updateRateLimiting()
 
         // Toggle the timer according to whether or not rate limiting is enabled
         // If we're here, useCustomMessageRate is true.  Thus, the logic becomes
-        // _skipMessageRates = (useCustomMessageRate && unlimitedMessageRate)
-        _skipMessageRates = unlimitedMessageRate();
+        // _skipMessageRates = (useCustomMessageRate && (unlimitedMessageRate || forceUnlimited))
+        // Override user preferences if called with force unlimited
+        _skipMessageRates = (unlimitedMessageRate() || forceUnlimited);
         if (_skipMessageRates) {
             // If the message queue already contains messages, they need sent before disabling the
             // timer.  Set the timer to a rapid pace and let it disable itself.
index 509df19..8201b43 100644 (file)
@@ -284,8 +284,14 @@ public slots:
      * @see Network::messageRateBurstSize()
      * @see Network::messageRateDelay()
      * @see Network::unlimitedMessageRate()
+     *
+     * @param[in] forceUnlimited
+     * @parmblock
+     * If true, override user settings to disable message rate limiting, otherwise apply rate limits
+     * set by the user.  Use with caution and remember to re-enable configured limits when done.
+     * @endparmblock
      */
-    void updateRateLimiting();
+    void updateRateLimiting(const bool forceUnlimited = false);
 
     /**
      * Resets the token bucket up to the maximum