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