Add a flag to enable Qt deprecation warnings on Qt < 5.13
[quassel.git] / src / common / network.h
index 09310fd..cefe53b 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2005-2016 by the Quassel Project                        *
+ *   Copyright (C) 2005-2019 by the Quassel Project                        *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
  ***************************************************************************/
 
-#ifndef NETWORK_H
-#define NETWORK_H
+#pragma once
 
-#include <QString>
-#include <QStringList>
+#include "common-export.h"
+
+#include <utility>
+
+#include <QByteArray>
+#include <QHash>
 #include <QList>
+#include <QMutex>
 #include <QNetworkProxy>
-#include <QHash>
-#include <QVariantMap>
 #include <QPointer>
-#include <QMutex>
-#include <QByteArray>
+#include <QString>
+#include <QStringList>
+#include <QVariantMap>
 
+#include "ircchannel.h"
+#include "ircuser.h"
+#include "signalproxy.h"
+#include "syncableobject.h"
 #include "types.h"
 #include "util.h"
-#include "syncableobject.h"
 
-#include "signalproxy.h"
-#include "ircuser.h"
-#include "ircchannel.h"
+// IRCv3 capabilities
+#include "irccap.h"
 
 // defined below!
 struct NetworkInfo;
 
 // TODO: ConnectionInfo to propagate and sync the current state of NetworkConnection, encodings etcpp
 
-class Network : public SyncableObject
+class COMMON_EXPORT Network : public SyncableObject
 {
-    SYNCABLE_OBJECT
     Q_OBJECT
+    SYNCABLE_OBJECT
+
     Q_ENUMS(ConnectionState)
 
     Q_PROPERTY(QString networkName READ networkName WRITE setNetworkName)
@@ -59,7 +65,7 @@ class Network : public SyncableObject
     Q_PROPERTY(QByteArray codecForDecoding READ codecForDecoding WRITE setCodecForDecoding)
     Q_PROPERTY(IdentityId identityId READ identity WRITE setIdentity)
     Q_PROPERTY(bool isConnected READ isConnected WRITE setConnected)
-    //Q_PROPERTY(Network::ConnectionState connectionState READ connectionState WRITE setConnectionState)
+    // Q_PROPERTY(Network::ConnectionState connectionState READ connectionState WRITE setConnectionState)
     Q_PROPERTY(int connectionState READ connectionState WRITE setConnectionState)
     Q_PROPERTY(bool useRandomServer READ useRandomServer WRITE setUseRandomServer)
     Q_PROPERTY(QStringList perform READ perform WRITE setPerform)
@@ -74,9 +80,15 @@ class Network : public SyncableObject
     Q_PROPERTY(quint16 autoReconnectRetries READ autoReconnectRetries WRITE setAutoReconnectRetries)
     Q_PROPERTY(bool unlimitedReconnectRetries READ unlimitedReconnectRetries WRITE setUnlimitedReconnectRetries)
     Q_PROPERTY(bool rejoinChannels READ rejoinChannels WRITE setRejoinChannels)
-
-public :
-        enum ConnectionState {
+    // Custom rate limiting
+    Q_PROPERTY(bool useCustomMessageRate READ useCustomMessageRate WRITE setUseCustomMessageRate)
+    Q_PROPERTY(quint32 msgRateBurstSize READ messageRateBurstSize WRITE setMessageRateBurstSize)
+    Q_PROPERTY(quint32 msgRateMessageDelay READ messageRateDelay WRITE setMessageRateDelay)
+    Q_PROPERTY(bool unlimitedMessageRate READ unlimitedMessageRate WRITE setUnlimitedMessageRate)
+
+public:
+    enum ConnectionState
+    {
         Disconnected,
         Connecting,
         Initializing,
@@ -88,7 +100,8 @@ public :
     // see:
     //  http://www.irc.org/tech_docs/005.html
     //  http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt
-    enum ChannelModeType {
+    enum ChannelModeType
+    {
         NOT_A_CHANMODE = 0x00,
         A_CHANMODE = 0x01,
         B_CHANMODE = 0x02,
@@ -96,41 +109,65 @@ public :
         D_CHANMODE = 0x08
     };
 
-    struct Server {
+    // Default port assignments according to what many IRC networks have settled on.
+    // Technically not a standard, but it's fairly widespread.
+    // See https://freenode.net/news/port-6697-irc-via-tlsssl
+    enum PortDefaults
+    {
+        PORT_PLAINTEXT = 6667,  /// Default port for unencrypted connections
+        PORT_SSL = 6697         /// Default port for encrypted connections
+    };
+
+    struct Server
+    {
         QString host;
-        uint port;
+        uint port{6667};
         QString password;
-        bool useSsl;
-        int sslVersion;
+        bool useSsl{false};
+        bool sslVerify{true};  /// If true, validate SSL certificates
+        int sslVersion{0};
 
-        bool useProxy;
-        int proxyType;
+        bool useProxy{false};
+        int proxyType{QNetworkProxy::Socks5Proxy};
         QString proxyHost;
-        uint proxyPort;
+        uint proxyPort{8080};
         QString proxyUser;
         QString proxyPass;
 
-        Server() : port(6667), useSsl(false), sslVersion(0), useProxy(false), proxyType(QNetworkProxy::Socks5Proxy), proxyHost("localhost"), proxyPort(8080) {}
-        Server(const QString &host, uint port, const QString &password, bool useSsl)
-            : host(host), port(port), password(password), useSsl(useSsl), sslVersion(0),
-            useProxy(false), proxyType(QNetworkProxy::Socks5Proxy), proxyHost("localhost"), proxyPort(8080) {}
-        bool operator==(const Server &other) const;
-        bool operator!=(const Server &other) const;
+        // sslVerify only applies when useSsl is true.  sslVerify should be enabled by default,
+        // so enabling useSsl offers a more secure default.
+        Server()
+            : proxyHost("localhost")
+        {}
+
+        Server(QString host, uint port, QString password, bool useSsl, bool sslVerify)
+            : host(std::move(host))
+            , port(port)
+            , password(std::move(password))
+            , useSsl(useSsl)
+            , sslVerify(sslVerify)
+            , proxyType(QNetworkProxy::Socks5Proxy)
+            , proxyHost("localhost")
+            , proxyPort(8080)
+        {}
+
+        bool operator==(const Server& other) const;
+        bool operator!=(const Server& other) const;
     };
-    typedef QList<Server> ServerList;
+    using ServerList = QList<Server>;
 
-    Network(const NetworkId &networkid, QObject *parent = 0);
-    ~Network();
+    Network(const NetworkId& networkid, QObject* parent = nullptr);
+    ~Network() override;
 
     inline NetworkId networkId() const { return _networkId; }
 
-    inline SignalProxy *proxy() const { return _proxy; }
-    inline void setProxy(SignalProxy *proxy) { _proxy = proxy; }
+    inline SignalProxyproxy() const { return _proxy; }
+    inline void setProxy(SignalProxyproxy) { _proxy = proxy; }
 
-    inline bool isMyNick(const QString &nick) const { return (myNick().toLower() == nick.toLower()); }
-    inline bool isMe(IrcUser *ircuser) const { return (ircuser->nick().toLower() == myNick().toLower()); }
+    inline bool isMyNick(const QStringnick) const { return (myNick().toLower() == nick.toLower()); }
+    inline bool isMe(IrcUserircuser) const { return (ircuser->nick().toLower() == myNick().toLower()); }
 
-    bool isChannelName(const QString &channelname) const;
+    bool isChannelName(const QStringchannelname) const;
 
     /**
      * Checks if the target counts as a STATUSMSG
@@ -142,25 +179,90 @@ public :
      * @param[in] target Name of destination, e.g. a channel or query
      * @returns True if a STATUSMSG, otherwise false
      */
-    bool isStatusMsg(const QString &target) const;
+    bool isStatusMsg(const QStringtarget) const;
 
     inline bool isConnected() const { return _connected; }
-    //Network::ConnectionState connectionState() const;
+    // Network::ConnectionState connectionState() const;
     inline int connectionState() const { return _connectionState; }
 
-    QString prefixToMode(const QString &prefix) const;
-    inline QString prefixToMode(const QCharRef &prefix) const { return prefixToMode(QString(prefix)); }
-    QString modeToPrefix(const QString &mode) const;
-    inline QString modeToPrefix(const QCharRef &mode) const { return modeToPrefix(QString(mode)); }
+    /**@{*/
+    /**
+     * Translates a user’s prefix to the channelmode associated with it.
+     * @param prefix Prefix to be translated.
+     */
+    QString prefixToMode(const QString& prefix) const;
+    inline QString prefixToMode(const QCharRef& prefix) const { return prefixToMode(QString(prefix)); }
+    inline QString prefixesToModes(const QString& prefix) const
+    {
+        QString modes;
+        for (QChar c : prefix) {
+            modes += prefixToMode(c);
+        }
+        return modes;
+    }
+    /**@}*/
+
+    /**@{*/
+    /**
+     * Translates a user’s prefix to the channelmode associated with it.
+     * @param prefix Prefix to be translated.
+     */
+    QString modeToPrefix(const QString& mode) const;
+    inline QString modeToPrefix(const QCharRef& mode) const { return modeToPrefix(QString(mode)); }
+    inline QString modesToPrefixes(const QString& mode) const
+    {
+        QString prefixes;
+        for (QChar c : mode) {
+            prefixes += modeToPrefix(c);
+        }
+        return prefixes;
+    }
+    /**@}*/
 
-    ChannelModeType channelModeType(const QString &mode);
-    inline ChannelModeType channelModeType(const QCharRef &mode) { return channelModeType(QString(mode)); }
+    /**
+     * Sorts the user channelmodes according to priority set by PREFIX
+     *
+     * Given a list of channel modes, sorts according to the order of PREFIX, putting the highest
+     * modes first.  Any unknown modes are moved to the end in no given order.
+     *
+     * If prefix modes cannot be determined from the network, no changes will be made.
+     *
+     * @param modes User channelmodes
+     * @return Priority-sorted user channelmodes
+     */
+    QString sortPrefixModes(const QString& modes) const;
 
-    inline const QString &networkName() const { return _networkName; }
-    inline const QString &currentServer() const { return _currentServer; }
-    inline const QString &myNick() const { return _myNick; }
+    /**@{*/
+    /**
+     * Sorts the list of users' channelmodes according to priority set by PREFIX
+     *
+     * Maintains order of the modes list.
+     *
+     * @seealso Network::sortPrefixModes()
+     *
+     * @param modesList List of users' channel modes
+     * @return Priority-sorted list of users' channel modes
+     */
+    inline QStringList sortPrefixModes(const QStringList& modesList) const
+    {
+        QStringList sortedModesList;
+        // Sort each individual mode string, appending back
+        // Must maintain the order received!
+        for (QString modes : modesList) {
+            sortedModesList << sortPrefixModes(modes);
+        }
+        return sortedModesList;
+    }
+    /**@}*/
+
+    ChannelModeType channelModeType(const QString& mode);
+    inline ChannelModeType channelModeType(const QCharRef& mode) { return channelModeType(QString(mode)); }
+
+    inline const QString& networkName() const { return _networkName; }
+    inline const QString& currentServer() const { return _currentServer; }
+    inline const QString& myNick() const { return _myNick; }
     inline int latency() const { return _latency; }
-    inline IrcUser *me() const { return ircUser(myNick()); }
+    inline IrcUserme() const { return ircUser(myNick()); }
     inline IdentityId identity() const { return _identity; }
     QStringList nicks() const;
     inline QStringList channels() const { return _ircChannels.keys(); }
@@ -176,30 +278,81 @@ public :
      * @returns QStringList of enabled (acknowledged) capabilities
      */
     inline const QStringList capsEnabled() const { return _capsEnabled; }
-    inline const ServerList &serverList() const { return _serverList; }
+    inline const ServerListserverList() const { return _serverList; }
     inline bool useRandomServer() const { return _useRandomServer; }
-    inline const QStringList &perform() const { return _perform; }
+    inline const QStringListperform() const { return _perform; }
     inline bool useAutoIdentify() const { return _useAutoIdentify; }
-    inline const QString &autoIdentifyService() const { return _autoIdentifyService; }
-    inline const QString &autoIdentifyPassword() const { return _autoIdentifyPassword; }
+    inline const QStringautoIdentifyService() const { return _autoIdentifyService; }
+    inline const QStringautoIdentifyPassword() const { return _autoIdentifyPassword; }
     inline bool useSasl() const { return _useSasl; }
-    inline const QString &saslAccount() const { return _saslAccount; }
-    inline const QString &saslPassword() const { return _saslPassword; }
+    inline const QStringsaslAccount() const { return _saslAccount; }
+    inline const QStringsaslPassword() const { return _saslPassword; }
     inline bool useAutoReconnect() const { return _useAutoReconnect; }
     inline quint32 autoReconnectInterval() const { return _autoReconnectInterval; }
     inline quint16 autoReconnectRetries() const { return _autoReconnectRetries; }
     inline bool unlimitedReconnectRetries() const { return _unlimitedReconnectRetries; }
     inline bool rejoinChannels() const { return _rejoinChannels; }
 
+    // Custom rate limiting
+
+    /**
+     * Gets whether or not custom rate limiting is used
+     *
+     * @return True if custom rate limiting is enabled, otherwise false.
+     */
+    inline bool useCustomMessageRate() const { return _useCustomMessageRate; }
+
+    /**
+     * Gets maximum number of messages to send without any delays
+     *
+     * @return
+     * @parblock
+     * Maximum number of messages to send without any delays.  A value of 1 disables message
+     * bursting.
+     * @endparblock
+     */
+    inline quint32 messageRateBurstSize() const { return _messageRateBurstSize; }
+
+    /**
+     * Gets the delay between messages after the maximum number of undelayed messages have been sent
+     *
+     * @return
+     * @parblock
+     * Delay in milliseconds between messages after the maximum number of undelayed messages have
+     * been sent.
+     * @endparblock
+     */
+    inline quint32 messageRateDelay() const { return _messageRateDelay; }
+
+    /**
+     * Gets whether or not all rate limiting is disabled, e.g. for IRC bridges
+     *
+     * @return If true, disable rate limiting, otherwise apply configured limits.
+     */
+    inline bool unlimitedMessageRate() const { return _unlimitedMessageRate; }
+
     NetworkInfo networkInfo() const;
-    void setNetworkInfo(const NetworkInfo &);
+    void setNetworkInfo(const NetworkInfo&);
 
     QString prefixes() const;
     QString prefixModes() const;
     void determinePrefixes() const;
 
-    bool supports(const QString &param) const { return _supports.contains(param); }
-    QString support(const QString &param) const;
+    bool supports(const QString& param) const { return _supports.contains(param); }
+    QString support(const QString& param) const;
+
+    /**
+     * Checks if a given capability is advertised by the server.
+     *
+     * These results aren't valid if the network is disconnected or capability negotiation hasn't
+     * happened, and some servers might not correctly advertise capabilities.  Don't treat this as
+     * a guarantee.
+     *
+     * @param[in] capability Name of capability
+     * @returns True if connected and advertised by the server, otherwise false
+     */
+    inline bool capAvailable(const QString& capability) const { return _caps.contains(capability.toLower()); }
+    // IRCv3 specs all use lowercase capability names
 
     /**
      * Checks if a given capability is acknowledged and active.
@@ -207,7 +360,7 @@ public :
      * @param[in] capability Name of capability
      * @returns True if acknowledged (active), otherwise false
      */
-    inline bool capEnabled(const QString &capability) const { return _capsEnabled.contains(capability.toLower()); }
+    inline bool capEnabled(const QStringcapability) const { return _capsEnabled.contains(capability.toLower()); }
     // IRCv3 specs all use lowercase capability names
 
     /**
@@ -216,77 +369,130 @@ public :
      * @param[in] capability Name of capability
      * @returns Value of capability if one was specified, otherwise empty string
      */
-    QString capValue(const QString &capability) const { return _caps.value(capability.toLower()); }
+    QString capValue(const QStringcapability) const { return _caps.value(capability.toLower()); }
     // IRCv3 specs all use lowercase capability names
     // QHash returns the default constructed value if not found, in this case, empty string
     // See:  https://doc.qt.io/qt-4.8/qhash.html#value
 
-    IrcUser *newIrcUser(const QString &hostmask, const QVariantMap &initData = QVariantMap());
-    inline IrcUser *newIrcUser(const QByteArray &hostmask) { return newIrcUser(decodeServerString(hostmask)); }
-    IrcUser *ircUser(QString nickname) const;
-    inline IrcUser *ircUser(const QByteArray &nickname) const { return ircUser(decodeServerString(nickname)); }
-    inline QList<IrcUser *> ircUsers() const { return _ircUsers.values(); }
+    /**
+     * Check if the given authentication mechanism is likely to be supported.
+     *
+     * This depends on the server advertising SASL support and either declaring available mechanisms
+     * (SASL 3.2), or just indicating something is supported (SASL 3.1).
+     *
+     * @param[in] saslMechanism  Desired SASL mechanism
+     * @return True if mechanism supported or unknown, otherwise false
+     */
+    bool saslMaybeSupports(const QString& saslMechanism) const;
+
+    IrcUser* newIrcUser(const QString& hostmask, const QVariantMap& initData = QVariantMap());
+    inline IrcUser* newIrcUser(const QByteArray& hostmask) { return newIrcUser(decodeServerString(hostmask)); }
+    IrcUser* ircUser(QString nickname) const;
+    inline IrcUser* ircUser(const QByteArray& nickname) const { return ircUser(decodeServerString(nickname)); }
+    inline QList<IrcUser*> ircUsers() const { return _ircUsers.values(); }
     inline quint32 ircUserCount() const { return _ircUsers.count(); }
 
-    IrcChannel *newIrcChannel(const QString &channelname, const QVariantMap &initData = QVariantMap());
-    inline IrcChannel *newIrcChannel(const QByteArray &channelname) { return newIrcChannel(decodeServerString(channelname)); }
-    IrcChannel *ircChannel(QString channelname) const;
-    inline IrcChannel *ircChannel(const QByteArray &channelname) const { return ircChannel(decodeServerString(channelname)); }
-    inline QList<IrcChannel *> ircChannels() const { return _ircChannels.values(); }
+    IrcChannel* newIrcChannel(const QString& channelname, const QVariantMap& initData = QVariantMap());
+    inline IrcChannel* newIrcChannel(const QByteArray& channelname) { return newIrcChannel(decodeServerString(channelname)); }
+    IrcChannelircChannel(QString channelname) const;
+    inline IrcChannel* ircChannel(const QByteArray& channelname) const { return ircChannel(decodeServerString(channelname)); }
+    inline QList<IrcChannel*> ircChannels() const { return _ircChannels.values(); }
     inline quint32 ircChannelCount() const { return _ircChannels.count(); }
 
     QByteArray codecForServer() const;
     QByteArray codecForEncoding() const;
     QByteArray codecForDecoding() const;
-    void setCodecForServer(QTextCodec *codec);
-    void setCodecForEncoding(QTextCodec *codec);
-    void setCodecForDecoding(QTextCodec *codec);
+    void setCodecForServer(QTextCodeccodec);
+    void setCodecForEncoding(QTextCodeccodec);
+    void setCodecForDecoding(QTextCodeccodec);
 
-    QString decodeString(const QByteArray &text) const;
-    QByteArray encodeString(const QString &string) const;
-    QString decodeServerString(const QByteArray &text) const;
-    QByteArray encodeServerString(const QString &string) const;
+    QString decodeString(const QByteArraytext) const;
+    QByteArray encodeString(const QStringstring) const;
+    QString decodeServerString(const QByteArraytext) const;
+    QByteArray encodeServerString(const QStringstring) const;
 
     static QByteArray defaultCodecForServer();
     static QByteArray defaultCodecForEncoding();
     static QByteArray defaultCodecForDecoding();
-    static void setDefaultCodecForServer(const QByteArray &name);
-    static void setDefaultCodecForEncoding(const QByteArray &name);
-    static void setDefaultCodecForDecoding(const QByteArray &name);
+    static void setDefaultCodecForServer(const QByteArrayname);
+    static void setDefaultCodecForEncoding(const QByteArrayname);
+    static void setDefaultCodecForDecoding(const QByteArrayname);
 
     inline bool autoAwayActive() const { return _autoAwayActive; }
     inline void setAutoAwayActive(bool active) { _autoAwayActive = active; }
 
 public slots:
-    void setNetworkName(const QString &networkName);
-    void setCurrentServer(const QString &currentServer);
+    void setNetworkName(const QStringnetworkName);
+    void setCurrentServer(const QStringcurrentServer);
     void setConnected(bool isConnected);
     void setConnectionState(int state);
-    virtual void setMyNick(const QString &mynick);
+    virtual void setMyNick(const QStringmynick);
     void setLatency(int latency);
     void setIdentity(IdentityId);
 
-    void setServerList(const QVariantList &serverList);
+    void setServerList(const QVariantListserverList);
     void setUseRandomServer(bool);
-    void setPerform(const QStringList &);
+    void setPerform(const QStringList&);
     void setUseAutoIdentify(bool);
-    void setAutoIdentifyService(const QString &);
-    void setAutoIdentifyPassword(const QString &);
+    void setAutoIdentifyService(const QString&);
+    void setAutoIdentifyPassword(const QString&);
     void setUseSasl(bool);
-    void setSaslAccount(const QString &);
-    void setSaslPassword(const QString &);
+    void setSaslAccount(const QString&);
+    void setSaslPassword(const QString&);
     virtual void setUseAutoReconnect(bool);
     virtual void setAutoReconnectInterval(quint32);
     virtual void setAutoReconnectRetries(quint16);
     void setUnlimitedReconnectRetries(bool);
     void setRejoinChannels(bool);
 
-    void setCodecForServer(const QByteArray &codecName);
-    void setCodecForEncoding(const QByteArray &codecName);
-    void setCodecForDecoding(const QByteArray &codecName);
+    // Custom rate limiting
+
+    /**
+     * Sets whether or not custom rate limiting is used.
+     *
+     * Setting limits too low may get you disconnected from the server!
+     *
+     * @param[in] useCustomRate If true, use custom rate limits, otherwise use Quassel defaults.
+     */
+    void setUseCustomMessageRate(bool useCustomRate);
+
+    /**
+     * Sets maximum number of messages to send without any delays
+     *
+     * @param[in] burstSize
+     * @parblock
+     * Maximum number of messages to send without any delays.  A value of 1 disables message
+     * bursting.  Cannot be less than 1 as sending 0 messages at a time accomplishes nothing.
+     * @endparblock
+     */
+    void setMessageRateBurstSize(quint32 burstSize);
+
+    /**
+     * Sets the delay between messages after the maximum number of undelayed messages have been sent
+     *
+     * @param[in] messageDelay
+     * @parblock
+     * Delay in milliseconds between messages after the maximum number of undelayed messages have
+     * been sent.
+     * @endparblock
+     */
+    void setMessageRateDelay(quint32 messageDelay);
 
-    void addSupport(const QString &param, const QString &value = QString());
-    void removeSupport(const QString &param);
+    /**
+     * Sets whether or not all rate limiting is disabled, e.g. for IRC bridges
+     *
+     * Don't use with most normal networks.
+     *
+     * @param[in] unlimitedRate If true, disable rate limiting, otherwise apply configured limits.
+     */
+    void setUnlimitedMessageRate(bool unlimitedRate);
+
+    void setCodecForServer(const QByteArray& codecName);
+    void setCodecForEncoding(const QByteArray& codecName);
+    void setCodecForDecoding(const QByteArray& codecName);
+
+    void addSupport(const QString& param, const QString& value = QString());
+    void removeSupport(const QString& param);
 
     // IRCv3 capability negotiation (can be connected to signals)
 
@@ -302,14 +508,14 @@ public slots:
      * Optional value of the capability, e.g. sasl=plain.
      * @endparblock
      */
-    void addCap(const QString &capability, const QString &value = QString());
+    void addCap(const QString& capability, const QString& value = QString());
 
     /**
      * Marks a capability as acknowledged (enabled by the IRC server).
      *
      * @param[in] capability Name of the capability
      */
-    void acknowledgeCap(const QString &capability);
+    void acknowledgeCap(const QStringcapability);
 
     /**
      * Removes a capability from the list of available capabilities.
@@ -320,7 +526,7 @@ public slots:
      *
      * @param[in] capability Name of the capability
      */
-    void removeCap(const QString &capability);
+    void removeCap(const QStringcapability);
 
     /**
      * Clears all capabilities from the list of available capabilities.
@@ -329,10 +535,10 @@ public slots:
      */
     void clearCaps();
 
-    inline void addIrcUser(const QString &hostmask) { newIrcUser(hostmask); }
-    inline void addIrcChannel(const QString &channel) { newIrcChannel(channel); }
+    inline void addIrcUser(const QStringhostmask) { newIrcUser(hostmask); }
+    inline void addIrcChannel(const QStringchannel) { newIrcChannel(channel); }
 
-    //init geters
+    // init geters
     QVariantMap initSupports() const;
     /**
      * Get the initial list of available capabilities.
@@ -349,22 +555,22 @@ public slots:
     inline QVariantList initServerList() const { return toVariantList(serverList()); }
     virtual QVariantMap initIrcUsersAndChannels() const;
 
-    //init seters
-    void initSetSupports(const QVariantMap &supports);
+    // init seters
+    void initSetSupports(const QVariantMapsupports);
     /**
      * Initialize the list of available capabilities.
      *
      * @param[in] caps QVariantMap of <QString, QString> indicating available capabilities and values
      */
-    void initSetCaps(const QVariantMap &caps);
+    void initSetCaps(const QVariantMapcaps);
     /**
      * Initialize the list of enabled (acknowledged) capabilities.
      *
      * @param[in] caps QVariantList of QString indicating enabled (acknowledged) capabilities and values
      */
-    inline void initSetCapsEnabled(const QVariantList &capsEnabled) { _capsEnabled = fromVariantList<QString>(capsEnabled); }
-    inline void initSetServerList(const QVariantList &serverList) { _serverList = fromVariantList<Server>(serverList); }
-    virtual void initSetIrcUsersAndChannels(const QVariantMap &usersAndChannels);
+    inline void initSetCapsEnabled(const QVariantListcapsEnabled) { _capsEnabled = fromVariantList<QString>(capsEnabled); }
+    inline void initSetServerList(const QVariantListserverList) { _serverList = fromVariantList<Server>(serverList); }
+    virtual void initSetIrcUsersAndChannels(const QVariantMapusersAndChannels);
 
     /**
      * Update IrcUser hostmask and username from mask, creating an IrcUser if one does not exist.
@@ -372,7 +578,7 @@ public slots:
      * @param[in] mask   Full nick!user@hostmask string
      * @return IrcUser of the matching nick if exists, otherwise a new IrcUser
      */
-    IrcUser *updateNickFromMask(const QString &mask);
+    IrcUser* updateNickFromMask(const QString& mask);
 
     // these slots are to keep the hashlists of all users and the
     // channel lists up to date
@@ -380,47 +586,85 @@ public slots:
 
     virtual inline void requestConnect() const { REQUEST(NO_ARG) }
     virtual inline void requestDisconnect() const { REQUEST(NO_ARG) }
-    virtual inline void requestSetNetworkInfo(const NetworkInfo &info) { REQUEST(ARG(info)) }
+    virtual inline void requestSetNetworkInfo(const NetworkInfoinfo) { REQUEST(ARG(info)) }
 
-    void emitConnectionError(const QString &);
+    void emitConnectionError(const QString&);
 
 protected slots:
-    virtual void removeIrcUser(IrcUser *ircuser);
-    virtual void removeIrcChannel(IrcChannel *ircChannel);
+    virtual void removeIrcUser(IrcUserircuser);
+    virtual void removeIrcChannel(IrcChannelircChannel);
     virtual void removeChansAndUsers();
 
 signals:
     void aboutToBeDestroyed();
-    void networkNameSet(const QString &networkName);
-    void currentServerSet(const QString &currentServer);
+    void networkNameSet(const QStringnetworkName);
+    void currentServerSet(const QStringcurrentServer);
     void connectedSet(bool isConnected);
     void connectionStateSet(Network::ConnectionState);
-//   void connectionStateSet(int);
-    void connectionError(const QString &errorMsg);
-    void myNickSet(const QString &mynick);
-//   void latencySet(int latency);
+    //   void connectionStateSet(int);
+    void connectionError(const QStringerrorMsg);
+    void myNickSet(const QStringmynick);
+    //   void latencySet(int latency);
     void identitySet(IdentityId);
 
     void configChanged();
 
     //   void serverListSet(QVariantList serverList);
-//   void useRandomServerSet(bool);
-//   void performSet(const QStringList &);
-//   void useAutoIdentifySet(bool);
-//   void autoIdentifyServiceSet(const QString &);
-//   void autoIdentifyPasswordSet(const QString &);
-//   void useAutoReconnectSet(bool);
-//   void autoReconnectIntervalSet(quint32);
-//   void autoReconnectRetriesSet(quint16);
-//   void unlimitedReconnectRetriesSet(bool);
-//   void rejoinChannelsSet(bool);
-
-//   void codecForServerSet(const QByteArray &codecName);
-//   void codecForEncodingSet(const QByteArray &codecName);
-//   void codecForDecodingSet(const QByteArray &codecName);
-
-//   void supportAdded(const QString &param, const QString &value);
-//   void supportRemoved(const QString &param);
+    //   void useRandomServerSet(bool);
+    //   void performSet(const QStringList &);
+    //   void useAutoIdentifySet(bool);
+    //   void autoIdentifyServiceSet(const QString &);
+    //   void autoIdentifyPasswordSet(const QString &);
+    //   void useAutoReconnectSet(bool);
+    //   void autoReconnectIntervalSet(quint32);
+    //   void autoReconnectRetriesSet(quint16);
+    //   void unlimitedReconnectRetriesSet(bool);
+    //   void rejoinChannelsSet(bool);
+
+    // Custom rate limiting (can drive other slots)
+
+    /**
+     * Signals enabling or disabling custom rate limiting
+     *
+     * @see Network::useCustomMessageRate()
+     *
+     * @param[out] useCustomRate
+     */
+    void useCustomMessageRateSet(const bool useCustomRate);
+
+    /**
+     * Signals a change in maximum number of messages to send without any delays
+     *
+     * @see Network::messageRateBurstSize()
+     *
+     * @param[out] burstSize
+     */
+    void messageRateBurstSizeSet(const quint32 burstSize);
+
+    /**
+     * Signals a change in delay between messages after the max. undelayed messages have been sent
+     *
+     * @see Network::messageRateDelay()
+     *
+     * @param[out] messageDelay
+     */
+    void messageRateDelaySet(const quint32 messageDelay);
+
+    /**
+     * Signals enabling or disabling all rate limiting
+     *
+     * @see Network::unlimitedMessageRate()
+     *
+     * @param[out] unlimitedRate
+     */
+    void unlimitedMessageRateSet(const bool unlimitedRate);
+
+    //   void codecForServerSet(const QByteArray &codecName);
+    //   void codecForEncodingSet(const QByteArray &codecName);
+    //   void codecForDecodingSet(const QByteArray &codecName);
+
+    //   void supportAdded(const QString &param, const QString &value);
+    //   void supportRemoved(const QString &param);
 
     // IRCv3 capability negotiation (can drive other slots)
     /**
@@ -430,7 +674,7 @@ signals:
      *
      * @param[in] capability Name of the capability
      */
-    void capAdded (const QString &capability);
+    void capAdded(const QString& capability);
 
     /**
      * Indicates a capability was acknowledged (enabled by the IRC server).
@@ -439,7 +683,7 @@ signals:
      *
      * @param[in] capability Name of the capability
      */
-    void capAcknowledged(const QString &capability);
+    void capAcknowledged(const QStringcapability);
 
     /**
      * Indicates a capability was removed from the list of available capabilities.
@@ -448,20 +692,20 @@ signals:
      *
      * @param[in] capability Name of the capability
      */
-    void capRemoved(const QString &capability);
+    void capRemoved(const QStringcapability);
 
-//   void ircUserAdded(const QString &hostmask);
-    void ircUserAdded(IrcUser *);
-//   void ircChannelAdded(const QString &channelname);
-    void ircChannelAdded(IrcChannel *);
+    //   void ircUserAdded(const QString &hostmask);
+    void ircUserAdded(IrcUser*);
+    //   void ircChannelAdded(const QString &channelname);
+    void ircChannelAdded(IrcChannel*);
 
-//   void connectRequested() const;
-//   void disconnectRequested() const;
-//   void setNetworkInfoRequested(const NetworkInfo &) const;
+    //   void connectRequested() const;
+    //   void disconnectRequested() const;
+    //   void setNetworkInfoRequested(const NetworkInfo &) const;
 
 protected:
-    inline virtual IrcChannel *ircChannelFactory(const QString &channelname) { return new IrcChannel(channelname, this); }
-    inline virtual IrcUser *ircUserFactory(const QString &hostmask) { return new IrcUser(hostmask, this); }
+    inline virtual IrcChannel* ircChannelFactory(const QString& channelname) { return new IrcChannel(channelname, this); }
+    inline virtual IrcUser* ircUserFactory(const QString& hostmask) { return new IrcUser(hostmask, this); }
 
 private:
     QPointer<SignalProxy> _proxy;
@@ -479,15 +723,15 @@ private:
     mutable QString _prefixes;
     mutable QString _prefixModes;
 
-    QHash<QString, IrcUser *> _ircUsers; // stores all known nicks for the server
-    QHash<QString, IrcChannel *> _ircChannels; // stores all known channels
-    QHash<QString, QString> _supports; // stores results from RPL_ISUPPORT
+    QHash<QString, IrcUser*> _ircUsers;        // stores all known nicks for the server
+    QHash<QString, IrcChannel*> _ircChannels;  // stores all known channels
+    QHash<QString, QString> _supports;         // stores results from RPL_ISUPPORT
 
     QHash<QString, QString> _caps;  /// Capabilities supported by the IRC server
     // By synchronizing the supported capabilities, the client could suggest certain behaviors, e.g.
     // in the Network settings dialog, recommending SASL instead of using NickServ, or warning if
     // SASL EXTERNAL isn't available.
-    QStringList _capsEnabled;       /// Enabled capabilities that received 'CAP ACK'
+    QStringList _capsEnabled;  /// Enabled capabilities that received 'CAP ACK'
     // _capsEnabled uses the same values from the <name>=<value> pairs stored in _caps
 
     ServerList _serverList;
@@ -508,66 +752,73 @@ private:
     bool _unlimitedReconnectRetries;
     bool _rejoinChannels;
 
-    QTextCodec *_codecForServer;
-    QTextCodec *_codecForEncoding;
-    QTextCodec *_codecForDecoding;
+    // Custom rate limiting
+    bool _useCustomMessageRate;     /// If true, use custom rate limits, otherwise use defaults
+    quint32 _messageRateBurstSize;  /// Maximum number of messages to send without any delays
+    quint32 _messageRateDelay;      /// Delay in ms. for messages when max. burst messages sent
+    bool _unlimitedMessageRate;     /// If true, disable rate limiting, otherwise apply limits
 
-    static QTextCodec *_defaultCodecForServer;
-    static QTextCodec *_defaultCodecForEncoding;
-    static QTextCodec *_defaultCodecForDecoding;
+    QTextCodec* _codecForServer;
+    QTextCodec* _codecForEncoding;
+    QTextCodec* _codecForDecoding;
 
-    bool _autoAwayActive; // when this is active handle305 and handle306 don't trigger any output
+    static QTextCodec* _defaultCodecForServer;
+    static QTextCodec* _defaultCodecForEncoding;
+    static QTextCodec* _defaultCodecForDecoding;
+
+    bool _autoAwayActive;  // when this is active handle305 and handle306 don't trigger any output
 
     friend class IrcUser;
     friend class IrcChannel;
 };
 
-
 //! Stores all editable information about a network (as opposed to runtime state).
-struct NetworkInfo {
-    // set some default values, note that this does not initialize e.g. name and id
-    NetworkInfo();
-
-    NetworkId networkId;
+struct COMMON_EXPORT NetworkInfo
+{
     QString networkName;
-    IdentityId identity;
-
-    bool useCustomEncodings; // not used!
-    QByteArray codecForServer;
-    QByteArray codecForEncoding;
-    QByteArray codecForDecoding;
 
     Network::ServerList serverList;
-    bool useRandomServer;
-
     QStringList perform;
 
-    bool useAutoIdentify;
-    QString autoIdentifyService;
+    QString autoIdentifyService{"NickServ"};
     QString autoIdentifyPassword;
 
-    bool useSasl;
     QString saslAccount;
     QString saslPassword;
 
-    bool useAutoReconnect;
-    quint32 autoReconnectInterval;
-    quint16 autoReconnectRetries;
-    bool unlimitedReconnectRetries;
-    bool rejoinChannels;
+    QByteArray codecForServer;
+    QByteArray codecForEncoding;
+    QByteArray codecForDecoding;
+
+    NetworkId networkId{0};
+    IdentityId identity{1};
 
-    bool operator==(const NetworkInfo &other) const;
-    bool operator!=(const NetworkInfo &other) const;
+    quint32 messageRateBurstSize{5};  ///< Maximum number of messages to send without any delays
+    quint32 messageRateDelay{2200};   ///< Delay in ms. for messages when max. burst messages sent
+
+    quint32 autoReconnectInterval{60};
+    quint16 autoReconnectRetries{20};
+
+    bool rejoinChannels{true};
+    bool useRandomServer{false};
+    bool useAutoIdentify{false};
+    bool useSasl{false};
+    bool useAutoReconnect{true};
+    bool unlimitedReconnectRetries{false};
+    bool useCustomMessageRate{false};  ///< If true, use custom rate limits, otherwise use defaults
+    bool unlimitedMessageRate{false};  ///< If true, disable rate limiting, otherwise apply limits
+
+public:
+    bool operator==(const NetworkInfo& other) const;
+    bool operator!=(const NetworkInfo& other) const;
 };
 
-QDataStream &operator<<(QDataStream &out, const NetworkInfo &info);
-QDataStream &operator>>(QDataStream &in, NetworkInfo &info);
-QDebug operator<<(QDebug dbg, const NetworkInfo &i);
+COMMON_EXPORT QDataStream& operator<<(QDataStream& out, const NetworkInfo& info);
+COMMON_EXPORT QDataStream& operator>>(QDataStream& in, NetworkInfo& info);
+COMMON_EXPORT QDebug operator<<(QDebug dbg, const NetworkInfo& i);
 Q_DECLARE_METATYPE(NetworkInfo)
 
-QDataStream &operator<<(QDataStream &out, const Network::Server &server);
-QDataStream &operator>>(QDataStream &in, Network::Server &server);
-QDebug operator<<(QDebug dbg, const Network::Server &server);
+COMMON_EXPORT QDataStream& operator<<(QDataStream& out, const Network::Server& server);
+COMMON_EXPORT QDataStream& operator>>(QDataStream& in, Network::Server& server);
+COMMON_EXPORT QDebug operator<<(QDebug dbg, const Network::Server& server);
 Q_DECLARE_METATYPE(Network::Server)
-
-#endif