From 5a2f79450f5de00dab58b41e39810a8212781828 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Tue, 24 Jul 2018 14:39:25 +0200 Subject: [server] Cleanup and simplify SslServer --- src/server/net/sslserver.cpp | 102 ++++++++++++++----------------------------- src/server/net/sslserver.h | 20 +++------ 2 files changed, 38 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/server/net/sslserver.cpp b/src/server/net/sslserver.cpp index c11f0ae..9e1e82d 100644 --- a/src/server/net/sslserver.cpp +++ b/src/server/net/sslserver.cpp @@ -17,17 +17,35 @@ #include "sslserver.h" #include #include +#include #include "certmanager.h" #include -SslServer::SslServer() : QTcpServer(nullptr) +SslServer::SslServer() : QTcpServer(nullptr), _timer(new QTimer(this)) { - _tmr = startTimer(5123); + connect(_timer, &QTimer::timeout, [=]() { + if (_pending.empty()) + return; + const qint64 deadline = QDateTime::currentSecsSinceEpoch() - 10; + QMutableHashIterator it(_pending); + while (it.hasNext()) { // Remove lingering connections after 10s + it.next(); + if (it.value() < deadline) { + it.key()->blockSignals(true); + it.key()->deleteLater(); + it.remove(); + } + } + }); + _timer->start(10000); } SslServer::~SslServer() { - killTimer(_tmr); + _timer->stop(); + for (QSslSocket *sock : _pending.keys()) { + sock->deleteLater(); + } } /** @@ -47,93 +65,37 @@ void SslServer::incomingConnection(qintptr socketDescriptor) return; } QSslSocket *serverSocket = new QSslSocket(nullptr); - connect(serverSocket, SIGNAL(sslErrors(const QList &)), this, SLOT(sslErrors(const QList &))); - connect(serverSocket, SIGNAL(disconnected()), this, SLOT(sock_closed())); - connect(serverSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(sock_error(QAbstractSocket::SocketError))); + connect(serverSocket, QOverload &>::of(&QSslSocket::sslErrors), this, &SslServer::sslErrors); serverSocket->setPrivateKey(key); serverSocket->setLocalCertificate(cert); serverSocket->setPeerVerifyMode(QSslSocket::VerifyNone); serverSocket->setProtocol(QSsl::SecureProtocols); if (serverSocket->setSocketDescriptor(socketDescriptor)) { + _pending.insert(serverSocket, QDateTime::currentSecsSinceEpoch()); // Once the connection is successfully encrypted, raise our newConnection event connect(serverSocket, &QSslSocket::encrypted, [=]() { - disconnect(serverSocket, SIGNAL(sslErrors(const QList &)), this, SLOT(sslErrors(const QList &))); - disconnect(serverSocket, SIGNAL(disconnected()), this, SLOT(sock_closed())); - disconnect(serverSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(sock_error(QAbstractSocket::SocketError))); + serverSocket->disconnect(this); + if (_pending.remove(serverSocket) == 0) { + // Should never happen, so better log... + qDebug() << "Encryption event for socket that is not pending!?"; + } else { + this->addPendingConnection(serverSocket); + emit newConnection(); + } }); - connect(serverSocket, SIGNAL(encrypted()), this, SIGNAL(newConnection())); serverSocket->startServerEncryption(); - _pending.push_back(serverSocket); } else { qDebug() << "Failed to setSocketDescriptor on new SSL Socket"; serverSocket->deleteLater(); } } -void SslServer::sslErrors(const QList& /* errors */) +void SslServer::sslErrors(const QList& errors) { - /* qDebug() << "Client caused sslErrors before connection:"; for (QList::const_iterator it = errors.begin(); it != errors.end(); it++) { qDebug() << it->errorString(); } - */ -} - -void SslServer::sock_closed() -{ - qDebug() << "Client closed connection before SSL handshake completed."; - sender()->deleteLater(); -} - -void SslServer::sock_error(QAbstractSocket::SocketError err) -{ - qDebug() << "Client error before SSL handshake completed: " << err; - sender()->deleteLater(); -} - -void SslServer::timerEvent(QTimerEvent* /* event */ ) -{ - // Remove all sockets marked for deletion - while (!_delete.isEmpty()) { - QSslSocket *sock = _delete.takeFirst(); - sock->blockSignals(true); - sock->deleteLater(); - } - _delete = _pending; - _pending.clear(); -} - -bool SslServer::hasPendingConnections() const -{ - for (QList::const_iterator it(_pending.begin()); it != _pending.end(); it++) { - qDebug("State: %d - Encrypted: %d", (int)(*it)->state(), (*it)->isEncrypted()); - if ((*it)->state() == QAbstractSocket::ConnectedState && (*it)->isEncrypted()) - return true; - } - return false; -} -QTcpSocket* SslServer::nextPendingConnection() -{ - for (QList::iterator it(_pending.begin()); it != _pending.end(); it++) { - if ((*it)->state() == QAbstractSocket::ConnectedState && (*it)->isEncrypted()) { - QSslSocket *sock = *it; - QObject::disconnect(sock, SIGNAL(encrypted()), this, SIGNAL(newConnection())); - _pending.removeAll(sock); - _delete.removeAll(sock); - return sock; - } - } - for (QList::iterator it(_delete.begin()); it != _delete.end(); it++) { - if ((*it)->state() == QAbstractSocket::ConnectedState && (*it)->isEncrypted()) { - QSslSocket *sock = *it; - QObject::disconnect(sock, SIGNAL(encrypted()), this, SIGNAL(newConnection())); - _pending.removeAll(sock); - _delete.removeAll(sock); - return sock; - } - } - return nullptr; } diff --git a/src/server/net/sslserver.h b/src/server/net/sslserver.h index 6e8f26e..03d947a 100644 --- a/src/server/net/sslserver.h +++ b/src/server/net/sslserver.h @@ -17,11 +17,12 @@ #ifndef SSLSERVER_H_ #define SSLSERVER_H_ -#include +#include #include #include class QSslSocket; +class QTimer; /** * Class for handling ssl server connections. @@ -30,26 +31,17 @@ class SslServer : public QTcpServer { Q_OBJECT -private Q_SLOTS: +private slots: void sslErrors ( const QList & errors ); - void sock_closed(); - void sock_error(QAbstractSocket::SocketError err); public: - SslServer(); + explicit SslServer(); virtual ~SslServer(); - virtual bool hasPendingConnections () const; - // This one has to return a TcpSocket as we're overwriting from the base class - // just cast it to QSslSocket later - virtual QTcpSocket* nextPendingConnection(); - protected: void incomingConnection(qintptr handle); - void timerEvent(QTimerEvent* event); - QList _pending; - QList _delete; - int _tmr; + QHash _pending; // Queue for connected but unencrypted connections + QTimer* _timer; }; #endif /* SSLSERVER_H_ */ -- cgit v1.2.3-55-g7522