[AFV] Ref T730, use callbacks for "connectTo", avoid EventLoop

* this is a pure asynchronous concept
* callbacks are called when network request "is done"
This commit is contained in:
Klaus Basan
2019-10-15 00:07:53 +02:00
parent 218c099456
commit a334b97ac6
5 changed files with 73 additions and 44 deletions

View File

@@ -132,18 +132,21 @@ namespace BlackCore
this->connectWithContexts(); this->connectWithContexts();
this->setCallsign(callsign); this->setCallsign(callsign);
QVector<StationDto> aliasedStations;
// thread safe connect // thread safe connect
{ {
// QMutexLocker lock(&m_mutexConnection); QMutexLocker lock(&m_mutexConnection);
m_connection->connectTo(cid, password, callsign);
aliasedStations = m_connection->getAllAliasedStations(); // async connection
} m_connection->connectTo(cid, password, callsign, { this, [ = ](bool authenticated)
{
// this is the callback when the connection has been established
const QVector<StationDto> aliasedStations = m_connection->getAllAliasedStations();
this->setAliasedStations(aliasedStations); // threadsafe this->setAliasedStations(aliasedStations); // threadsafe
this->onTimerUpdate(); this->onTimerUpdate();
const bool isConnected = this->isConnected(); // threadsafe // const bool isConnected = this->isConnected(); // threadsafe
if (isConnected) if (authenticated)
{ {
// restart timer, normally it should be started already, paranoia // restart timer, normally it should be started already, paranoia
// as I run in "my thread" starting timer should be OK // as I run in "my thread" starting timer should be OK
@@ -158,6 +161,9 @@ namespace BlackCore
emit this->connectionStatusChanged(Disconnected); emit this->connectionStatusChanged(Disconnected);
} }
} }
});
}
}
void CAfvClient::disconnectFrom() void CAfvClient::disconnectFrom()
{ {

View File

@@ -43,9 +43,9 @@ namespace BlackCore
CLogMessage(this).debug(u"ApiServerConnection instantiated"); 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_username = username;
m_password = password; m_password = password;
@@ -62,8 +62,8 @@ namespace BlackCore
{"networkversion", networkVersion.toString()}, {"networkversion", networkVersion.toString()},
}; };
QPointer<QEventLoop> loop(this->newEventLoop());
QNetworkRequest request(url); QNetworkRequest request(url);
QPointer<CApiServerConnection> myself(this);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
// posted in QAM thread, reply is nullptr if called from another thread // posted in QAM thread, reply is nullptr if called from another thread
@@ -73,13 +73,13 @@ namespace BlackCore
{ {
// called in "this" thread // called in "this" thread
const QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(nwReply); const QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(nwReply);
if (!loop || isShuttingDown()) { return; } if (!myself || isShuttingDown()) { return; }
this->logRequestDuration(reply.data(), "authentication"); this->logRequestDuration(reply.data(), "authentication");
if (reply->error() != QNetworkReply::NoError) if (reply->error() != QNetworkReply::NoError)
{ {
this->logReplyErrorMessage(reply.data(), "authentication error"); this->logReplyErrorMessage(reply.data(), "authentication error");
if (loop) { loop->exit(); } callback(false);
return; return;
} }
@@ -117,13 +117,11 @@ namespace BlackCore
m_isAuthenticated = true; m_isAuthenticated = true;
} }
if (loop) { loop->exit(); } // connected, callback
callback(m_isAuthenticated);
} }
}); });
Q_UNUSED(reply) Q_UNUSED(reply)
if (loop) { loop->exec(); }
return m_isAuthenticated;
} }
PostCallsignResponseDto CApiServerConnection::addCallsign(const QString &callsign) PostCallsignResponseDto CApiServerConnection::addCallsign(const QString &callsign)
@@ -297,7 +295,7 @@ namespace BlackCore
{ {
if (QDateTime::currentDateTimeUtc() > m_expiryLocalUtc.addSecs(-5 * 60)) 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) {}});
} }
} }

View File

@@ -13,6 +13,7 @@
#include "blackcore/afv/dto.h" #include "blackcore/afv/dto.h"
#include "blackcore/application.h" #include "blackcore/application.h"
#include "blackmisc/slot.h"
#include "blackmisc/logmessage.h" #include "blackmisc/logmessage.h"
#include "blackmisc/logcategorylist.h" #include "blackmisc/logcategorylist.h"
@@ -33,6 +34,9 @@ namespace BlackCore
{ {
namespace Connection namespace Connection
{ {
//! Callback for
using ConnectionCallback = BlackMisc::CSlot<void(bool)>;
//! A server connection //! A server connection
class CApiServerConnection : public QObject class CApiServerConnection : public QObject
{ {
@@ -55,7 +59,8 @@ namespace BlackCore
bool isAuthenticated() const { return m_isAuthenticated; } bool isAuthenticated() const { return m_isAuthenticated; }
//! Connect to network //! 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 //! Add callsign to network
PostCallsignResponseDto addCallsign(const QString &callsign); PostCallsignResponseDto addCallsign(const QString &callsign);
@@ -121,8 +126,8 @@ namespace BlackCore
QVector<TResponse> dtos; QVector<TResponse> dtos;
if (jsonDoc.isArray()) if (jsonDoc.isArray())
{ {
QJsonArray rootArray = jsonDoc.array(); const QJsonArray rootArray = jsonDoc.array();
for (auto o : rootArray) for (const auto &o : rootArray)
{ {
const QJsonObject d = o.toObject(); const QJsonObject d = o.toObject();
const TResponse dto = TResponse::fromJson(d); const TResponse dto = TResponse::fromJson(d);

View File

@@ -37,7 +37,7 @@ namespace BlackCore
connect(m_udpSocket, qOverload<QAbstractSocket::SocketError>(&QUdpSocket::error), this, &CClientConnection::handleSocketError); connect(m_udpSocket, qOverload<QAbstractSocket::SocketError>(&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()) if (m_connection.isConnected())
{ {
@@ -47,20 +47,35 @@ namespace BlackCore
m_connection.setUserName(userName); m_connection.setUserName(userName);
m_connection.setCallsign(callsign); m_connection.setCallsign(callsign);
bool result = m_apiServerConnection->connectTo(userName, password, m_networkVersion);
if (!result) { return; } QPointer<CClientConnection> myself(this);
m_connection.setTokens(m_apiServerConnection->addCallsign(m_connection.getCallsign())); 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);
if (authenticated)
{
const QString callsign = m_connection.getCallsign();
m_connection.setTokens(m_apiServerConnection->addCallsign(callsign));
m_connection.setTsAuthenticatedToNow(); m_connection.setTsAuthenticatedToNow();
m_connection.createCryptoChannels(); m_connection.createCryptoChannels();
this->connectToVoiceServer();
connectToVoiceServer();
// taskServerConnectionCheck.Start(); // 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) void CClientConnection::disconnectFrom(const QString &reason)
{ {
if (!m_connection.isConnected()) if (!m_connection.isConnected())

View File

@@ -44,9 +44,14 @@ namespace BlackCore
//! Ctor //! Ctor
CClientConnection(const QString &apiServer, QObject *parent = nullptr); CClientConnection(const QString &apiServer, QObject *parent = nullptr);
//! Connect/disconnect @{ //! Connect
void connectTo(const QString &userName, const QString &password, const QString &callsign); //! \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 = {}); void disconnectFrom(const QString &reason = {});
//! Is connected
bool isConnected() const { return m_connection.isConnected(); } bool isConnected() const { return m_connection.isConnected(); }
//! @} //! @}