X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fidentserver.cpp;h=08b1b67721cd8b048884a529c83d361642e24331;hp=21ea5ff6f6755392e461ce19e690248d5b93ea8e;hb=41b9d689945e784b160a25d12076600ff4b7ae90;hpb=9451580d19875b23ec52af64585496efb7268e0f diff --git a/src/core/identserver.cpp b/src/core/identserver.cpp index 21ea5ff6..08b1b677 100644 --- a/src/core/identserver.cpp +++ b/src/core/identserver.cpp @@ -19,11 +19,12 @@ ***************************************************************************/ #include +#include #include "corenetwork.h" #include "identserver.h" -IdentServer::IdentServer(bool strict, QObject *parent) : QObject(parent), _strict(strict) { +IdentServer::IdentServer(bool strict, QObject *parent) : QObject(parent), _strict(strict), _socketId(0), _requestId(0) { connect(&_server, SIGNAL(newConnection()), this, SLOT(incomingConnection())); connect(&_v6server, SIGNAL(newConnection()), this, SLOT(incomingConnection())); } @@ -90,69 +91,130 @@ void IdentServer::incomingConnection() { } void IdentServer::respond() { - auto *socket = qobject_cast(sender()); + QTcpSocket *socket = qobject_cast(sender()); Q_ASSERT(socket); + qint64 transactionId = _socketId; + if (socket->canReadLine()) { - QByteArray s = socket->readLine(); - if (s.endsWith("\r\n")) - s.chop(2); - else if (s.endsWith("\n")) - s.chop(1); + QByteArray query = socket->readLine(); + if (query.endsWith("\r\n")) + query.chop(2); + else if (query.endsWith("\n")) + query.chop(1); - QList split = s.split(','); + QList split = query.split(','); bool success = false; - uint16_t localPort; + quint16 localPort; if (!split.empty()) { - localPort = split[0].toUShort(&success, 10); + localPort = split[0].trimmed().toUShort(&success, 10); } - QString user; - if (success) { - if (_connections.contains(localPort)) { - user = _connections[localPort]; + Request request{socket, localPort, query, transactionId, _requestId++}; + if (!success) { + responseUnavailable(request); + } else if (!responseAvailable(request)) { + if (hasSocketsBelowId(transactionId)) { + _requestQueue.emplace_back(request); } else { - success = false; + responseUnavailable(request); } } + } +} - QString data; - if (success) { - data += s + " : USERID : Quassel : " + user + "\r\n"; - } else { - data += s + " : ERROR : NO-USER\r\n"; - } +bool IdentServer::responseAvailable(Request request) { + QString user; + bool success = true; + if (_connections.contains(request.localPort)) { + user = _connections[request.localPort]; + } else { + success = false; + } + + QString data; + if (success) { + data += request.query + " : USERID : Quassel : " + user + "\r\n"; - socket->write(data.toUtf8()); - socket->flush(); - socket->close(); - socket->deleteLater(); + request.socket->write(data.toUtf8()); + request.socket->flush(); + request.socket->close(); } + return success; +} + +void IdentServer::responseUnavailable(Request request) { + QString data = request.query + " : ERROR : NO-USER\r\n"; + + request.socket->write(data.toUtf8()); + request.socket->flush(); + request.socket->close(); } bool IdentServer::addSocket(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, - const QHostAddress &peerAddress, quint16 peerPort) { + const QHostAddress &peerAddress, quint16 peerPort, qint64 socketId) { Q_UNUSED(localAddress) Q_UNUSED(peerAddress) Q_UNUSED(peerPort) const CoreNetwork *network = qobject_cast(sender()); _connections[localPort] = network->coreSession()->strictCompliantIdent(identity);; + processWaiting(socketId); return true; } -//! not yet implemented bool IdentServer::removeSocket(const CoreIdentity *identity, const QHostAddress &localAddress, quint16 localPort, - const QHostAddress &peerAddress, quint16 peerPort) { + const QHostAddress &peerAddress, quint16 peerPort, qint64 socketId) { Q_UNUSED(identity) Q_UNUSED(localAddress) Q_UNUSED(peerAddress) Q_UNUSED(peerPort) _connections.remove(localPort); + processWaiting(socketId); return true; } + +qint64 IdentServer::addWaitingSocket() { + qint64 newSocketId = _socketId++; + _waiting.push_back(newSocketId); + return newSocketId; +} + +bool IdentServer::hasSocketsBelowId(qint64 id) { + return std::any_of(_waiting.begin(), _waiting.end(), [=](qint64 socketId) { + return socketId <= id; + }); +} + +void IdentServer::removeWaitingSocket(qint64 socketId) { + _waiting.remove(socketId); +} + +void IdentServer::processWaiting(qint64 socketId) { + qint64 lowestSocketId = std::numeric_limits::max(); + for (qint64 id : _waiting) { + if (id < lowestSocketId) { + lowestSocketId = id; + } + } + removeWaitingSocket(socketId); + _requestQueue.remove_if([=](Request request) { + if (request.transactionId < lowestSocketId) { + responseUnavailable(request); + return true; + } else if (request.transactionId > socketId) { + return responseAvailable(request); + } else { + return false; + } + }); +} + +bool operator==(const Request &a, const Request &b) { + return a.requestId == b.requestId; +}