From a334b97ac605fdb65c1bb8ba1b166f9bc81a0454 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Tue, 15 Oct 2019 00:07:53 +0200 Subject: [PATCH] [AFV] Ref T730, use callbacks for "connectTo", avoid EventLoop * this is a pure asynchronous concept * callbacks are called when network request "is done" --- src/blackcore/afv/clients/afvclient.cpp | 44 +++++++++++-------- .../afv/connection/apiserverconnection.cpp | 18 ++++---- .../afv/connection/apiserverconnection.h | 11 +++-- .../afv/connection/clientconnection.cpp | 35 ++++++++++----- .../afv/connection/clientconnection.h | 9 +++- 5 files changed, 73 insertions(+), 44 deletions(-) diff --git a/src/blackcore/afv/clients/afvclient.cpp b/src/blackcore/afv/clients/afvclient.cpp index d1707522f..76b24e707 100644 --- a/src/blackcore/afv/clients/afvclient.cpp +++ b/src/blackcore/afv/clients/afvclient.cpp @@ -132,30 +132,36 @@ namespace BlackCore this->connectWithContexts(); this->setCallsign(callsign); - QVector aliasedStations; // thread safe connect { - // QMutexLocker lock(&m_mutexConnection); - m_connection->connectTo(cid, password, callsign); - aliasedStations = m_connection->getAllAliasedStations(); - } - this->setAliasedStations(aliasedStations); // threadsafe - this->onTimerUpdate(); + QMutexLocker lock(&m_mutexConnection); - const bool isConnected = this->isConnected(); // threadsafe - if (isConnected) - { - // restart timer, normally it should be started already, paranoia - // as I run in "my thread" starting timer should be OK + // async connection + m_connection->connectTo(cid, password, callsign, { this, [ = ](bool authenticated) { - QMutexLocker lock(&m_mutex); - if (m_voiceServerTimer) { m_voiceServerTimer->start(PositionUpdatesMs); } + // this is the callback when the connection has been established + + const QVector aliasedStations = m_connection->getAllAliasedStations(); + this->setAliasedStations(aliasedStations); // threadsafe + this->onTimerUpdate(); + + // const bool isConnected = this->isConnected(); // threadsafe + if (authenticated) + { + // restart timer, normally it should be started already, paranoia + // as I run in "my thread" starting timer should be OK + { + QMutexLocker lock(&m_mutex); + if (m_voiceServerTimer) { m_voiceServerTimer->start(PositionUpdatesMs); } + } + emit this->connectionStatusChanged(Connected); + } + else + { + emit this->connectionStatusChanged(Disconnected); + } } - emit this->connectionStatusChanged(Connected); - } - else - { - emit this->connectionStatusChanged(Disconnected); + }); } } diff --git a/src/blackcore/afv/connection/apiserverconnection.cpp b/src/blackcore/afv/connection/apiserverconnection.cpp index b9128b838..b5db29178 100644 --- a/src/blackcore/afv/connection/apiserverconnection.cpp +++ b/src/blackcore/afv/connection/apiserverconnection.cpp @@ -43,9 +43,9 @@ namespace BlackCore CLogMessage(this).debug(u"ApiServerConnection instantiated"); } - bool CApiServerConnection::connectTo(const QString &username, const QString &password, const QUuid &networkVersion) + void CApiServerConnection::connectTo(const QString &username, const QString &password, const QUuid &networkVersion, ConnectionCallback callback) { - if (isShuttingDown()) { return false; } + if (isShuttingDown()) { return; } m_username = username; m_password = password; @@ -62,8 +62,8 @@ namespace BlackCore {"networkversion", networkVersion.toString()}, }; - QPointer loop(this->newEventLoop()); QNetworkRequest request(url); + QPointer myself(this); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); // posted in QAM thread, reply is nullptr if called from another thread @@ -73,13 +73,13 @@ namespace BlackCore { // called in "this" thread const QScopedPointer reply(nwReply); - if (!loop || isShuttingDown()) { return; } + if (!myself || isShuttingDown()) { return; } this->logRequestDuration(reply.data(), "authentication"); if (reply->error() != QNetworkReply::NoError) { this->logReplyErrorMessage(reply.data(), "authentication error"); - if (loop) { loop->exit(); } + callback(false); return; } @@ -117,13 +117,11 @@ namespace BlackCore m_isAuthenticated = true; } - if (loop) { loop->exit(); } + // connected, callback + callback(m_isAuthenticated); } }); Q_UNUSED(reply) - - if (loop) { loop->exec(); } - return m_isAuthenticated; } PostCallsignResponseDto CApiServerConnection::addCallsign(const QString &callsign) @@ -297,7 +295,7 @@ namespace BlackCore { if (QDateTime::currentDateTimeUtc() > m_expiryLocalUtc.addSecs(-5 * 60)) { - this->connectTo(m_username, m_password, m_networkVersion); + this->connectTo(m_username, m_password, m_networkVersion, { this, [ = ](bool) {}}); } } diff --git a/src/blackcore/afv/connection/apiserverconnection.h b/src/blackcore/afv/connection/apiserverconnection.h index f811ddecc..78451955a 100644 --- a/src/blackcore/afv/connection/apiserverconnection.h +++ b/src/blackcore/afv/connection/apiserverconnection.h @@ -13,6 +13,7 @@ #include "blackcore/afv/dto.h" #include "blackcore/application.h" +#include "blackmisc/slot.h" #include "blackmisc/logmessage.h" #include "blackmisc/logcategorylist.h" @@ -33,6 +34,9 @@ namespace BlackCore { namespace Connection { + //! Callback for + using ConnectionCallback = BlackMisc::CSlot; + //! A server connection class CApiServerConnection : public QObject { @@ -55,7 +59,8 @@ namespace BlackCore bool isAuthenticated() const { return m_isAuthenticated; } //! Connect to network - bool connectTo(const QString &username, const QString &password, const QUuid &networkVersion); + //! \remark ASYNC, calling callback when done + void connectTo(const QString &username, const QString &password, const QUuid &networkVersion, ConnectionCallback callback); //! Add callsign to network PostCallsignResponseDto addCallsign(const QString &callsign); @@ -121,8 +126,8 @@ namespace BlackCore QVector dtos; if (jsonDoc.isArray()) { - QJsonArray rootArray = jsonDoc.array(); - for (auto o : rootArray) + const QJsonArray rootArray = jsonDoc.array(); + for (const auto &o : rootArray) { const QJsonObject d = o.toObject(); const TResponse dto = TResponse::fromJson(d); diff --git a/src/blackcore/afv/connection/clientconnection.cpp b/src/blackcore/afv/connection/clientconnection.cpp index 5d03250c3..ed58d30ea 100644 --- a/src/blackcore/afv/connection/clientconnection.cpp +++ b/src/blackcore/afv/connection/clientconnection.cpp @@ -37,7 +37,7 @@ namespace BlackCore connect(m_udpSocket, qOverload(&QUdpSocket::error), this, &CClientConnection::handleSocketError); } - void CClientConnection::connectTo(const QString &userName, const QString &password, const QString &callsign) + void CClientConnection::connectTo(const QString &userName, const QString &password, const QString &callsign, ConnectionCallback callback) { if (m_connection.isConnected()) { @@ -47,18 +47,33 @@ namespace BlackCore m_connection.setUserName(userName); m_connection.setCallsign(callsign); - bool result = m_apiServerConnection->connectTo(userName, password, m_networkVersion); - if (!result) { return; } - m_connection.setTokens(m_apiServerConnection->addCallsign(m_connection.getCallsign())); - m_connection.setTsAuthenticatedToNow(); - m_connection.createCryptoChannels(); - connectToVoiceServer(); + QPointer myself(this); + m_apiServerConnection->connectTo(userName, password, m_networkVersion, + { + // callback called when connected + this, [ = ](bool authenticated) + { + // callback when connection has been established + if (!myself) { return; } + m_connection.setConnected(authenticated); - // taskServerConnectionCheck.Start(); + if (authenticated) + { + const QString callsign = m_connection.getCallsign(); + m_connection.setTokens(m_apiServerConnection->addCallsign(callsign)); + m_connection.setTsAuthenticatedToNow(); + m_connection.createCryptoChannels(); + this->connectToVoiceServer(); + // taskServerConnectionCheck.Start(); - m_connection.setConnected(true); - CLogMessage(this).debug(u"Connected: '%1'") << callsign; + CLogMessage(this).debug(u"Connected: '%1'") << callsign; + } + + // callback of the calling parent + if (callback) { callback(authenticated); } + } + }); } void CClientConnection::disconnectFrom(const QString &reason) diff --git a/src/blackcore/afv/connection/clientconnection.h b/src/blackcore/afv/connection/clientconnection.h index b1ec8fb7f..b99bdd8da 100644 --- a/src/blackcore/afv/connection/clientconnection.h +++ b/src/blackcore/afv/connection/clientconnection.h @@ -44,9 +44,14 @@ namespace BlackCore //! Ctor CClientConnection(const QString &apiServer, QObject *parent = nullptr); - //! Connect/disconnect @{ - void connectTo(const QString &userName, const QString &password, const QString &callsign); + //! Connect + //! \remark ASYNC, calling callback when done + void connectTo(const QString &userName, const QString &password, const QString &callsign, ConnectionCallback callback); + + //! Disconnect void disconnectFrom(const QString &reason = {}); + + //! Is connected bool isConnected() const { return m_connection.isConnected(); } //! @}