X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fnetsplit.cpp;h=fd49a7d41957eb5fc8c6b063849a8ebd2997bf21;hp=89d27a4e277dfc550f2fef3908628cee45cb6a6b;hb=b64a1e62e2168dc21e350fccc6c42b0d0d5e2a35;hpb=fd80315c076ede937f5d51ba6f8061a32d0107ec diff --git a/src/core/netsplit.cpp b/src/core/netsplit.cpp index 89d27a4e..fd49a7d4 100644 --- a/src/core/netsplit.cpp +++ b/src/core/netsplit.cpp @@ -19,11 +19,12 @@ ***************************************************************************/ #include "netsplit.h" +#include "util.h" #include Netsplit::Netsplit() - : _quitMsg("") + : _quitMsg(""), _sentQuit(false), _joinCounter(0), _quitCounter(0) { _discardTimer.setSingleShot(true); _joinTimer.setSingleShot(true); @@ -45,8 +46,9 @@ void Netsplit::userQuit(const QString &sender, const QStringList &channels, cons foreach(QString channel, channels) { _quits[channel].append(sender); } - // now let's wait 5s to finish the netsplit-quit - _quitTimer.start(5000); + _quitCounter++; + // now let's wait 10s to finish the netsplit-quit + _quitTimer.start(10000); } bool Netsplit::userJoined(const QString &sender, const QString &channel) { @@ -54,19 +56,49 @@ bool Netsplit::userJoined(const QString &sender, const QString &channel) { return false; QStringList &users = _quits[channel]; - int idx = users.indexOf(sender); - if(idx == -1) + + QStringList::iterator userIter; + const QString senderNick = nickFromMask(sender); + for(userIter = users.begin(); userIter != users.end(); ++userIter) { + if(nickFromMask(*userIter) == senderNick) + break; + } + if(userIter == users.end()) return false; - _joins[channel].append(users.takeAt(idx)); + _joins[channel].first.append(*userIter); + _joins[channel].second.append(QString()); + + users.erase(userIter); + if(users.empty()) _quits.remove(channel); - // now let's wait 5s to finish the netsplit-join - _joinTimer.start(5000); + _joinCounter++; + + if(_quits.empty()) // all users joined already - no need to wait + _joinTimer.start(0); + else // wait 30s to finish the netsplit-join + _joinTimer.start(30000); + return true; } +bool Netsplit::userAlreadyJoined(const QString &sender, const QString &channel) { + if(_joins.value(channel).first.contains(sender)) + return true; + return false; +} + +void Netsplit::addMode(const QString &sender, const QString &channel, const QString &mode) { + if(!_joins.contains(channel)) + return; + int idx = _joins.value(channel).first.indexOf(sender); + if(idx == -1) + return; + _joins[channel].second[idx].append(mode); +} + bool Netsplit::isNetsplit(const QString &quitMessage) { // check if we find some common chars that disqualify the netsplit as such @@ -84,9 +116,38 @@ bool Netsplit::isNetsplit(const QString &quitMessage) void Netsplit::joinTimeout() { - QHash::iterator it; + if(!_sentQuit) { + _quitTimer.stop(); + quitTimeout(); + } + + QHash >::iterator it; + + /* + Try to catch server jumpers. + If we have too few joins for a netsplit-quit, + we assume that the users manually changed servers and join them + without ending the netsplit. + A netsplit is assumed over only if at least 1/3 of all quits had their corresponding + join again. + */ + if(_joinCounter < _quitCounter/3) { + for(it = _joins.begin(); it != _joins.end(); ++it) + emit earlyJoin(it.key(), it.value().first, it.value().second); + + // we don't care about those anymore + _joins.clear(); + + // restart the timer with 5min timeout + // This might happen a few times if netsplit lasts longer. + // As soon as another user joins, the timer is set to a shorter timeout again. + _joinTimer.start(300000); + return; + } + + // send netsplitJoin for every recorded channel for(it = _joins.begin(); it != _joins.end(); ++it) - emit netsplitJoin(it.key(), it.value(),_quitMsg); + emit netsplitJoin(it.key(), it.value().first, it.value().second ,_quitMsg); _joins.clear(); _discardTimer.stop(); emit finished(); @@ -94,7 +155,19 @@ void Netsplit::joinTimeout() void Netsplit::quitTimeout() { - QHash::iterator it; - for(it = _quits.begin(); it != _quits.end(); ++it) - emit netsplitQuit(it.key(), it.value(),_quitMsg); + // send netsplitQuit for every recorded channel + QHash::iterator channelIter; + for(channelIter = _quits.begin(); channelIter != _quits.end(); ++channelIter) { + + QStringList usersToSend; + + foreach(QString user, channelIter.value()) { + if(!_quitsWithMessageSent.value(channelIter.key()).contains(user)) { + usersToSend << user; + _quitsWithMessageSent[channelIter.key()].append(user); + } + } + emit netsplitQuit(channelIter.key(), usersToSend, _quitMsg); + } + _sentQuit = true; }