aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKitsune Ral <Kitsune-Ral@users.sf.net>2017-11-25 19:59:47 +0900
committerKitsune Ral <Kitsune-Ral@users.sf.net>2017-11-25 19:59:47 +0900
commitad12695aceabc7db7cbdfdd760175c65f4f3d0d1 (patch)
tree8b5110f18a4329e80cbb640ada77e92a77b976d1
parentca70d70f441d93a1da431a8fa3e927396e2abf70 (diff)
downloadlibquotient-ad12695aceabc7db7cbdfdd760175c65f4f3d0d1.tar.gz
libquotient-ad12695aceabc7db7cbdfdd760175c65f4f3d0d1.zip
Make Connection::resolveServer() work as it should
Closes #119; many thanks to @r0kk3rz for prodding me into that.
-rw-r--r--connection.cpp73
-rw-r--r--connection.h10
2 files changed, 68 insertions, 15 deletions
diff --git a/connection.cpp b/connection.cpp
index 7aa2c4eb..bb9cdd32 100644
--- a/connection.cpp
+++ b/connection.cpp
@@ -37,6 +37,7 @@
#include <QtCore/QStandardPaths>
#include <QtCore/QStringBuilder>
#include <QtCore/QElapsedTimer>
+#include <QtCore/QRegularExpression>
using namespace QMatrixClient;
@@ -85,27 +86,61 @@ Connection::~Connection()
delete d;
}
-void Connection::resolveServer(const QString& domain)
+void Connection::resolveServer(const QString& mxidOrDomain)
{
- // Find the Matrix server for the given domain.
- QScopedPointer<QDnsLookup, QScopedPointerDeleteLater> dns { new QDnsLookup() };
+ // At this point we may have something as complex as
+ // @username:[IPv6:address]:port, or as simple as a plain domain name.
+
+ // Try to parse as an FQID; if there's no @ part, assume it's a domain name.
+ QRegularExpression parser(
+ "^(@.+?:)?" // Optional username (allow everything for compatibility)
+ "((\\[[^]]+\\]|[^:@]+)" // Either IPv6 address or hostname/IPv4 address
+ "(:\\d{1,5})?)$", // Optional port
+ QRegularExpression::UseUnicodePropertiesOption); // Because asian digits
+ auto match = parser.match(mxidOrDomain);
+
+ QUrl maybeBaseUrl = QUrl::fromUserInput(match.captured(2));
+ if (!match.hasMatch() || !maybeBaseUrl.isValid())
+ {
+ emit resolveError(
+ tr("%1 is not a valid homeserver address")
+ .arg(maybeBaseUrl.toString()));
+ return;
+ }
+
+ maybeBaseUrl.setScheme("https"); // Instead of the Qt-default "http"
+ if (maybeBaseUrl.port() != -1)
+ {
+ setHomeserver(maybeBaseUrl);
+ emit resolved();
+ return;
+ }
+
+ auto domain = maybeBaseUrl.host();
+ qCDebug(MAIN) << "Resolving server" << domain;
+ // Check if the Matrix server has a dedicated service record.
+ QDnsLookup* dns = new QDnsLookup();
dns->setType(QDnsLookup::SRV);
dns->setName("_matrix._tcp." + domain);
dns->lookup();
- connect(dns.data(), &QDnsLookup::finished, [&]() {
- // Check the lookup succeeded.
- if (dns->error() != QDnsLookup::NoError ||
- dns->serviceRecords().isEmpty()) {
- emit resolveError("DNS lookup failed");
- return;
+ connect(dns, &QDnsLookup::finished, [this,dns,maybeBaseUrl]() {
+ QUrl baseUrl { maybeBaseUrl };
+ if (dns->error() == QDnsLookup::NoError &&
+ dns->serviceRecords().isEmpty())
+ {
+ auto record = dns->serviceRecords().front();
+ baseUrl.setHost(record.target());
+ baseUrl.setPort(record.port());
+ qCDebug(MAIN) << "SRV record for" << maybeBaseUrl.host()
+ << "is" << baseUrl.authority();
+ } else {
+ qCDebug(MAIN) << baseUrl.host() << "doesn't have SRV record"
+ << dns->name() << "- using the hostname as is";
}
-
- // Handle the results.
- auto record = dns->serviceRecords().front();
- d->data->setHost(record.target());
- d->data->setPort(record.port());
+ setHomeserver(baseUrl);
emit resolved();
+ dns->deleteLater();
});
}
@@ -395,11 +430,21 @@ Connection::room_factory_t Connection::createRoom =
Connection::user_factory_t Connection::createUser =
[](Connection* c, const QString& id) { return new User(id, c); };
+
QByteArray Connection::generateTxnId()
{
return d->data->generateTxnId();
}
+void Connection::setHomeserver(const QUrl& url)
+{
+ if (d->data->baseUrl() == url)
+ return;
+
+ d->data->setBaseUrl(url);
+ emit homeserverChanged(url);
+}
+
static constexpr int CACHE_VERSION_MAJOR = 1;
static constexpr int CACHE_VERSION_MINOR = 0;
diff --git a/connection.h b/connection.h
index da211371..cd74b512 100644
--- a/connection.h
+++ b/connection.h
@@ -75,6 +75,8 @@ namespace QMatrixClient
*/
ForgetRoomJob* forgetRoom(const QString& id);
+ // FIXME: Convert Q_INVOKABLEs to Q_PROPERTIES
+ // (breaks back-compatibility)
Q_INVOKABLE QUrl homeserver() const;
Q_INVOKABLE User* user(const QString& userId);
Q_INVOKABLE User* user();
@@ -153,7 +155,12 @@ namespace QMatrixClient
}
public slots:
- void resolveServer(const QString& domain);
+ /** Set the homeserver base URL */
+ void setHomeserver(const QUrl& baseUrl);
+
+ /** Determine and set the homeserver from domain or MXID */
+ void resolveServer(const QString& mxidOrDomain);
+
void connectToServer(const QString& user, const QString& password,
const QString& initialDeviceName,
const QString& deviceId = {});
@@ -190,6 +197,7 @@ namespace QMatrixClient
const QString& from) const;
signals:
void resolved();
+ void homeserverChanged(QUrl baseUrl);
void connected();
void reconnected(); //< Unused; use connected() instead
void loggedOut();