diff --git a/client/main.cpp b/client/main.cpp index 894b203..5eb68e4 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -155,7 +155,7 @@ int main(int argc, char *argv[]) QLoggingCategory::installFilter(loggingCategoryFilter); if (!parser.isSet(tokenOption)) { - qCCritical(dcProxyClient()) << "Please specify the token for authentication using -t or --token ." << endl << endl; + qCCritical(dcProxyClient()) << "Please specify the token for authentication using -t or --token ." << "\n" << "\n"; parser.showHelp(-1); } diff --git a/libnymea-remoteproxy/authentication/aws/authenticationprocess.cpp b/libnymea-remoteproxy/authentication/aws/authenticationprocess.cpp index 24f03b0..d77a3d5 100644 --- a/libnymea-remoteproxy/authentication/aws/authenticationprocess.cpp +++ b/libnymea-remoteproxy/authentication/aws/authenticationprocess.cpp @@ -197,13 +197,13 @@ void AuthenticationProcess::onProcessFinished(int exitCode, QProcess::ExitStatus { qCDebug(dcAuthenticationProcess()) << "Authentication process finished (" << m_processTimer.elapsed() << "[ms] )";; if (exitStatus == QProcess::CrashExit) { - qCWarning(dcAuthenticationProcess()) << "Authentication process crashed:" << endl << qUtf8Printable(m_process->readAll()); + qCWarning(dcAuthenticationProcess()) << "Authentication process crashed:" << "\n" << qUtf8Printable(m_process->readAll()); emit authenticationFinished(Authenticator::AuthenticationErrorProxyError); return; } if (exitCode != 0) { - qCWarning(dcAuthenticationProcess()) << "The authentication process finished with error" << exitCode << endl << qUtf8Printable(m_process->readAll()); + qCWarning(dcAuthenticationProcess()) << "The authentication process finished with error" << exitCode << "\n" << qUtf8Printable(m_process->readAll()); emit authenticationFinished(Authenticator::AuthenticationErrorProxyError); return; } diff --git a/libnymea-remoteproxy/authentication/aws/sigv4utils.cpp b/libnymea-remoteproxy/authentication/aws/sigv4utils.cpp index 76df170..8e60516 100644 --- a/libnymea-remoteproxy/authentication/aws/sigv4utils.cpp +++ b/libnymea-remoteproxy/authentication/aws/sigv4utils.cpp @@ -60,9 +60,9 @@ void SigV4Utils::signRequest(QNetworkAccessManager::Operation operation, QNetwor } QByteArray canonicalRequest = SigV4Utils::getCanonicalRequest(operation, request, payload); - qCDebug(dcAuthenticationProcess()) << "canonical request:" << endl << qUtf8Printable(canonicalRequest); + qCDebug(dcAuthenticationProcess()) << "canonical request:" << "\n" << qUtf8Printable(canonicalRequest); QByteArray stringToSign = SigV4Utils::getStringToSign(canonicalRequest, dateTime, region.toUtf8(), service.toUtf8()); - qCDebug(dcAuthenticationProcess()) << "string to sign:" << endl << qUtf8Printable(stringToSign); + qCDebug(dcAuthenticationProcess()) << "string to sign:" << "\n" << qUtf8Printable(stringToSign); QByteArray signature = SigV4Utils::getSignature(stringToSign, secretAccessKey, dateTime, region, service); qCDebug(dcAuthenticationProcess()) << "signature:" << signature; QByteArray authorizeHeader = SigV4Utils::getAuthorizationHeader(accessKeyId, dateTime, region, service, request, signature); diff --git a/libnymea-remoteproxy/authentication/aws/userinformation.cpp b/libnymea-remoteproxy/authentication/aws/userinformation.cpp index 8203063..6a2e5e7 100644 --- a/libnymea-remoteproxy/authentication/aws/userinformation.cpp +++ b/libnymea-remoteproxy/authentication/aws/userinformation.cpp @@ -68,10 +68,11 @@ bool UserInformation::isValid() QDebug operator<<(QDebug debug, const UserInformation &userInformation) { + QDebugStateSaver saver(debug); debug.nospace() << "UserInformation(" << userInformation.email(); debug.nospace() << ", cognito:" << userInformation.cognitoUsername() << ") "; debug.nospace() << ", vendor" << userInformation.vendorId() << ") "; - debug.nospace() << ", userpool" << userInformation.userPoolId() << ") "; + debug.nospace() << ", userpool" << userInformation.userPoolId() << ")"; return debug; } diff --git a/libnymea-remoteproxy/logengine.cpp b/libnymea-remoteproxy/logengine.cpp index e547ff2..ab7392c 100644 --- a/libnymea-remoteproxy/logengine.cpp +++ b/libnymea-remoteproxy/logengine.cpp @@ -60,7 +60,7 @@ void LogEngine::logTunnel(const TunnelConnection &tunnel) logString << QString::number(tunnel.clientOne()->rxDataCount() + tunnel.clientOne()->txDataCount()); QTextStream textStream(&m_tunnelsFile); - textStream << logString.join(" ") << endl; + textStream << logString.join(" ") << "\n"; } void LogEngine::logStatistics(int tunnelCount, int connectionCount, int troughput) @@ -76,7 +76,7 @@ void LogEngine::logStatistics(int tunnelCount, int connectionCount, int troughpu logString << QString::number(troughput); QTextStream textStream(&m_statisticsFile); - textStream << logString.join(" ") << endl; + textStream << logString.join(" ") << "\n"; // Check if we have to rotate the logfile if (m_currentDay != QDateTime::currentDateTimeUtc().date().day()) { diff --git a/libnymea-remoteproxy/proxy/proxyclient.cpp b/libnymea-remoteproxy/proxy/proxyclient.cpp index 1731d25..118b8b2 100644 --- a/libnymea-remoteproxy/proxy/proxyclient.cpp +++ b/libnymea-remoteproxy/proxy/proxyclient.cpp @@ -145,6 +145,7 @@ QList ProxyClient::processData(const QByteArray &data) QDebug operator<<(QDebug debug, ProxyClient *proxyClient) { + QDebugStateSaver saver(debug); debug.nospace() << "ProxyClient("; if (!proxyClient->name().isEmpty()) { debug.nospace() << proxyClient->name() << ", "; @@ -154,7 +155,7 @@ QDebug operator<<(QDebug debug, ProxyClient *proxyClient) debug.nospace() << ", " << proxyClient->userName(); debug.nospace() << ", " << proxyClient->peerAddress().toString(); debug.nospace() << ", " << proxyClient->creationTimeString() << ")"; - return debug.space(); + return debug; } } diff --git a/libnymea-remoteproxy/proxy/tunnelconnection.cpp b/libnymea-remoteproxy/proxy/tunnelconnection.cpp index d097d9e..6a88014 100644 --- a/libnymea-remoteproxy/proxy/tunnelconnection.cpp +++ b/libnymea-remoteproxy/proxy/tunnelconnection.cpp @@ -106,9 +106,10 @@ bool TunnelConnection::isValid() const QDebug operator<<(QDebug debug, const TunnelConnection &tunnel) { - debug.nospace() << "TunnelConnection(" << tunnel.creationTimeString() << ")" << endl; - debug.nospace() << " --> " << tunnel.clientOne() << endl; - debug.nospace() << " --> " << tunnel.clientTwo() << endl; + QDebugStateSaver saver(debug); + debug.nospace() << "TunnelConnection(" << tunnel.creationTimeString() << ")\n"; + debug.nospace() << " --> " << tunnel.clientOne() << "\n"; + debug.nospace() << " --> " << tunnel.clientTwo() << "\n"; return debug; } diff --git a/libnymea-remoteproxy/proxyconfiguration.cpp b/libnymea-remoteproxy/proxyconfiguration.cpp index 7bd4534..cbc72fd 100644 --- a/libnymea-remoteproxy/proxyconfiguration.cpp +++ b/libnymea-remoteproxy/proxyconfiguration.cpp @@ -419,60 +419,61 @@ void ProxyConfiguration::setTcpServerTunnelProxyPort(quint16 port) QDebug operator<<(QDebug debug, ProxyConfiguration *configuration) { - debug.nospace() << endl << "========== ProxyConfiguration ==========" << endl; - debug.nospace() << "Configuration file:" << configuration->fileName() << endl; - debug.nospace() << "RemoteProxy configuration" << endl; - debug.nospace() << " - Server name:" << configuration->serverName() << endl; - debug.nospace() << " - Write logfile:" << configuration->writeLogFile() << endl; - debug.nospace() << " - Logfile:" << configuration->logFileName() << endl; - debug.nospace() << " - Log engine enabled:" << configuration->logEngineEnabled() << endl; - debug.nospace() << " - JSON RPC timeout:" << configuration->jsonRpcTimeout() << " [ms]" << endl; - debug.nospace() << " - Authentication timeout:" << configuration->authenticationTimeout() << " [ms]" << endl; - debug.nospace() << " - Inactive timeout:" << configuration->inactiveTimeout() << " [ms]" << endl; - debug.nospace() << " - Alone timeout:" << configuration->aloneTimeout() << " [ms]" << endl; - debug.nospace() << "SSL configuration" << endl; - debug.nospace() << " - Enabled:" << configuration->sslEnabled() << endl; - debug.nospace() << " - Certificate:" << configuration->sslCertificateFileName() << endl; - debug.nospace() << " - Certificate key:" << configuration->sslCertificateKeyFileName() << endl; - debug.nospace() << " - Certificate chain:" << configuration->sslCertificateChainFileName() << endl; - debug.nospace() << " - SSL certificate information:" << endl; - debug.nospace() << " Common name:" << configuration->sslConfiguration().localCertificate().subjectInfo(QSslCertificate::CommonName) << endl; - debug.nospace() << " Organisation:" << configuration->sslConfiguration().localCertificate().subjectInfo(QSslCertificate::Organization) << endl; - debug.nospace() << " Organisation unit name:" << configuration->sslConfiguration().localCertificate().subjectInfo(QSslCertificate::OrganizationalUnitName) << endl; - debug.nospace() << " Country name:" << configuration->sslConfiguration().localCertificate().subjectInfo(QSslCertificate::CountryName) << endl; - debug.nospace() << " Locality name:" << configuration->sslConfiguration().localCertificate().subjectInfo(QSslCertificate::LocalityName) << endl; - debug.nospace() << " State/Province:" << configuration->sslConfiguration().localCertificate().subjectInfo(QSslCertificate::StateOrProvinceName) << endl; - debug.nospace() << " Email address:" << configuration->sslConfiguration().localCertificate().subjectInfo(QSslCertificate::EmailAddress) << endl; - debug.nospace() << " - SSL certificate issuer information:" << endl; - debug.nospace() << " Common name:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::CommonName) << endl; - debug.nospace() << " Organisation:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::Organization) << endl; - debug.nospace() << " Organisation unit name:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::OrganizationalUnitName) << endl; - debug.nospace() << " Country name:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::CountryName) << endl; - debug.nospace() << " Locality name:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::LocalityName) << endl; - debug.nospace() << " State/Province:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::StateOrProvinceName) << endl; - debug.nospace() << " Email address:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::EmailAddress) << endl; + QDebugStateSaver saver(debug); + debug.nospace() << "\n" << "========== ProxyConfiguration ==========" << "\n"; + debug.nospace() << "Configuration file:" << configuration->fileName() << "\n"; + debug.nospace() << "RemoteProxy configuration" << "\n"; + debug.nospace() << " - Server name:" << configuration->serverName() << "\n"; + debug.nospace() << " - Write logfile:" << configuration->writeLogFile() << "\n"; + debug.nospace() << " - Logfile:" << configuration->logFileName() << "\n"; + debug.nospace() << " - Log engine enabled:" << configuration->logEngineEnabled() << "\n"; + debug.nospace() << " - JSON RPC timeout:" << configuration->jsonRpcTimeout() << " [ms]" << "\n"; + debug.nospace() << " - Authentication timeout:" << configuration->authenticationTimeout() << " [ms]" << "\n"; + debug.nospace() << " - Inactive timeout:" << configuration->inactiveTimeout() << " [ms]" << "\n"; + debug.nospace() << " - Alone timeout:" << configuration->aloneTimeout() << " [ms]" << "\n"; + debug.nospace() << "SSL configuration" << "\n"; + debug.nospace() << " - Enabled:" << configuration->sslEnabled() << "\n"; + debug.nospace() << " - Certificate:" << configuration->sslCertificateFileName() << "\n"; + debug.nospace() << " - Certificate key:" << configuration->sslCertificateKeyFileName() << "\n"; + debug.nospace() << " - Certificate chain:" << configuration->sslCertificateChainFileName() << "\n"; + debug.nospace() << " - SSL certificate information:" << "\n"; + debug.nospace() << " Common name:" << configuration->sslConfiguration().localCertificate().subjectInfo(QSslCertificate::CommonName) << "\n"; + debug.nospace() << " Organisation:" << configuration->sslConfiguration().localCertificate().subjectInfo(QSslCertificate::Organization) << "\n"; + debug.nospace() << " Organisation unit name:" << configuration->sslConfiguration().localCertificate().subjectInfo(QSslCertificate::OrganizationalUnitName) << "\n"; + debug.nospace() << " Country name:" << configuration->sslConfiguration().localCertificate().subjectInfo(QSslCertificate::CountryName) << "\n"; + debug.nospace() << " Locality name:" << configuration->sslConfiguration().localCertificate().subjectInfo(QSslCertificate::LocalityName) << "\n"; + debug.nospace() << " State/Province:" << configuration->sslConfiguration().localCertificate().subjectInfo(QSslCertificate::StateOrProvinceName) << "\n"; + debug.nospace() << " Email address:" << configuration->sslConfiguration().localCertificate().subjectInfo(QSslCertificate::EmailAddress) << "\n"; + debug.nospace() << " - SSL certificate issuer information:" << "\n"; + debug.nospace() << " Common name:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::CommonName) << "\n"; + debug.nospace() << " Organisation:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::Organization) << "\n"; + debug.nospace() << " Organisation unit name:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::OrganizationalUnitName) << "\n"; + debug.nospace() << " Country name:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::CountryName) << "\n"; + debug.nospace() << " Locality name:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::LocalityName) << "\n"; + debug.nospace() << " State/Province:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::StateOrProvinceName) << "\n"; + debug.nospace() << " Email address:" << configuration->sslConfiguration().localCertificate().issuerInfo(QSslCertificate::EmailAddress) << "\n"; if (configuration->proxyEnabled()) { - debug.nospace() << "AWS configuration" << endl; - debug.nospace() << " - Region:" << configuration->awsRegion() << endl; - debug.nospace() << " - Authorizer lambda function:" << configuration->awsAuthorizerLambdaFunctionName() << endl; - debug.nospace() << " - Credentials URL:" << configuration->awsCredentialsUrl().toString() << endl; - debug.nospace() << "WebSocketServer Proxy" << endl; - debug.nospace() << " - Host:" << configuration->webSocketServerProxyHost().toString() << endl; - debug.nospace() << " - Port:" << configuration->webSocketServerProxyPort() << endl; - debug.nospace() << "TcpServer Proxy" << endl; - debug.nospace() << " - Host:" << configuration->tcpServerHost().toString() << endl; - debug.nospace() << " - Port:" << configuration->tcpServerPort() << endl; - debug.nospace() << "UnixSocketServer Proxy" << endl; - debug.nospace() << " - Filename:" << configuration->unixSocketFileName() << endl; + debug.nospace() << "AWS configuration" << "\n"; + debug.nospace() << " - Region:" << configuration->awsRegion() << "\n"; + debug.nospace() << " - Authorizer lambda function:" << configuration->awsAuthorizerLambdaFunctionName() << "\n"; + debug.nospace() << " - Credentials URL:" << configuration->awsCredentialsUrl().toString() << "\n"; + debug.nospace() << "WebSocketServer Proxy" << "\n"; + debug.nospace() << " - Host:" << configuration->webSocketServerProxyHost().toString() << "\n"; + debug.nospace() << " - Port:" << configuration->webSocketServerProxyPort() << "\n"; + debug.nospace() << "TcpServer Proxy" << "\n"; + debug.nospace() << " - Host:" << configuration->tcpServerHost().toString() << "\n"; + debug.nospace() << " - Port:" << configuration->tcpServerPort() << "\n"; + debug.nospace() << "UnixSocketServer Proxy" << "\n"; + debug.nospace() << " - Filename:" << configuration->unixSocketFileName() << "\n"; } else { - debug.nospace() << "Proxy Server: disabled" << endl; + debug.nospace() << "Proxy Server: disabled" << "\n"; } - debug.nospace() << "WebSocketServer TunnelProxy" << endl; - debug.nospace() << " - Host:" << configuration->webSocketServerTunnelProxyHost().toString() << endl; - debug.nospace() << " - Port:" << configuration->webSocketServerTunnelProxyPort() << endl; - debug.nospace() << "TcpServer TunnelProxy" << endl; - debug.nospace() << " - Host:" << configuration->tcpServerTunnelProxyHost().toString() << endl; - debug.nospace() << " - Port:" << configuration->tcpServerTunnelProxyPort() << endl; + debug.nospace() << "WebSocketServer TunnelProxy" << "\n"; + debug.nospace() << " - Host:" << configuration->webSocketServerTunnelProxyHost().toString() << "\n"; + debug.nospace() << " - Port:" << configuration->webSocketServerTunnelProxyPort() << "\n"; + debug.nospace() << "TcpServer TunnelProxy" << "\n"; + debug.nospace() << " - Host:" << configuration->tcpServerTunnelProxyHost().toString() << "\n"; + debug.nospace() << " - Port:" << configuration->tcpServerTunnelProxyPort() << "\n"; debug.nospace() << "========== ProxyConfiguration =========="; return debug; } diff --git a/libnymea-remoteproxy/server/tcpsocketserver.cpp b/libnymea-remoteproxy/server/tcpsocketserver.cpp index 7607c84..8a14f07 100644 --- a/libnymea-remoteproxy/server/tcpsocketserver.cpp +++ b/libnymea-remoteproxy/server/tcpsocketserver.cpp @@ -160,8 +160,6 @@ void TcpSocketServer::onSocketDisconnected(QSslSocket *client) emit clientDisconnected(clientId); } - - SslServer::SslServer(bool sslEnabled, const QSslConfiguration &config, QObject *parent) : QTcpServer(parent), m_sslEnabled(sslEnabled), @@ -173,13 +171,8 @@ SslServer::SslServer(bool sslEnabled, const QSslConfiguration &config, QObject * connect(this, &QTcpServer::newConnection, this, [this](){ while (hasPendingConnections()) { - QSslSocket *sslSocket = qobject_cast(nextPendingConnection()); - if (m_sslEnabled) { - if (sslSocket->isEncrypted()) { - qCDebug(dcTcpSocketServer()) << "SSL encryption established for" << sslSocket; - emit socketConnected(sslSocket); - } - } else { + SslClient *sslSocket = qobject_cast(nextPendingConnection()); + if (!m_sslEnabled) { emit socketConnected(sslSocket); } } @@ -188,7 +181,7 @@ SslServer::SslServer(bool sslEnabled, const QSslConfiguration &config, QObject * void SslServer::incomingConnection(qintptr socketDescriptor) { - QSslSocket *sslSocket = new QSslSocket(this); + SslClient *sslSocket = new SslClient(this); qCDebug(dcTcpSocketServer()) << "New incomming connection. Creating" << sslSocket; if (!sslSocket->setSocketDescriptor(socketDescriptor)) { qCWarning(dcTcpSocketServer()) << "Failed to set SSL socket descriptor" << sslSocket << "Discard connection..."; @@ -196,39 +189,73 @@ void SslServer::incomingConnection(qintptr socketDescriptor) return; } - connect(sslSocket, &QSslSocket::disconnected, this, [this, sslSocket](){ + connect(sslSocket, &SslClient::disconnected, this, [this, sslSocket](){ qCDebug(dcTcpSocketServer()) << "Client socket disconnected:" << sslSocket << sslSocket->peerAddress().toString();; - emit socketDisconnected(sslSocket); + if (sslSocket->isEncrypted()) { + emit socketDisconnected(sslSocket); + } + + m_clients.removeAll(sslSocket); + qCDebug(dcTcpSocketServer()) << "SSL server client count" << m_clients.count(); sslSocket->deleteLater(); }); - - typedef void (QAbstractSocket:: *errorSignal)(QAbstractSocket::SocketError); - connect(sslSocket, static_cast(&QAbstractSocket::error), this, [sslSocket](QAbstractSocket::SocketError error){ - qCWarning(dcTcpSocketServer()) << "Socket error occurred on" << sslSocket << error << sslSocket->errorString() << "Explicitly closing the socket connection."; - sslSocket->abort(); + connect(sslSocket, &QSslSocket::readyRead, this, [this, sslSocket](){ + if (sslSocket->isEncrypted()) { + QByteArray data = sslSocket->readAll(); + qCDebug(dcTcpSocketServerTraffic()) << "Data from socket" << sslSocket->peerAddress().toString() << data; + emit dataAvailable(sslSocket, data); + } }); - connect(sslSocket, &QSslSocket::encrypted, this, [this, sslSocket](){ + connect(sslSocket, &SslClient::encrypted, this, [this, sslSocket](){ qCDebug(dcTcpSocketServer()) << "SSL encryption established for" << sslSocket; emit socketConnected(sslSocket); }); - connect(sslSocket, QOverload &>::of(&QSslSocket::sslErrors), this, [=](const QList &errors){ + typedef void (QAbstractSocket:: *errorSignal)(QAbstractSocket::SocketError); + connect(sslSocket, static_cast(&QAbstractSocket::error), this, [sslSocket](QAbstractSocket::SocketError error){ + qCWarning(dcTcpSocketServer()) << "Socket error occurred on" << sslSocket << error << sslSocket->errorString() << "Explicitly closing the client connection."; + sslSocket->close(); + }); + + typedef void (QSslSocket:: *sslErrorsSignal)(const QList &); + connect(sslSocket, static_cast(&QSslSocket::sslErrors), this, [sslSocket](const QList &errors) { qCWarning(dcTcpSocketServer()) << "SSL error occurred in the client connection" << sslSocket; foreach (const QSslError &error, errors) { - qCWarning(dcTcpSocketServer()) << "SSL error:" << error.error() << error.errorString(); + qCWarning(dcTcpSocketServer()) << "--> SSL error:" << error.error() << error.errorString(); } }); if (m_sslEnabled) { - qCDebug(dcTcpSocketServer()) << "Start SSL encryption for" << sslSocket; + qCDebug(dcTcpSocketServer()) << "Starting SSL encryption for" << sslSocket; sslSocket->setSslConfiguration(m_config); sslSocket->startServerEncryption(); + sslSocket->startWaitingForEncrypted(); } + m_clients.append(sslSocket); + qCDebug(dcTcpSocketServer()) << "SSL server client count" << m_clients.count(); addPendingConnection(sslSocket); } +SslClient::SslClient(QObject *parent) : + QSslSocket(parent) +{ + m_timer.setSingleShot(true); + m_timer.setInterval(5000); + connect(&m_timer, &QTimer::timeout, this, [this](){ + qCWarning(dcTcpSocketServer()) << "SSL socket timeout occurred. The client has not encrypted the connection within" << (m_timer.interval() / 1000) << "seconds. Terminate connection"; + close(); + }); + + connect(this, &SslClient::encrypted, &m_timer, &QTimer::stop); +} + +void SslClient::startWaitingForEncrypted() +{ + m_timer.start(); +} + } diff --git a/libnymea-remoteproxy/server/tcpsocketserver.h b/libnymea-remoteproxy/server/tcpsocketserver.h index f77a906..a76dae5 100644 --- a/libnymea-remoteproxy/server/tcpsocketserver.h +++ b/libnymea-remoteproxy/server/tcpsocketserver.h @@ -29,6 +29,7 @@ #define TCPSOCKETSERVER_H #include +#include #include #include #include @@ -37,6 +38,20 @@ namespace remoteproxy { +class SslClient: public QSslSocket +{ + Q_OBJECT + +public: + explicit SslClient(QObject *parent = nullptr); + + void startWaitingForEncrypted(); + +private: + QTimer m_timer; + +}; + class SslServer: public QTcpServer { Q_OBJECT @@ -56,6 +71,8 @@ private: bool m_sslEnabled = false; QSslConfiguration m_config; + QVector m_clients; + }; diff --git a/libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.cpp b/libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.cpp index 6663c0b..a9174ab 100644 --- a/libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.cpp +++ b/libnymea-remoteproxy/tunnelproxy/tunnelproxyclient.cpp @@ -85,13 +85,14 @@ void TunnelProxyClient::makeClientActive() QDebug operator<<(QDebug debug, TunnelProxyClient *tunnelProxyClient) { + QDebugStateSaver saver(debug); debug.nospace() << "TunnelProxyClient("; debug.nospace() << tunnelProxyClient->name() << ", "; debug.nospace() << tunnelProxyClient->interface()->serverName()<< ", "; debug.nospace() << tunnelProxyClient->clientId().toString()<< ", "; debug.nospace() << tunnelProxyClient->peerAddress().toString() << ", "; debug.nospace() << tunnelProxyClient->creationTimeString() << ")"; - return debug.space(); + return debug; } } diff --git a/libnymea-remoteproxy/tunnelproxy/tunnelproxyclientconnection.cpp b/libnymea-remoteproxy/tunnelproxy/tunnelproxyclientconnection.cpp index c39a5f5..6d965b3 100644 --- a/libnymea-remoteproxy/tunnelproxy/tunnelproxyclientconnection.cpp +++ b/libnymea-remoteproxy/tunnelproxy/tunnelproxyclientconnection.cpp @@ -88,12 +88,13 @@ void TunnelProxyClientConnection::setSocketAddress(quint16 socketAddress) QDebug operator<<(QDebug debug, TunnelProxyClientConnection *clientConnection) { + QDebugStateSaver saver(debug); debug.nospace() << "TunnelProxyClientConnection("; debug.nospace() << clientConnection->clientName() << ", "; debug.nospace() << clientConnection->clientUuid().toString() << ", "; debug.nospace() << "server: " << clientConnection->serverUuid().toString() << ", "; debug.nospace() << clientConnection->transportClient() << ")"; - return debug.space(); + return debug; } } diff --git a/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.cpp b/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.cpp index 02ac1d2..7e141df 100644 --- a/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.cpp +++ b/libnymea-remoteproxy/tunnelproxy/tunnelproxyserver.cpp @@ -85,7 +85,7 @@ TunnelProxyServer::TunnelProxyError TunnelProxyServer::registerServer(const QUui { qCDebug(dcTunnelProxyServer()) << "Register new server" << m_proxyClients.value(clientId) << serverName << serverUuid.toString(); - // Check if requested already as client + // Make sure we have a proxy client for this id TunnelProxyClient *tunnelProxyClient = m_proxyClients.value(clientId); if (!tunnelProxyClient) { qCWarning(dcTunnelProxyServer()) << "There is no client with client uuid" << clientId.toString(); @@ -99,8 +99,22 @@ TunnelProxyServer::TunnelProxyError TunnelProxyServer::registerServer(const QUui return TunnelProxyServer::TunnelProxyErrorAlreadyRegistered; } + // Make sure there is no server trying to make multiple server tunnel connections. We allow only one + if (m_tunnelProxyServerConnections.contains(serverUuid)) { + qCWarning(dcTunnelProxyServer()) << "Client tried to register as server" << tunnelProxyClient << "but there is already a server registered with this server uuid:" << serverUuid.toString(); + tunnelProxyClient->killConnectionAfterResponse("Already registered"); + return TunnelProxyServer::TunnelProxyErrorAlreadyRegistered; + } + + // Also make sure this uuid has not been alreay used for any client connections... + if (m_tunnelProxyClientConnections.contains(serverUuid)) { + qCWarning(dcTunnelProxyServer()) << "Client tried to register as server" << tunnelProxyClient << "but there is already a client connection using this server uuid:" << serverUuid.toString(); + tunnelProxyClient->killConnectionAfterResponse("UUID cross registeration"); + return TunnelProxyServer::TunnelProxyErrorAlreadyRegistered; + } + // This client has been registered successfully. - // Make sure it does not get disconnected any more because due to inactivity. + // Make sure it does not get disconnected any more because of inactivity. tunnelProxyClient->makeClientActive(); tunnelProxyClient->setType(TunnelProxyClient::TypeServer); @@ -116,8 +130,9 @@ TunnelProxyServer::TunnelProxyError TunnelProxyServer::registerServer(const QUui qCDebug(dcTunnelProxyServer()) << "New server connection registered successfully" << serverConnection; // For debugging - qCDebug(dcTunnelProxyServer()) << "####" << "Total clients" << m_proxyClients.count() << "JSON RPC clients" << m_jsonRpcServer->registeredClientCount() << "interface connections" << tunnelProxyClient->interface()->connectionsCount() - << "Servers" << m_tunnelProxyServerConnections.count() << "Clients" << m_tunnelProxyClientConnections.count(); + qCDebug(dcTunnelProxyServer()) << "#### Total clients:" << m_proxyClients.count() << "JSON RPC clients:" << m_jsonRpcServer->registeredClientCount() + << "Interface connections:" << tunnelProxyClient->interface()->connectionsCount() + << "Servers:" << m_tunnelProxyServerConnections.count() << "Clients:" << m_tunnelProxyClientConnections.count(); return TunnelProxyServer::TunnelProxyErrorNoError; } @@ -143,6 +158,14 @@ TunnelProxyServer::TunnelProxyError TunnelProxyServer::registerClient(const QUui return TunnelProxyServer::TunnelProxyErrorAlreadyRegistered; } + // Also make sure this uuid has not been alreay used for any client connections... + if (m_tunnelProxyServerConnections.contains(clientUuid)) { + qCWarning(dcTunnelProxyServer()) << "Client tried to register as client" << tunnelProxyClient << "but there is already a server connection using this client uuid:" << clientUuid.toString(); + tunnelProxyClient->killConnectionAfterResponse("UUID cross registeration"); + return TunnelProxyServer::TunnelProxyErrorAlreadyRegistered; + } + + // Get the desired server connection TunnelProxyServerConnection *serverConnection = m_tunnelProxyServerConnections.value(serverUuid); if (!serverConnection) { @@ -160,7 +183,7 @@ TunnelProxyServer::TunnelProxyError TunnelProxyServer::registerClient(const QUui tunnelProxyClient->setUuid(clientUuid); tunnelProxyClient->setName(clientName); - TunnelProxyClientConnection *clientConnection = new TunnelProxyClientConnection(tunnelProxyClient, clientUuid, clientName, tunnelProxyClient); + TunnelProxyClientConnection *clientConnection = new TunnelProxyClientConnection(tunnelProxyClient, clientUuid, clientName, this); clientConnection->setServerConnection(serverConnection); m_tunnelProxyClientConnections.insert(clientUuid, clientConnection); @@ -291,9 +314,15 @@ void TunnelProxyServer::tick() } void TunnelProxyServer::onClientConnected(const QUuid &clientId, const QHostAddress &address) -{ +{ TransportInterface *interface = static_cast(sender()); - qCDebug(dcTunnelProxyServer()) << "New client connected" << interface->serverName() << clientId.toString() << address.toString(); + qCDebug(dcTunnelProxyServer()) << "New client connected" << interface->serverName() << address.toString() << clientId.toString(); + + if (m_proxyClients.contains(clientId)) { + qCWarning(dcTunnelProxyServer()) << "Internal error. A client with clientId" << clientId.toString() << "has already connected before. Terminate new connection."; + interface->killClientConnection(clientId, "Internal server error"); + return; + } TunnelProxyClient *tunnelProxyClient = new TunnelProxyClient(interface, clientId, address, this); m_proxyClients.insert(clientId, tunnelProxyClient); @@ -308,8 +337,6 @@ void TunnelProxyServer::onClientConnected(const QUuid &clientId, const QHostAddr void TunnelProxyServer::onClientDisconnected(const QUuid &clientId) { TransportInterface *interface = static_cast(sender()); - qCDebug(dcTunnelProxyServer()) << "Client disconnected" << interface->serverName() << clientId.toString(); - TunnelProxyClient *tunnelProxyClient = m_proxyClients.take(clientId); if (!tunnelProxyClient) { qCWarning(dcTunnelProxyServer()) << "Unknown client disconnected from proxy server." << clientId.toString(); @@ -321,6 +348,7 @@ void TunnelProxyServer::onClientDisconnected(const QUuid &clientId) if (!serverConnection) { qCWarning(dcTunnelProxyServer()) << "Could not find server connection for disconnected tunnel proxy client claiming to be a server."; } else { + qCDebug(dcTunnelProxyServer()) << "Server connection disconnected" << interface->serverName() << clientId.toString(); foreach (TunnelProxyClientConnection *clientConnection, serverConnection->clientConnections()) { serverConnection->unregisterClientConnection(clientConnection); clientConnection->transportClient()->killConnection("Server disconnected"); diff --git a/libnymea-remoteproxy/tunnelproxy/tunnelproxyserverconnection.cpp b/libnymea-remoteproxy/tunnelproxy/tunnelproxyserverconnection.cpp index c543dc1..d7b3615 100644 --- a/libnymea-remoteproxy/tunnelproxy/tunnelproxyserverconnection.cpp +++ b/libnymea-remoteproxy/tunnelproxy/tunnelproxyserverconnection.cpp @@ -100,11 +100,12 @@ quint16 TunnelProxyServerConnection::getFreeAddress() QDebug operator<<(QDebug debug, TunnelProxyServerConnection *serverConnection) { + QDebugStateSaver saver(debug); debug.nospace() << "TunnelProxyServerConnection("; debug.nospace() << serverConnection->serverName() << ", "; debug.nospace() << serverConnection->serverUuid().toString() << ", "; debug.nospace() << serverConnection->transportClient() << ")"; - return debug.space(); + return debug; } } diff --git a/libnymea-remoteproxyclient/tunnelproxy/tunnelproxysocket.cpp b/libnymea-remoteproxyclient/tunnelproxy/tunnelproxysocket.cpp index 4aff722..deab5b8 100644 --- a/libnymea-remoteproxyclient/tunnelproxy/tunnelproxysocket.cpp +++ b/libnymea-remoteproxyclient/tunnelproxy/tunnelproxysocket.cpp @@ -91,12 +91,13 @@ void TunnelProxySocket::setDisconnected() QDebug operator<<(QDebug debug, TunnelProxySocket *tunnelProxySocket) { + QDebugStateSaver saver(debug); debug.nospace() << "TunnelProxySocket("; debug.nospace() << tunnelProxySocket->clientName() << ", "; debug.nospace() << tunnelProxySocket->clientUuid().toString() << ", "; debug.nospace() << tunnelProxySocket->clientPeerAddress().toString() << ", "; debug.nospace() << tunnelProxySocket->socketAddress() << ")"; - return debug.space(); + return debug; } } diff --git a/server/main.cpp b/server/main.cpp index f478c2c..690da03 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -94,7 +94,7 @@ static void consoleLogHandler(QtMsgType type, const QMessageLogContext& context, if (s_logFile.isOpen()) { QTextStream textStream(&s_logFile); - textStream << messageString << endl; + textStream << messageString << "\n"; } } diff --git a/tests/scripts/create-many-connections.sh b/tests/scripts/create-many-connections.sh index 752cd93..9d77399 100755 --- a/tests/scripts/create-many-connections.sh +++ b/tests/scripts/create-many-connections.sh @@ -1,7 +1,7 @@ #!/bin/bash CHILD_PROCESSES=() -SERVER_URL=tcp://127.0.0.1:2213 +SERVER_URL=ssl://127.0.0.1:2213 SERVER_COUNTER=0 CLIENT_COUNTER=0 diff --git a/tests/test-tunnelproxy/remoteproxyteststunnelproxy.cpp b/tests/test-tunnelproxy/remoteproxyteststunnelproxy.cpp index 4483605..d365c74 100644 --- a/tests/test-tunnelproxy/remoteproxyteststunnelproxy.cpp +++ b/tests/test-tunnelproxy/remoteproxyteststunnelproxy.cpp @@ -441,7 +441,6 @@ void RemoteProxyTestsTunnelProxy::registerClientDuplicated() addDebugCategory("TunnelProxyServer.debug=true"); addDebugCategory("JsonRpcTraffic.debug=true"); - // Create the server and keep it up QString serverName = "creative server name"; QUuid serverUuid = QUuid::createUuid();