X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fnetsplit.cpp;h=c84297f38dc821e9e6a0bd66d227c9a78165e821;hp=d824d9b46cfdc70c5ae765064e2c9f94378a0fa6;hb=fdfd62334f728bd05470c5191194d55027fec86e;hpb=1489728cd358f6bf7151bcdd87b9ea2cbdff7bec diff --git a/src/core/netsplit.cpp b/src/core/netsplit.cpp index d824d9b4..c84297f3 100644 --- a/src/core/netsplit.cpp +++ b/src/core/netsplit.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-09 by the Quassel Project * + * Copyright (C) 2005-2012 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -19,11 +19,14 @@ ***************************************************************************/ #include "netsplit.h" +#include "network.h" +#include "util.h" #include -Netsplit::Netsplit() - : _quitMsg(""), _sentQuit(false) +Netsplit::Netsplit(Network *network, QObject *parent) + : QObject(parent), + _network(network), _quitMsg(""), _sentQuit(false), _joinCounter(0), _quitCounter(0) { _discardTimer.setSingleShot(true); _joinTimer.setSingleShot(true); @@ -45,8 +48,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 +58,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 @@ -88,9 +122,34 @@ void Netsplit::joinTimeout() _quitTimer.stop(); quitTimeout(); } - QHash::iterator it; + + 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(network(), 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(network(), it.key(), it.value().first, it.value().second ,_quitMsg); _joins.clear(); _discardTimer.stop(); emit finished(); @@ -98,8 +157,22 @@ 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); + } + } + // not yet sure how that could happen, but never send empty netsplit-quits + // anyway. + if(!usersToSend.isEmpty()) + emit netsplitQuit(network(), channelIter.key(), usersToSend, _quitMsg); + } _sentQuit = true; }