Fix a crash when a delayed reply would call a callback for an object that disappeared
This commit is contained in:
parent
4e11026ea4
commit
0eadb8dcd3
@ -8,6 +8,7 @@
|
|||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
#include "sigv4utils.h"
|
#include "sigv4utils.h"
|
||||||
|
|
||||||
@ -820,7 +821,7 @@ void AWSClient::getCredentialsForIdentity(const QString &identityId)
|
|||||||
if (qc.method == "fetchDevices") {
|
if (qc.method == "fetchDevices") {
|
||||||
fetchDevices();
|
fetchDevices();
|
||||||
} else if (qc.method == "postToMQTT") {
|
} else if (qc.method == "postToMQTT") {
|
||||||
postToMQTT(qc.arg1, qc.arg2, qc.callback);
|
postToMQTT(qc.arg1, qc.arg2, qc.sender, qc.callback);
|
||||||
} else if (qc.method == "deleteAccount") {
|
} else if (qc.method == "deleteAccount") {
|
||||||
deleteAccount();
|
deleteAccount();
|
||||||
} else if (qc.method == "registerPushNotificationEndpoint") {
|
} else if (qc.method == "registerPushNotificationEndpoint") {
|
||||||
@ -837,7 +838,7 @@ bool AWSClient::tokensExpired() const
|
|||||||
return (m_accessTokenExpiry.addSecs(-10) < QDateTime::currentDateTime()) || (m_sessionTokenExpiry.addSecs(-10) < QDateTime::currentDateTime());
|
return (m_accessTokenExpiry.addSecs(-10) < QDateTime::currentDateTime()) || (m_sessionTokenExpiry.addSecs(-10) < QDateTime::currentDateTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AWSClient::postToMQTT(const QString &boxId, const QString ×tamp, std::function<void(bool)> callback)
|
bool AWSClient::postToMQTT(const QString &boxId, const QString ×tamp, QObject* sender, std::function<void (bool)> callback)
|
||||||
{
|
{
|
||||||
if (!isLoggedIn()) {
|
if (!isLoggedIn()) {
|
||||||
qWarning() << "Cannot post to MQTT. Not logged in to AWS";
|
qWarning() << "Cannot post to MQTT. Not logged in to AWS";
|
||||||
@ -846,11 +847,13 @@ bool AWSClient::postToMQTT(const QString &boxId, const QString ×tamp, std::
|
|||||||
if (tokensExpired()) {
|
if (tokensExpired()) {
|
||||||
qDebug() << "Cannot post to MQTT. Need to refresh the tokens first";
|
qDebug() << "Cannot post to MQTT. Need to refresh the tokens first";
|
||||||
refreshAccessToken();
|
refreshAccessToken();
|
||||||
QueuedCall::enqueue(m_callQueue, QueuedCall("postToMQTT", boxId, timestamp, callback));
|
QueuedCall::enqueue(m_callQueue, QueuedCall("postToMQTT", boxId, timestamp, sender, callback));
|
||||||
return true; // So far it looks we're doing ok... let's return true
|
return true; // So far it looks we're doing ok... let's return true
|
||||||
}
|
}
|
||||||
QString topic = QString("%1/%2/proxy").arg(boxId).arg(QString(m_identityId));
|
QString topic = QString("%1/%2/proxy").arg(boxId).arg(QString(m_identityId));
|
||||||
|
|
||||||
|
QPointer<QObject> senderWatcher = QPointer<QObject>(sender);
|
||||||
|
|
||||||
// This is somehow broken in AWS...
|
// This is somehow broken in AWS...
|
||||||
// The Signature needs to be created with having the topic percentage-encoded twice
|
// The Signature needs to be created with having the topic percentage-encoded twice
|
||||||
// while the actual request needs to go out with it only being encoded once.
|
// while the actual request needs to go out with it only being encoded once.
|
||||||
@ -882,15 +885,21 @@ bool AWSClient::postToMQTT(const QString &boxId, const QString ×tamp, std::
|
|||||||
// }
|
// }
|
||||||
// qDebug() << "Payload:" << payload;
|
// qDebug() << "Payload:" << payload;
|
||||||
QNetworkReply *reply = m_nam->post(request, payload);
|
QNetworkReply *reply = m_nam->post(request, payload);
|
||||||
QTimer::singleShot(5000, reply, [reply, callback](){
|
QTimer::singleShot(5000, reply, [reply, senderWatcher, callback](){
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
qWarning() << "Timeout posting to MQTT";
|
qWarning() << "Timeout posting to MQTT";
|
||||||
callback(false);
|
if (senderWatcher) {
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
connect(reply, &QNetworkReply::finished, this, [reply, callback]() {
|
connect(reply, &QNetworkReply::finished, this, [reply, senderWatcher, callback]() {
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
QByteArray data = reply->readAll();
|
QByteArray data = reply->readAll();
|
||||||
// qDebug() << "MQTT post reply" << data;
|
// qDebug() << "MQTT post reply" << data;
|
||||||
|
if (senderWatcher.isNull()) {
|
||||||
|
qDebug() << "Request object disappeared. Discarding MQTT reply...";
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (reply->error() != QNetworkReply::NoError) {
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
qWarning() << "MQTT Network reply error" << reply->error() << reply->errorString();
|
qWarning() << "MQTT Network reply error" << reply->error() << reply->errorString();
|
||||||
callback(false);
|
callback(false);
|
||||||
@ -909,7 +918,6 @@ bool AWSClient::postToMQTT(const QString &boxId, const QString ×tamp, std::
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
callback(true);
|
callback(true);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QDate>
|
#include <QDate>
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
class QNetworkAccessManager;
|
class QNetworkAccessManager;
|
||||||
|
|
||||||
@ -117,7 +118,7 @@ public:
|
|||||||
|
|
||||||
Q_INVOKABLE void fetchDevices();
|
Q_INVOKABLE void fetchDevices();
|
||||||
|
|
||||||
Q_INVOKABLE bool postToMQTT(const QString &boxId, const QString ×tamp, std::function<void(bool)> callback);
|
Q_INVOKABLE bool postToMQTT(const QString &boxId, const QString ×tamp, QObject* sender, std::function<void(bool)> callback);
|
||||||
Q_INVOKABLE void getId();
|
Q_INVOKABLE void getId();
|
||||||
|
|
||||||
Q_INVOKABLE void registerPushNotificationEndpoint(const QString ®istrationId, const QString &deviceDisplayName, const QString mobileDeviceId, const QString &mobileDeviceManufacturer, const QString &mobileDeviceModel);
|
Q_INVOKABLE void registerPushNotificationEndpoint(const QString ®istrationId, const QString &deviceDisplayName, const QString mobileDeviceId, const QString &mobileDeviceManufacturer, const QString &mobileDeviceModel);
|
||||||
@ -184,13 +185,14 @@ private:
|
|||||||
QueuedCall(const QString &method): method(method) { }
|
QueuedCall(const QString &method): method(method) { }
|
||||||
QueuedCall(const QString &method, const QString &arg1): method(method), arg1(arg1) { }
|
QueuedCall(const QString &method, const QString &arg1): method(method), arg1(arg1) { }
|
||||||
QueuedCall(const QString &method, const QString &arg1, const QString &arg2, const QString &arg3, const QString &arg4, const QString &arg5): method(method), arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5) { }
|
QueuedCall(const QString &method, const QString &arg1, const QString &arg2, const QString &arg3, const QString &arg4, const QString &arg5): method(method), arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5) { }
|
||||||
QueuedCall(const QString &method, const QString &arg1, const QString &arg2, std::function<void(bool)> callback): method(method), arg1(arg1), arg2(arg2), callback(callback) {}
|
QueuedCall(const QString &method, const QString &arg1, const QString &arg2, QObject* sender, std::function<void(bool)> callback): method(method), arg1(arg1), arg2(arg2), sender(sender), callback(callback) {}
|
||||||
QString method;
|
QString method;
|
||||||
QString arg1;
|
QString arg1;
|
||||||
QString arg2;
|
QString arg2;
|
||||||
QString arg3;
|
QString arg3;
|
||||||
QString arg4;
|
QString arg4;
|
||||||
QString arg5;
|
QString arg5;
|
||||||
|
QPointer<QObject> sender;
|
||||||
std::function<void(bool)> callback;
|
std::function<void(bool)> callback;
|
||||||
|
|
||||||
static void enqueue(QList<QueuedCall> &queue, const QueuedCall &call) {
|
static void enqueue(QList<QueuedCall> &queue, const QueuedCall &call) {
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
#include <QHostInfo>
|
#include <QHostInfo>
|
||||||
|
#include <QPointer>
|
||||||
|
|
||||||
using namespace remoteproxyclient;
|
using namespace remoteproxyclient;
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ bool CloudTransport::connect(const QUrl &url)
|
|||||||
m_url = url;
|
m_url = url;
|
||||||
|
|
||||||
m_timestamp = QDateTime::currentDateTime();
|
m_timestamp = QDateTime::currentDateTime();
|
||||||
bool postResult = m_awsClient->postToMQTT(url.host(), QString::number(m_timestamp.toMSecsSinceEpoch()), [this](bool success) {
|
bool postResult = m_awsClient->postToMQTT(url.host(), QString::number(m_timestamp.toMSecsSinceEpoch()), QPointer<QObject>(this), [this](bool success) {
|
||||||
if (success) {
|
if (success) {
|
||||||
qDebug() << "MQTT Post done. Connecting to remote proxy";
|
qDebug() << "MQTT Post done. Connecting to remote proxy";
|
||||||
m_remoteproxyConnection->connectServer(QUrl("wss://remoteproxy.nymea.io"));
|
m_remoteproxyConnection->connectServer(QUrl("wss://remoteproxy.nymea.io"));
|
||||||
|
|||||||
Reference in New Issue
Block a user