diff options
author | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2020-04-15 13:05:16 +0200 |
---|---|---|
committer | Kitsune Ral <Kitsune-Ral@users.sf.net> | 2020-04-15 13:07:06 +0200 |
commit | 753c281f4eb055d684e63472468fd091f2166526 (patch) | |
tree | 5862bd41c592a7330cdbb67adf1632569133e5e9 /lib | |
parent | b27e4e2b75180c920deef1399487228f79882f47 (diff) | |
download | libquotient-753c281f4eb055d684e63472468fd091f2166526.tar.gz libquotient-753c281f4eb055d684e63472468fd091f2166526.zip |
Connection: track resolving and login flows jobs; isUsable()
This is to prevent the jobs from several
resolveServer() / setHomeserver() invocations running in parallel.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/connection.cpp | 98 | ||||
-rw-r--r-- | lib/connection.h | 3 |
2 files changed, 58 insertions, 43 deletions
diff --git a/lib/connection.cpp b/lib/connection.cpp index db61986a..9f4f7082 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -116,6 +116,9 @@ public: QScopedPointer<EncryptionManager> encryptionManager; #endif // Quotient_E2EE_ENABLED + QPointer<GetWellknownJob> resolverJob = nullptr; + QPointer<GetLoginFlowsJob> loginFlowsJob = nullptr; + SyncJob* syncJob = nullptr; bool cacheState = true; @@ -245,6 +248,9 @@ Connection::~Connection() void Connection::resolveServer(const QString& mxid) { + if (isJobRunning(d->resolverJob)) + d->resolverJob->abandon(); + auto maybeBaseUrl = QUrl::fromUserInput(serverPart(mxid)); maybeBaseUrl.setScheme("https"); // Instead of the Qt-default "http" if (maybeBaseUrl.isEmpty() || !maybeBaseUrl.isValid()) { @@ -257,46 +263,43 @@ void Connection::resolveServer(const QString& mxid) qCDebug(MAIN) << "Finding the server" << domain; d->data->setBaseUrl(maybeBaseUrl); // Just enough to check .well-known file - auto getWellKnownJob = callApi<GetWellknownJob>(); - connect(getWellKnownJob, &BaseJob::finished, this, - [this, getWellKnownJob, maybeBaseUrl] { - if (getWellKnownJob->status() != BaseJob::NotFoundError) { - if (getWellKnownJob->status() != BaseJob::Success) { - qCWarning(MAIN) - << "Fetching .well-known file failed, FAIL_PROMPT"; - emit resolveError(tr("Failed resolving the homeserver")); - return; - } - QUrl baseUrl { getWellKnownJob->data().homeserver.baseUrl }; - if (baseUrl.isEmpty()) { - qCWarning(MAIN) << "base_url not provided, FAIL_PROMPT"; - emit resolveError( - tr("The homeserver base URL is not provided")); - return; - } - if (!baseUrl.isValid()) { - qCWarning(MAIN) << "base_url invalid, FAIL_ERROR"; - emit resolveError(tr("The homeserver base URL is invalid")); - return; - } - qCInfo(MAIN) << ".well-known URL for" << maybeBaseUrl.host() - << "is" << baseUrl.toString(); - setHomeserver(baseUrl); - } else { - qCInfo(MAIN) << "No .well-known file, using" << maybeBaseUrl - << "for base URL"; - setHomeserver(maybeBaseUrl); + d->resolverJob = callApi<GetWellknownJob>(); + connect(d->resolverJob, &BaseJob::finished, this, [this, maybeBaseUrl] { + if (d->resolverJob->status() != BaseJob::NotFoundError) { + if (d->resolverJob->status() != BaseJob::Success) { + qCWarning(MAIN) + << "Fetching .well-known file failed, FAIL_PROMPT"; + emit resolveError(tr("Failed resolving the homeserver")); + return; } - - auto getVersionsJob = callApi<GetVersionsJob>(); - connect(getVersionsJob, &BaseJob::success, this, - &Connection::resolved); - connect(getVersionsJob, &BaseJob::failure, this, [this] { - qCWarning(MAIN) << "Homeserver base URL invalid"; - emit resolveError(tr("The homeserver base URL " - "doesn't seem to work")); - }); + QUrl baseUrl { d->resolverJob->data().homeserver.baseUrl }; + if (baseUrl.isEmpty()) { + qCWarning(MAIN) << "base_url not provided, FAIL_PROMPT"; + emit resolveError( + tr("The homeserver base URL is not provided")); + return; + } + if (!baseUrl.isValid()) { + qCWarning(MAIN) << "base_url invalid, FAIL_ERROR"; + emit resolveError(tr("The homeserver base URL is invalid")); + return; + } + qCInfo(MAIN) << ".well-known URL for" << maybeBaseUrl.host() << "is" + << baseUrl.toString(); + setHomeserver(baseUrl); + } else { + qCInfo(MAIN) << "No .well-known file, using" << maybeBaseUrl + << "for base URL"; + setHomeserver(maybeBaseUrl); + } + connect(d->loginFlowsJob, &BaseJob::success, this, + &Connection::resolved); + connect(d->loginFlowsJob, &BaseJob::failure, this, [this] { + qCWarning(MAIN) << "Homeserver base URL sanity check failed"; + emit resolveError( + tr("The homeserver base URL doesn't seem to work")); }); + }); } inline UserIdentifier makeUserIdentifier(const QString& id) @@ -1045,6 +1048,8 @@ QUrl Connection::homeserver() const { return d->data->baseUrl(); } QString Connection::domain() const { return userId().section(':', 1); } +bool Connection::isUsable() const { return !loginFlows().isEmpty(); } + QVector<GetLoginFlowsJob::LoginFlow> Connection::loginFlows() const { return d->loginFlows; @@ -1454,17 +1459,24 @@ QByteArray Connection::generateTxnId() const void Connection::setHomeserver(const QUrl& url) { + if (isJobRunning(d->resolverJob)) + d->resolverJob->abandon(); + d->resolverJob = nullptr; + if (isJobRunning(d->loginFlowsJob)) + d->loginFlowsJob->abandon(); + d->loginFlowsJob = nullptr; + d->loginFlows.clear(); + if (homeserver() != url) { d->data->setBaseUrl(url); - d->loginFlows.clear(); emit homeserverChanged(homeserver()); } // Whenever a homeserver is updated, retrieve available login flows from it - auto* j = callApi<GetLoginFlowsJob>(BackgroundRequest); - connect(j, &BaseJob::finished, this, [this, j] { - if (j->status().good()) - d->loginFlows = j->flows(); + d->loginFlowsJob = callApi<GetLoginFlowsJob>(BackgroundRequest); + connect(d->loginFlowsJob, &BaseJob::finished, this, [this] { + if (d->loginFlowsJob->status().good()) + d->loginFlows = d->loginFlowsJob->flows(); else d->loginFlows.clear(); emit loginFlowsChanged(); diff --git a/lib/connection.h b/lib/connection.h index c908b58b..7998afa8 100644 --- a/lib/connection.h +++ b/lib/connection.h @@ -142,6 +142,7 @@ class Connection : public QObject { Q_PROPERTY(QUrl homeserver READ homeserver WRITE setHomeserver NOTIFY homeserverChanged) Q_PROPERTY(QString domain READ domain NOTIFY homeserverChanged) Q_PROPERTY(QVector<GetLoginFlowsJob::LoginFlow> loginFlows READ loginFlows NOTIFY loginFlowsChanged) + Q_PROPERTY(bool isUsable READ isUsable NOTIFY loginFlowsChanged) Q_PROPERTY(bool supportsSso READ supportsSso NOTIFY loginFlowsChanged) Q_PROPERTY(bool supportsPasswordAuth READ supportsPasswordAuth NOTIFY loginFlowsChanged) Q_PROPERTY(bool cacheState READ cacheState WRITE setCacheState NOTIFY cacheStateChanged) @@ -306,6 +307,8 @@ public: QUrl homeserver() const; /** Get the domain name used for ids/aliases on the server */ QString domain() const; + /** Whether the configured homeserver is known to be reachable and working */ + bool isUsable() const; /** Get the list of supported login flows */ QVector<GetLoginFlowsJob::LoginFlow> loginFlows() const; /** Check whether the current homeserver supports password auth */ |