X-Git-Url: https://git.quassel-irc.org/?a=blobdiff_plain;f=src%2Fcore%2Fcorenetwork.h;h=a77491245623fcb1a4266555fe863db19936dc51;hb=fcacaaf16551524c7ebb6114254d005274cc3d63;hp=d26935878cc39b1785a9e6e58700fad01629cc7b;hpb=6a63070246d89aa2a2474e3a9a1035fa889ad77e;p=quassel.git diff --git a/src/core/corenetwork.h b/src/core/corenetwork.h index d2693587..a7749124 100644 --- a/src/core/corenetwork.h +++ b/src/core/corenetwork.h @@ -18,8 +18,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ -#ifndef CORENETWORK_H -#define CORENETWORK_H +#pragma once #include "network.h" #include "coreircchannel.h" @@ -52,13 +51,11 @@ class Event; class CoreNetwork : public Network { - SYNCABLE_OBJECT - Q_OBJECT + Q_OBJECT public: CoreNetwork(const NetworkId &networkid, CoreSession *session); - ~CoreNetwork(); - inline virtual const QMetaObject *syncMetaObject() const { return &Network::staticMetaObject; } + ~CoreNetwork() override; inline CoreIdentity *identityPtr() const { return coreSession()->identity(identity()); } inline CoreSession *coreSession() const { return _coreSession; } @@ -90,7 +87,16 @@ public: inline QByteArray readChannelCipherKey(const QString &channel) const { return _cipherKeys.value(channel.toLower()); } inline void storeChannelCipherKey(const QString &channel, const QByteArray &key) { _cipherKeys[channel.toLower()] = key; } - inline bool isAutoWhoInProgress(const QString &channel) const { return _autoWhoPending.value(channel.toLower(), 0); } + /** + * Checks if the given target has an automatic WHO in progress + * + * @param name Channel or nickname + * @return True if an automatic WHO is in progress, otherwise false + */ + inline bool isAutoWhoInProgress(const QString &name) const + { + return _autoWhoPending.value(name.toLower(), 0); + } inline UserId userId() const { return _coreSession->user(); } @@ -110,6 +116,25 @@ public: */ inline bool disconnectExpected() const { return _disconnectExpected; } + /** + * Gets whether or not the server replies to automated PINGs with a valid timestamp + * + * Distinguishes between servers that reply by quoting the text sent, and those that respond + * with whatever they want. + * + * @return True if a valid timestamp has been received as a PONG, otherwise false. + */ + inline bool isPongTimestampValid() const { return _pongTimestampValid; } + + /** + * Gets whether or not an automated PING has been sent without any PONG received + * + * Reset whenever any PONG is received, not just the automated one sent. + * + * @return True if a PING has been sent without a PONG received, otherwise false. + */ + inline bool isPongReplyPending() const { return _pongReplyPending; } + QList> splitMessage(const QString &cmd, const QString &message, std::function(QString &)> cmdGenerator); // IRCv3 capability negotiation @@ -178,18 +203,36 @@ public: }; public slots: - virtual void setMyNick(const QString &mynick); + void setMyNick(const QString &mynick) override; - virtual void requestConnect() const; - virtual void requestDisconnect() const; - virtual void requestSetNetworkInfo(const NetworkInfo &info); + void requestConnect() const override; + void requestDisconnect() const override; + void requestSetNetworkInfo(const NetworkInfo &info) override; - virtual void setUseAutoReconnect(bool); - virtual void setAutoReconnectInterval(quint32); - virtual void setAutoReconnectRetries(quint16); + void setUseAutoReconnect(bool) override; + void setAutoReconnectInterval(quint32) override; + void setAutoReconnectRetries(quint16) override; void setPingInterval(int interval); + /** + * Sets whether or not the IRC server has replied to PING with a valid timestamp + * + * This allows determining whether or not an IRC server responds to PING with a PONG that quotes + * what was sent, or if it does something else (and therefore PONGs should be more aggressively + * hidden). + * + * @param timestampValid If true, a valid timestamp has been received via PONG reply + */ + void setPongTimestampValid(bool validTimestamp); + + /** + * Indicates that the CoreSession is shutting down. + * + * Disconnects the network if connected, and sets a flag that prevents reconnections. + */ + void shutdown(); + void connectToIrc(bool reconnecting = false); /** * Disconnect from the IRC server. @@ -199,16 +242,14 @@ public slots: * @param requested If true, user requested this disconnect; don't try to reconnect * @param reason Reason for quitting, defaulting to the user-configured quit reason * @param withReconnect Reconnect to the network after disconnecting (e.g. ping timeout) - * @param forceImmediate Immediately disconnect from network, skipping queue of other commands */ - void disconnectFromIrc(bool requested = true, const QString &reason = QString(), - bool withReconnect = false, bool forceImmediate = false); + void disconnectFromIrc(bool requested = true, const QString &reason = QString(), bool withReconnect = false); /** * Forcibly close the IRC server socket, waiting for it to close. * * Call CoreNetwork::disconnectFromIrc() first, allow the event loop to run, then if you need to - * be sure the network's disconencted (e.g. clean-up), call this. + * be sure the network's disconnected (e.g. clean-up), call this. * * @param msecs Maximum time to wait for socket to close, in milliseconds. * @return True if socket closes successfully; false if error occurs or timeout reached @@ -358,11 +399,17 @@ public slots: * When 'away-notify' is enabled, this will trigger an immediate AutoWho since regular * who-cycles are disabled as per IRCv3 specifications. * - * @param[in] channelOrNick Channel or nickname to WHO + * @param[in] name Channel or nickname */ - void queueAutoWhoOneshot(const QString &channelOrNick); + void queueAutoWhoOneshot(const QString &name); - bool setAutoWhoDone(const QString &channel); + /** + * Checks if the given target has an automatic WHO in progress, and sets it as done if so + * + * @param name Channel or nickname + * @return True if an automatic WHO is in progress (and should be silenced), otherwise false + */ + bool setAutoWhoDone(const QString &name); void updateIssuedModes(const QString &requestedModes); void updatePersistentModes(QString addModes, QString removeModes); @@ -372,6 +419,11 @@ public slots: inline void resetPingTimeout() { _pingCount = 0; } + /** + * Marks the network as no longer having a pending reply to an automated PING + */ + inline void resetPongReplyPending() { _pongReplyPending = false; } + inline void displayMsg(Message::Type msgType, BufferInfo::Type bufferType, const QString &target, const QString &text, const QString &sender = "", Message::Flags flags = Message::None) { emit displayMsg(networkId(), msgType, bufferType, target, text, sender, flags); @@ -389,12 +441,12 @@ signals: void sslErrors(const QVariant &errorData); void newEvent(Event *event); - void socketInitialized(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort); - void socketDisconnected(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort); + void socketInitialized(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort, qint64 socketId); + void socketDisconnected(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, const QHostAddress &peerAddress, quint16 peerPort, qint64 socketId); protected: - inline virtual IrcChannel *ircChannelFactory(const QString &channelname) { return new CoreIrcChannel(channelname, this); } - inline virtual IrcUser *ircUserFactory(const QString &hostmask) { return new CoreIrcUser(hostmask, this); } + inline IrcChannel *ircChannelFactory(const QString &channelname) override { return new CoreIrcChannel(channelname, this); } + inline IrcUser *ircUserFactory(const QString &hostmask) override { return new CoreIrcUser(hostmask, this); } protected slots: // TODO: remove cached cipher keys, when appropriate @@ -406,7 +458,7 @@ private slots: void socketHasData(); void socketError(QAbstractSocket::SocketError); void socketInitialized(); - inline void socketCloseTimeout() { socket.abort(); } + void socketCloseTimeout(); void socketDisconnected(); void socketStateChanged(QAbstractSocket::SocketState); void networkInitialized(); @@ -448,11 +500,15 @@ private slots: private: CoreSession *_coreSession; + bool _debugLogRawIrc; ///< If true, include raw IRC socket messages in the debug log + qint32 _debugLogRawNetId; ///< Network ID for logging raw IRC socket messages, or -1 for all + #ifdef HAVE_SSL QSslSocket socket; #else QTcpSocket socket; #endif + qint64 _socketId{0}; CoreUserInputHandler *_userInputHandler; @@ -473,13 +529,19 @@ private: // This avoids logging a spurious RemoteHostClosedError whenever disconnect is called without // specifying a permanent (saved to core session) disconnect. + bool _shuttingDown{false}; ///< If true, we're shutting down and ignore requests to (dis)connect networks + bool _previousConnectionAttemptFailed; int _lastUsedServerIndex; QTimer _pingTimer; - qint64 _lastPingTime; - uint _pingCount; - bool _sendPings; + qint64 _lastPingTime = 0; ///< Unix time of most recently sent automatic ping + uint _pingCount = 0; ///< Unacknowledged automatic pings + bool _sendPings = false; ///< If true, pings should be periodically sent to server + bool _pongTimestampValid = false; ///< If true, IRC server responds to PING by quoting in PONG + // This tracks whether or not a server responds to PING with a PONG of what was sent, or if it + // does something else. If false, PING reply hiding should be more aggressive. + bool _pongReplyPending = false; ///< If true, at least one PING sent without a PONG reply QStringList _autoWhoQueue; QHash _autoWhoPending; @@ -535,6 +597,3 @@ private: // List of blowfish keys for channels QHash _cipherKeys; }; - - -#endif //CORENETWORK_H