23 #include "refresher.h" 
   25 #include "configuration/doomseekerconfig.h" 
   26 #include "configuration/queryspeed.h" 
   28 #include "plugins/pluginloader.h" 
   29 #include "refresher/canrefreshserver.h" 
   30 #include "refresher/udpsocketpool.h" 
   31 #include "serverapi/masterclient.h" 
   32 #include "serverapi/mastermanager.h" 
   33 #include "serverapi/server.h" 
   35 #include <QElapsedTimer> 
   39 #include <QMutexLocker> 
   46 class ServerRefreshTime
 
   49         QPointer<Server> server;
 
   52         ServerRefreshTime(QPointer<Server> server)
 
   54                 this->server = server;
 
   58         bool operator==(
const ServerRefreshTime &other)
 
   60                 return server == other.server;
 
   67         typedef QHash<MasterClient *, MasterClientInfo *> MasterHashtable;
 
   68         typedef QHash<MasterClient *, MasterClientInfo *>::iterator MasterHashtableIt;
 
   73         int delayBetweenResends;
 
   74         QTimer flushPendingDatagramsTimer;
 
   75         MasterHashtable registeredMasters;
 
   77         QList<QPointer<Server> > unchallengedServers;
 
   78         QList<ServerRefreshTime> refreshingServers;
 
   80         QSet<MasterClient *> unchallengedMasters;
 
   82         bool hasAnyServers()
 const 
   84                 return !unchallengedServers.isEmpty() || !refreshingServers.isEmpty();
 
   87         bool isServerRegistered(
Server *server)
 const 
   89                 return unchallengedServers.contains(server) ||
 
   90                         refreshingServers.contains(ServerRefreshTime(server));
 
   93         QPointer<Server> popNextUnchallengedServer()
 
   95                 while (!unchallengedServers.isEmpty())
 
   97                         QPointer<Server> server = unchallengedServers.takeFirst();
 
  106         QUdpSocket *socket(
const Server *server)
 
  108                 return socketPool.acquire(server->
address(), server->
port());
 
  114 class Refresher::MasterClientInfo
 
  119                 connect(&lastChallengeTimer, SIGNAL(timeout()),
 
  120                         parent, SLOT(attemptTimeoutMasters()));
 
  121                 lastChallengeTimer.setSingleShot(
true);
 
  122                 lastChallengeTimer.setInterval(MASTER_SERVER_TIMEOUT_DELAY);
 
  125         void fireLastChallengeSentTimer()
 
  127                 lastChallengeTimer.start();
 
  130         bool isLastChallengeTimerActive()
 const 
  132                 return lastChallengeTimer.isActive();
 
  136         QTimer lastChallengeTimer;
 
  141 Refresher *Refresher::staticInstance = 
nullptr;
 
  142 QMutex Refresher::instanceMutex;
 
  144 Refresher::Refresher()
 
  148         d->bKeepRunning = 
true;
 
  149         d->delayBetweenResends = 1000;
 
  151         this->connect(&d->flushPendingDatagramsTimer, SIGNAL(timeout()), SLOT(readAllPendingDatagrams()));
 
  152         this->connect(&d->socketPool, SIGNAL(readyRead()), SLOT(readAllPendingDatagrams()));
 
  153         d->flushPendingDatagramsTimer.start(1000);
 
  156 Refresher::~Refresher()
 
  161 void Refresher::attemptTimeoutMasters()
 
  163         QList<MasterClient *> masters = d->registeredMasters.keys();
 
  166                 MasterClientInfo *pMasterInfo = d->registeredMasters[master];
 
  167                 if (!pMasterInfo->isLastChallengeTimerActive())
 
  169                         master->timeoutRefresh();
 
  174 void Refresher::concludeRefresh()
 
  177         d->socketPool.releaseAll();
 
  183         if (staticInstance == 
nullptr)
 
  185                 QMutexLocker locker(&instanceMutex);
 
  186                 if (staticInstance == 
nullptr)
 
  191         return staticInstance;
 
  194 bool Refresher::isInstantiated()
 
  196         return staticInstance != 
nullptr;
 
  199 void Refresher::deinstantiate()
 
  201         QMutexLocker locker(&instanceMutex);
 
  202         if (isInstantiated())
 
  204                 delete staticInstance;
 
  205                 staticInstance = 
nullptr;
 
  209 Server *Refresher::findRefreshingServer(
const QHostAddress &address,
 
  212         for (
const ServerRefreshTime &refreshOp : d->refreshingServers)
 
  214                 if (refreshOp.server.isNull())
 
  218                 if (refreshOp.server->address().toIPv4Address() == address.toIPv4Address() && refreshOp.server->port() == port)
 
  220                         return refreshOp.server;
 
  226 bool Refresher::isAnythingToRefresh()
 const 
  228         return d->hasAnyServers() || !d->registeredMasters.isEmpty() || !d->unchallengedMasters.isEmpty();
 
  231 void Refresher::masterFinishedRefreshing()
 
  234         const QList<ServerPtr> &servers = pMaster->servers();
 
  235         for (ServerPtr pServer : servers)
 
  240         unregisterMaster(pMaster);
 
  242         if (servers.size() == 0 && !isAnythingToRefresh())
 
  247         emit finishedQueryingMaster(pMaster);
 
  250 void Refresher::purgeNullServers()
 
  252         d->refreshingServers.removeAll(ServerRefreshTime(
nullptr));
 
  253         d->unchallengedServers.removeAll(
nullptr);
 
  258         d->bKeepRunning = 
false;
 
  263         if (!d->registeredMasters.contains(pMaster))
 
  265                 auto pMasterInfo = 
new MasterClientInfo(
this);
 
  266                 this->connect(pMaster, SIGNAL(listUpdated()), SLOT(masterFinishedRefreshing()));
 
  268                 d->registeredMasters.insert(pMaster, pMasterInfo);
 
  269                 d->unchallengedMasters.insert(pMaster);
 
  272                 if (d->registeredMasters.size() == 1)
 
  276                                 d->bSleeping = 
false;
 
  279                         QTimer::singleShot(20, 
this, SLOT(sendMasterQueries()));
 
  286         bool hadAnyServers = d->hasAnyServers();
 
  288         if (!d->isServerRegistered(server))
 
  291                 if (!refreshChecker.shouldRefresh())
 
  295                 d->unchallengedServers.append(server);
 
  302                 if (!hadAnyServers && d->hasAnyServers())
 
  306                                 d->bSleeping = 
false;
 
  309                         QTimer::singleShot(20, 
this, SLOT(sendServerQueries()));
 
  315 void Refresher::readAllPendingDatagrams()
 
  317         while (d->socketPool.hasPendingDatagrams() && d->bKeepRunning)
 
  319                 readPendingDatagram();
 
  323 void Refresher::readPendingDatagram()
 
  325         QHostAddress address;
 
  327         QByteArray dataArray = d->socketPool.readNextDatagram(&address, &port);
 
  329         if (tryReadDatagramByMasterClient(address, port, dataArray))
 
  333         tryReadDatagramByServer(address, port, dataArray);
 
  336 void Refresher::sendMasterQueries()
 
  338         while (!d->unchallengedMasters.isEmpty())
 
  340                 MasterClient *pMaster = *d->unchallengedMasters.begin();
 
  342                 MasterClientInfo *pMasterInfo = d->registeredMasters[pMaster];
 
  343                 pMasterInfo->fireLastChallengeSentTimer();
 
  346                 pMaster->
sendRequest(d->socketPool.acquireMasterSocket());
 
  347                 d->unchallengedMasters.remove(pMaster);
 
  351 void Refresher::sendServerQueries()
 
  353         if (!d->bKeepRunning)
 
  359         if (d->hasAnyServers())
 
  361                 startNewServerRefresh();
 
  362                 resendCurrentServerRefreshesIfTimeout();
 
  366                 QTimer::singleShot(qMax(1, gConfig.doomseeker.querySpeed().intervalBetweenServers),
 
  367                         this, SLOT(sendServerQueries()));
 
  371                 if (!isAnythingToRefresh())
 
  380         d->delayBetweenResends = qMax(delay, 100);
 
  383 bool Refresher::start()
 
  385         return d->socketPool.acquireMasterSocket() != 
nullptr;
 
  388 void Refresher::startNewServerRefresh()
 
  392         QPointer<Server> server = d->popNextUnchallengedServer();
 
  393         if (!server.isNull())
 
  395                 if (server->sendRefreshQuery(d->socket(server)))
 
  397                         d->refreshingServers.append(server);
 
  402 void Refresher::resendCurrentServerRefreshesIfTimeout()
 
  404         for (
int i = 0; i < d->refreshingServers.size(); ++i)
 
  406                 ServerRefreshTime &refreshOp = d->refreshingServers[i];
 
  407                 if (refreshOp.time.elapsed() > d->delayBetweenResends)
 
  409                         if (refreshOp.server->sendRefreshQuery(d->socket(refreshOp.server)))
 
  411                                 refreshOp.time.start();
 
  415                                 d->refreshingServers.removeOne(refreshOp);
 
  424 bool Refresher::tryReadDatagramByMasterClient(QHostAddress &address,
 
  425         unsigned short port, QByteArray &packet)
 
  427         for (
MasterClient *pMaster : d->registeredMasters.keys())
 
  429                 if (!d->bKeepRunning)
 
  435                         MasterClient::Response response = pMaster->
readResponse(packet);
 
  438                         case MasterClient::RESPONSE_BANNED:
 
  439                         case MasterClient::RESPONSE_WAIT:
 
  440                         case MasterClient::RESPONSE_BAD:
 
  441                         case MasterClient::RESPONSE_OLD:
 
  442                                 pMaster->notifyResponse(response);
 
  443                                 unregisterMaster(pMaster);
 
  445                         case MasterClient::RESPONSE_REPLY:
 
  446                                 pMaster->
sendRequest(d->socketPool.acquireMasterSocket());
 
  456 bool Refresher::tryReadDatagramByServer(
const QHostAddress &address,
 
  457         unsigned short port, QByteArray &packet)
 
  459         if (!d->bKeepRunning)
 
  463         Server *server = findRefreshingServer(address, port);
 
  464         if (server != 
nullptr)
 
  474                                 ServerRefreshTime refreshOp(server);
 
  475                                 d->refreshingServers.removeAll(refreshOp);
 
  476                                 d->refreshingServers.append(refreshOp);
 
  480                         [[gnu::fallthrough]];
 
  482                         d->refreshingServers.removeAll(ServerRefreshTime(server));
 
  483                         server->
refreshStops(static_cast<Server::Response>(response));
 
  489                         ServerRefreshTime refreshOp(server);
 
  490                         d->refreshingServers.removeAll(refreshOp);
 
  491                         d->refreshingServers.append(refreshOp);
 
  501         pMaster->disconnect(
this);
 
  502         Data::MasterHashtableIt it = d->registeredMasters.find(pMaster);
 
  503         if (it != d->registeredMasters.end())
 
  505                 MasterClientInfo *pMasterInfo = it.value();
 
  507                 d->registeredMasters.erase(it);