1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the network module of the Qt Toolkit.
7
** This file may be distributed under the terms of the Q Public License
8
** as defined by Trolltech AS of Norway and appearing in the file
9
** LICENSE.QPL included in the packaging of this file.
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 as published by the Free Software
13
** Foundation and appearing in the file LICENSE.GPL included in the
14
** packaging of this file.
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
17
** information about Qt Commercial License Agreements.
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
21
** Contact info@trolltech.com if any conditions of this licensing are
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27
****************************************************************************/
29
#include "qhostinfo.h"
30
#include "qhostinfo_p.h"
32
#include <qabstracteventdispatcher.h>
33
#include <private/qunicodetables_p.h>
34
#include <qcoreapplication.h>
35
#include <qmetaobject.h>
37
#include <private/qsocketlayer_p.h>
38
#include <qstringlist.h>
47
Q_GLOBAL_STATIC(QHostInfoAgent, agent)
49
//#define QHOSTINFO_DEBUG
53
\brief The QHostInfo class provides static functions for host name lookups.
59
QHostInfo uses the lookup mechanisms provided by the operating
60
system to find the IP address(es) associated with a host name.
61
The class provides two static convenience functions: one that
62
works asynchronously and emits a signal once the host is found,
63
and one that blocks and returns a QHostInfo object.
65
To look up a host's IP addresses asynchronously, call lookupHost(),
66
which takes the host name, a receiver object, and a slot
67
signature as arguments and returns an ID. You can abort the
68
lookup by calling abortHostLookup() with the lookup ID.
73
QHostInfo::lookupHost("www.trolltech.com",
74
this, SLOT(printResults(QHostInfo)));
78
The slot is invoked when the results are ready. (If you use
79
Qt/Embedded and disabled multithread support by defining \c
80
QT_NO_THREAD, lookupHost() will block until the lookup has
81
finished.) The results are stored in a QHostInfo object. Call
82
addresses() to get the list of IP addresses for the host, and
83
hostName() to get the host name that was looked up.
85
If the lookup failed, error() returns the type of error that
86
occurred. errorString() gives a human-readable description of the
89
If you want a blocking lookup, use the QHostInfo::fromName() function:
92
QHostInfo info = QHostInfo::fromName("www.trolltech.com");
95
QHostInfo supports Internationalized Domain Names (IDNs) through the
96
IDNA and Punycode standards.
98
To retrieve the name of the local host, use the static
99
QHostInfo::localHostName() function.
101
\sa QAbstractSocket, {http://ietf.org/rfc/rfc3492}{RFC 3492}
104
static QBasicAtomic idCounter = Q_ATOMIC_INIT(1);
105
static int qt_qhostinfo_newid()
110
if (idCounter.testAndSet(id, id + 1))
117
Looks up the IP address(es) associated with host name \a name, and
118
returns an ID for the lookup. When the result of the lookup is
119
ready, the slot or signal \a member in \a receiver is called with
120
a QHostInfo argument. The QHostInfo object can then be inspected
121
to get the results of the lookup.
123
The lookup is performed by a single function call, for example:
126
QHostInfo::lookupHost("www.kde.org",
127
this, SLOT(lookedUp(QHostInfo)));
130
The implementation of the slot prints basic information about the
131
addresses returned by the lookup, or reports an error if it failed:
134
void MyWidget::lookedUp(const QHostInfo &host)
136
if (host.error() != QHostInfo::NoError) {
137
qDebug() << "Lookup failed:" << host.errorString();
141
foreach (QHostAddress address, host.addresses())
142
qDebug() << "Found address:" << address.toString();
146
\sa abortHostLookup(), addresses(), error(), fromName()
148
int QHostInfo::lookupHost(const QString &name, QObject *receiver,
151
#if defined QHOSTINFO_DEBUG
152
qDebug("QHostInfo::lookupHost(\"%s\", %p, %s)",
153
name.toLatin1().constData(), receiver, member ? member + 1 : 0);
155
if (!QAbstractEventDispatcher::instance(QThread::currentThread())) {
156
qWarning("QHostInfo::lookupHost() called with no event dispatcher");
160
qRegisterMetaType<QHostInfo>("QHostInfo");
162
// Don't start a thread if we don't have to do any lookup.
164
if (addr.setAddress(name)) {
165
if (!member || !member[0]) {
166
qWarning("QHostInfo::lookupHost() called with invalid slot [%s]", member);
170
QByteArray arr(member + 1);
171
if (!arr.contains('(')) {
172
qWarning("QHostInfo::lookupHost() called with invalid slot [%s]", member);
176
QHostInfo info(::qt_qhostinfo_newid());
177
info.setAddresses(QList<QHostAddress>() << addr);
178
arr.resize(arr.indexOf('('));
180
// To mimic the same behavior that the lookup would have if it was not
181
// an IP, we need to choose a Qt::QueuedConnection if there is thread support;
182
// otherwise Qt::DirectConnection.
183
if (!QMetaObject::invokeMethod(receiver, arr,
184
#if !defined QT_NO_THREAD
185
Qt::QueuedConnection,
187
Qt::DirectConnection,
189
QGenericArgument("QHostInfo", &info))) {
190
qWarning("QHostInfo::lookupHost() called with invalid slot (QMetaObject::invokeMethod failed)");
192
return info.lookupId();
195
#if defined Q_OS_WIN32
196
QSocketLayer bust; // makes sure WSAStartup was callled
199
// Support for IDNA by first splitting the name into labels, then
200
// running the punycode decoder on each part, then merging
201
// together before passing the name to the lookup agent.
203
const unsigned short delimiters[] = {0x2e, 0x3002, 0xff0e, 0xff61, 0};
204
QStringList labels = name.split(QRegExp("[" + QString::fromUtf16(delimiters) + "]"));
205
for (int i = 0; i < labels.count(); ++i) {
206
if (i != 0) lookup += '.';
207
QString label = QUnicodeTables::normalize(labels.at(i), QString::NormalizationForm_KC, QChar::Unicode_3_1);
208
lookup += QString::fromAscii(QUrl::toPunycode(label));
211
QHostInfoAgent *agent = ::agent();
213
QHostInfoResult *result = new QHostInfoResult;
214
QObject::connect(result, SIGNAL(resultsReady(QHostInfo)),
216
QObject::connect(result, SIGNAL(resultsReady(QHostInfo)),
217
result, SLOT(deleteLater()));
218
result->lookupId = ::qt_qhostinfo_newid();
219
agent->addHostName(lookup, result);
221
#if !defined QT_NO_THREAD
222
if (!agent->isRunning())
225
if (!agent->isRunning())
230
return result->lookupId;
234
Aborts the host lookup with the ID \a id, as returned by lookupHost().
236
\sa lookupHost(), lookupId()
238
void QHostInfo::abortHostLookup(int id)
240
QHostInfoAgent *agent = ::agent();
241
agent->abortLookup(id);
245
Looks up the IP address(es) for the given host \a name. The
246
function blocks during the lookup which means that execution of
247
the program is suspended until the results of the lookup are
248
ready. Returns the result of the lookup in a QHostInfo object.
252
QHostInfo QHostInfo::fromName(const QString &name)
254
#if defined QHOSTINFO_DEBUG
255
qDebug("QHostInfo::fromName(\"%s\")",name.toLatin1().constData());
258
// If the address string is an IP address, don't do a lookup.
260
if (addr.setAddress(name)) {
262
info.setAddresses(QList<QHostAddress>() << addr);
266
// Support for IDNA by first splitting the name into labels, then
267
// running the punycode decoder on each part, then merging
268
// together before passing the name to the lookup agent.
270
const unsigned short delimiters[] = {0x2e, 0x3002, 0xff0e, 0xff61, 0};
271
QStringList labels = name.split(QRegExp("[" + QString::fromUtf16(delimiters) + "]"));
272
for (int i = 0; i < labels.count(); ++i) {
273
if (i != 0) lookup += '.';
274
QString label = QUnicodeTables::normalize(labels.at(i), QString::NormalizationForm_KC, QChar::Unicode_3_1);
275
lookup += QString::fromAscii(QUrl::toPunycode(label));
278
return QHostInfoAgent::fromName(lookup);
283
Pops a query off the queries list, performs a blocking call to
284
QHostInfoAgent::lookupHost(), and emits the resultsReady()
285
signal. This process repeats until the queries list is empty.
287
void QHostInfoAgent::run()
290
QHostInfoQuery *query;
292
// the queries list is shared between threads. lock all
294
QMutexLocker locker(&mutex);
295
if (!quit && queries.isEmpty())
299
if (queries.isEmpty())
301
query = queries.takeFirst();
304
#if defined(QHOSTINFO_DEBUG)
305
qDebug("QHostInfoAgent::run(%p): looking up \"%s\"", this,
306
query->hostName.toLatin1().constData());
309
QHostInfo info = fromName(query->hostName);
310
info.setLookupId(query->object->lookupId);
311
query->object->emitResultsReady(info);
318
\enum QHostInfo::HostInfoError
320
This enum describes the various errors that can occur when trying
321
to resolve a host name.
323
\value NoError The lookup was successful.
324
\value HostNotFound No IP addresses were found for the host.
325
\value UnknownError An unknown error occurred.
327
\sa error(), setError()
331
Constructs an empty host info object with lookup ID \a id.
335
QHostInfo::QHostInfo(int id)
336
: d(new QHostInfoPrivate)
342
Constructs a copy of \a other.
344
QHostInfo::QHostInfo(const QHostInfo &other)
345
: d(new QHostInfoPrivate(*other.d))
350
Assigns the data of the \a other object to this host info object,
351
and returns a reference to it.
353
QHostInfo &QHostInfo::operator=(const QHostInfo &other)
360
Destroys the host info object.
362
QHostInfo::~QHostInfo()
368
Returns the list of IP addresses associated with hostName(). This
376
if (!info.addresses.isEmpty()) {
377
QHostAddress address = info.addresses().first();
378
// use the first IP address
382
\sa hostName(), error()
384
QList<QHostAddress> QHostInfo::addresses() const
390
Sets the list of addresses in this QHostInfo to \a addresses.
394
void QHostInfo::setAddresses(const QList<QHostAddress> &addresses)
396
d->addrs = addresses;
400
Returns the name of the host whose IP addresses were looked up.
404
QString QHostInfo::hostName() const
410
Sets the host name of this QHostInfo to \a hostName.
414
void QHostInfo::setHostName(const QString &hostName)
416
d->hostName = hostName;
420
Returns the type of error that occurred if the host name lookup
421
failed; otherwise returns NoError.
423
\sa setError(), errorString()
425
QHostInfo::HostInfoError QHostInfo::error() const
431
Sets the error type of this QHostInfo to \a error.
433
\sa error(), errorString()
435
void QHostInfo::setError(HostInfoError error)
441
Returns the ID of this lookup.
443
\sa setLookupId(), abortHostLookup(), hostName()
445
int QHostInfo::lookupId() const
451
Sets the ID of this lookup to \a id.
453
\sa lookupId(), lookupHost()
455
void QHostInfo::setLookupId(int id)
461
If the lookup failed, this function returns a human readable
462
description of the error; otherwise "Unknown error" is returned.
464
\sa setErrorString(), error()
466
QString QHostInfo::errorString() const
472
Sets the human readable description of the error that occurred to \a str
473
if the lookup failed.
475
\sa errorString(), setError()
477
void QHostInfo::setErrorString(const QString &str)
483
\fn QString QHostInfo::localHostName()
485
Returns the host name of this machine.