X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fnetworkconnection.cpp;h=1adf827a12c30aa2df84f34b9a53ec24915e8304;hp=35d44ad9352e7cc2c1b5aa807257393c309afbeb;hb=2f515f5ea173837eae501292c45af69793da6d60;hpb=464a20552a20ff976ef4d696f69bc73b389886ad diff --git a/src/core/networkconnection.cpp b/src/core/networkconnection.cpp index 35d44ad9..1adf827a 100644 --- a/src/core/networkconnection.cpp +++ b/src/core/networkconnection.cpp @@ -61,6 +61,14 @@ NetworkConnection::NetworkConnection(Network *network, CoreSession *session) : Q _autoWhoCycleTimer.setInterval(_autoWhoInterval * 1000); _autoWhoCycleTimer.setSingleShot(false); + // TokenBucket to avaid sending too much at once + _messagesPerSecond = 1; + _burstSize = 5; + _tokenBucket = 5; // init with a full bucket + + _tokenBucketTimer.start(_messagesPerSecond * 1000); + _tokenBucketTimer.setSingleShot(false); + QHash channels = coreSession()->persistentChannels(networkId()); foreach(QString chan, channels.keys()) { _channelKeys[chan.toLower()] = channels[chan]; @@ -69,6 +77,7 @@ NetworkConnection::NetworkConnection(Network *network, CoreSession *session) : Q connect(&_autoReconnectTimer, SIGNAL(timeout()), this, SLOT(doAutoReconnect())); connect(&_autoWhoTimer, SIGNAL(timeout()), this, SLOT(sendAutoWho())); connect(&_autoWhoCycleTimer, SIGNAL(timeout()), this, SLOT(startAutoWhoCycle())); + connect(&_tokenBucketTimer, SIGNAL(timeout()), this, SLOT(fillBucketAndProcessQueue())); connect(network, SIGNAL(currentServerSet(const QString &)), this, SLOT(networkInitialized(const QString &))); connect(network, SIGNAL(useAutoReconnectSet(bool)), this, SLOT(autoReconnectSettingsChanged())); @@ -276,6 +285,7 @@ void NetworkConnection::socketError(QAbstractSocket::SocketError) { #ifndef QT_NO_OPENSSL void NetworkConnection::sslErrors(const QList &sslErrors) { + Q_UNUSED(sslErrors) socket.ignoreSslErrors(); /* TODO errorhandling QVariantMap errmsg; @@ -380,9 +390,27 @@ void NetworkConnection::userInput(BufferInfo buf, QString msg) { } void NetworkConnection::putRawLine(QByteArray s) { + if(_tokenBucket > 0) { + writeToSocket(s); + } else { + _msgQueue.append(s); + } +} + +void NetworkConnection::writeToSocket(QByteArray s) { s += "\r\n"; socket.write(s); - if(Global::SPUTDEV) qDebug() << "SENT:" << s; + _tokenBucket--; +} + +void NetworkConnection::fillBucketAndProcessQueue() { + if(_tokenBucket < _burstSize) { + _tokenBucket++; + } + + while(_msgQueue.size() > 0 && _tokenBucket > 0) { + writeToSocket(_msgQueue.takeFirst()); + } } void NetworkConnection::putCmd(const QString &cmd, const QVariantList ¶ms, const QByteArray &prefix) { @@ -406,7 +434,7 @@ void NetworkConnection::sendAutoWho() { IrcChannel *ircchan = network()->ircChannel(chan); if(!ircchan) continue; if(_autoWhoNickLimit > 0 && ircchan->ircUsers().count() > _autoWhoNickLimit) continue; - _autoWhoInProgress.insert(chan); + _autoWhoInProgress[chan]++; putRawLine("WHO " + serverEncode(chan)); if(_autoWhoQueue.isEmpty() && _autoWhoEnabled && !_autoWhoCycleTimer.isActive()) { // Timer was stopped, means a new cycle is due immediately @@ -426,18 +454,20 @@ void NetworkConnection::startAutoWhoCycle() { } bool NetworkConnection::setAutoWhoDone(const QString &channel) { - return _autoWhoInProgress.remove(channel); + if(_autoWhoInProgress.value(channel.toLower(), 0) <= 0) return false; + _autoWhoInProgress[channel.toLower()]--; + return true; } void NetworkConnection::setChannelJoined(const QString &channel) { emit channelJoined(networkId(), channel, _channelKeys[channel.toLower()]); - _autoWhoQueue.prepend(channel); // prepend so this new chan is the first to be checked + _autoWhoQueue.prepend(channel.toLower()); // prepend so this new chan is the first to be checked } void NetworkConnection::setChannelParted(const QString &channel) { removeChannelKey(channel); - _autoWhoQueue.removeAll(channel); - _autoWhoInProgress.remove(channel); + _autoWhoQueue.removeAll(channel.toLower()); + _autoWhoInProgress.remove(channel.toLower()); emit channelParted(networkId(), channel); }