diff options
| author | Jeremy Lainé <jeremy.laine@m4x.org> | 2010-10-20 13:55:08 +0000 |
|---|---|---|
| committer | Jeremy Lainé <jeremy.laine@m4x.org> | 2010-10-20 13:55:08 +0000 |
| commit | dc42da2e630955262e7b1b0318c0528834a53969 (patch) | |
| tree | 9fd1d1b1c85068dbe81f50ad34decab58edfa529 /src | |
| parent | f8c729d64378b062f721fe5fbf903f2d41a4f971 (diff) | |
| download | qxmpp-dc42da2e630955262e7b1b0318c0528834a53969.tar.gz | |
use asynchronous DNS SRV lookups to avoid freezing clients during lookup
Diffstat (limited to 'src')
| -rw-r--r-- | src/QXmppOutgoingClient.cpp | 44 | ||||
| -rw-r--r-- | src/QXmppOutgoingClient.h | 2 | ||||
| -rw-r--r-- | src/QXmppOutgoingServer.cpp | 16 | ||||
| -rw-r--r-- | src/QXmppOutgoingServer.h | 2 | ||||
| -rw-r--r-- | src/QXmppSrvInfo.cpp | 31 | ||||
| -rw-r--r-- | src/QXmppSrvInfo_p.h | 60 | ||||
| -rw-r--r-- | src/src.pro | 1 |
7 files changed, 135 insertions, 21 deletions
diff --git a/src/QXmppOutgoingClient.cpp b/src/QXmppOutgoingClient.cpp index ed51eb9c..08f557a9 100644 --- a/src/QXmppOutgoingClient.cpp +++ b/src/QXmppOutgoingClient.cpp @@ -144,25 +144,41 @@ QXmppConfiguration& QXmppOutgoingClient::configuration() void QXmppOutgoingClient::connectToHost() { + const QString host = configuration().host(); + const quint16 port = configuration().port(); + + // if an explicit host was provided, connect to it + if (!host.isEmpty() && port) + { + info(QString("Connecting to %1:%2").arg(host, QString::number(port))); + socket()->setProxy(configuration().networkProxy()); + socket()->connectToHost(host, port); + return; + } + + // otherwise, lookup server + const QString domain = configuration().domain(); + debug(QString("Looking up server for domain %1").arg(domain)); + QXmppSrvInfo::lookupService("_xmpp-client._tcp." + domain, this, + SLOT(connectToHost(QXmppSrvInfo))); +} + +void QXmppOutgoingClient::connectToHost(const QXmppSrvInfo &serviceInfo) +{ const QString domain = configuration().domain(); QString host = configuration().host(); quint16 port = configuration().port(); - // if we do not have no explicit host was provided, look it up - if (host.isEmpty() || !port) + if (!serviceInfo.records().isEmpty()) { - debug(QString("Looking up server for domain %1").arg(domain)); - QXmppSrvInfo serviceInfo = QXmppSrvInfo::fromName("_xmpp-client._tcp." + domain); - if (!serviceInfo.records().isEmpty()) - { - // take the first returned record - host = serviceInfo.records().first().target(); - port = serviceInfo.records().first().port(); - } else { - // as a fallback, use domain as the host name - warning(QString("Lookup for domain %1 failed: %2").arg(domain, serviceInfo.errorString())); - host = domain; - } + // take the first returned record + host = serviceInfo.records().first().target(); + port = serviceInfo.records().first().port(); + } else { + // as a fallback, use domain as the host name + warning(QString("Lookup for domain %1 failed: %2") + .arg(domain, serviceInfo.errorString())); + host = domain; } // connect to server diff --git a/src/QXmppOutgoingClient.h b/src/QXmppOutgoingClient.h index c87c5b14..3d744854 100644 --- a/src/QXmppOutgoingClient.h +++ b/src/QXmppOutgoingClient.h @@ -39,6 +39,7 @@ class QXmppIq; class QXmppMessage; class QXmppRpcResponseIq; class QXmppRpcErrorIq; +class QXmppSrvInfo; class QXmppOutgoingClientPrivate; @@ -87,6 +88,7 @@ protected: /// \endcond private slots: + void connectToHost(const QXmppSrvInfo &serviceInfo); void socketError(QAbstractSocket::SocketError); void socketSslErrors(const QList<QSslError>&); diff --git a/src/QXmppOutgoingServer.cpp b/src/QXmppOutgoingServer.cpp index a7c92a56..93fcc703 100644 --- a/src/QXmppOutgoingServer.cpp +++ b/src/QXmppOutgoingServer.cpp @@ -77,12 +77,18 @@ QXmppOutgoingServer::~QXmppOutgoingServer() void QXmppOutgoingServer::connectToHost(const QString &domain) { d->remoteDomain = domain; - QString host; - quint16 port; // lookup server for domain debug(QString("Looking up server for domain %1").arg(domain)); - QXmppSrvInfo serviceInfo = QXmppSrvInfo::fromName("_xmpp-server._tcp." + domain); + QXmppSrvInfo::lookupService("_xmpp-server._tcp." + domain, this, + SLOT(connectHost(serviceInfo))); +} + +void QXmppOutgoingServer::connectToHost(const QXmppSrvInfo &serviceInfo) +{ + QString host; + quint16 port; + if (!serviceInfo.records().isEmpty()) { // take the first returned record @@ -90,8 +96,8 @@ void QXmppOutgoingServer::connectToHost(const QString &domain) port = serviceInfo.records().first().port(); } else { // as a fallback, use domain as the host name - warning(QString("Lookup for domain %1 failed: %2").arg(domain, serviceInfo.errorString())); - host = domain; + warning(QString("Lookup for domain %1 failed: %2").arg(d->remoteDomain, serviceInfo.errorString())); + host = d->remoteDomain; port = 5269; } diff --git a/src/QXmppOutgoingServer.h b/src/QXmppOutgoingServer.h index 055fe133..8298d9c0 100644 --- a/src/QXmppOutgoingServer.h +++ b/src/QXmppOutgoingServer.h @@ -30,6 +30,7 @@ class QSslError; class QXmppDialback; class QXmppOutgoingServer; class QXmppOutgoingServerPrivate; +class QXmppSrvInfo; /// \brief The QXmppOutgoingServer class represents an outgoing XMPP stream /// to another XMPP server. @@ -64,6 +65,7 @@ protected: /// \endcond private slots: + void connectToHost(const QXmppSrvInfo &serviceInfo); void slotSslErrors(const QList<QSslError> &errors); private: diff --git a/src/QXmppSrvInfo.cpp b/src/QXmppSrvInfo.cpp index 4a0a95ea..7c2b06d8 100644 --- a/src/QXmppSrvInfo.cpp +++ b/src/QXmppSrvInfo.cpp @@ -22,9 +22,12 @@ */ #include "QXmppSrvInfo.h" +#include "QXmppSrvInfo_p.h" +#include <QCoreApplication> #include <QLibrary> #include <QMetaObject> +#include <QMetaType> #if defined(Q_OS_WIN) #include <windows.h> @@ -41,6 +44,8 @@ #include <resolv.h> #endif +Q_GLOBAL_STATIC(QXmppSrvInfoLookupManager, theSrvInfoLookupManager) + #if defined(Q_OS_WIN) typedef DNS_STATUS (*dns_query_utf8_proto)(PCSTR,WORD,DWORD,PIP4_ARRAY,PDNS_RECORD*,PVOID*); static dns_query_utf8_proto local_dns_query_utf8 = 0; @@ -535,7 +540,29 @@ QXmppSrvInfo QXmppSrvInfo::fromName(const QString &dname) void QXmppSrvInfo::lookupService(const QString &name, QObject *receiver, const char *member) { - QXmppSrvInfo result = QXmppSrvInfo::fromName(name); - QMetaObject::invokeMethod(receiver, member, Qt::QueuedConnection, Q_ARG(QXmppSrvInfo, result)); + qRegisterMetaType<QXmppSrvInfo>("QXmppSrvInfo"); + + QXmppSrvInfoLookupManager *manager = theSrvInfoLookupManager(); + if (manager) + { + // the application is still alive + QXmppSrvInfoLookupRunnable *runnable = new QXmppSrvInfoLookupRunnable(name); + QObject::connect(runnable, SIGNAL(foundInfo(QXmppSrvInfo)), receiver, member); + manager->start(runnable); + } +} + +QXmppSrvInfoLookupManager::QXmppSrvInfoLookupManager() +{ + moveToThread(QCoreApplication::instance()->thread()); + connect(QCoreApplication::instance(), SIGNAL(destroyed()), + SLOT(waitForThreadPoolDone()), Qt::DirectConnection); + setMaxThreadCount(5); // do 5 SRV lookups in parallel +} + +void QXmppSrvInfoLookupRunnable::run() +{ + const QXmppSrvInfo result = QXmppSrvInfo::fromName(lookupName); + emit foundInfo(result); } diff --git a/src/QXmppSrvInfo_p.h b/src/QXmppSrvInfo_p.h new file mode 100644 index 00000000..59076c70 --- /dev/null +++ b/src/QXmppSrvInfo_p.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2008-2010 The QXmpp developers + * + * Author: + * Jeremy Lainé + * + * Source: + * http://code.google.com/p/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#ifndef QXMPPSRVINFO_P_H +#define QXMPPSRVINFO_P_H + +#include <QRunnable> +#include <QThreadPool> + +class QXmppSrvInfo; + +class QXmppSrvInfoLookupManager : public QThreadPool +{ + Q_OBJECT + +public: + QXmppSrvInfoLookupManager(); + +private slots: + void waitForThreadPoolDone() { waitForDone(); } +}; + +class QXmppSrvInfoLookupRunnable : public QObject, public QRunnable +{ + Q_OBJECT + +public: + QXmppSrvInfoLookupRunnable(const QString &name) + : lookupName(name) + { } + void run(); + +signals: + void foundInfo(const QXmppSrvInfo &info); + +private: + QString lookupName; +}; + +#endif diff --git a/src/src.pro b/src/src.pro index 0ee158d5..7fc88239 100644 --- a/src/src.pro +++ b/src/src.pro @@ -81,6 +81,7 @@ INSTALL_HEADERS = QXmppUtils.h \ QXmppVersionManager.h HEADERS += $$INSTALL_HEADERS +HEADERS += QXmppSrvInfo_p.h # Source files SOURCES += QXmppUtils.cpp \ |
