Fix JsonRpc server breaking transports upon guard timer timeouts

This commit is contained in:
Michael Zanetti 2019-04-16 19:48:56 +02:00
parent 6c5f8c482a
commit 9e2d495f9a
10 changed files with 51 additions and 57 deletions

View File

@ -776,6 +776,7 @@ void JsonRPCServer::registerHandler(JsonHandler *handler)
void JsonRPCServer::clientConnected(const QUuid &clientId)
{
qCDebug(dcJsonRpc()) << "Client connected with uuid" << clientId.toString();
TransportInterface *interface = qobject_cast<TransportInterface *>(sender());
m_clientTransports.insert(clientId, interface);
@ -788,11 +789,9 @@ void JsonRPCServer::clientConnected(const QUuid &clientId)
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, [this, timer, clientId, interface](){
// Client did not initiate handshake within timeout. Drop connection...
m_clientTransports.value(clientId)->disconnect();
qCDebug(dcJsonRpc()) << "Client" << clientId << "did not initiate the handshake within the required timeout. Dropping connection.";
timer->deleteLater();
m_newConnectionWaitTimers.remove(clientId);
qCDebug(dcJsonRpc()) << "Client" << clientId << "did not initiate the handshake within the required timeout. Dropping connection.";
interface->terminateClientConnection(clientId);
});
m_newConnectionWaitTimers.insert(clientId, timer);

View File

@ -59,9 +59,9 @@ ServerManager::ServerManager(NymeaConfiguration *configuration, QObject *parent)
m_sslConfiguration(QSslConfiguration())
{
if (!QSslSocket::supportsSsl()) {
qCWarning(dcConnection) << "SSL is not supported/installed on this platform.";
qCWarning(dcServerManager()) << "SSL is not supported/installed on this platform.";
} else {
qCDebug(dcConnection) << "SSL library version:" << QSslSocket::sslLibraryVersionString();
qCDebug(dcServerManager()) << "SSL library version:" << QSslSocket::sslLibraryVersionString();
QString configCertificateFileName = configuration->sslCertificate();
QString configKeyFileName = configuration->sslCertificateKey();
@ -71,19 +71,19 @@ ServerManager::ServerManager(NymeaConfiguration *configuration, QObject *parent)
bool certsLoaded = false;
if (loadCertificate(configKeyFileName, configCertificateFileName)) {
qCDebug(dcConnection) << "Using SSL certificate:" << configKeyFileName;
qCDebug(dcServerManager()) << "Using SSL certificate:" << configKeyFileName;
certsLoaded = true;
} else if (loadCertificate(fallbackKeyFileName, fallbackCertificateFileName)) {
certsLoaded = true;
qCWarning(dcConnection) << "Using fallback self-signed SSL certificate:" << fallbackCertificateFileName;
qCWarning(dcServerManager()) << "Using fallback self-signed SSL certificate:" << fallbackCertificateFileName;
} else {
qCDebug(dcConnection) << "Generating self signed certificates...";
qCDebug(dcServerManager()) << "Generating self signed certificates...";
CertificateGenerator::generate(fallbackCertificateFileName, fallbackKeyFileName);
if (loadCertificate(fallbackKeyFileName, fallbackCertificateFileName)) {
qCWarning(dcConnection) << "Using newly created self-signed SSL certificate:" << fallbackCertificateFileName;
qCWarning(dcServerManager()) << "Using newly created self-signed SSL certificate:" << fallbackCertificateFileName;
certsLoaded = true;
} else {
qCWarning(dcConnection) << "Failed to load SSL certificates. SSL encryption disabled.";
qCWarning(dcServerManager()) << "Failed to load SSL certificates. SSL encryption disabled.";
}
}
if (certsLoaded) {
@ -182,11 +182,11 @@ void ServerManager::tcpServerConfigurationChanged(const QString &id)
ServerConfiguration config = NymeaCore::instance()->configuration()->tcpServerConfigurations().value(id);
TcpServer *server = m_tcpServers.value(id);
if (server) {
qDebug(dcConnection) << "Restarting TCP server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
qDebug(dcServerManager()) << "Restarting TCP server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
server->stopServer();
server->setConfiguration(config);
} else {
qDebug(dcConnection) << "Received a TCP Server config change event but don't have a TCP Server instance for it. Creating new Server instance.";
qDebug(dcServerManager()) << "Received a TCP Server config change event but don't have a TCP Server instance for it. Creating new Server instance.";
server = new TcpServer(config, m_sslConfiguration, this);
m_tcpServers.insert(config.id, server);
}
@ -197,7 +197,7 @@ void ServerManager::tcpServerConfigurationChanged(const QString &id)
void ServerManager::tcpServerConfigurationRemoved(const QString &id)
{
if (!m_tcpServers.contains(id)) {
qWarning(dcConnection) << "Received a TCP Server config removed event but don't have a TCP Server instance for it.";
qWarning(dcServerManager()) << "Received a TCP Server config removed event but don't have a TCP Server instance for it.";
return;
}
TcpServer *server = m_tcpServers.take(id);
@ -211,11 +211,11 @@ void ServerManager::webSocketServerConfigurationChanged(const QString &id)
WebSocketServer *server = m_webSocketServers.value(id);
ServerConfiguration config = NymeaCore::instance()->configuration()->webSocketServerConfigurations().value(id);
if (server) {
qDebug(dcConnection) << "Restarting WebSocket server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
qDebug(dcServerManager()) << "Restarting WebSocket server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
server->stopServer();
server->setConfiguration(config);
} else {
qDebug(dcConnection) << "Received a WebSocket Server config change event but don't have a WebSocket Server instance for it. Creating new instance.";
qDebug(dcServerManager()) << "Received a WebSocket Server config change event but don't have a WebSocket Server instance for it. Creating new instance.";
server = new WebSocketServer(config, m_sslConfiguration, this);
m_webSocketServers.insert(server->configuration().id, server);
}
@ -226,7 +226,7 @@ void ServerManager::webSocketServerConfigurationChanged(const QString &id)
void ServerManager::webSocketServerConfigurationRemoved(const QString &id)
{
if (!m_webSocketServers.contains(id)) {
qWarning(dcConnection) << "Received a WebSocket Server config removed event but don't have a WebSocket Server instance for it.";
qWarning(dcServerManager()) << "Received a WebSocket Server config removed event but don't have a WebSocket Server instance for it.";
return;
}
WebSocketServer *server = m_webSocketServers.take(id);
@ -240,11 +240,11 @@ void ServerManager::webServerConfigurationChanged(const QString &id)
WebServerConfiguration config = NymeaCore::instance()->configuration()->webServerConfigurations().value(id);
WebServer *server = m_webServers.value(id);
if (server) {
qDebug(dcConnection) << "Restarting Web server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
qDebug(dcServerManager()) << "Restarting Web server for" << config.address << config.port << "SSL" << (config.sslEnabled ? "enabled" : "disabled") << "Authentication" << (config.authenticationEnabled ? "enabled" : "disabled");
server->stopServer();
server->reconfigureServer(config);
} else {
qDebug(dcConnection) << "Received a Web Server config change event but don't have a Web Server instance for it. Creating new WebServer instance on" << config.address.toString() << config.port << "(SSL:" << config.sslEnabled << ")";
qDebug(dcServerManager()) << "Received a Web Server config change event but don't have a Web Server instance for it. Creating new WebServer instance on" << config.address.toString() << config.port << "(SSL:" << config.sslEnabled << ")";
server = new WebServer(config, m_sslConfiguration, this);
m_restServer->registerWebserver(server);
m_webServers.insert(config.id, server);
@ -254,7 +254,7 @@ void ServerManager::webServerConfigurationChanged(const QString &id)
void ServerManager::webServerConfigurationRemoved(const QString &id)
{
if (!m_webServers.contains(id)) {
qWarning(dcConnection) << "Received a Web Server config removed event but don't have a Web Server instance for it.";
qWarning(dcServerManager()) << "Received a Web Server config removed event but don't have a Web Server instance for it.";
return;
}
WebServer *server = m_webServers.take(id);
@ -290,20 +290,20 @@ bool ServerManager::loadCertificate(const QString &certificateKeyFileName, const
{
QFile certificateKeyFile(certificateKeyFileName);
if (!certificateKeyFile.open(QIODevice::ReadOnly)) {
qCWarning(dcConnection) << "Could not open" << certificateKeyFile.fileName() << ":" << certificateKeyFile.errorString();
qCWarning(dcServerManager()) << "Could not open" << certificateKeyFile.fileName() << ":" << certificateKeyFile.errorString();
return false;
}
m_certificateKey = QSslKey(certificateKeyFile.readAll(), QSsl::Rsa);
qCDebug(dcConnection) << "Loaded private certificate key " << certificateKeyFileName;
qCDebug(dcServerManager()) << "Loaded private certificate key " << certificateKeyFileName;
certificateKeyFile.close();
QFile certificateFile(certificateFileName);
if (!certificateFile.open(QIODevice::ReadOnly)) {
qCWarning(dcConnection) << "Could not open" << certificateFile.fileName() << ":" << certificateFile.errorString();
qCWarning(dcServerManager()) << "Could not open" << certificateFile.fileName() << ":" << certificateFile.errorString();
return false;
}
m_certificate = QSslCertificate(certificateFile.readAll());
qCDebug(dcConnection) << "Loaded certificate file " << certificateFileName;
qCDebug(dcServerManager()) << "Loaded certificate file " << certificateFileName;
certificateFile.close();
return true;
@ -312,7 +312,7 @@ bool ServerManager::loadCertificate(const QString &certificateKeyFileName, const
/*! Set the server name for all servers to the given \a serverName. */
void ServerManager::setServerName(const QString &serverName)
{
qCDebug(dcConnection()) << "Server name changed" << serverName;
qCDebug(dcServerManager()) << "Server name changed" << serverName;
foreach (WebSocketServer *websocketServer, m_webSocketServers.values()) {
websocketServer->setServerName(serverName);

View File

@ -107,7 +107,7 @@ void BluetoothServer::onClientConnected()
if (!client)
return;
qCDebug(dcConnection()) << "BluetoothServer: New client connected:" << client->peerName() << client->peerAddress().toString();
qCDebug(dcBluetoothServer()) << "New client connected:" << client->peerName() << client->peerAddress().toString();
QUuid clientId = QUuid::createUuid();
m_clientList.insert(clientId, client);
@ -126,7 +126,7 @@ void BluetoothServer::onClientDisconnected()
if (!client)
return;
qCDebug(dcConnection()) << "BluetoothServer: Client disconnected:" << client->peerName() << client->peerAddress().toString();
qCDebug(dcBluetoothServer()) << "Client disconnected:" << client->peerName() << client->peerAddress().toString();
QUuid clientId = m_clientList.key(client);
m_clientList.take(clientId)->deleteLater();
emit clientDisconnected(clientId);
@ -182,8 +182,6 @@ bool BluetoothServer::startServer()
return false;
}
qCDebug(dcBluetoothServer()) << "Started bluetooth server" << m_server->serverAddress().toString();
// Set service attributes
QBluetoothServiceInfo::Sequence browseSequence;
browseSequence << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::PublicBrowseGroup));
@ -221,8 +219,7 @@ bool BluetoothServer::startServer()
m_server = nullptr;
return false;
}
qCDebug(dcBluetoothServer()) << "Registered successfully service" << m_serviceInfo.serviceName() << nymeaServiceUuid.toString();
qCDebug(dcConnection()) << "Started bluetooth server" << m_localDevice->name() << m_localDevice->address().toString() << "Serivce:" << m_serviceInfo.serviceName() << nymeaServiceUuid.toString();
qCDebug(dcBluetoothServer()) << "Started bluetooth server" << m_localDevice->name() << m_localDevice->address().toString() << "Serivce:" << m_serviceInfo.serviceName() << nymeaServiceUuid.toString();
return true;
}

View File

@ -127,16 +127,16 @@ void TcpServer::sendData(const QUuid &clientId, const QByteArray &data)
void TcpServer::onClientConnected(QSslSocket *socket)
{
qCDebug(dcConnection) << "Tcp server: new client connected:" << socket->peerAddress().toString();
QUuid clientId = QUuid::createUuid();
qCDebug(dcTcpServer()) << "New client connected:" << clientId.toString() << "(Remote address:" << socket->peerAddress().toString() << ")";
m_clientList.insert(clientId, socket);
emit clientConnected(clientId);
}
void TcpServer::onClientDisconnected(QSslSocket *socket)
{
qCDebug(dcConnection) << "Tcp server: client disconnected:" << socket->peerAddress().toString();
QUuid clientId = m_clientList.key(socket);
qCDebug(dcTcpServer()) << "Client disconnected:" << clientId.toString() << "(Remote address:" << socket->peerAddress().toString() << ")";
m_clientList.take(clientId);
emit clientDisconnected(clientId);
}
@ -144,15 +144,10 @@ void TcpServer::onClientDisconnected(QSslSocket *socket)
void TcpServer::onError(QAbstractSocket::SocketError error)
{
QTcpServer *server = qobject_cast<QTcpServer *>(sender());
qCWarning(dcTcpServer) << server->serverAddress().toString() << "error:" << error << server->errorString();
qCWarning(dcTcpServer) << "Server error on" << server->serverAddress().toString() << ":" << error << server->errorString();
stopServer();
}
void TcpServer::onEncrypted()
{
qCDebug(dcTcpServer) << "TCP Server connection encrypted";
}
void TcpServer::onDataAvailable(QSslSocket * socket, const QByteArray &data)
{
qCDebug(dcTcpServerTraffic()) << "Emitting data available";
@ -214,7 +209,7 @@ bool TcpServer::startServer()
{
m_server = new SslServer(configuration().sslEnabled, m_sslConfig);
if(!m_server->listen(configuration().address, static_cast<quint16>(configuration().port))) {
qCWarning(dcConnection) << "Tcp server error: can not listen on" << configuration().address.toString() << configuration().port;
qCWarning(dcTcpServer()) << "Tcp server error: can not listen on" << configuration().address.toString() << configuration().port;
delete m_server;
m_server = nullptr;
return false;
@ -224,7 +219,7 @@ bool TcpServer::startServer()
connect(m_server, SIGNAL(clientDisconnected(QSslSocket *)), SLOT(onClientDisconnected(QSslSocket *)));
connect(m_server, &SslServer::dataAvailable, this, &TcpServer::onDataAvailable);
qCDebug(dcConnection) << "Started Tcp server" << serverUrl().toString();
qCDebug(dcTcpServer()) << "Started Tcp server" << serverUrl().toString();
resetAvahiService();
return true;
@ -260,7 +255,7 @@ void SslServer::incomingConnection(qintptr socketDescriptor)
connect(sslSocket, &QSslSocket::disconnected, this, &SslServer::onClientDisconnected);
if (!sslSocket->setSocketDescriptor(socketDescriptor)) {
qCWarning(dcConnection) << "Failed to set SSL socket descriptor.";
qCWarning(dcTcpServer()) << "Failed to set SSL socket descriptor.";
delete sslSocket;
return;
}

View File

@ -96,7 +96,6 @@ private slots:
void onClientDisconnected(QSslSocket *socket);
void onDataAvailable(QSslSocket *socket, const QByteArray &data);
void onError(QAbstractSocket::SocketError error);
void onEncrypted();
void onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state);
void resetAvahiService();

View File

@ -614,7 +614,7 @@ bool WebServer::startServer()
return false;
}
qCDebug(dcConnection()) << "Started web server on" << serverUrl().toString();
qCDebug(dcWebServer()) << "Started web server on" << serverUrl().toString();
resetAvahiService();
m_enabled = true;

View File

@ -145,7 +145,7 @@ void WebSocketServer::onClientConnected()
QUuid clientId = QUuid::createUuid();
qCDebug(dcConnection) << "Websocket server: new client connected:" << client->peerAddress().toString() << clientId;
qCDebug(dcWebSocketServer()) << "New client connected:" << clientId.toString() << "(Remote address:" << client->peerAddress().toString() << ")";
// append the new client to the client list
m_clientList.insert(clientId, client);
@ -163,7 +163,7 @@ void WebSocketServer::onClientDisconnected()
{
QWebSocket *client = qobject_cast<QWebSocket *>(sender());
QUuid clientId = m_clientList.key(client);
qCDebug(dcConnection) << "Websocket server: client disconnected:" << client->peerAddress().toString() << clientId;
qCDebug(dcWebSocketServer()) << "Client" << clientId.toString() << "disconnected. (Remote address:" << client->peerAddress().toString() << ")" ;
m_clientList.take(clientId)->deleteLater();
emit clientDisconnected(clientId);
}
@ -171,31 +171,35 @@ void WebSocketServer::onClientDisconnected()
void WebSocketServer::onBinaryMessageReceived(const QByteArray &data)
{
QWebSocket *client = qobject_cast<QWebSocket *>(sender());
qCDebug(dcWebSocketServerTraffic()) << "Binary message from" << client->peerAddress().toString() << ":" << data;
QUuid clientId = m_clientList.key(client);
qCDebug(dcWebSocketServerTraffic()) << "Binary message from" << clientId.toString() << ":" << data;
}
void WebSocketServer::onTextMessageReceived(const QString &message)
{
QWebSocket *client = qobject_cast<QWebSocket *>(sender());
qCDebug(dcWebSocketServerTraffic()) << "Text message from" << client->peerAddress().toString() << ":" << message;
emit dataAvailable(m_clientList.key(client), message.toUtf8());
QUuid clientId = m_clientList.key(client);
qCDebug(dcWebSocketServerTraffic()) << "Text message from" << clientId.toString() << ":" << message;
emit dataAvailable(clientId, message.toUtf8());
}
void WebSocketServer::onClientError(QAbstractSocket::SocketError error)
{
QWebSocket *client = qobject_cast<QWebSocket *>(sender());
qCWarning(dcConnection) << "Websocket client error:" << error << client->errorString();
QUuid clientId = m_clientList.key(client);
qCWarning(dcWebSocketServer()) << "Client error from" << clientId.toString() << ":" << error << client->errorString();
}
void WebSocketServer::onServerError(QAbstractSocket::SocketError error)
{
qCWarning(dcConnection) << "Websocket server error:" << error << m_server->errorString();
qCWarning(dcWebSocketServer()) << "Server error " << error << m_server->errorString();
}
void WebSocketServer::onPing(quint64 elapsedTime, const QByteArray &payload)
{
QWebSocket *client = qobject_cast<QWebSocket *>(sender());
qCDebug(dcWebSocketServer) << "ping response" << client->peerAddress() << elapsedTime << payload;
QUuid clientId = m_clientList.key(client);
qCDebug(dcWebSocketServer) << "Ping response from" << clientId.toString() << elapsedTime << payload;
}
void WebSocketServer::onAvahiServiceStateChanged(const QtAvahiService::QtAvahiServiceState &state)
@ -210,7 +214,7 @@ void WebSocketServer::resetAvahiService()
m_avahiService->resetService();
if (!m_avahiService->registerService(QString("nymea-ws-%1").arg(configuration().id), configuration().address, static_cast<quint16>(configuration().port), "_ws._tcp", createTxtRecord())) {
qCWarning(dcWebServer()) << "Could not register avahi service for" << configuration();
qCWarning(dcWebSocketServer()) << "Could not register avahi service for" << configuration();
}
}
@ -255,11 +259,11 @@ bool WebSocketServer::startServer()
connect (m_server, &QWebSocketServer::acceptError, this, &WebSocketServer::onServerError);
if (!m_server->listen(configuration().address, static_cast<quint16>(configuration().port))) {
qCWarning(dcConnection) << "Websocket server" << m_server->serverName() << "could not listen on" << serverUrl().toString();
qCWarning(dcWebSocketServer()) << "Error listening on" << serverUrl().toString();
return false;
}
qCDebug(dcConnection()) << "Started websocket server" << m_server->serverName() << "on" << serverUrl().toString();
qCDebug(dcWebSocketServer()) << "Server started on" << serverUrl().toString();
resetAvahiService();
return true;
}

View File

@ -28,8 +28,8 @@ Q_LOGGING_CATEGORY(dcTimeManager, "TimeManager")
Q_LOGGING_CATEGORY(dcRuleEngine, "RuleEngine")
Q_LOGGING_CATEGORY(dcRuleEngineDebug, "RuleEngineDebug")
Q_LOGGING_CATEGORY(dcHardware, "Hardware")
Q_LOGGING_CATEGORY(dcConnection, "Connection")
Q_LOGGING_CATEGORY(dcLogEngine, "LogEngine")
Q_LOGGING_CATEGORY(dcServerManager, "ServerManager")
Q_LOGGING_CATEGORY(dcTcpServer, "TcpServer")
Q_LOGGING_CATEGORY(dcTcpServerTraffic, "TcpServerTraffic")
Q_LOGGING_CATEGORY(dcWebServer, "WebServer")

View File

@ -36,8 +36,8 @@ Q_DECLARE_LOGGING_CATEGORY(dcTimeManager)
Q_DECLARE_LOGGING_CATEGORY(dcRuleEngine)
Q_DECLARE_LOGGING_CATEGORY(dcRuleEngineDebug)
Q_DECLARE_LOGGING_CATEGORY(dcHardware)
Q_DECLARE_LOGGING_CATEGORY(dcConnection)
Q_DECLARE_LOGGING_CATEGORY(dcLogEngine)
Q_DECLARE_LOGGING_CATEGORY(dcServerManager)
Q_DECLARE_LOGGING_CATEGORY(dcTcpServer)
Q_DECLARE_LOGGING_CATEGORY(dcTcpServerTraffic)
Q_DECLARE_LOGGING_CATEGORY(dcWebServer)

View File

@ -106,8 +106,8 @@ int main(int argc, char *argv[])
"RuleEngineDebug",
"Hardware",
"Bluetooth",
"Connection",
"LogEngine",
"ServerManager",
"TcpServer",
"TcpServerTraffic",
"WebServer",