X-Git-Url: https://git.quassel-irc.org/?a=blobdiff_plain;f=src%2Fcore%2Fcorenetwork.h;h=8d5f7201eb21e3e162d10615ff0b00d015898e09;hb=815f878218872c630f0b054aee40f524cad8f1a8;hp=ae1ebd8eb501674ad91104f746c56c02f9eacab7;hpb=dd711790dddee81442e2138b3917764dac39c487;p=quassel.git diff --git a/src/core/corenetwork.h b/src/core/corenetwork.h index ae1ebd8e..8d5f7201 100644 --- a/src/core/corenetwork.h +++ b/src/core/corenetwork.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2015 by the Quassel Project * + * Copyright (C) 2005-2016 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -25,6 +25,9 @@ #include "coreircchannel.h" #include "coreircuser.h" +// IRCv3 capabilities +#include "irccap.h" + #include #ifdef HAVE_SSL @@ -102,13 +105,6 @@ public: // IRCv3 capability negotiation - /** - * Checks if a given capability is enabled. - * - * @returns True if enabled, otherwise false - */ - inline bool capEnabled(const QString &capability) const { return _capsSupported.contains(capability); } - /** * Checks if capability negotiation is currently ongoing. * @@ -117,95 +113,121 @@ public: inline bool capNegotiationInProgress() const { return !_capsQueued.empty(); } /** - * Gets the value of an enabled or pending capability, e.g. sasl=plain. + * Queues a capability to be requested. + * + * Adds to the list of capabilities being requested. If non-empty, CAP REQ messages are sent + * to the IRC server. This may happen at login or if capabilities are announced via CAP NEW. * - * @returns Value of capability if one was specified, otherwise empty string + * @param[in] capability Name of the capability */ - QString capValue(const QString &capability) const; + void queueCap(const QString &capability); /** - * Gets the next capability to request, removing it from the queue. + * Begins capability negotiation if capabilities are queued, otherwise returns. * - * @returns Name of capability to request + * If any capabilities are queued, this will begin the cycle of taking each capability and + * requesting it. When no capabilities remain, capability negotiation is suitably ended. */ - QString takeQueuedCap(); - - // Specific capabilities for easy reference + void beginCapNegotiation(); /** - * Gets the status of the sasl authentication capability. + * List of capabilities requiring further core<->server messages to configure. * - * http://ircv3.net/specs/extensions/sasl-3.2.html + * For example, SASL requires the back-and-forth of AUTHENTICATE, so the next capability cannot + * be immediately sent. * - * @returns True if SASL authentication is enabled, otherwise false + * See: http://ircv3.net/specs/extensions/sasl-3.2.html */ - inline bool useCapSASL() const { return capEnabled("sasl"); } + const QStringList capsRequiringConfiguration = QStringList { + IrcCap::SASL + }; + +public slots: + virtual void setMyNick(const QString &mynick); + + virtual void requestConnect() const; + virtual void requestDisconnect() const; + virtual void requestSetNetworkInfo(const NetworkInfo &info); + + virtual void setUseAutoReconnect(bool); + virtual void setAutoReconnectInterval(quint32); + virtual void setAutoReconnectRetries(quint16); + void setPingInterval(int interval); + + void connectToIrc(bool reconnecting = false); /** - * Gets the status of the away-notify capability. + * Disconnect from the IRC server. * - * http://ircv3.net/specs/extensions/away-notify-3.1.html + * Begin disconnecting from the IRC server, including optionally reconnecting. * - * @returns True if away-notify is enabled, otherwise false + * @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 */ - inline bool useCapAwayNotify() const { return capEnabled("away-notify"); } + void disconnectFromIrc(bool requested = true, const QString &reason = QString(), + bool withReconnect = false, bool forceImmediate = false); /** - * Gets the status of the account-notify capability. + * Forcibly close the IRC server socket, waiting for it to close. * - * http://ircv3.net/specs/extensions/account-notify-3.1.html + * 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. * - * @returns True if account-notify is enabled, otherwise false + * @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 */ - inline bool useCapAccountNotify() const { return capEnabled("account-notify"); } + bool forceDisconnect(int msecs = 1000); + + void userInput(BufferInfo bufferInfo, QString msg); /** - * Gets the status of the extended-join capability. + * Sends the raw (encoded) line, adding to the queue if needed, optionally with higher priority. * - * http://ircv3.net/specs/extensions/extended-join-3.1.html - * - * @returns True if extended-join is enabled, otherwise false + * @param[in] input QByteArray of encoded characters + * @param[in] prepend + * @parmblock + * If true, the line is prepended into the start of the queue, otherwise, it's appended to the + * end. This should be used sparingly, for if either the core or the IRC server cannot maintain + * PING/PONG replies, the other side will close the connection. + * @endparmblock */ - inline bool useCapExtendedJoin() const { return capEnabled("extended-join"); } + void putRawLine(const QByteArray input, const bool prepend = false); /** - * Gets the status of the userhost-in-names capability. - * - * http://ircv3.net/specs/extensions/userhost-in-names-3.2.html + * Sends the command with encoded parameters, with optional prefix or high priority. * - * @returns True if userhost-in-names is enabled, otherwise false + * @param[in] cmd Command to send, ignoring capitalization + * @param[in] params Parameters for the command, encoded within a QByteArray + * @param[in] prefix Optional command prefix + * @param[in] prepend + * @parmblock + * If true, the command is prepended into the start of the queue, otherwise, it's appended to + * the end. This should be used sparingly, for if either the core or the IRC server cannot + * maintain PING/PONG replies, the other side will close the connection. + * @endparmblock */ - inline bool useCapUserhostInNames() const { return capEnabled("userhost-in-names"); } + void putCmd(const QString &cmd, const QList ¶ms, const QByteArray &prefix = QByteArray(), const bool prepend = false); /** - * Gets the status of the multi-prefix capability. - * - * http://ircv3.net/specs/extensions/multi-prefix-3.1.html + * Sends the command for each set of encoded parameters, with optional prefix or high priority. * - * @returns True if multi-prefix is enabled, otherwise false + * @param[in] cmd Command to send, ignoring capitalization + * @param[in] params + * @parmblock + * List of parameter lists for the command, encoded within a QByteArray. The command will be + * sent multiple times, once for each set of params stored within the outer list. + * @endparmblock + * @param[in] prefix Optional command prefix + * @param[in] prependAll + * @parmblock + * If true, ALL of the commands are prepended into the start of the queue, otherwise, they're + * appended to the end. This should be used sparingly, for if either the core or the IRC server + * cannot maintain PING/PONG replies, the other side will close the connection. + * @endparmblock */ - inline bool useCapMultiPrefix() const { return capEnabled("multi-prefix"); } - -public slots: - virtual void setMyNick(const QString &mynick); - - virtual void requestConnect() const; - virtual void requestDisconnect() const; - virtual void requestSetNetworkInfo(const NetworkInfo &info); - - virtual void setUseAutoReconnect(bool); - virtual void setAutoReconnectInterval(quint32); - virtual void setAutoReconnectRetries(quint16); - - void setPingInterval(int interval); - - void connectToIrc(bool reconnecting = false); - void disconnectFromIrc(bool requested = true, const QString &reason = QString(), bool withReconnect = false); - - void userInput(BufferInfo bufferInfo, QString msg); - void putRawLine(QByteArray input); - void putCmd(const QString &cmd, const QList ¶ms, const QByteArray &prefix = QByteArray()); - void putCmd(const QString &cmd, const QList> ¶ms, const QByteArray &prefix = QByteArray()); + void putCmd(const QString &cmd, const QList> ¶ms, const QByteArray &prefix = QByteArray(), const bool prependAll = false); void setChannelJoined(const QString &channel); void setChannelParted(const QString &channel); @@ -223,40 +245,39 @@ public slots: // IRCv3 capability negotiation (can be connected to signals) /** - * Marks a capability as accepted, providing an optional value. + * Indicates a capability is now available, with optional value in Network::capValue(). * - * Removes it from queue of pending capabilities and triggers any capability-specific - * activation. + * @see Network::addCap() * * @param[in] capability Name of the capability - * @param[in] value - * @parblock - * Optional value of the capability, e.g. sasl=plain. If left empty, will be copied from the - * pending capability. - * @endparblock */ - void addCap(const QString &capability, const QString &value = QString()); + void serverCapAdded(const QString &capability); /** - * Marks a capability as denied. + * Indicates a capability was acknowledged (enabled by the IRC server). * - * Removes it from the queue of pending capabilities and triggers any capability-specific - * deactivation. + * @see Network::acknowledgeCap() * * @param[in] capability Name of the capability */ - void removeCap(const QString &capability); + void serverCapAcknowledged(const QString &capability); /** - * Queues a capability as available but not yet accepted or denied. + * Indicates a capability was removed from the list of available capabilities. * - * Capabilities should be queued when registration pauses for CAP LS for capabilities are only - * requested during login. + * @see Network::removeCap() * * @param[in] capability Name of the capability - * @param[in] value Optional value of the capability, e.g. sasl=plain */ - void queuePendingCap(const QString &capability, const QString &value = QString()); + void serverCapRemoved(const QString &capability); + + /** + * Sends the next capability from the queue. + * + * During nick registration if any capabilities remain queued, this will take the next and + * request it. When no capabilities remain, capability negotiation is ended. + */ + void sendNextCap(); void setAutoWhoEnabled(bool enabled); void setAutoWhoInterval(int interval); @@ -362,6 +383,10 @@ private: bool _quitRequested; QString _quitReason; + bool _disconnectExpected; /// If true, connection is quitting, expect a socket close + // This avoids logging a spurious RemoteHostClosedError whenever disconnect is called without + // specifying a permanent (saved to core session) disconnect. + bool _previousConnectionAttemptFailed; int _lastUsedServerIndex; @@ -374,11 +399,20 @@ private: QHash _autoWhoPending; QTimer _autoWhoTimer, _autoWhoCycleTimer; - // CAPs may have parameter values + // Maintain a list of CAPs that are being checked; if empty, negotiation finished // See http://ircv3.net/specs/core/capability-negotiation-3.2.html - QStringList _capsQueued; /// Capabilities to be checked - QHash _capsPending; /// Capabilities pending 'CAP ACK' from server - QHash _capsSupported; /// Enabled capabilities that received 'CAP ACK' + QStringList _capsQueued; /// Capabilities to be checked + bool _capNegotiationActive; /// Whether or not full capability negotiation was started + // Avoid displaying repeat "negotiation finished" messages + bool _capInitialNegotiationEnded; /// Whether or not initial capability negotiation finished + // Avoid sending repeat "CAP END" replies when registration is already ended + + /** + * Gets the next capability to request, removing it from the queue. + * + * @returns Name of capability to request + */ + QString takeQueuedCap(); QTimer _tokenBucketTimer; int _messageDelay; // token refill speed in ms