aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKitsune Ral <Kitsune-Ral@users.sf.net>2020-04-15 13:05:16 +0200
committerKitsune Ral <Kitsune-Ral@users.sf.net>2020-04-15 13:07:06 +0200
commit753c281f4eb055d684e63472468fd091f2166526 (patch)
tree5862bd41c592a7330cdbb67adf1632569133e5e9
parentb27e4e2b75180c920deef1399487228f79882f47 (diff)
downloadlibquotient-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.
-rw-r--r--lib/connection.cpp98
-rw-r--r--lib/connection.h3
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 */