source: trunk/src/network/kernel/qhostinfo.cpp@ 160

Last change on this file since 160 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 13.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtNetwork module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qhostinfo.h"
43#include "qhostinfo_p.h"
44
45#include <qabstracteventdispatcher.h>
46#include <private/qunicodetables_p.h>
47#include <qcoreapplication.h>
48#include <qmetaobject.h>
49#include <qregexp.h>
50#include <private/qnativesocketengine_p.h>
51#include <qstringlist.h>
52#include <qthread.h>
53#include <qtimer.h>
54#include <qurl.h>
55
56#ifdef Q_OS_UNIX
57# include <unistd.h>
58#endif
59
60QT_BEGIN_NAMESPACE
61
62Q_GLOBAL_STATIC(QHostInfoAgent, theAgent)
63void QHostInfoAgent::staticCleanup()
64{
65 theAgent()->cleanup();
66}
67
68//#define QHOSTINFO_DEBUG
69
70/*!
71 \class QHostInfo
72 \brief The QHostInfo class provides static functions for host name lookups.
73
74 \reentrant
75 \inmodule QtNetwork
76 \ingroup io
77
78 QHostInfo uses the lookup mechanisms provided by the operating
79 system to find the IP address(es) associated with a host name,
80 or the host name associated with an IP address.
81 The class provides two static convenience functions: one that
82 works asynchronously and emits a signal once the host is found,
83 and one that blocks and returns a QHostInfo object.
84
85 To look up a host's IP addresses asynchronously, call lookupHost(),
86 which takes the host name or IP address, a receiver object, and a slot
87 signature as arguments and returns an ID. You can abort the
88 lookup by calling abortHostLookup() with the lookup ID.
89
90 Example:
91
92 \snippet doc/src/snippets/code/src_network_kernel_qhostinfo.cpp 0
93
94
95 The slot is invoked when the results are ready. (If you use
96 Qt for Embedded Linux and disabled multithreading support by defining
97 \c QT_NO_THREAD, lookupHost() will block until the lookup has
98 finished.) The results are stored in a QHostInfo object. Call
99 addresses() to get the list of IP addresses for the host, and
100 hostName() to get the host name that was looked up.
101
102 If the lookup failed, error() returns the type of error that
103 occurred. errorString() gives a human-readable description of the
104 lookup error.
105
106 If you want a blocking lookup, use the QHostInfo::fromName() function:
107
108 \snippet doc/src/snippets/code/src_network_kernel_qhostinfo.cpp 1
109
110 QHostInfo supports Internationalized Domain Names (IDNs) through the
111 IDNA and Punycode standards.
112
113 To retrieve the name of the local host, use the static
114 QHostInfo::localHostName() function.
115
116 \sa QAbstractSocket, {http://www.rfc-editor.org/rfc/rfc3492.txt}{RFC 3492}
117*/
118
119static QBasicAtomicInt theIdCounter = Q_BASIC_ATOMIC_INITIALIZER(1);
120
121/*!
122 Looks up the IP address(es) associated with host name \a name, and
123 returns an ID for the lookup. When the result of the lookup is
124 ready, the slot or signal \a member in \a receiver is called with
125 a QHostInfo argument. The QHostInfo object can then be inspected
126 to get the results of the lookup.
127
128 The lookup is performed by a single function call, for example:
129
130 \snippet doc/src/snippets/code/src_network_kernel_qhostinfo.cpp 2
131
132 The implementation of the slot prints basic information about the
133 addresses returned by the lookup, or reports an error if it failed:
134
135 \snippet doc/src/snippets/code/src_network_kernel_qhostinfo.cpp 3
136
137 If you pass a literal IP address to \a name instead of a host name,
138 QHostInfo will search for the domain name for the IP (i.e., QHostInfo will
139 perform a \e reverse lookup). On success, the resulting QHostInfo will
140 contain both the resolved domain name and IP addresses for the host
141 name. Example:
142
143 \snippet doc/src/snippets/code/src_network_kernel_qhostinfo.cpp 4
144
145 \sa abortHostLookup(), addresses(), error(), fromName()
146*/
147int QHostInfo::lookupHost(const QString &name, QObject *receiver,
148 const char *member)
149{
150#if defined QHOSTINFO_DEBUG
151 qDebug("QHostInfo::lookupHost(\"%s\", %p, %s)",
152 name.toLatin1().constData(), receiver, member ? member + 1 : 0);
153#endif
154 if (!QAbstractEventDispatcher::instance(QThread::currentThread())) {
155 qWarning("QHostInfo::lookupHost() called with no event dispatcher");
156 return -1;
157 }
158
159 qRegisterMetaType<QHostInfo>("QHostInfo");
160
161#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
162 QWindowsSockInit bust; // makes sure WSAStartup was callled
163#endif
164
165 // Support for IDNA
166 QString lookup = QString::fromLatin1(QUrl::toAce(name));
167
168 QHostInfoResult *result = new QHostInfoResult;
169 result->autoDelete = false;
170 QObject::connect(result, SIGNAL(resultsReady(QHostInfo)),
171 receiver, member);
172 int id = result->lookupId = theIdCounter.fetchAndAddRelaxed(1);
173
174 if (lookup.isEmpty()) {
175 QHostInfo info(id);
176 info.setError(QHostInfo::HostNotFound);
177 info.setErrorString(QObject::tr("No host name given"));
178 QMetaObject::invokeMethod(result, "emitResultsReady", Qt::QueuedConnection,
179 Q_ARG(QHostInfo, info));
180 result->autoDelete = true;
181 return id;
182 }
183
184 QHostInfoAgent *agent = theAgent();
185 agent->addHostName(lookup, result);
186
187#if !defined QT_NO_THREAD
188 if (!agent->isRunning())
189 agent->start();
190#else
191// if (!agent->isRunning())
192 agent->run();
193// else
194// agent->wakeOne();
195#endif
196 return id;
197}
198
199/*!
200 Aborts the host lookup with the ID \a id, as returned by lookupHost().
201
202 \sa lookupHost(), lookupId()
203*/
204void QHostInfo::abortHostLookup(int id)
205{
206 QHostInfoAgent *agent = theAgent();
207 agent->abortLookup(id);
208}
209
210/*!
211 Looks up the IP address(es) for the given host \a name. The
212 function blocks during the lookup which means that execution of
213 the program is suspended until the results of the lookup are
214 ready. Returns the result of the lookup in a QHostInfo object.
215
216 If you pass a literal IP address to \a name instead of a host name,
217 QHostInfo will search for the domain name for the IP (i.e., QHostInfo will
218 perform a \e reverse lookup). On success, the returned QHostInfo will
219 contain both the resolved domain name and IP addresses for the host name.
220
221 \sa lookupHost()
222*/
223QHostInfo QHostInfo::fromName(const QString &name)
224{
225#if defined QHOSTINFO_DEBUG
226 qDebug("QHostInfo::fromName(\"%s\")",name.toLatin1().constData());
227#endif
228
229 if (!name.isEmpty())
230 return QHostInfoAgent::fromName(QLatin1String(QUrl::toAce(name)));
231
232 QHostInfo retval;
233 retval.d->err = HostNotFound;
234 retval.d->errorStr = QObject::tr("No host name given");
235 return retval;
236}
237
238/*!
239 \internal
240 Pops a query off the queries list, performs a blocking call to
241 QHostInfoAgent::lookupHost(), and emits the resultsReady()
242 signal. This process repeats until the queries list is empty.
243*/
244void QHostInfoAgent::run()
245{
246#ifndef QT_NO_THREAD
247 // Dont' allow thread termination during event delivery, but allow it
248 // during the actual blocking host lookup stage.
249 setTerminationEnabled(false);
250 forever
251#endif
252 {
253 QHostInfoQuery *query;
254 {
255#ifndef QT_NO_THREAD
256 // the queries list is shared between threads. lock all
257 // access to it.
258 QMutexLocker locker(&mutex);
259 if (!quit && queries.isEmpty())
260 cond.wait(&mutex);
261 if (quit) {
262 // Reset the quit variable in case QCoreApplication is
263 // destroyed and recreated.
264 quit = false;
265 break;
266 }
267 if (queries.isEmpty())
268 continue;
269#else
270 if (queries.isEmpty())
271 return;
272#endif
273 query = queries.takeFirst();
274 pendingQueryId = query->object->lookupId;
275 }
276
277#if defined(QHOSTINFO_DEBUG)
278 qDebug("QHostInfoAgent::run(%p): looking up \"%s\"", this,
279 query->hostName.toLatin1().constData());
280#endif
281
282#ifndef QT_NO_THREAD
283 // Start query - allow termination at this point, but not outside. We
284 // don't want to all termination during event delivery, but we don't
285 // want the lookup to prevent the app from quitting (the agent
286 // destructor terminates the thread).
287 setTerminationEnabled(true);
288#endif
289 QHostInfo info = fromName(query->hostName);
290#ifndef QT_NO_THREAD
291 setTerminationEnabled(false);
292#endif
293
294 int id = query->object->lookupId;
295 info.setLookupId(id);
296 if (pendingQueryId == id)
297 query->object->emitResultsReady(info);
298 delete query;
299 }
300}
301
302/*!
303 \enum QHostInfo::HostInfoError
304
305 This enum describes the various errors that can occur when trying
306 to resolve a host name.
307
308 \value NoError The lookup was successful.
309 \value HostNotFound No IP addresses were found for the host.
310 \value UnknownError An unknown error occurred.
311
312 \sa error(), setError()
313*/
314
315/*!
316 Constructs an empty host info object with lookup ID \a id.
317
318 \sa lookupId()
319*/
320QHostInfo::QHostInfo(int id)
321 : d(new QHostInfoPrivate)
322{
323 d->lookupId = id;
324}
325
326/*!
327 Constructs a copy of \a other.
328*/
329QHostInfo::QHostInfo(const QHostInfo &other)
330 : d(new QHostInfoPrivate(*other.d))
331{
332}
333
334/*!
335 Assigns the data of the \a other object to this host info object,
336 and returns a reference to it.
337*/
338QHostInfo &QHostInfo::operator=(const QHostInfo &other)
339{
340 *d = *other.d;
341 return *this;
342}
343
344/*!
345 Destroys the host info object.
346*/
347QHostInfo::~QHostInfo()
348{
349 delete d;
350}
351
352/*!
353 Returns the list of IP addresses associated with hostName(). This
354 list may be empty.
355
356 Example:
357
358 \snippet doc/src/snippets/code/src_network_kernel_qhostinfo.cpp 5
359
360 \sa hostName(), error()
361*/
362QList<QHostAddress> QHostInfo::addresses() const
363{
364 return d->addrs;
365}
366
367/*!
368 Sets the list of addresses in this QHostInfo to \a addresses.
369
370 \sa addresses()
371*/
372void QHostInfo::setAddresses(const QList<QHostAddress> &addresses)
373{
374 d->addrs = addresses;
375}
376
377/*!
378 Returns the name of the host whose IP addresses were looked up.
379
380 \sa localHostName()
381*/
382QString QHostInfo::hostName() const
383{
384 return d->hostName;
385}
386
387/*!
388 Sets the host name of this QHostInfo to \a hostName.
389
390 \sa hostName()
391*/
392void QHostInfo::setHostName(const QString &hostName)
393{
394 d->hostName = hostName;
395}
396
397/*!
398 Returns the type of error that occurred if the host name lookup
399 failed; otherwise returns NoError.
400
401 \sa setError(), errorString()
402*/
403QHostInfo::HostInfoError QHostInfo::error() const
404{
405 return d->err;
406}
407
408/*!
409 Sets the error type of this QHostInfo to \a error.
410
411 \sa error(), errorString()
412*/
413void QHostInfo::setError(HostInfoError error)
414{
415 d->err = error;
416}
417
418/*!
419 Returns the ID of this lookup.
420
421 \sa setLookupId(), abortHostLookup(), hostName()
422*/
423int QHostInfo::lookupId() const
424{
425 return d->lookupId;
426}
427
428/*!
429 Sets the ID of this lookup to \a id.
430
431 \sa lookupId(), lookupHost()
432*/
433void QHostInfo::setLookupId(int id)
434{
435 d->lookupId = id;
436}
437
438/*!
439 If the lookup failed, this function returns a human readable
440 description of the error; otherwise "Unknown error" is returned.
441
442 \sa setErrorString(), error()
443*/
444QString QHostInfo::errorString() const
445{
446 return d->errorStr;
447}
448
449/*!
450 Sets the human readable description of the error that occurred to \a str
451 if the lookup failed.
452
453 \sa errorString(), setError()
454*/
455void QHostInfo::setErrorString(const QString &str)
456{
457 d->errorStr = str;
458}
459
460/*!
461 \fn QString QHostInfo::localHostName()
462
463 Returns the host name of this machine.
464
465 \sa hostName()
466*/
467
468/*!
469 \fn QString QHostInfo::localDomainName()
470
471 Returns the DNS domain of this machine.
472
473 Note: DNS domains are not related to domain names found in
474 Windows networks.
475
476 \sa hostName()
477*/
478
479QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.