diff --git a/libnymea-core/cloud/awsconnector.cpp b/libnymea-core/cloud/awsconnector.cpp index 2cf57742..0f9be5db 100644 --- a/libnymea-core/cloud/awsconnector.cpp +++ b/libnymea-core/cloud/awsconnector.cpp @@ -50,6 +50,17 @@ AWSConnector::AWSConnector(QObject *parent) : QObject(parent) m_reconnectTimer.setSingleShot(true); connect(&m_reconnectTimer, &QTimer::timeout, this, &AWSConnector::doConnect); + + // In rare circumstances (I've observed this when the wifi driver panics) it happens that a connection + // attempt never completes but also doesn't emit any error (bug in Qt?). To catch that, manually call the + // disconnected slot to trigger reconnecting. + m_connectTimer.setSingleShot(true); + connect(&m_connectTimer, &QTimer::timeout, this, [this](){ + if (m_client && !m_client->isConnected()) { + qCWarning(dcAWS()) << "Connection guard timer timed out! Resetting connection."; + onDisconnected(); + } + }); } AWSConnector::~AWSConnector() @@ -63,6 +74,14 @@ AWSConnector::~AWSConnector() void AWSConnector::connect2AWS(const QString &endpoint, const QString &clientId, const QString &clientName, const QString &caFile, const QString &clientCertFile, const QString &clientPrivKeyFile) { + if (m_client) { + qCDebug(dcAWS()) << "Cleaning up old connection"; + m_shouldReconnect = false; + m_client->disconnectFromHost(); + // Don't rely on the graceful disconnect to actually happen... Force cleanup of the old connection + onDisconnected(); + } + m_shouldReconnect = true; m_currentEndpoint = endpoint; m_caFile = caFile; @@ -71,12 +90,6 @@ void AWSConnector::connect2AWS(const QString &endpoint, const QString &clientId, m_clientId = clientId; m_clientName = clientName; - if (m_client) { - m_client->disconnectFromHost(); - qCDebug(dcAWS()) << "Disconnecting from AWS"; - return; - } - doConnect(); } @@ -121,6 +134,7 @@ void AWSConnector::doConnect() connect(m_client, &MqttClient::connected, this, &AWSConnector::onConnected); connect(m_client, &MqttClient::disconnected, this, &AWSConnector::onDisconnected); connect(m_client, &MqttClient::error, this, [this](const QAbstractSocket::SocketError error){ + m_connectTimer.stop(); qCWarning(dcAWS()) << "An error happened in the MQTT transport" << error; // In order to also call onDisconnected (and start the reconnect timer) even when we have never been connected // we'll call it here. However, that might cause onDisconnected to be called twice. Let's prevent that. @@ -131,10 +145,15 @@ void AWSConnector::doConnect() connect(m_client, &MqttClient::subscribed, this, &AWSConnector::onSubscribed); connect(m_client, &MqttClient::publishReceived, this, &AWSConnector::onPublishReceived); connect(m_client, &MqttClient::published, this, &AWSConnector::onPublished); + + // If none of the above slots are called within a minute, reset ourselves... + m_connectTimer.start(60000); } void AWSConnector::onConnected() { + m_connectTimer.stop(); + if (!readRegisteredFlag()) { qCDebug(dcAWS()) << "AWS connected. Device not registered yet. Registering..."; registerDevice(); @@ -286,6 +305,8 @@ quint16 AWSConnector::publish(const QString &topic, const QVariantMap &message) void AWSConnector::onDisconnected() { + m_connectTimer.stop(); + qCDebug(dcAWS) << "AWS disconnected."; m_client->deleteLater(); m_client = nullptr; diff --git a/libnymea-core/cloud/awsconnector.h b/libnymea-core/cloud/awsconnector.h index 7c9c6fc2..6ab1c6c6 100644 --- a/libnymea-core/cloud/awsconnector.h +++ b/libnymea-core/cloud/awsconnector.h @@ -113,6 +113,7 @@ private: bool m_isCleanSession = true; bool m_shouldReconnect = false; QTimer m_reconnectTimer; + QTimer m_connectTimer; quint8 m_transactionId = 0; QString m_createDeviceId;