From f4693532403c2bcba592d322d0b5dbceaf76e758 Mon Sep 17 00:00:00 2001 From: Marcus Eggenberger Date: Fri, 13 Feb 2009 15:51:06 +0100 Subject: [PATCH 1/1] taming and reenabling the irc timeout detection --- src/core/corenetwork.cpp | 44 +++++++++++++++++++++-------------- src/core/corenetwork.h | 7 +++--- src/core/ircserverhandler.cpp | 5 ++-- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/core/corenetwork.cpp b/src/core/corenetwork.cpp index b4a6d86d..c0233853 100644 --- a/src/core/corenetwork.cpp +++ b/src/core/corenetwork.cpp @@ -40,7 +40,7 @@ CoreNetwork::CoreNetwork(const NetworkId &networkid, CoreSession *session) _previousConnectionAttemptFailed(false), _lastUsedServerIndex(0), - _gotPong(true), + _lastPingTime(0), // TODO make autowho configurable (possibly per-network) _autoWhoEnabled(true), @@ -189,6 +189,7 @@ void CoreNetwork::disconnectFromIrc(bool requested, const QString &reason, bool _autoReconnectTimer.stop(); _autoReconnectCount = 0; // prohibiting auto reconnect } + disablePingTimeout(); IrcUser *me_ = me(); if(me_) { @@ -204,21 +205,18 @@ void CoreNetwork::disconnectFromIrc(bool requested, const QString &reason, bool else _quitReason = reason; - displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Disconnecting.")); + displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Disconnecting. (%1)").arg((!requested && !withReconnect) ? tr("Core Shutdown") : reason)); switch(socket.state()) { - case QAbstractSocket::UnconnectedState: - socketDisconnected(); - break; case QAbstractSocket::ConnectedState: userInputHandler()->issueQuit(_quitReason); - default: - if(!requested) { - socket.close(); - socketDisconnected(); - } else { + if(requested || withReconnect) { // the irc server has 10 seconds to close the socket _socketCloseTimer.start(10000); + break; } + default: + socket.close(); + socketDisconnected(); } } @@ -338,8 +336,7 @@ void CoreNetwork::socketInitialized() { } void CoreNetwork::socketDisconnected() { - _pingTimer.stop(); - resetPong(); + disablePingTimeout(); _autoWhoCycleTimer.stop(); _autoWhoTimer.stop(); @@ -420,8 +417,7 @@ void CoreNetwork::networkInitialized() { sendPerform(); - resetPong(); - _pingTimer.start(); + enablePingTimeout(); if(_autoWhoEnabled) { _autoWhoCycleTimer.start(); @@ -517,14 +513,28 @@ void CoreNetwork::doAutoReconnect() { } void CoreNetwork::sendPing() { - if(!gotPong()) { - // disconnectFromIrc(false, QString("No Ping reply in %1 seconds.").arg(_pingTimer.interval() / 1000), true /* withReconnect */); + uint now = QDateTime::currentDateTime().toTime_t(); + if(_lastPingTime != 0 && now - _lastPingTime <= (uint)(_pingTimer.interval() / 1000) + 1) { + // the second check compares the actual elapsed time since the last ping and the pingTimer interval + // if the interval is shorter then the actual elapsed time it means that this thread was somehow blocked + // and unable to even handle a ping answer. So we ignore those misses. + disconnectFromIrc(false, QString("No Ping reply in %1 seconds.").arg(_pingTimer.interval() / 1000), true /* withReconnect */); } else { - _gotPong = false; + _lastPingTime = now; userInputHandler()->handlePing(BufferInfo(), QString()); } } +void CoreNetwork::enablePingTimeout() { + resetPingTimeout(); + _pingTimer.start(); +} + +void CoreNetwork::disablePingTimeout() { + _pingTimer.stop(); + resetPingTimeout(); +} + void CoreNetwork::sendAutoWho() { while(!_autoWhoQueue.isEmpty()) { QString chan = _autoWhoQueue.takeFirst(); diff --git a/src/core/corenetwork.h b/src/core/corenetwork.h index f50717b0..42ad12d5 100644 --- a/src/core/corenetwork.h +++ b/src/core/corenetwork.h @@ -106,8 +106,7 @@ public slots: Server usedServer() const; - inline void resetPong() { _gotPong = true; } - inline bool gotPong() { return _gotPong; } + inline void resetPingTimeout() { _lastPingTime = 0; } signals: void recvRawServerMsg(QString); @@ -135,6 +134,8 @@ private slots: void restoreUserModes(); void doAutoReconnect(); void sendPing(); + void enablePingTimeout(); + void disablePingTimeout(); void sendAutoWho(); void startAutoWhoCycle(); @@ -176,7 +177,7 @@ private: int _lastUsedServerIndex; QTimer _pingTimer; - bool _gotPong; + uint _lastPingTime; bool _autoWhoEnabled; QStringList _autoWhoQueue; diff --git a/src/core/ircserverhandler.cpp b/src/core/ircserverhandler.cpp index bcdcf446..34573d9b 100644 --- a/src/core/ircserverhandler.cpp +++ b/src/core/ircserverhandler.cpp @@ -94,6 +94,9 @@ void IrcServerHandler::handleServerMsg(QByteArray msg) { params.removeFirst(); } + // note that the IRC server is still alive + network()->resetPingTimeout(); + // Now we try to find a handler for this message. BTW, I do love the Trolltech guys ;-) handle(cmd, Q_ARG(QString, prefix), Q_ARG(QList, params)); } @@ -385,8 +388,6 @@ void IrcServerHandler::handlePong(const QString &prefix, const QList if(params.count() < 2) return; - network()->resetPong(); - QString timestamp = serverDecode(params[1]); QTime sendTime = QTime::fromString(timestamp, "hh:mm:ss.zzz"); if(!sendTime.isValid()) { -- 2.20.1