util/src/network/socket/qnativesocketengine.cpp
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 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 //#define QNATIVESOCKETENGINE_DEBUG
       
    43 
       
    44 /*! \class QNativeSocketEngine
       
    45     \internal
       
    46 
       
    47     \brief The QNativeSocketEngine class provides low level access to a socket.
       
    48 
       
    49     \reentrant
       
    50     \ingroup network
       
    51     \inmodule QtNetwork
       
    52 
       
    53     QtSocketLayer provides basic socket functionality provided by the
       
    54     operating system. It also keeps track of what state the socket is
       
    55     in, and which errors that occur.
       
    56 
       
    57     The classes QTcpSocket, QUdpSocket and QTcpServer provide a
       
    58     higher level API, and are in general more useful for the common
       
    59     application.
       
    60 
       
    61     There are two main ways of initializing the a QNativeSocketEngine; either
       
    62     create a new socket by passing the socket type (TcpSocket or
       
    63     UdpSocket) and network layer protocol (IPv4Protocol or
       
    64     IPv6Protocol) to initialize(), or pass an existing socket
       
    65     descriptor and have QNativeSocketEngine determine the type and protocol
       
    66     itself. The native socket descriptor can later be fetched by
       
    67     calling socketDescriptor(). The socket is made non-blocking, but
       
    68     blocking behavior can still be achieved by calling waitForRead()
       
    69     and waitForWrite(). isValid() can be called to check if the socket
       
    70     has been successfully initialized and is ready to use.
       
    71 
       
    72     To connect to a host, determine its address and pass this and the
       
    73     port number to connectToHost(). The socket can then be used as a
       
    74     TCP or UDP client. Otherwise; bind(), listen() and accept() are
       
    75     used to have the socket function as a TCP or UDP server. Call
       
    76     close() to close the socket.
       
    77 
       
    78     bytesAvailable() is called to determine how much data is available
       
    79     for reading. read() and write() are used by both TCP and UDP
       
    80     clients to exchange data with the connected peer. UDP clients can
       
    81     also call hasMoreDatagrams(), nextDatagramSize(),
       
    82     readDatagram(), and writeDatagram().
       
    83 
       
    84     Call state() to determine the state of the socket, for
       
    85     example, ListeningState or ConnectedState. socketType() tells
       
    86     whether the socket is a TCP socket or a UDP socket, or if the
       
    87     socket type is unknown. protocol() is used to determine the
       
    88     socket's network layer protocol.
       
    89 
       
    90     localAddress(), localPort() are called to find the address and
       
    91     port that are currently bound to the socket. If the socket is
       
    92     connected, peerAddress() and peerPort() determine the address and
       
    93     port of the connected peer.
       
    94 
       
    95     Finally, if any function should fail, error() and
       
    96     errorString() can be called to determine the cause of the error.
       
    97 */
       
    98 
       
    99 #include <qabstracteventdispatcher.h>
       
   100 #include <qsocketnotifier.h>
       
   101 
       
   102 #include "qnativesocketengine_p.h"
       
   103 #include <private/qthread_p.h>
       
   104 #include <private/qobject_p.h>
       
   105 
       
   106 #if !defined(QT_NO_NETWORKPROXY)
       
   107 # include "qnetworkproxy.h"
       
   108 # include "qabstractsocket.h"
       
   109 # include "qtcpserver.h"
       
   110 #endif
       
   111 
       
   112 QT_BEGIN_NAMESPACE
       
   113 
       
   114 //#define QNATIVESOCKETENGINE_DEBUG
       
   115 
       
   116 #define Q_VOID
       
   117 
       
   118 // Common constructs
       
   119 #define Q_CHECK_VALID_SOCKETLAYER(function, returnValue) do { \
       
   120     if (!isValid()) { \
       
   121         qWarning(""#function" was called on an uninitialized socket device"); \
       
   122         return returnValue; \
       
   123     } } while (0)
       
   124 #define Q_CHECK_INVALID_SOCKETLAYER(function, returnValue) do { \
       
   125     if (isValid()) { \
       
   126         qWarning(""#function" was called on an already initialized socket device"); \
       
   127         return returnValue; \
       
   128     } } while (0)
       
   129 #define Q_CHECK_STATE(function, checkState, returnValue) do { \
       
   130     if (d->socketState != (checkState)) { \
       
   131         qWarning(""#function" was not called in "#checkState); \
       
   132         return (returnValue); \
       
   133     } } while (0)
       
   134 #define Q_CHECK_NOT_STATE(function, checkState, returnValue) do { \
       
   135     if (d->socketState == (checkState)) { \
       
   136         qWarning(""#function" was called in "#checkState); \
       
   137         return (returnValue); \
       
   138     } } while (0)
       
   139 #define Q_CHECK_STATES(function, state1, state2, returnValue) do { \
       
   140     if (d->socketState != (state1) && d->socketState != (state2)) { \
       
   141         qWarning(""#function" was called" \
       
   142                  " not in "#state1" or "#state2); \
       
   143         return (returnValue); \
       
   144     } } while (0)
       
   145 #define Q_CHECK_TYPE(function, type, returnValue) do { \
       
   146     if (d->socketType != (type)) { \
       
   147         qWarning(#function" was called by a" \
       
   148                  " socket other than "#type""); \
       
   149         return (returnValue); \
       
   150     } } while (0)
       
   151 #define Q_TR(a) QT_TRANSLATE_NOOP(QNativeSocketEngine, a)
       
   152 
       
   153 /*! \internal
       
   154     Constructs the private class and initializes all data members.
       
   155 
       
   156     On Windows, WSAStartup is called "recursively" for every
       
   157     concurrent QNativeSocketEngine. This is safe, because WSAStartup and
       
   158     WSACleanup are reference counted.
       
   159 */
       
   160 QNativeSocketEnginePrivate::QNativeSocketEnginePrivate()
       
   161 {
       
   162     socketDescriptor = -1;
       
   163     readNotifier = 0;
       
   164     writeNotifier = 0;
       
   165     exceptNotifier = 0;
       
   166 }
       
   167 
       
   168 /*! \internal
       
   169     Destructs the private class.
       
   170 */
       
   171 QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate()
       
   172 {
       
   173 }
       
   174 
       
   175 /*! \internal
       
   176 
       
   177     Sets the error and error string if not set already. The only
       
   178     interesting error is the first one that occurred, and not the last
       
   179     one.
       
   180 */
       
   181 void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, ErrorString errorString) const
       
   182 {
       
   183     if (hasSetSocketError) {
       
   184         // Only set socket errors once for one engine; expect the
       
   185         // socket to recreate its engine after an error. Note: There's
       
   186         // one exception: SocketError(11) bypasses this as it's purely
       
   187         // a temporary internal error condition.
       
   188         return;
       
   189     }
       
   190     if (error != QAbstractSocket::SocketError(11))
       
   191         hasSetSocketError = true;
       
   192 
       
   193     socketError = error;
       
   194 
       
   195     switch (errorString) {
       
   196     case NonBlockingInitFailedErrorString:
       
   197         socketErrorString = QNativeSocketEngine::tr("Unable to initialize non-blocking socket");
       
   198         break;
       
   199     case BroadcastingInitFailedErrorString:
       
   200         socketErrorString = QNativeSocketEngine::tr("Unable to initialize broadcast socket");
       
   201         break;
       
   202     case NoIpV6ErrorString:
       
   203         socketErrorString = QNativeSocketEngine::tr("Attempt to use IPv6 socket on a platform with no IPv6 support");
       
   204         break;
       
   205     case RemoteHostClosedErrorString:
       
   206         socketErrorString = QNativeSocketEngine::tr("The remote host closed the connection");
       
   207         break;
       
   208     case TimeOutErrorString:
       
   209         socketErrorString = QNativeSocketEngine::tr("Network operation timed out");
       
   210         break;
       
   211     case ResourceErrorString:
       
   212         socketErrorString = QNativeSocketEngine::tr("Out of resources");
       
   213         break;
       
   214     case OperationUnsupportedErrorString:
       
   215         socketErrorString = QNativeSocketEngine::tr("Unsupported socket operation");
       
   216         break;
       
   217     case ProtocolUnsupportedErrorString:
       
   218         socketErrorString = QNativeSocketEngine::tr("Protocol type not supported");
       
   219         break;
       
   220     case InvalidSocketErrorString:
       
   221         socketErrorString = QNativeSocketEngine::tr("Invalid socket descriptor");
       
   222         break;
       
   223     case HostUnreachableErrorString:
       
   224         socketErrorString = QNativeSocketEngine::tr("Host unreachable");
       
   225         break;
       
   226     case NetworkUnreachableErrorString:
       
   227         socketErrorString = QNativeSocketEngine::tr("Network unreachable");
       
   228         break;
       
   229     case AccessErrorString:
       
   230         socketErrorString = QNativeSocketEngine::tr("Permission denied");
       
   231         break;
       
   232     case ConnectionTimeOutErrorString:
       
   233         socketErrorString = QNativeSocketEngine::tr("Connection timed out");
       
   234         break;
       
   235     case ConnectionRefusedErrorString:
       
   236         socketErrorString = QNativeSocketEngine::tr("Connection refused");
       
   237         break;
       
   238     case AddressInuseErrorString:
       
   239         socketErrorString = QNativeSocketEngine::tr("The bound address is already in use");
       
   240         break;
       
   241     case AddressNotAvailableErrorString:
       
   242         socketErrorString = QNativeSocketEngine::tr("The address is not available");
       
   243         break;
       
   244     case AddressProtectedErrorString:
       
   245         socketErrorString = QNativeSocketEngine::tr("The address is protected");
       
   246         break;
       
   247     case DatagramTooLargeErrorString:
       
   248         socketErrorString = QNativeSocketEngine::tr("Datagram was too large to send");
       
   249         break;
       
   250     case SendDatagramErrorString:
       
   251         socketErrorString = QNativeSocketEngine::tr("Unable to send a message");
       
   252         break;
       
   253     case ReceiveDatagramErrorString:
       
   254         socketErrorString = QNativeSocketEngine::tr("Unable to receive a message");
       
   255         break;
       
   256     case WriteErrorString:
       
   257         socketErrorString = QNativeSocketEngine::tr("Unable to write");
       
   258         break;
       
   259     case ReadErrorString:
       
   260         socketErrorString = QNativeSocketEngine::tr("Network error");
       
   261         break;
       
   262     case PortInuseErrorString:
       
   263         socketErrorString = QNativeSocketEngine::tr("Another socket is already listening on the same port");
       
   264         break;
       
   265     case NotSocketErrorString:
       
   266         socketErrorString = QNativeSocketEngine::tr("Operation on non-socket");
       
   267         break;
       
   268     case InvalidProxyTypeString:
       
   269         socketErrorString = QNativeSocketEngine::tr("The proxy type is invalid for this operation");
       
   270         break;
       
   271     case UnknownSocketErrorString:
       
   272         socketErrorString = QNativeSocketEngine::tr("Unknown error");
       
   273         break;
       
   274     }
       
   275 }
       
   276 
       
   277 bool QNativeSocketEnginePrivate::checkProxy(const QHostAddress &address)
       
   278 {
       
   279     if (address == QHostAddress::LocalHost || address == QHostAddress::LocalHostIPv6)
       
   280         return true;
       
   281 
       
   282 #if !defined(QT_NO_NETWORKPROXY)
       
   283     QObject *parent = q_func()->parent();
       
   284     QNetworkProxy proxy;
       
   285     if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(parent)) {
       
   286         proxy = socket->proxy();
       
   287     } else if (QTcpServer *server = qobject_cast<QTcpServer *>(parent)) {
       
   288         proxy = server->proxy();
       
   289     } else {
       
   290         // no parent -> no proxy
       
   291         return true;
       
   292     }
       
   293 
       
   294     if (proxy.type() == QNetworkProxy::DefaultProxy)
       
   295         proxy = QNetworkProxy::applicationProxy();
       
   296 
       
   297     if (proxy.type() != QNetworkProxy::DefaultProxy &&
       
   298         proxy.type() != QNetworkProxy::NoProxy) {
       
   299         // QNativeSocketEngine doesn't do proxies
       
   300         setError(QAbstractSocket::UnsupportedSocketOperationError,
       
   301                  QNativeSocketEnginePrivate::InvalidProxyTypeString);
       
   302         return false;
       
   303     }
       
   304 #endif
       
   305 
       
   306     return true;
       
   307 }
       
   308 
       
   309 /*!
       
   310     Constructs a QNativeSocketEngine.
       
   311 
       
   312     \sa initialize()
       
   313 */
       
   314 QNativeSocketEngine::QNativeSocketEngine(QObject *parent)
       
   315     : QAbstractSocketEngine(*new QNativeSocketEnginePrivate(), parent)
       
   316 {
       
   317 }
       
   318 
       
   319 /*!
       
   320     Destructs a QNativeSocketEngine.
       
   321 */
       
   322 QNativeSocketEngine::~QNativeSocketEngine()
       
   323 {
       
   324     close();
       
   325 }
       
   326 
       
   327 /*!
       
   328     Initializes a QNativeSocketEngine by creating a new socket of type \a
       
   329     socketType and network layer protocol \a protocol. Returns true on
       
   330     success; otherwise returns false.
       
   331 
       
   332     If the socket was already initialized, this function closes the
       
   333     socket before reeinitializing it.
       
   334 
       
   335     The new socket is non-blocking, and for UDP sockets it's also
       
   336     broadcast enabled.
       
   337 */
       
   338 bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol protocol)
       
   339 {
       
   340     Q_D(QNativeSocketEngine);
       
   341     if (isValid())
       
   342         close();
       
   343 
       
   344 #if defined(QT_NO_IPV6)
       
   345     if (protocol == QAbstractSocket::IPv6Protocol) {
       
   346         d->setError(QAbstractSocket::UnsupportedSocketOperationError,
       
   347                     QNativeSocketEnginePrivate::NoIpV6ErrorString);
       
   348         return false;
       
   349     }
       
   350 #endif
       
   351 
       
   352     // Create the socket
       
   353     if (!d->createNewSocket(socketType, protocol)) {
       
   354 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   355         QString typeStr = QLatin1String("UnknownSocketType");
       
   356         if (socketType == QAbstractSocket::TcpSocket) typeStr = QLatin1String("TcpSocket");
       
   357         else if (socketType == QAbstractSocket::UdpSocket) typeStr = QLatin1String("UdpSocket");
       
   358         QString protocolStr = QLatin1String("UnknownProtocol");
       
   359         if (protocol == QAbstractSocket::IPv4Protocol) protocolStr = QLatin1String("IPv4Protocol");
       
   360         else if (protocol == QAbstractSocket::IPv6Protocol) protocolStr = QLatin1String("IPv6Protocol");
       
   361         qDebug("QNativeSocketEngine::initialize(type == %s, protocol == %s) failed: %s",
       
   362                typeStr.toLatin1().constData(), protocolStr.toLatin1().constData(), d->socketErrorString.toLatin1().constData());
       
   363 #endif
       
   364         return false;
       
   365     }
       
   366 
       
   367     // Make the socket nonblocking.
       
   368     if (!setOption(NonBlockingSocketOption, 1)) {
       
   369         d->setError(QAbstractSocket::UnsupportedSocketOperationError,
       
   370                     QNativeSocketEnginePrivate::NonBlockingInitFailedErrorString);
       
   371         close();
       
   372         return false;
       
   373     }
       
   374 
       
   375     // Set the broadcasting flag if it's a UDP socket.
       
   376     if (socketType == QAbstractSocket::UdpSocket
       
   377         && !setOption(BroadcastSocketOption, 1)) {
       
   378         d->setError(QAbstractSocket::UnsupportedSocketOperationError,
       
   379                     QNativeSocketEnginePrivate::BroadcastingInitFailedErrorString);
       
   380         close();
       
   381         return false;
       
   382     }
       
   383 
       
   384 
       
   385     // Make sure we receive out-of-band data
       
   386     // On Symbian OS this works only with native IP stack, not with WinSock
       
   387     if (socketType == QAbstractSocket::TcpSocket
       
   388         && !setOption(ReceiveOutOfBandData, 1)) {
       
   389         qWarning("QNativeSocketEngine::initialize unable to inline out-of-band data");
       
   390     }
       
   391 
       
   392     // Before Qt 4.6, we always set the send and receive buffer size to 49152 as
       
   393     // this was found to be an optimal value. However, modern OS
       
   394     // all have some kind of auto tuning for this and we therefore don't set
       
   395     // this explictly anymore.
       
   396     // If it introduces any performance regressions for Qt 4.6.x (x > 0) then
       
   397     // it will be put back in.
       
   398     //
       
   399     // You can use tests/manual/qhttpnetworkconnection to test HTTP download speed
       
   400     // with this.
       
   401     //
       
   402     // pre-4.6:
       
   403     // setReceiveBufferSize(49152);
       
   404     // setSendBufferSize(49152);
       
   405 
       
   406     d->socketType = socketType;
       
   407     d->socketProtocol = protocol;
       
   408     return true;
       
   409 }
       
   410 
       
   411 /*! \overload
       
   412 
       
   413     Initializes the socket using \a socketDescriptor instead of
       
   414     creating a new one. The socket type and network layer protocol are
       
   415     determined automatically. The socket's state is set to \a
       
   416     socketState.
       
   417 
       
   418     If the socket type is either TCP or UDP, it is made non-blocking.
       
   419     UDP sockets are also broadcast enabled.
       
   420  */
       
   421 bool QNativeSocketEngine::initialize(int socketDescriptor, QAbstractSocket::SocketState socketState)
       
   422 {
       
   423     Q_D(QNativeSocketEngine);
       
   424 
       
   425     if (isValid())
       
   426         close();
       
   427 
       
   428     d->socketDescriptor = socketDescriptor;
       
   429 
       
   430     // determine socket type and protocol
       
   431     if (!d->fetchConnectionParameters()) {
       
   432 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   433         qDebug("QNativeSocketEngine::initialize(socketDescriptor == %i) failed: %s",
       
   434                socketDescriptor, d->socketErrorString.toLatin1().constData());
       
   435 #endif
       
   436         d->socketDescriptor = -1;
       
   437         return false;
       
   438     }
       
   439 
       
   440     if (d->socketType != QAbstractSocket::UnknownSocketType) {
       
   441         // Make the socket nonblocking.
       
   442         if (!setOption(NonBlockingSocketOption, 1)) {
       
   443             d->setError(QAbstractSocket::UnsupportedSocketOperationError,
       
   444                 QNativeSocketEnginePrivate::NonBlockingInitFailedErrorString);
       
   445             close();
       
   446             return false;
       
   447         }
       
   448 
       
   449         // Set the broadcasting flag if it's a UDP socket.
       
   450         if (d->socketType == QAbstractSocket::UdpSocket
       
   451             && !setOption(BroadcastSocketOption, 1)) {
       
   452             d->setError(QAbstractSocket::UnsupportedSocketOperationError,
       
   453                 QNativeSocketEnginePrivate::BroadcastingInitFailedErrorString);
       
   454             close();
       
   455             return false;
       
   456         }
       
   457     }
       
   458 
       
   459     d->socketState = socketState;
       
   460     return true;
       
   461 }
       
   462 
       
   463 /*!
       
   464     Returns true if the socket is valid; otherwise returns false. A
       
   465     socket is valid if it has not been successfully initialized, or if
       
   466     it has been closed.
       
   467 */
       
   468 bool QNativeSocketEngine::isValid() const
       
   469 {
       
   470     Q_D(const QNativeSocketEngine);
       
   471     return d->socketDescriptor != -1;
       
   472 }
       
   473 
       
   474 /*!
       
   475     Returns the native socket descriptor. Any use of this descriptor
       
   476     stands the risk of being non-portable.
       
   477 */
       
   478 int QNativeSocketEngine::socketDescriptor() const
       
   479 {
       
   480     Q_D(const QNativeSocketEngine);
       
   481     return d->socketDescriptor;
       
   482 }
       
   483 
       
   484 /*!
       
   485     Connects to the IP address and port specified by \a address and \a
       
   486     port. If the connection is established, this function returns true
       
   487     and the socket enters ConnectedState. Otherwise, false is
       
   488     returned.
       
   489 
       
   490     If false is returned, state() should be called to see if the
       
   491     socket is in ConnectingState. If so, a delayed TCP connection is
       
   492     taking place, and connectToHost() must be called again later to
       
   493     determine if the connection was established successfully or
       
   494     not. The second connection attempt must be made when the socket is
       
   495     ready for writing. This state can be determined either by
       
   496     connecting a QSocketNotifier to the socket descriptor returned by
       
   497     socketDescriptor(), or by calling the blocking function
       
   498     waitForWrite().
       
   499 
       
   500     Example:
       
   501     \snippet doc/src/snippets/code/src_network_socket_qnativesocketengine.cpp 0
       
   502 
       
   503     Otherwise, error() should be called to determine the cause of the
       
   504     error.
       
   505 */
       
   506 bool QNativeSocketEngine::connectToHost(const QHostAddress &address, quint16 port)
       
   507 {
       
   508     Q_D(QNativeSocketEngine);
       
   509     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::connectToHost(), false);
       
   510 
       
   511 #if defined (QT_NO_IPV6)
       
   512     if (address.protocol() == QAbstractSocket::IPv6Protocol) {
       
   513         d->setError(QAbstractSocket::UnsupportedSocketOperationError,
       
   514                     QNativeSocketEnginePrivate::NoIpV6ErrorString);
       
   515         return false;
       
   516     }
       
   517 #endif
       
   518     if (!d->checkProxy(address))
       
   519         return false;
       
   520 
       
   521     Q_CHECK_STATES(QNativeSocketEngine::connectToHost(),
       
   522                    QAbstractSocket::UnconnectedState, QAbstractSocket::ConnectingState, false);
       
   523 
       
   524     d->peerAddress = address;
       
   525     d->peerPort = port;
       
   526     bool connected = d->nativeConnect(address, port);
       
   527     if (connected)
       
   528         d->fetchConnectionParameters();
       
   529 
       
   530     return connected;
       
   531 }
       
   532 
       
   533 /*!
       
   534     If there's a connection activity on the socket, process it. Then
       
   535     notify our parent if there really was activity.
       
   536 */
       
   537 void QNativeSocketEngine::connectionNotification()
       
   538 {
       
   539     Q_D(QNativeSocketEngine);
       
   540     Q_ASSERT(state() == QAbstractSocket::ConnectingState);
       
   541 
       
   542     connectToHost(d->peerAddress, d->peerPort);
       
   543     if (state() != QAbstractSocket::ConnectingState) {
       
   544         // we changed states
       
   545         QAbstractSocketEngine::connectionNotification();
       
   546     }
       
   547 }
       
   548 
       
   549 /*!
       
   550     Connects to the remote host name given by \a name on port \a
       
   551     port. When this function is called, the upper-level will not
       
   552     perform a hostname lookup.
       
   553 
       
   554     The native socket engine does not support this operation,
       
   555     but some other socket engines (notably proxy-based ones) do.
       
   556 */
       
   557 bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
       
   558 {
       
   559     Q_UNUSED(name);
       
   560     Q_UNUSED(port);
       
   561     Q_D(QNativeSocketEngine);
       
   562     d->setError(QAbstractSocket::UnsupportedSocketOperationError,
       
   563                 QNativeSocketEnginePrivate::OperationUnsupportedErrorString);
       
   564     return false;
       
   565 }
       
   566 
       
   567 /*!
       
   568     Binds the socket to the address \a address and port \a
       
   569     port. Returns true on success; otherwise false is returned. The
       
   570     port may be 0, in which case an arbitrary unused port is assigned
       
   571     automatically by the operating system.
       
   572 
       
   573     Servers call this function to set up the server's address and
       
   574     port. TCP servers must in addition call listen() after bind().
       
   575 */
       
   576 bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
       
   577 {
       
   578     Q_D(QNativeSocketEngine);
       
   579     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bind(), false);
       
   580 
       
   581 #if defined (QT_NO_IPV6)
       
   582     if (address.protocol() == QAbstractSocket::IPv6Protocol) {
       
   583         d->setError(QAbstractSocket::UnsupportedSocketOperationError,
       
   584                     QNativeSocketEnginePrivate::NoIpV6ErrorString);
       
   585         return false;
       
   586     }
       
   587 #endif
       
   588     if (!d->checkProxy(address))
       
   589         return false;
       
   590 
       
   591     Q_CHECK_STATE(QNativeSocketEngine::bind(), QAbstractSocket::UnconnectedState, false);
       
   592 
       
   593     if (!d->nativeBind(address, port))
       
   594         return false;
       
   595 
       
   596     d->fetchConnectionParameters();
       
   597     return true;
       
   598 }
       
   599 
       
   600 /*!
       
   601     Prepares a TCP server for accepting incoming connections. This
       
   602     function must be called after bind(), and only by TCP sockets.
       
   603 
       
   604     After this function has been called, pending client connections
       
   605     are detected by checking if the socket is ready for reading. This
       
   606     can be done by either creating a QSocketNotifier, passing the
       
   607     socket descriptor returned by socketDescriptor(), or by calling
       
   608     the blocking function waitForRead().
       
   609 
       
   610     Example:
       
   611     \snippet doc/src/snippets/code/src_network_socket_qnativesocketengine.cpp 1
       
   612 
       
   613     \sa bind(), accept()
       
   614 */
       
   615 bool QNativeSocketEngine::listen()
       
   616 {
       
   617     Q_D(QNativeSocketEngine);
       
   618     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::listen(), false);
       
   619     Q_CHECK_STATE(QNativeSocketEngine::listen(), QAbstractSocket::BoundState, false);
       
   620     Q_CHECK_TYPE(QNativeSocketEngine::listen(), QAbstractSocket::TcpSocket, false);
       
   621 
       
   622     // We're using a backlog of 50. Most modern kernels support TCP
       
   623     // syncookies by default, and if they do, the backlog is ignored.
       
   624     // When there is no support for TCP syncookies, this value is
       
   625     // fine.
       
   626     return d->nativeListen(50);
       
   627 }
       
   628 
       
   629 /*!
       
   630     Accepts a pending connection from the socket, which must be in
       
   631     ListeningState, and returns its socket descriptor. If no pending
       
   632     connections are available, -1 is returned.
       
   633 
       
   634     \sa bind(), listen()
       
   635 */
       
   636 int QNativeSocketEngine::accept()
       
   637 {
       
   638     Q_D(QNativeSocketEngine);
       
   639     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::accept(), -1);
       
   640     Q_CHECK_STATE(QNativeSocketEngine::accept(), QAbstractSocket::ListeningState, false);
       
   641     Q_CHECK_TYPE(QNativeSocketEngine::accept(), QAbstractSocket::TcpSocket, false);
       
   642 
       
   643     return d->nativeAccept();
       
   644 }
       
   645 
       
   646 /*!
       
   647     Returns the number of bytes that are currently available for
       
   648     reading. On error, -1 is returned.
       
   649 
       
   650     For UDP sockets, this function returns the accumulated size of all
       
   651     pending datagrams, and it is therefore more useful for UDP sockets
       
   652     to call hasPendingDatagrams() and pendingDatagramSize().
       
   653 */
       
   654 qint64 QNativeSocketEngine::bytesAvailable() const
       
   655 {
       
   656     Q_D(const QNativeSocketEngine);
       
   657     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bytesAvailable(), -1);
       
   658     Q_CHECK_NOT_STATE(QNativeSocketEngine::bytesAvailable(), QAbstractSocket::UnconnectedState, false);
       
   659 
       
   660     return d->nativeBytesAvailable();
       
   661 }
       
   662 
       
   663 /*!
       
   664     Returns true if there is at least one datagram pending. This
       
   665     function is only called by UDP sockets, where a datagram can have
       
   666     a size of 0. TCP sockets call bytesAvailable().
       
   667 */
       
   668 bool QNativeSocketEngine::hasPendingDatagrams() const
       
   669 {
       
   670     Q_D(const QNativeSocketEngine);
       
   671     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::hasPendingDatagrams(), false);
       
   672     Q_CHECK_NOT_STATE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UnconnectedState, false);
       
   673     Q_CHECK_TYPE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UdpSocket, false);
       
   674 
       
   675     return d->nativeHasPendingDatagrams();
       
   676 }
       
   677 
       
   678 /*!
       
   679     Returns the size of the pending datagram, or -1 if no datagram is
       
   680     pending. A datagram size of 0 is perfectly valid. This function is
       
   681     called by UDP sockets before receiveMessage(). For TCP sockets,
       
   682     call bytesAvailable().
       
   683 */
       
   684 qint64 QNativeSocketEngine::pendingDatagramSize() const
       
   685 {
       
   686     Q_D(const QNativeSocketEngine);
       
   687     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::pendingDatagramSize(), -1);
       
   688     Q_CHECK_TYPE(QNativeSocketEngine::pendingDatagramSize(), QAbstractSocket::UdpSocket, false);
       
   689 
       
   690     return d->nativePendingDatagramSize();
       
   691 }
       
   692 
       
   693 /*!
       
   694     Reads up to \a maxSize bytes of a datagram from the socket,
       
   695     stores it in \a data and returns the number of bytes read. The
       
   696     address and port of the sender are stored in \a address and \a
       
   697     port. If either of these pointers is 0, the corresponding value is
       
   698     discarded.
       
   699 
       
   700     To avoid unnecessarily loss of data, call pendingDatagramSize() to
       
   701     determine the size of the pending message before reading it. If \a
       
   702     maxSize is too small, the rest of the datagram will be lost.
       
   703 
       
   704     Returns -1 if an error occurred.
       
   705 
       
   706     \sa hasPendingDatagrams()
       
   707 */
       
   708 qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxSize, QHostAddress *address,
       
   709                                       quint16 *port)
       
   710 {
       
   711     Q_D(QNativeSocketEngine);
       
   712     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::readDatagram(), -1);
       
   713     Q_CHECK_TYPE(QNativeSocketEngine::readDatagram(), QAbstractSocket::UdpSocket, false);
       
   714 
       
   715     return d->nativeReceiveDatagram(data, maxSize, address, port);
       
   716 }
       
   717 
       
   718 /*!
       
   719     Writes a UDP datagram of size \a size bytes to the socket from
       
   720     \a data to the address \a host on port \a port, and returns the
       
   721     number of bytes written, or -1 if an error occurred.
       
   722 
       
   723     Only one datagram is sent, and if there is too much data to fit
       
   724     into a single datagram, the operation will fail and error()
       
   725     will return QAbstractSocket::DatagramTooLargeError. Operating systems impose an
       
   726     upper limit to the size of a datagram, but this size is different
       
   727     on almost all platforms. Sending large datagrams is in general
       
   728     disadvised, as even if they are sent successfully, they are likely
       
   729     to be fragmented before arriving at their destination.
       
   730 
       
   731     Experience has shown that it is in general safe to send datagrams
       
   732     no larger than 512 bytes.
       
   733 
       
   734     \sa readDatagram()
       
   735 */
       
   736 qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 size,
       
   737                                        const QHostAddress &host, quint16 port)
       
   738 {
       
   739     Q_D(QNativeSocketEngine);
       
   740     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::writeDatagram(), -1);
       
   741     Q_CHECK_TYPE(QNativeSocketEngine::writeDatagram(), QAbstractSocket::UdpSocket, -1);
       
   742     return d->nativeSendDatagram(data, size, host, port);
       
   743 }
       
   744 
       
   745 /*!
       
   746     Writes a block of \a size bytes from \a data to the socket.
       
   747     Returns the number of bytes written, or -1 if an error occurred.
       
   748 */
       
   749 qint64 QNativeSocketEngine::write(const char *data, qint64 size)
       
   750 {
       
   751     Q_D(QNativeSocketEngine);
       
   752     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::write(), -1);
       
   753     Q_CHECK_STATE(QNativeSocketEngine::write(), QAbstractSocket::ConnectedState, -1);
       
   754     return d->nativeWrite(data, size);
       
   755 }
       
   756 
       
   757 
       
   758 qint64 QNativeSocketEngine::bytesToWrite() const
       
   759 {
       
   760     return 0;
       
   761 }
       
   762 
       
   763 /*!
       
   764     Reads up to \a maxSize bytes into \a data from the socket.
       
   765     Returns the number of bytes read, or -1 if an error occurred.
       
   766 */
       
   767 qint64 QNativeSocketEngine::read(char *data, qint64 maxSize)
       
   768 {
       
   769     Q_D(QNativeSocketEngine);
       
   770     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::read(), -1);
       
   771     Q_CHECK_STATES(QNativeSocketEngine::read(), QAbstractSocket::ConnectedState, QAbstractSocket::BoundState, -1);
       
   772 
       
   773     qint64 readBytes = d->nativeRead(data, maxSize);
       
   774 
       
   775     // Handle remote close
       
   776     if (readBytes == 0 && d->socketType == QAbstractSocket::TcpSocket) {
       
   777         d->setError(QAbstractSocket::RemoteHostClosedError,
       
   778                     QNativeSocketEnginePrivate::RemoteHostClosedErrorString);
       
   779         close();
       
   780         return -1;
       
   781     } else if (readBytes == -1) {
       
   782         if (!d->hasSetSocketError) {
       
   783             d->hasSetSocketError = true;
       
   784             d->socketError = QAbstractSocket::NetworkError;
       
   785             d->socketErrorString = qt_error_string();
       
   786         }
       
   787         close();
       
   788         return -1;
       
   789     }
       
   790     return readBytes;
       
   791 }
       
   792 
       
   793 /*!
       
   794     Closes the socket. In order to use the socket again, initialize()
       
   795     must be called.
       
   796 */
       
   797 void QNativeSocketEngine::close()
       
   798 {
       
   799     Q_D(QNativeSocketEngine);
       
   800     if (d->readNotifier)
       
   801         d->readNotifier->setEnabled(false);
       
   802     if (d->writeNotifier)
       
   803         d->writeNotifier->setEnabled(false);
       
   804     if (d->exceptNotifier)
       
   805         d->exceptNotifier->setEnabled(false);
       
   806 
       
   807     if(d->socketDescriptor != -1) {
       
   808         d->nativeClose();
       
   809         d->socketDescriptor = -1;
       
   810     }
       
   811     d->socketState = QAbstractSocket::UnconnectedState;
       
   812     d->hasSetSocketError = false;
       
   813     d->localPort = 0;
       
   814     d->localAddress.clear();
       
   815     d->peerPort = 0;
       
   816     d->peerAddress.clear();
       
   817     if (d->readNotifier) {
       
   818         qDeleteInEventHandler(d->readNotifier);
       
   819         d->readNotifier = 0;
       
   820     }
       
   821     if (d->writeNotifier) {
       
   822         qDeleteInEventHandler(d->writeNotifier);
       
   823         d->writeNotifier = 0;
       
   824     }
       
   825     if (d->exceptNotifier) {
       
   826         qDeleteInEventHandler(d->exceptNotifier);
       
   827         d->exceptNotifier = 0;
       
   828     }
       
   829 }
       
   830 
       
   831 /*!
       
   832     Waits for \a msecs milliseconds or until the socket is ready for
       
   833     reading. If \a timedOut is not 0 and \a msecs milliseconds have
       
   834     passed, the value of \a timedOut is set to true.
       
   835 
       
   836     Returns true if data is available for reading; otherwise returns
       
   837     false.
       
   838 
       
   839     This is a blocking function call; its use is disadvised in a
       
   840     single threaded application, as the whole thread will stop
       
   841     responding until the function returns. waitForRead() is most
       
   842     useful when there is no event loop available. The general approach
       
   843     is to create a QSocketNotifier, passing the socket descriptor
       
   844     returned by socketDescriptor() to its constructor.
       
   845 */
       
   846 bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut)
       
   847 {
       
   848     Q_D(const QNativeSocketEngine);
       
   849     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForRead(), false);
       
   850     Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForRead(),
       
   851                       QAbstractSocket::UnconnectedState, false);
       
   852 
       
   853     if (timedOut)
       
   854         *timedOut = false;
       
   855 
       
   856     int ret = d->nativeSelect(msecs, true);
       
   857     if (ret == 0) {
       
   858         if (timedOut)
       
   859             *timedOut = true;
       
   860         d->setError(QAbstractSocket::SocketTimeoutError,
       
   861             QNativeSocketEnginePrivate::TimeOutErrorString);
       
   862         return false;
       
   863     } else if (state() == QAbstractSocket::ConnectingState) {
       
   864         connectToHost(d->peerAddress, d->peerPort);
       
   865     }
       
   866 
       
   867     return ret > 0;
       
   868 }
       
   869 
       
   870 /*!
       
   871     Waits for \a msecs milliseconds or until the socket is ready for
       
   872     writing. If \a timedOut is not 0 and \a msecs milliseconds have
       
   873     passed, the value of \a timedOut is set to true.
       
   874 
       
   875     Returns true if data is available for writing; otherwise returns
       
   876     false.
       
   877 
       
   878     This is a blocking function call; its use is disadvised in a
       
   879     single threaded application, as the whole thread will stop
       
   880     responding until the function returns. waitForWrite() is most
       
   881     useful when there is no event loop available. The general approach
       
   882     is to create a QSocketNotifier, passing the socket descriptor
       
   883     returned by socketDescriptor() to its constructor.
       
   884 */
       
   885 bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut)
       
   886 {
       
   887     Q_D(QNativeSocketEngine);
       
   888     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForWrite(), false);
       
   889     Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForWrite(),
       
   890                       QAbstractSocket::UnconnectedState, false);
       
   891 
       
   892     if (timedOut)
       
   893         *timedOut = false;
       
   894 
       
   895     int ret = d->nativeSelect(msecs, false);
       
   896     // On Windows, the socket is in connected state if a call to
       
   897     // select(writable) is successful. In this case we should not
       
   898     // issue a second call to WSAConnect()
       
   899 #if defined (Q_WS_WIN)
       
   900     if (ret > 0) {
       
   901         setState(QAbstractSocket::ConnectedState);
       
   902         d_func()->fetchConnectionParameters();
       
   903         return true;
       
   904     } else {
       
   905         int value = 0;
       
   906         int valueSize = sizeof(value);
       
   907         if (::getsockopt(d->socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) {
       
   908             if (value == WSAECONNREFUSED) {
       
   909                 d->setError(QAbstractSocket::ConnectionRefusedError, QNativeSocketEnginePrivate::ConnectionRefusedErrorString);
       
   910                 d->socketState = QAbstractSocket::UnconnectedState;
       
   911                 return false;
       
   912             } else if (value == WSAETIMEDOUT) {
       
   913                 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::ConnectionTimeOutErrorString);
       
   914                 d->socketState = QAbstractSocket::UnconnectedState;
       
   915                 return false;
       
   916             } else if (value == WSAEHOSTUNREACH) {
       
   917                 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::HostUnreachableErrorString);
       
   918                 d->socketState = QAbstractSocket::UnconnectedState;
       
   919                 return false;
       
   920             }
       
   921         }
       
   922     }
       
   923 #endif
       
   924 
       
   925     if (ret == 0) {
       
   926         if (timedOut)
       
   927             *timedOut = true;
       
   928         d->setError(QAbstractSocket::SocketTimeoutError,
       
   929                     QNativeSocketEnginePrivate::TimeOutErrorString);
       
   930         return false;
       
   931     } else if (state() == QAbstractSocket::ConnectingState) {
       
   932         connectToHost(d->peerAddress, d->peerPort);
       
   933     }
       
   934 
       
   935     return ret > 0;
       
   936 }
       
   937 
       
   938 bool QNativeSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite,
       
   939                                       bool checkRead, bool checkWrite,
       
   940                                       int msecs, bool *timedOut)
       
   941 {
       
   942     Q_D(QNativeSocketEngine);
       
   943     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForWrite(), false);
       
   944     Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForReadOrWrite(),
       
   945                       QAbstractSocket::UnconnectedState, false);
       
   946 
       
   947     int ret = d->nativeSelect(msecs, checkRead, checkWrite, readyToRead, readyToWrite);
       
   948     // On Windows, the socket is in connected state if a call to
       
   949     // select(writable) is successful. In this case we should not
       
   950     // issue a second call to WSAConnect()
       
   951 #if defined (Q_WS_WIN)
       
   952     if (checkWrite && ((readyToWrite && *readyToWrite) || !readyToWrite) && ret > 0) {
       
   953         setState(QAbstractSocket::ConnectedState);
       
   954         d_func()->fetchConnectionParameters();
       
   955         return true;
       
   956     } else {
       
   957         int value = 0;
       
   958         int valueSize = sizeof(value);
       
   959         if (::getsockopt(d->socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) {
       
   960             if (value == WSAECONNREFUSED) {
       
   961                 d->setError(QAbstractSocket::ConnectionRefusedError, QNativeSocketEnginePrivate::ConnectionRefusedErrorString);
       
   962                 d->socketState = QAbstractSocket::UnconnectedState;
       
   963                 return false;
       
   964             } else if (value == WSAETIMEDOUT) {
       
   965                 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::ConnectionTimeOutErrorString);
       
   966                 d->socketState = QAbstractSocket::UnconnectedState;
       
   967                 return false;
       
   968             } else if (value == WSAEHOSTUNREACH) {
       
   969                 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::HostUnreachableErrorString);
       
   970                 d->socketState = QAbstractSocket::UnconnectedState;
       
   971                 return false;
       
   972             }
       
   973         }
       
   974     }
       
   975 #endif
       
   976     if (ret == 0) {
       
   977         if (timedOut)
       
   978             *timedOut = true;
       
   979         d->setError(QAbstractSocket::SocketTimeoutError,
       
   980                     QNativeSocketEnginePrivate::TimeOutErrorString);
       
   981         return false;
       
   982     } else if (state() == QAbstractSocket::ConnectingState) {
       
   983         connectToHost(d->peerAddress, d->peerPort);
       
   984     }
       
   985 
       
   986     return ret > 0;
       
   987 }
       
   988 
       
   989 /*!
       
   990     Returns the size of the operating system's socket receive
       
   991     buffer. Depending on the operating system, this size may be
       
   992     different from what has been set earlier with
       
   993     setReceiveBufferSize().
       
   994 */
       
   995 qint64 QNativeSocketEngine::receiveBufferSize() const
       
   996 {
       
   997     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::receiveBufferSize(), -1);
       
   998     return option(ReceiveBufferSocketOption);
       
   999 }
       
  1000 
       
  1001 /*!
       
  1002     Sets the size of the operating system receive buffer to \a size.
       
  1003 
       
  1004     For clients, this should be set before connectToHost() is called;
       
  1005     otherwise it will have no effect. For servers, it should be called
       
  1006     before listen().
       
  1007 
       
  1008     The operating system receive buffer size effectively limits two
       
  1009     things: how much data can be in transit at any one moment, and how
       
  1010     much data can be received in one iteration of the main event loop.
       
  1011     Setting the size of the receive buffer may have an impact on the
       
  1012     socket's performance.
       
  1013 
       
  1014     The default value is operating system-dependent.
       
  1015 */
       
  1016 void QNativeSocketEngine::setReceiveBufferSize(qint64 size)
       
  1017 {
       
  1018     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setReceiveBufferSize(), Q_VOID);
       
  1019     setOption(ReceiveBufferSocketOption, size);
       
  1020 }
       
  1021 
       
  1022 /*!
       
  1023     Returns the size of the operating system send buffer. Depending on
       
  1024     the operating system, this size may be different from what has
       
  1025     been set earlier with setSendBufferSize().
       
  1026 */
       
  1027 qint64 QNativeSocketEngine::sendBufferSize() const
       
  1028 {
       
  1029     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setSendBufferSize(), -1);
       
  1030     return option(SendBufferSocketOption);
       
  1031 }
       
  1032 
       
  1033 /*!
       
  1034     Sets the size of the operating system send buffer to \a size.
       
  1035 
       
  1036     The operating system send buffer size effectively limits how much
       
  1037     data can be in transit at any one moment. Setting the size of the
       
  1038     send buffer may have an impact on the socket's performance.
       
  1039 
       
  1040     The default value is operating system-dependent.
       
  1041 */
       
  1042 void QNativeSocketEngine::setSendBufferSize(qint64 size)
       
  1043 {
       
  1044     Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setSendBufferSize(), Q_VOID);
       
  1045     setOption(SendBufferSocketOption, size);
       
  1046 }
       
  1047 
       
  1048 
       
  1049 /*!
       
  1050     Sets the option \a option to the value \a value.
       
  1051 */
       
  1052 bool QNativeSocketEngine::setOption(SocketOption option, int value)
       
  1053 {
       
  1054     Q_D(QNativeSocketEngine);
       
  1055     return d->setOption(option, value);
       
  1056 }
       
  1057 
       
  1058 /*!
       
  1059     Returns the value of the option \a socketOption.
       
  1060 */
       
  1061 int QNativeSocketEngine::option(SocketOption socketOption) const
       
  1062 {
       
  1063     Q_D(const QNativeSocketEngine);
       
  1064     return d->option(socketOption);
       
  1065 }
       
  1066 
       
  1067 bool QNativeSocketEngine::isReadNotificationEnabled() const
       
  1068 {
       
  1069     Q_D(const QNativeSocketEngine);
       
  1070     return d->readNotifier && d->readNotifier->isEnabled();
       
  1071 }
       
  1072 
       
  1073 /*
       
  1074   \internal
       
  1075   \class QReadNotifier
       
  1076   \brief The QReadNotifer class is used to improve performance.
       
  1077 
       
  1078   QReadNotifier is a private class used for performance reasons vs
       
  1079   connecting to the QSocketNotifier activated() signal.
       
  1080  */
       
  1081 class QReadNotifier : public QSocketNotifier
       
  1082 {
       
  1083 public:
       
  1084     QReadNotifier(int fd, QNativeSocketEngine *parent)
       
  1085         : QSocketNotifier(fd, QSocketNotifier::Read, parent)
       
  1086     { engine = parent; }
       
  1087 
       
  1088 protected:
       
  1089     bool event(QEvent *);
       
  1090 
       
  1091     QNativeSocketEngine *engine;
       
  1092 };
       
  1093 
       
  1094 bool QReadNotifier::event(QEvent *e)
       
  1095 {
       
  1096     if (e->type() == QEvent::SockAct) {
       
  1097         engine->readNotification();
       
  1098         return true;
       
  1099     }
       
  1100     return QSocketNotifier::event(e);
       
  1101 }
       
  1102 
       
  1103 /*
       
  1104   \internal
       
  1105   \class QWriteNotifier
       
  1106   \brief The QWriteNotifer class is used to improve performance.
       
  1107 
       
  1108   QWriteNotifier is a private class used for performance reasons vs
       
  1109   connecting to the QSocketNotifier activated() signal.
       
  1110  */
       
  1111 class QWriteNotifier : public QSocketNotifier
       
  1112 {
       
  1113 public:
       
  1114     QWriteNotifier(int fd, QNativeSocketEngine *parent)
       
  1115         : QSocketNotifier(fd, QSocketNotifier::Write, parent) { engine = parent; }
       
  1116 
       
  1117 protected:
       
  1118     bool event(QEvent *);
       
  1119 
       
  1120     QNativeSocketEngine *engine;
       
  1121 };
       
  1122 
       
  1123 bool QWriteNotifier::event(QEvent *e)
       
  1124 {
       
  1125     if (e->type() == QEvent::SockAct) {
       
  1126         if (engine->state() == QAbstractSocket::ConnectingState)
       
  1127             engine->connectionNotification();
       
  1128         else
       
  1129             engine->writeNotification();
       
  1130         return true;
       
  1131     }
       
  1132     return QSocketNotifier::event(e);
       
  1133 }
       
  1134 
       
  1135 class QExceptionNotifier : public QSocketNotifier
       
  1136 {
       
  1137 public:
       
  1138     QExceptionNotifier(int fd, QNativeSocketEngine *parent)
       
  1139         : QSocketNotifier(fd, QSocketNotifier::Exception, parent) { engine = parent; }
       
  1140 
       
  1141 protected:
       
  1142     bool event(QEvent *);
       
  1143 
       
  1144     QNativeSocketEngine *engine;
       
  1145 };
       
  1146 
       
  1147 bool QExceptionNotifier::event(QEvent *e)
       
  1148 {
       
  1149     if (e->type() == QEvent::SockAct) {
       
  1150         if (engine->state() == QAbstractSocket::ConnectingState)
       
  1151             engine->connectionNotification();
       
  1152         else
       
  1153             engine->exceptionNotification();
       
  1154         return true;
       
  1155     }
       
  1156     return QSocketNotifier::event(e);
       
  1157 }
       
  1158 
       
  1159 void QNativeSocketEngine::setReadNotificationEnabled(bool enable)
       
  1160 {
       
  1161     Q_D(QNativeSocketEngine);
       
  1162     if (d->readNotifier) {
       
  1163         d->readNotifier->setEnabled(enable);
       
  1164     } else if (enable && d->threadData->eventDispatcher) {
       
  1165         d->readNotifier = new QReadNotifier(d->socketDescriptor, this);
       
  1166         d->readNotifier->setEnabled(true);
       
  1167     }
       
  1168 }
       
  1169 
       
  1170 bool QNativeSocketEngine::isWriteNotificationEnabled() const
       
  1171 {
       
  1172     Q_D(const QNativeSocketEngine);
       
  1173     return d->writeNotifier && d->writeNotifier->isEnabled();
       
  1174 }
       
  1175 
       
  1176 void QNativeSocketEngine::setWriteNotificationEnabled(bool enable)
       
  1177 {
       
  1178     Q_D(QNativeSocketEngine);
       
  1179     if (d->writeNotifier) {
       
  1180         d->writeNotifier->setEnabled(enable);
       
  1181     } else if (enable && d->threadData->eventDispatcher) {
       
  1182         d->writeNotifier = new QWriteNotifier(d->socketDescriptor, this);
       
  1183         d->writeNotifier->setEnabled(true);
       
  1184     }
       
  1185 }
       
  1186 
       
  1187 bool QNativeSocketEngine::isExceptionNotificationEnabled() const
       
  1188 {
       
  1189     Q_D(const QNativeSocketEngine);
       
  1190     return d->exceptNotifier && d->exceptNotifier->isEnabled();
       
  1191 }
       
  1192 
       
  1193 void QNativeSocketEngine::setExceptionNotificationEnabled(bool enable)
       
  1194 {
       
  1195     Q_D(QNativeSocketEngine);
       
  1196     if (d->exceptNotifier) {
       
  1197         d->exceptNotifier->setEnabled(enable);
       
  1198     } else if (enable && d->threadData->eventDispatcher) {
       
  1199         d->exceptNotifier = new QExceptionNotifier(d->socketDescriptor, this);
       
  1200         d->exceptNotifier->setEnabled(true);
       
  1201     }
       
  1202 }
       
  1203 
       
  1204 QT_END_NAMESPACE