From decf1c04bd47eff39b9bef55b37c237f076917d5 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 10 Mar 2012 16:16:31 +0100 Subject: [PATCH] switched NetworkServerThread to new thread creation method, SSL is working --- servatrice/CMakeLists.txt | 2 - servatrice/src/networkserverinterface.cpp | 82 ++++++++++++++---- servatrice/src/networkserverinterface.h | 17 +++- servatrice/src/networkserverthread.cpp | 100 ---------------------- servatrice/src/networkserverthread.h | 38 -------- servatrice/src/servatrice.cpp | 24 ++++-- 6 files changed, 98 insertions(+), 165 deletions(-) delete mode 100644 servatrice/src/networkserverthread.cpp delete mode 100644 servatrice/src/networkserverthread.h diff --git a/servatrice/CMakeLists.txt b/servatrice/CMakeLists.txt index 68e6b668..dea8f606 100644 --- a/servatrice/CMakeLists.txt +++ b/servatrice/CMakeLists.txt @@ -10,7 +10,6 @@ SET(servatrice_SOURCES src/serversocketinterface.cpp src/serversocketthread.cpp src/networkserverinterface.cpp - src/networkserverthread.cpp ${CMAKE_CURRENT_BINARY_DIR}/version_string.cpp ) SET(servatrice_HEADERS @@ -19,7 +18,6 @@ SET(servatrice_HEADERS src/serversocketinterface.h src/serversocketthread.h src/networkserverinterface.h - src/networkserverthread.h ) SET(QT_DONTUSE_QTGUI) diff --git a/servatrice/src/networkserverinterface.cpp b/servatrice/src/networkserverinterface.cpp index be3ea229..a6397913 100644 --- a/servatrice/src/networkserverinterface.cpp +++ b/servatrice/src/networkserverinterface.cpp @@ -9,17 +9,75 @@ #include "pb/event_server_complete_list.pb.h" #include -void NetworkServerInterface::sharedCtor() +void NetworkServerInterface::sharedCtor(const QSslCertificate &cert, const QSslKey &privateKey) { + socket = new QSslSocket(this); + socket->setLocalCertificate(cert); + socket->setPrivateKey(privateKey); + connect(socket, SIGNAL(readyRead()), this, SLOT(readClient())); connect(socket, SIGNAL(disconnected()), this, SLOT(deleteLater())); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(catchSocketError(QAbstractSocket::SocketError))); connect(this, SIGNAL(outputBufferChanged()), this, SLOT(flushOutputBuffer()), Qt::QueuedConnection); } -NetworkServerInterface::NetworkServerInterface(Servatrice *_server, QSslSocket *_socket) - : QObject(), server(_server), socket(_socket), messageInProgress(false) +NetworkServerInterface::NetworkServerInterface(int _socketDescriptor, const QSslCertificate &cert, const QSslKey &privateKey, Servatrice *_server) + : QObject(), socketDescriptor(_socketDescriptor), server(_server), messageInProgress(false) { + sharedCtor(cert, privateKey); +} + +NetworkServerInterface::NetworkServerInterface(const QString &_peerHostName, const QString &_peerAddress, int _peerPort, const QSslCertificate &_peerCert, const QSslCertificate &cert, const QSslKey &privateKey, Servatrice *_server) + : QObject(), peerHostName(_peerHostName), peerAddress(_peerAddress), peerPort(_peerPort), peerCert(_peerCert), server(_server), messageInProgress(false) +{ + sharedCtor(cert, privateKey); +} + +NetworkServerInterface::~NetworkServerInterface() +{ + logger->logMessage("[SN] session ended", this); + + flushOutputBuffer(); +} + +void NetworkServerInterface::initServer() +{ + socket->setSocketDescriptor(socketDescriptor); + + logger->logMessage(QString("[SN] incoming connection: %1").arg(socket->peerAddress().toString())); + + QList serverList = server->getServerList(); + int listIndex = -1; + for (int i = 0; i < serverList.size(); ++i) + if (serverList[i].address == socket->peerAddress()) { + listIndex = i; + break; + } + if (listIndex == -1) { + logger->logMessage(QString("[SN] address %1 unknown, terminating connection").arg(socket->peerAddress().toString())); + deleteLater(); + return; + } + + socket->startServerEncryption(); + if (!socket->waitForEncrypted(5000)) { + QList sslErrors(socket->sslErrors()); + if (sslErrors.isEmpty()) + qDebug() << "[SN] SSL handshake timeout, terminating connection"; + else + qDebug() << "[SN] SSL errors:" << sslErrors; + deleteLater(); + return; + } + + if (serverList[listIndex].cert == socket->peerCertificate()) + logger->logMessage(QString("[SN] Peer authenticated as " + serverList[listIndex].hostname)); + else { + logger->logMessage(QString("[SN] Authentication failed, terminating connection")); + deleteLater(); + return; + } + Event_ServerCompleteList event; event.set_server_id(server->getServerId()); @@ -49,11 +107,14 @@ NetworkServerInterface::NetworkServerInterface(Servatrice *_server, QSslSocket * server->serverMutex.unlock(); } -NetworkServerInterface::NetworkServerInterface(const QString &peerHostName, const QString &peerAddress, int peerPort, Servatrice *_server, QSslSocket *_socket) - : QObject(), server(_server), socket(_socket), messageInProgress(false) +void NetworkServerInterface::initClient() { - sharedCtor(); + QList expectedErrors; + expectedErrors.append(QSslError(QSslError::SelfSignedCertificate, peerCert)); + socket->ignoreSslErrors(expectedErrors); + qDebug() << "[SN] Connecting to " << peerAddress << ":" << peerPort; + socket->connectToHostEncrypted(peerAddress, peerPort, peerHostName); if (!socket->waitForConnected(5000)) { qDebug() << "[SN] Socket error:" << socket->errorString(); @@ -72,17 +133,9 @@ NetworkServerInterface::NetworkServerInterface(const QString &peerHostName, cons server->addNetworkServerInterface(this); } -NetworkServerInterface::~NetworkServerInterface() -{ - logger->logMessage("[SN] session ended", this); - - flushOutputBuffer(); -} - void NetworkServerInterface::flushOutputBuffer() { QMutexLocker locker(&outputBufferMutex); - qDebug("FLUSH"); if (outputBuffer.isEmpty()) return; server->incTxBytes(outputBuffer.size()); @@ -142,7 +195,6 @@ void NetworkServerInterface::transmitMessage(const ServerNetworkMessage &item) outputBufferMutex.lock(); outputBuffer.append(buf); outputBufferMutex.unlock(); - qDebug("TRANSMIT"); emit outputBufferChanged(); } diff --git a/servatrice/src/networkserverinterface.h b/servatrice/src/networkserverinterface.h index 80f08c15..47a4398e 100644 --- a/servatrice/src/networkserverinterface.h +++ b/servatrice/src/networkserverinterface.h @@ -2,6 +2,9 @@ #define NETWORKSERVERINTERFACE_H #include "servatrice.h" +#include +#include +#include class Servatrice; class QSslSocket; @@ -16,6 +19,11 @@ private slots: signals: void outputBufferChanged(); private: + int socketDescriptor; + QString peerHostName, peerAddress; + int peerPort; + QSslCertificate peerCert; + QMutex outputBufferMutex; Servatrice *server; QSslSocket *socket; @@ -25,10 +33,13 @@ private: int messageLength; void processMessage(const ServerNetworkMessage &item); - void sharedCtor(); + void sharedCtor(const QSslCertificate &cert, const QSslKey &privateKey); +public slots: + void initServer(); + void initClient(); public: - NetworkServerInterface(Servatrice *_server, QSslSocket *_socket); - NetworkServerInterface(const QString &peerHostName, const QString &peerAddress, int peerPort, Servatrice *_server, QSslSocket *_socket); + NetworkServerInterface(int socketDescriptor, const QSslCertificate &cert, const QSslKey &privateKey, Servatrice *_server); + NetworkServerInterface(const QString &peerHostName, const QString &peerAddress, int peerPort, const QSslCertificate &peerCert, const QSslCertificate &cert, const QSslKey &privateKey, Servatrice *_server); ~NetworkServerInterface(); void transmitMessage(const ServerNetworkMessage &item); diff --git a/servatrice/src/networkserverthread.cpp b/servatrice/src/networkserverthread.cpp deleted file mode 100644 index 4c3f24cd..00000000 --- a/servatrice/src/networkserverthread.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "networkserverthread.h" -#include "networkserverinterface.h" -#include "server_logger.h" -#include "servatrice.h" -#include "main.h" -#include -#include - -NetworkServerThread::NetworkServerThread(int _socketDescriptor, Servatrice *_server, const QSslCertificate &_cert, const QSslKey &_privateKey, QObject *parent) - : QThread(parent), server(_server), socketDescriptor(_socketDescriptor), cert(_cert), privateKey(_privateKey), connectionType(ServerType) -{ - connect(this, SIGNAL(finished()), this, SLOT(deleteLater())); -} - -NetworkServerThread::NetworkServerThread(const QString &_hostName, const QString &_address, int _port, const QSslCertificate &_peerCert, Servatrice *_server, const QSslCertificate &_cert, const QSslKey &_privateKey, QObject *parent) - : QThread(parent), server(_server), cert(_cert), privateKey(_privateKey), peerHostName(_hostName), peerAddress(_address), peerPort(_port), peerCert(_peerCert), connectionType(ClientType) -{ - connect(this, SIGNAL(finished()), this, SLOT(deleteLater())); -} - -NetworkServerThread::~NetworkServerThread() -{ - quit(); - wait(); - - delete socket; -} - -void NetworkServerThread::run() -{ - socket = new QSslSocket; - socket->setLocalCertificate(cert); - socket->setPrivateKey(privateKey); - - if (connectionType == ClientType) - try { - initClient(); - } catch (bool) { - usleep(100000); - initWaitCondition.wakeAll(); - return; - } - else - try { - initServer(); - } catch (bool) { - return; - } - - interface = new NetworkServerInterface(server, socket); - connect(interface, SIGNAL(destroyed()), this, SLOT(deleteLater())); - - if (connectionType == ClientType) { - usleep(100000); - initWaitCondition.wakeAll(); - } - - exec(); -} - -void NetworkServerThread::initServer() -{ - socket->setSocketDescriptor(socketDescriptor); - logger->logMessage(QString("[SN] incoming connection: %1").arg(socket->peerAddress().toString())); - - QList serverList = server->getServerList(); - int listIndex = -1; - for (int i = 0; i < serverList.size(); ++i) - if (serverList[i].address == socket->peerAddress()) { - listIndex = i; - break; - } - if (listIndex == -1) { - logger->logMessage(QString("[SN] address %1 unknown, terminating connection").arg(socket->peerAddress().toString())); - return; - } - - socket->startServerEncryption(); - if (!socket->waitForEncrypted(5000)) { - logger->logMessage(QString("[SN] SSL handshake timeout, terminating connection")); - return; - } - - if (serverList[listIndex].cert == socket->peerCertificate()) - logger->logMessage(QString("[SN] Peer authenticated as " + serverList[listIndex].hostname)); - else { - logger->logMessage(QString("[SN] Authentication failed, terminating connection")); - return; - } -} - -void NetworkServerThread::initClient() -{ - qDebug() << "[SN] Connecting to " << peerAddress << ":" << peerPort; - - QList expectedErrors; - expectedErrors.append(QSslError(QSslError::SelfSignedCertificate, peerCert)); - socket->ignoreSslErrors(expectedErrors); - -} diff --git a/servatrice/src/networkserverthread.h b/servatrice/src/networkserverthread.h deleted file mode 100644 index 925e58f3..00000000 --- a/servatrice/src/networkserverthread.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef NETWORKSERVERTHREAD_H -#define NETWORKSERVERTHREAD_H - -#include -#include -#include -#include - -class Servatrice; -class NetworkServerInterface; -class QSslSocket; - -class NetworkServerThread : public QThread { - Q_OBJECT -private: - Servatrice *server; - NetworkServerInterface *interface; - QSslCertificate cert; - QSslKey privateKey; - QString peerHostName, peerAddress; - int peerPort; - QSslCertificate peerCert; - int socketDescriptor; - QSslSocket *socket; - enum ConnectionType { ClientType, ServerType } connectionType; - - void initClient(); - void initServer(); -public: - NetworkServerThread(int _socketDescriptor, Servatrice *_server, const QSslCertificate &_cert, const QSslKey &_privateKey, QObject *parent = 0); - NetworkServerThread(const QString &_hostName, const QString &_address, int _port, const QSslCertificate &peerCert, Servatrice *_server, const QSslCertificate &_cert, const QSslKey &_privateKey, QObject *parent = 0); - ~NetworkServerThread(); - QWaitCondition initWaitCondition; -protected: - void run(); -}; - -#endif diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 6b8095bb..dfd9c35f 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -25,7 +25,7 @@ #include "server_room.h" #include "serversocketinterface.h" #include "serversocketthread.h" -#include "networkserverthread.h" +#include "networkserverinterface.h" #include "server_logger.h" #include "main.h" #include "passwordhasher.h" @@ -50,8 +50,15 @@ void Servatrice_GameServer::incomingConnection(int socketDescriptor) void Servatrice_NetworkServer::incomingConnection(int socketDescriptor) { - NetworkServerThread *thread = new NetworkServerThread(socketDescriptor, server, cert, privateKey); + QThread *thread = new QThread; + connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); + + NetworkServerInterface *interface = new NetworkServerInterface(socketDescriptor, cert, privateKey, server); + interface->moveToThread(thread); + connect(interface, SIGNAL(destroyed()), thread, SLOT(quit())); + thread->start(); + QMetaObject::invokeMethod(interface, "initServer", Qt::QueuedConnection); } Servatrice::Servatrice(QSettings *_settings, QObject *parent) @@ -150,12 +157,15 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent) continue; } - NetworkServerThread *thread = new NetworkServerThread(prop.hostname, prop.address.toString(), prop.controlPort, prop.cert, this, cert, key); - thread->start(); + QThread *thread = new QThread; + connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); - QMutex initMutex; - initMutex.lock(); - thread->initWaitCondition.wait(&initMutex); + NetworkServerInterface *interface = new NetworkServerInterface(prop.hostname, prop.address.toString(), prop.controlPort, prop.cert, cert, key, this); + interface->moveToThread(thread); + connect(interface, SIGNAL(destroyed()), thread, SLOT(quit())); + + thread->start(); + QMetaObject::invokeMethod(interface, "initClient", Qt::BlockingQueuedConnection); } } } catch (QString error) {