switched NetworkServerThread to new thread creation method, SSL is working
This commit is contained in:
parent
0719d4c6ed
commit
decf1c04bd
6 changed files with 98 additions and 165 deletions
|
@ -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)
|
||||
|
|
|
@ -9,17 +9,75 @@
|
|||
#include "pb/event_server_complete_list.pb.h"
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
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<ServerProperties> 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<QSslError> 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<QSslError> 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();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
#define NETWORKSERVERINTERFACE_H
|
||||
|
||||
#include "servatrice.h"
|
||||
#include <QSslCertificate>
|
||||
#include <QSslKey>
|
||||
#include <QWaitCondition>
|
||||
|
||||
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);
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
#include "networkserverthread.h"
|
||||
#include "networkserverinterface.h"
|
||||
#include "server_logger.h"
|
||||
#include "servatrice.h"
|
||||
#include "main.h"
|
||||
#include <QSslSocket>
|
||||
#include <QSslError>
|
||||
|
||||
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<ServerProperties> 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<QSslError> expectedErrors;
|
||||
expectedErrors.append(QSslError(QSslError::SelfSignedCertificate, peerCert));
|
||||
socket->ignoreSslErrors(expectedErrors);
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
#ifndef NETWORKSERVERTHREAD_H
|
||||
#define NETWORKSERVERTHREAD_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QSslCertificate>
|
||||
#include <QSslKey>
|
||||
#include <QWaitCondition>
|
||||
|
||||
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
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue