[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,30 +132,36 @@ namespace BlackCore
this->connectWithContexts();
this->setCallsign(callsign);
QVector<StationDto> 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<StationDto> 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);
});
}
}

View File

@@ -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<QEventLoop> loop(this->newEventLoop());
QNetworkRequest request(url);
QPointer<CApiServerConnection> 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<QNetworkReply, QScopedPointerDeleteLater> 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) {}});
}
}

View File

@@ -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<void(bool)>;
//! 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<TResponse> 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);

View File

@@ -37,7 +37,7 @@ namespace BlackCore
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())
{
@@ -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<CClientConnection> 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)

View File

@@ -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(); }
//! @}