Bug 235186 - Timed reconnect cannot be cancelled without closing whole network tab
Summary: Timed reconnect cannot be cancelled without closing whole network tab
Status: RESOLVED FIXED
Alias: None
Product: konversation
Classification: Applications
Component: general (show other bugs)
Version: 1.2.3
Platform: Fedora RPMs Linux
: NOR normal
Target Milestone: ---
Assignee: Konversation Developers
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-04-23 17:37 UTC by Jonas Thiem
Modified: 2010-04-26 15:47 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonas Thiem 2010-04-23 17:37:02 UTC
When getting kicked from a server Konversation will depending on the configuration attempt a reconnect in X seconds.

Now if an actual reconnect takes place it is possible to stop it using /quit or /disconnect.

But during that X seconds until the reconnect attempt gets actually triggered, there seems to be no way to unqueue that reconnect attempt except
  a) being very fast when it actually happens and kill it off before e.g. the server ban kills it off and another reconnect gets scheduled (assuming you're throttled/banned)
 b) closing the whole network tab with all open channels/queries to stop any timed reconnect attempts although you probably wanted to reuse the tabs lateron after some delay.

This is especially annoying e.g. when getting throttled by a server during a reconnect so any additional reconnect attempt will enhance/prolong the throttling and an actual reconnect with subsequent server killoff due to the throttle will happen so fast that you can't type /quit while it happens.

So to stop the reconnecting you need to close the whole network tab to give that throttle a chance to calm down so you may actually get back to that server after some time - but then of course with all channels/queries you had previously opened closed.
Comment 1 Eike Hein 2010-04-26 15:47:12 UTC
commit 468e936c94ebf9263229244ced861c6e870b7d03
Author: Eike Hein <hein@kde.org>
Date:   Mon Apr 26 15:34:20 2010 +0200

    In-progress automatic reconnect can now be aborted using '/disconnect'.
    
    BUG:235186
    
    A manual disconnect also didn't use to reset the reconnection counter
    to 0 - only a successful connect would. Since there was no way to abort
    trying to connect until now that wasn't of consequence, but had to be
    and is fixed now. Also cleaned up Server::disconnect() shadowing the
    QObject version.

diff --git a/ChangeLog b/ChangeLog
index 4758612..64c98d2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -94,6 +94,8 @@ Changes since 1.2.3:
   supported in this release) and higher.
 * Not reacting to an SSL certificat validation error dialog in a
   timely manner should no longer result in Konversation locking up.
+* In-progress automatic reconnect in the event of connection failure
+  can now be aborted by using the '/disconnect' command.
 
 
 Changes from 1.2.2 to 1.2.3:
diff --git a/src/commit.h b/src/commit.h
index a5d1d78..bd51a15 100644
--- a/src/commit.h
+++ b/src/commit.h
@@ -1,4 +1,4 @@
 // This COMMIT number is added to version string to be used as "patch level"
 #ifndef COMMIT
-#define COMMIT 4039
+#define COMMIT 4040
 #endif
diff --git a/src/connectionmanager.cpp b/src/connectionmanager.cpp
index 3860010..289565c 100644
--- a/src/connectionmanager.cpp
+++ b/src/connectionmanager.cpp
@@ -271,8 +271,7 @@ void ConnectionManager::handleReconnect(Server* server)
         }
 
         server->getConnectionSettings().incrementReconnectCount();
-
-        QTimer::singleShot(Preferences::self()->reconnectDelay() * 1000, server, SLOT(connectToIRCServer()));
+        server->connectToIRCServerIn(Preferences::self()->reconnectDelay());
     }
     else
         server->getStatusView()->appendServerMessage(i18n("Error"), i18n("Reconnection attempts exceeded."));
@@ -291,7 +290,7 @@ void ConnectionManager::reconnectServers()
     QMap<int, Server*>::ConstIterator it;
 
     for (it = m_connectionList.constBegin(); it != m_connectionList.constEnd(); ++it)
-        it.value()->reconnect();
+        it.value()->reconnectServer();
 }
 
 void ConnectionManager::decodeIrcUrl(const QString& url, ConnectionSettings& settings)
@@ -534,7 +533,7 @@ bool ConnectionManager::reuseExistingConnection(ConnectionSettings& settings, bo
 
             if (result == KMessageBox::Continue)
             {
-                dupe->disconnect();
+                dupe->disconnectServer();
 
                 dupe->setConnectionSettings(settings);
             }
@@ -546,7 +545,7 @@ bool ConnectionManager::reuseExistingConnection(ConnectionSettings& settings, bo
                 dupe->updateAutoJoin(settings.oneShotChannelList());
 
             if (!dupe->isConnecting())
-                dupe->reconnect();
+                dupe->reconnectServer();
         }
         else
         {
diff --git a/src/irc/inputfilter.cpp b/src/irc/inputfilter.cpp
index 9a9d746..cf4dd39 100644
--- a/src/irc/inputfilter.cpp
+++ b/src/irc/inputfilter.cpp
@@ -1200,7 +1200,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString &comma
                         // The user chose to disconnect
                         if (newNick.isNull())
                         {
-                            server->disconnect();
+                            server->disconnectServer();
                         }
                         else
                         {
@@ -1231,7 +1231,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString &comma
                         // The user chose to disconnect
                         if (newNick.isNull())
                         {
-                            server->disconnect();
+                            server->disconnectServer();
                         }
                         else
                         {
diff --git a/src/irc/server.cpp b/src/irc/server.cpp
index f62ccfa..62f9162 100644
--- a/src/irc/server.cpp
+++ b/src/irc/server.cpp
@@ -68,6 +68,10 @@ Server::Server(QObject* parent, ConnectionSettings& settings) : QObject(parent)
 
     m_connectionState = Konversation::SSNeverConnected;
 
+    m_delayedConnectTimer = new QTimer(this);
+    m_delayedConnectTimer->setSingleShot(true);
+    connect(m_delayedConnectTimer, SIGNAL(timeout()), this, SLOT(connectToIRCServer()));
+
     for (int i=0; i <= Application::instance()->countOfQueues(); i++)
     {
         //QList<int> r=Preferences::queueRate(i);
@@ -245,8 +249,8 @@ void Server::connectSignals()
     connect(getOutputFilter(), SIGNAL(requestDccSend(const QString&)), this, SLOT(requestDccSend(const QString&)), Qt::QueuedConnection);
     connect(getOutputFilter(), SIGNAL(multiServerCommand(const QString&, const QString&)),
         this, SLOT(sendMultiServerCommand(const QString&, const QString&)));
-    connect(getOutputFilter(), SIGNAL(reconnectServer()), this, SLOT(reconnect()));
-    connect(getOutputFilter(), SIGNAL(disconnectServer()), this, SLOT(disconnect()));
+    connect(getOutputFilter(), SIGNAL(reconnectServer()), this, SLOT(reconnectServer()));
+    connect(getOutputFilter(), SIGNAL(disconnectServer()), this, SLOT(disconnectServer()));
     connect(getOutputFilter(), SIGNAL(openDccSend(const QString &, KUrl)), this, SLOT(addDccSend(const QString &, KUrl)), Qt::QueuedConnection);
     connect(getOutputFilter(), SIGNAL(openDccChat(const QString &)), this, SLOT(openDccChat(const QString &)), Qt::QueuedConnection);
     connect(getOutputFilter(), SIGNAL(openDccWBoard(const QString &)), this, SLOT(openDccWBoard(const QString &)), Qt::QueuedConnection);
@@ -432,6 +436,12 @@ void Server::connectToIRCServer()
         kDebug() << "connectToIRCServer() called while already connected: This should never happen.";
 }
 
+void Server::connectToIRCServerIn(uint delay)
+{
+    m_delayedConnectTimer->setInterval(delay * 1000);
+    m_delayedConnectTimer->start();
+}
+
 void Server::showSSLDialog()
 {
         //TODO
@@ -564,7 +574,7 @@ void Server::hostFound()
 
 void Server::ircServerConnectionSuccess()
 {
-        emit sslConnected(this);
+    emit sslConnected(this);
     getConnectionSettings().setReconnectCount(0);
 
     Konversation::ServerSettings serverSettings = getConnectionSettings().server();
@@ -3579,7 +3589,7 @@ void Server::updateConnectionState(Konversation::ConnectionState state)
     }
 }
 
-void Server::reconnect()
+void Server::reconnectServer()
 {
     if (isConnecting() || isSocketConnected()) quitServer();
 
@@ -3590,9 +3600,16 @@ void Server::reconnect()
     QTimer::singleShot(0, this, SLOT(connectToIRCServer()));
 }
 
-//! TODO FIXME this is a QObject....
-void Server::disconnect()
+void Server::disconnectServer()
 {
+    getConnectionSettings().setReconnectCount(0);
+
+    if (m_delayedConnectTimer->isActive())
+    {
+        m_delayedConnectTimer->stop();
+        getStatusView()->appendServerMessage(i18n("Info"), i18n("Delayed connect aborted."));
+    }
+
     if (isSocketConnected()) quitServer();
 }
 
@@ -3951,7 +3968,7 @@ void Server::involuntaryQuit()
 void Server::reconnectInvoluntary()
 {
     if(m_connectionState == Konversation::SSInvoluntarilyDisconnected)
-        reconnect();
+        reconnectServer();
 }
 
 #include "server.moc"
diff --git a/src/irc/server.h b/src/irc/server.h
index 385e480..2c75897 100644
--- a/src/irc/server.h
+++ b/src/irc/server.h
@@ -437,6 +437,7 @@ void resetNickSelection();
 
     public slots:
         void connectToIRCServer();
+        void connectToIRCServerIn(uint delay);
 
         /** Adds line to queue if non-empty. */
         bool queue(const QString& line, QueuePriority priority=StandardPriority);
@@ -477,8 +478,8 @@ void resetNickSelection();
         void updateChannelQuickButtons();
         void sendMultiServerCommand(const QString& command, const QString& parameter);
         void executeMultiServerCommand(const QString& command, const QString& parameter);
-        void reconnect();
-        void disconnect(); //FIXME is this overriding a qobject method? do we care?
+        void reconnectServer();
+        void disconnectServer();
         void showSSLDialog();
         void sendToAllChannels(const QString& text);
         void notifyTimeout();
@@ -755,7 +756,7 @@ void resetNickSelection();
 
         /// Creates a list of known users and returns the one chosen by the user
         inline QString recipientNick() const;
-        
+
         /**
           * shows a dialog to the user where he is asked if he wants to
           * ignore SSL certificate errors
@@ -803,6 +804,10 @@ void resetNickSelection();
 
         ConnectionSettings m_connectionSettings;
 
+        /// Used by ConnectionManaer to schedule a reconnect; stopped by /disconnect
+        /// and /quit.
+        QTimer* m_delayedConnectTimer;
+
         static int m_availableConnectionId;
         int m_connectionId;
 
diff --git a/src/viewer/viewcontainer.cpp b/src/viewer/viewcontainer.cpp
index 73243bb..578ca31 100644
--- a/src/viewer/viewcontainer.cpp
+++ b/src/viewer/viewcontainer.cpp
@@ -2229,7 +2229,7 @@ void ViewContainer::reconnectFrontServer()
     else
         server = m_frontServer;
 
-    if (server) server->reconnect();
+    if (server) server->reconnectServer();
 }
 
 void ViewContainer::disconnectFrontServer()
@@ -2242,7 +2242,7 @@ void ViewContainer::disconnectFrontServer()
         server = m_frontServer;
 
     if (server && server->isConnected())
-        server->disconnect();
+        server->disconnectServer();
 }
 
 void ViewContainer::showJoinChannelDialog()