123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990 |
- /****************************************************************************
- **
- ** Copyright (C) 2012 Jeremy Lainé <jeremy.laine@m4x.org>
- ** Contact: http://www.qt-project.org/
- **
- ** This file is part of the QtNetwork module of the Qt Toolkit.
- **
- ** $QT_BEGIN_LICENSE:LGPL$
- ** GNU Lesser General Public License Usage
- ** This file may be used under the terms of the GNU Lesser General Public
- ** License version 2.1 as published by the Free Software Foundation and
- ** appearing in the file LICENSE.LGPL included in the packaging of this
- ** file. Please review the following information to ensure the GNU Lesser
- ** General Public License version 2.1 requirements will be met:
- ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
- **
- ** In addition, as a special exception, Nokia gives you certain additional
- ** rights. These rights are described in the Nokia Qt LGPL Exception
- ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
- **
- ** GNU General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU General
- ** Public License version 3.0 as published by the Free Software Foundation
- ** and appearing in the file LICENSE.GPL included in the packaging of this
- ** file. Please review the following information to ensure the GNU General
- ** Public License version 3.0 requirements will be met:
- ** http://www.gnu.org/copyleft/gpl.html.
- **
- ** Other Usage
- ** Alternatively, this file may be used in accordance with the terms and
- ** conditions contained in a signed written agreement between you and Nokia.
- **
- **
- **
- **
- **
- **
- ** $QT_END_LICENSE$
- **
- ****************************************************************************/
- #include "qdnslookup.h"
- #include "qdnslookup_p.h"
- #include <QCoreApplication>
- #include <QDateTime>
- #include <QMetaType>
- #include <QThreadStorage>
- #include <QUrl>
- QT_BEGIN_NAMESPACE
- Q_GLOBAL_STATIC(QDnsLookupThreadPool, theDnsLookupThreadPool);
- Q_GLOBAL_STATIC(QThreadStorage<bool *>, theDnsLookupSeedStorage);
- static bool qt_qdnsmailexchangerecord_less_than(const QDnsMailExchangeRecord &r1, const QDnsMailExchangeRecord &r2)
- {
- // Lower numbers are more preferred than higher ones.
- return r1.preference() < r2.preference();
- }
- /*!
- Sorts a list of QDnsMailExchangeRecord objects according to RFC 5321.
- */
- static void qt_qdnsmailexchangerecord_sort(QList<QDnsMailExchangeRecord> &records)
- {
- // If we have no more than one result, we are done.
- if (records.size() <= 1)
- return;
- // Order the records by preference.
- qSort(records.begin(), records.end(), qt_qdnsmailexchangerecord_less_than);
- int i = 0;
- while (i < records.size()) {
- // Determine the slice of records with the current preference.
- QList<QDnsMailExchangeRecord> slice;
- const quint16 slicePreference = records[i].preference();
- for (int j = i; j < records.size(); ++j) {
- if (records[j].preference() != slicePreference)
- break;
- slice << records[j];
- }
- // Randomize the slice of records.
- while (!slice.isEmpty()) {
- const unsigned int pos = qrand() % slice.size();
- records[i++] = slice.takeAt(pos);
- }
- }
- }
- static bool qt_qdnsservicerecord_less_than(const QDnsServiceRecord &r1, const QDnsServiceRecord &r2)
- {
- // Order by priority, or if the priorities are equal,
- // put zero weight records first.
- return r1.priority() < r2.priority()
- || (r1.priority() == r2.priority()
- && r1.weight() == 0 && r2.weight() > 0);
- }
- /*!
- Sorts a list of QDnsServiceRecord objects according to RFC 2782.
- */
- static void qt_qdnsservicerecord_sort(QList<QDnsServiceRecord> &records)
- {
- // If we have no more than one result, we are done.
- if (records.size() <= 1)
- return;
- // Order the records by priority, and for records with an equal
- // priority, put records with a zero weight first.
- qSort(records.begin(), records.end(), qt_qdnsservicerecord_less_than);
- int i = 0;
- while (i < records.size()) {
- // Determine the slice of records with the current priority.
- QList<QDnsServiceRecord> slice;
- const quint16 slicePriority = records[i].priority();
- unsigned int sliceWeight = 0;
- for (int j = i; j < records.size(); ++j) {
- if (records[j].priority() != slicePriority)
- break;
- sliceWeight += records[j].weight();
- slice << records[j];
- }
- #ifdef QDNSLOOKUP_DEBUG
- qDebug("qt_qdnsservicerecord_sort() : priority %i (size: %i, total weight: %i)",
- slicePriority, slice.size(), sliceWeight);
- #endif
- // Order the slice of records.
- while (!slice.isEmpty()) {
- const unsigned int weightThreshold = qrand() % (sliceWeight + 1);
- unsigned int summedWeight = 0;
- for (int j = 0; j < slice.size(); ++j) {
- summedWeight += slice[j].weight();
- if (summedWeight >= weightThreshold) {
- #ifdef QDNSLOOKUP_DEBUG
- qDebug("qt_qdnsservicerecord_sort() : adding %s %i (weight: %i)",
- qPrintable(slice[j].target()), slice[j].port(),
- slice[j].weight());
- #endif
- // Adjust the slice weight and take the current record.
- sliceWeight -= slice[j].weight();
- records[i++] = slice.takeAt(j);
- break;
- }
- }
- }
- }
- }
- /*!
- \class QDnsLookup
- \brief The QDnsLookup class represents a DNS lookup.
- \inmodule QtNetwork
- \ingroup network
- QDnsLookup uses the mechanisms provided by the operating system to perform
- DNS lookups. To perform a lookup you need to specify a \l name and \l type
- then invoke the \l{QDnsLookup::lookup()}{lookup()} slot. The
- \l{QDnsLookup::finished()}{finished()} signal will be emitted upon
- completion.
- For example, you can determine which servers an XMPP chat client should
- connect to for a given domain with:
- \snippet doc/src/snippets/code/src_network_kernel_qdnslookup.cpp 0
- Once the request finishes you can handle the results with:
- \snippet doc/src/snippets/code/src_network_kernel_qdnslookup.cpp 1
- \note If you simply want to find the IP address(es) associated with a host
- name, or the host name associated with an IP address you should use
- QHostInfo instead.
- */
- /*!
- \enum QDnsLookup::Error
- Indicates all possible error conditions found during the
- processing of the DNS lookup.
- \value NoError no error condition.
- \value ResolverError there was an error initializing the system's
- DNS resolver.
- \value OperationCancelledError the lookup was aborted using the abort()
- method.
- \value InvalidRequestError the requested DNS lookup was invalid.
- \value InvalidReplyError the reply returned by the server was invalid.
- \value ServerFailureError the server encountered an internal failure
- while processing the request (SERVFAIL).
- \value ServerRefusedError the server refused to process the request for
- security or policy reasons (REFUSED).
- \value NotFoundError the requested domain name does not exist
- (NXDOMAIN).
- */
- /*!
- \enum QDnsLookup::Type
- Indicates the type of DNS lookup that was performed.
- \value A IPv4 address records.
- \value AAAA IPv6 address records.
- \value ANY any records.
- \value CNAME canonical name records.
- \value MX mail exchange records.
- \value NS name server records.
- \value PTR pointer records.
- \value SRV service records.
- \value TXT text records.
- */
- /*!
- \fn void QDnsLookup::finished()
- This signal is emitted when the reply has finished processing.
- */
- /*!
- \fn void QDnsLookup::nameChanged(const QString &name)
- This signal is emitted when the lookup \l name changes.
- \a name is the new lookup name.
- */
- /*!
- \fn void QDnsLookup::typeChanged(Type type)
- This signal is emitted when the lookup \l type changes.
- \a type is the new lookup type.
- */
- /*!
- Constructs a QDnsLookup object and sets \a parent as the parent object.
- The \l type property will default to QDnsLookup::A.
- */
- QDnsLookup::QDnsLookup(QObject *parent)
- : QObject(parent)
- , d_ptr(new QDnsLookupPrivate(this))
- {
- qRegisterMetaType<QDnsLookupReply>();
- }
- /*!
- Constructs a QDnsLookup object for the given \a type and \a name and sets
- \a parent as the parent object.
- */
- QDnsLookup::QDnsLookup(Type type, const QString &name, QObject *parent)
- : QObject(parent)
- , d_ptr(new QDnsLookupPrivate(this))
- {
- Q_D(QDnsLookup);
- qRegisterMetaType<QDnsLookupReply>();
- d->name = name;
- d->type = type;
- }
- /*!
- Destroys the QDnsLookup object.
- It is safe to delete a QDnsLookup object even if it is not finished, you
- will simply never receive its results.
- */
- QDnsLookup::~QDnsLookup()
- {
- }
- /*!
- \property QDnsLookup::error
- \brief the type of error that occurred if the DNS lookup failed, or NoError.
- */
- QDnsLookup::Error QDnsLookup::error() const
- {
- return d_func()->reply.error;
- }
- /*!
- \property QDnsLookup::errorString
- \brief a human-readable description of the error if the DNS lookup failed.
- */
- QString QDnsLookup::errorString() const
- {
- return d_func()->reply.errorString;
- }
- /*!
- \property QDnsLookup::finished
- \brief whether the reply has finished or was aborted.
- */
- bool QDnsLookup::isFinished() const
- {
- return d_func()->isFinished;
- }
- /*!
- \property QDnsLookup::name
- \brief the name to lookup.
- \note The name will be encoded using IDNA, which means it's unsuitable for
- querying SRV records compatible with the DNS-SD specification.
- */
- QString QDnsLookup::name() const
- {
- return d_func()->name;
- }
- void QDnsLookup::setName(const QString &name)
- {
- Q_D(QDnsLookup);
- if (name != d->name) {
- d->name = name;
- emit nameChanged(name);
- }
- }
- /*!
- \property QDnsLookup::type
- \brief the type of DNS lookup.
- */
- QDnsLookup::Type QDnsLookup::type() const
- {
- return d_func()->type;
- }
- void QDnsLookup::setType(Type type)
- {
- Q_D(QDnsLookup);
- if (type != d->type) {
- d->type = type;
- emit typeChanged(type);
- }
- }
- /*!
- Returns the list of canonical name records associated with this lookup.
- */
- QList<QDnsDomainNameRecord> QDnsLookup::canonicalNameRecords() const
- {
- return d_func()->reply.canonicalNameRecords;
- }
- /*!
- Returns the list of host address records associated with this lookup.
- */
- QList<QDnsHostAddressRecord> QDnsLookup::hostAddressRecords() const
- {
- return d_func()->reply.hostAddressRecords;
- }
- /*!
- Returns the list of mail exchange records associated with this lookup.
- The records are sorted according to
- \l{http://www.rfc-editor.org/rfc/rfc5321.txt}{RFC 5321}, so if you use them
- to connect to servers, you should try them in the order they are listed.
- */
- QList<QDnsMailExchangeRecord> QDnsLookup::mailExchangeRecords() const
- {
- return d_func()->reply.mailExchangeRecords;
- }
- /*!
- Returns the list of name server records associated with this lookup.
- */
- QList<QDnsDomainNameRecord> QDnsLookup::nameServerRecords() const
- {
- return d_func()->reply.nameServerRecords;
- }
- /*!
- Returns the list of pointer records associated with this lookup.
- */
- QList<QDnsDomainNameRecord> QDnsLookup::pointerRecords() const
- {
- return d_func()->reply.pointerRecords;
- }
- /*!
- Returns the list of service records associated with this lookup.
- The records are sorted according to
- \l{http://www.rfc-editor.org/rfc/rfc2782.txt}{RFC 2782}, so if you use them
- to connect to servers, you should try them in the order they are listed.
- */
- QList<QDnsServiceRecord> QDnsLookup::serviceRecords() const
- {
- return d_func()->reply.serviceRecords;
- }
- /*!
- Returns the list of text records associated with this lookup.
- */
- QList<QDnsTextRecord> QDnsLookup::textRecords() const
- {
- return d_func()->reply.textRecords;
- }
- /*!
- Aborts the DNS lookup operation.
- If the lookup is already finished, does nothing.
- */
- void QDnsLookup::abort()
- {
- Q_D(QDnsLookup);
- if (d->runnable) {
- d->runnable = 0;
- d->reply = QDnsLookupReply();
- d->reply.error = QDnsLookup::OperationCancelledError;
- d->reply.errorString = tr("Operation cancelled");
- d->isFinished = true;
- emit finished();
- }
- }
- /*!
- Performs the DNS lookup.
- The \l{QDnsLookup::finished()}{finished()} signal is emitted upon completion.
- */
- void QDnsLookup::lookup()
- {
- Q_D(QDnsLookup);
- d->isFinished = false;
- d->reply = QDnsLookupReply();
- d->runnable = new QDnsLookupRunnable(d->type, QUrl::toAce(d->name));
- connect(d->runnable, SIGNAL(finished(QDnsLookupReply)),
- this, SLOT(_q_lookupFinished(QDnsLookupReply)),
- Qt::BlockingQueuedConnection);
- theDnsLookupThreadPool()->start(d->runnable);
- }
- /*!
- \class QDnsDomainNameRecord
- \brief The QDnsDomainNameRecord class stores information about a domain
- name record.
- \inmodule QtNetwork
- \ingroup network
- When performing a name server lookup, zero or more records will be returned.
- Each record is represented by a QDnsDomainNameRecord instance.
- \sa QDnsLookup
- */
- /*!
- Constructs an empty domain name record object.
- */
- QDnsDomainNameRecord::QDnsDomainNameRecord()
- : d(new QDnsDomainNameRecordPrivate)
- {
- }
- /*!
- Constructs a copy of \a other.
- */
- QDnsDomainNameRecord::QDnsDomainNameRecord(const QDnsDomainNameRecord &other)
- : d(other.d)
- {
- }
- /*!
- Destroys a domain name record.
- */
- QDnsDomainNameRecord::~QDnsDomainNameRecord()
- {
- }
- /*!
- Returns the name for this record.
- */
- QString QDnsDomainNameRecord::name() const
- {
- return d->name;
- }
- /*!
- Returns the duration in seconds for which this record is valid.
- */
- quint32 QDnsDomainNameRecord::timeToLive() const
- {
- return d->timeToLive;
- }
- /*!
- Returns the value for this domain name record.
- */
- QString QDnsDomainNameRecord::value() const
- {
- return d->value;
- }
- /*!
- Assigns the data of the \a other object to this record object,
- and returns a reference to it.
- */
- QDnsDomainNameRecord &QDnsDomainNameRecord::operator=(const QDnsDomainNameRecord &other)
- {
- d = other.d;
- return *this;
- }
- /*!
- \class QDnsHostAddressRecord
- \brief The QDnsHostAddressRecord class stores information about a host
- address record.
- \inmodule QtNetwork
- \ingroup network
- When performing an address lookup, zero or more records will be
- returned. Each record is represented by a QDnsHostAddressRecord instance.
- \sa QDnsLookup
- */
- /*!
- Constructs an empty host address record object.
- */
- QDnsHostAddressRecord::QDnsHostAddressRecord()
- : d(new QDnsHostAddressRecordPrivate)
- {
- }
- /*!
- Constructs a copy of \a other.
- */
- QDnsHostAddressRecord::QDnsHostAddressRecord(const QDnsHostAddressRecord &other)
- : d(other.d)
- {
- }
- /*!
- Destroys a host address record.
- */
- QDnsHostAddressRecord::~QDnsHostAddressRecord()
- {
- }
- /*!
- Returns the name for this record.
- */
- QString QDnsHostAddressRecord::name() const
- {
- return d->name;
- }
- /*!
- Returns the duration in seconds for which this record is valid.
- */
- quint32 QDnsHostAddressRecord::timeToLive() const
- {
- return d->timeToLive;
- }
- /*!
- Returns the value for this host address record.
- */
- QHostAddress QDnsHostAddressRecord::value() const
- {
- return d->value;
- }
- /*!
- Assigns the data of the \a other object to this record object,
- and returns a reference to it.
- */
- QDnsHostAddressRecord &QDnsHostAddressRecord::operator=(const QDnsHostAddressRecord &other)
- {
- d = other.d;
- return *this;
- }
- /*!
- \class QDnsMailExchangeRecord
- \brief The QDnsMailExchangeRecord class stores information about a DNS MX record.
- \inmodule QtNetwork
- \ingroup network
- When performing a lookup on a service, zero or more records will be
- returned. Each record is represented by a QDnsMailExchangeRecord instance.
- The meaning of the fields is defined in
- \l{http://www.rfc-editor.org/rfc/rfc1035.txt}{RFC 1035}.
- \sa QDnsLookup
- */
- /*!
- Constructs an empty mail exchange record object.
- */
- QDnsMailExchangeRecord::QDnsMailExchangeRecord()
- : d(new QDnsMailExchangeRecordPrivate)
- {
- }
- /*!
- Constructs a copy of \a other.
- */
- QDnsMailExchangeRecord::QDnsMailExchangeRecord(const QDnsMailExchangeRecord &other)
- : d(other.d)
- {
- }
- /*!
- Destroys a mail exchange record.
- */
- QDnsMailExchangeRecord::~QDnsMailExchangeRecord()
- {
- }
- /*!
- Returns the domain name of the mail exchange for this record.
- */
- QString QDnsMailExchangeRecord::exchange() const
- {
- return d->exchange;
- }
- /*!
- Returns the name for this record.
- */
- QString QDnsMailExchangeRecord::name() const
- {
- return d->name;
- }
- /*!
- Returns the preference for this record.
- */
- quint16 QDnsMailExchangeRecord::preference() const
- {
- return d->preference;
- }
- /*!
- Returns the duration in seconds for which this record is valid.
- */
- quint32 QDnsMailExchangeRecord::timeToLive() const
- {
- return d->timeToLive;
- }
- /*!
- Assigns the data of the \a other object to this record object,
- and returns a reference to it.
- */
- QDnsMailExchangeRecord &QDnsMailExchangeRecord::operator=(const QDnsMailExchangeRecord &other)
- {
- d = other.d;
- return *this;
- }
- /*!
- \class QDnsServiceRecord
- \brief The QDnsServiceRecord class stores information about a DNS SRV record.
- \inmodule QtNetwork
- \ingroup network
- When performing a lookup on a service, zero or more records will be
- returned. Each record is represented by a QDnsServiceRecord instance.
- The meaning of the fields is defined in
- \l{http://www.rfc-editor.org/rfc/rfc2782.txt}{RFC 2782}.
- \sa QDnsLookup
- */
- /*!
- Constructs an empty service record object.
- */
- QDnsServiceRecord::QDnsServiceRecord()
- : d(new QDnsServiceRecordPrivate)
- {
- }
- /*!
- Constructs a copy of \a other.
- */
- QDnsServiceRecord::QDnsServiceRecord(const QDnsServiceRecord &other)
- : d(other.d)
- {
- }
- /*!
- Destroys a service record.
- */
- QDnsServiceRecord::~QDnsServiceRecord()
- {
- }
- /*!
- Returns the name for this record.
- */
- QString QDnsServiceRecord::name() const
- {
- return d->name;
- }
- /*!
- Returns the port on the target host for this service record.
- */
- quint16 QDnsServiceRecord::port() const
- {
- return d->port;
- }
- /*!
- Returns the priority for this service record.
- A client must attempt to contact the target host with the lowest-numbered
- priority.
- */
- quint16 QDnsServiceRecord::priority() const
- {
- return d->priority;
- }
- /*!
- Returns the domain name of the target host for this service record.
- */
- QString QDnsServiceRecord::target() const
- {
- return d->target;
- }
- /*!
- Returns the duration in seconds for which this record is valid.
- */
- quint32 QDnsServiceRecord::timeToLive() const
- {
- return d->timeToLive;
- }
- /*!
- Returns the weight for this service record.
- The weight field specifies a relative weight for entries with the same
- priority. Entries with higher weights should be selected with a higher
- probability.
- */
- quint16 QDnsServiceRecord::weight() const
- {
- return d->weight;
- }
- /*!
- Assigns the data of the \a other object to this record object,
- and returns a reference to it.
- */
- QDnsServiceRecord &QDnsServiceRecord::operator=(const QDnsServiceRecord &other)
- {
- d = other.d;
- return *this;
- }
- /*!
- \class QDnsTextRecord
- \brief The QDnsTextRecord class stores information about a DNS TXT record.
- \inmodule QtNetwork
- \ingroup network
- When performing a text lookup, zero or more records will be
- returned. Each record is represented by a QDnsTextRecord instance.
- The meaning of the fields is defined in
- \l{http://www.rfc-editor.org/rfc/rfc1035.txt}{RFC 1035}.
- \sa QDnsLookup
- */
- /*!
- Constructs an empty text record object.
- */
- QDnsTextRecord::QDnsTextRecord()
- : d(new QDnsTextRecordPrivate)
- {
- }
- /*!
- Constructs a copy of \a other.
- */
- QDnsTextRecord::QDnsTextRecord(const QDnsTextRecord &other)
- : d(other.d)
- {
- }
- /*!
- Destroys a text record.
- */
- QDnsTextRecord::~QDnsTextRecord()
- {
- }
- /*!
- Returns the name for this text record.
- */
- QString QDnsTextRecord::name() const
- {
- return d->name;
- }
- /*!
- Returns the duration in seconds for which this record is valid.
- */
- quint32 QDnsTextRecord::timeToLive() const
- {
- return d->timeToLive;
- }
- /*!
- Returns the values for this text record.
- */
- QList<QByteArray> QDnsTextRecord::values() const
- {
- return d->values;
- }
- /*!
- Assigns the data of the \a other object to this record object,
- and returns a reference to it.
- */
- QDnsTextRecord &QDnsTextRecord::operator=(const QDnsTextRecord &other)
- {
- d = other.d;
- return *this;
- }
- void QDnsLookupPrivate::_q_lookupFinished(const QDnsLookupReply &_reply)
- {
- Q_Q(QDnsLookup);
- if (runnable == q->sender()) {
- #ifdef QDNSLOOKUP_DEBUG
- qDebug("DNS reply for %s: %i (%s)", qPrintable(name), _reply.error, qPrintable(_reply.errorString));
- #endif
- reply = _reply;
- runnable = 0;
- isFinished = true;
- emit q->finished();
- }
- }
- void QDnsLookupRunnable::run()
- {
- QDnsLookupReply reply;
- // Validate input.
- if (requestName.isEmpty()) {
- reply.error = QDnsLookup::InvalidRequestError;
- reply.errorString = tr("Invalid domain name");
- emit finished(reply);
- return;
- }
- // Perform request.
- query(requestType, requestName, &reply);
- // Sort results.
- if (!theDnsLookupSeedStorage()->hasLocalData()) {
- qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()) ^ reinterpret_cast<quintptr>(this));
- theDnsLookupSeedStorage()->setLocalData(new bool(true));
- }
- qt_qdnsmailexchangerecord_sort(reply.mailExchangeRecords);
- qt_qdnsservicerecord_sort(reply.serviceRecords);
- emit finished(reply);
- }
- QDnsLookupThreadPool::QDnsLookupThreadPool()
- : signalsConnected(false)
- {
- // Run up to 5 lookups in parallel.
- setMaxThreadCount(5);
- }
- void QDnsLookupThreadPool::start(QRunnable *runnable)
- {
- // Ensure threads complete at application destruction.
- if (!signalsConnected) {
- QMutexLocker signalsLocker(&signalsMutex);
- if (!signalsConnected) {
- QCoreApplication *app = QCoreApplication::instance();
- if (!app) {
- qWarning("QDnsLookup requires a QCoreApplication");
- delete runnable;
- return;
- }
- moveToThread(app->thread());
- connect(app, SIGNAL(destroyed()),
- SLOT(_q_applicationDestroyed()), Qt::DirectConnection);
- signalsConnected = true;
- }
- }
- QThreadPool::start(runnable);
- }
- void QDnsLookupThreadPool::_q_applicationDestroyed()
- {
- waitForDone();
- signalsConnected = false;
- }
- QT_END_NAMESPACE
|