src/network/socket/qnativesocketengine_win.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 <winsock2.h>
       
    43 
       
    44 #include "qnativesocketengine_p.h"
       
    45 
       
    46 #include <qabstracteventdispatcher.h>
       
    47 #include <qsocketnotifier.h>
       
    48 #include <qdebug.h>
       
    49 #include <qdatetime.h>
       
    50 
       
    51 //#define QNATIVESOCKETENGINE_DEBUG
       
    52 #if defined(QNATIVESOCKETENGINE_DEBUG)
       
    53 #   include <qstring.h>
       
    54 #   include <qbytearray.h>
       
    55 #endif
       
    56 
       
    57 QT_BEGIN_NAMESPACE
       
    58 
       
    59 #if defined(QNATIVESOCKETENGINE_DEBUG)
       
    60 
       
    61 void verboseWSErrorDebug(int r)
       
    62 {
       
    63     switch (r) {
       
    64         case WSANOTINITIALISED : qDebug("WSA error : WSANOTINITIALISED"); break;
       
    65         case WSAEINTR: qDebug("WSA error : WSAEINTR"); break;
       
    66         case WSAEBADF: qDebug("WSA error : WSAEBADF"); break;
       
    67         case WSAEACCES: qDebug("WSA error : WSAEACCES"); break;
       
    68         case WSAEFAULT: qDebug("WSA error : WSAEFAULT"); break;
       
    69         case WSAEINVAL: qDebug("WSA error : WSAEINVAL"); break;
       
    70         case WSAEMFILE: qDebug("WSA error : WSAEMFILE"); break;
       
    71         case WSAEWOULDBLOCK: qDebug("WSA error : WSAEWOULDBLOCK"); break;
       
    72         case WSAEINPROGRESS: qDebug("WSA error : WSAEINPROGRESS"); break;
       
    73         case WSAEALREADY: qDebug("WSA error : WSAEALREADY"); break;
       
    74         case WSAENOTSOCK: qDebug("WSA error : WSAENOTSOCK"); break;
       
    75         case WSAEDESTADDRREQ: qDebug("WSA error : WSAEDESTADDRREQ"); break;
       
    76         case WSAEMSGSIZE: qDebug("WSA error : WSAEMSGSIZE"); break;
       
    77         case WSAEPROTOTYPE: qDebug("WSA error : WSAEPROTOTYPE"); break;
       
    78         case WSAENOPROTOOPT: qDebug("WSA error : WSAENOPROTOOPT"); break;
       
    79         case WSAEPROTONOSUPPORT: qDebug("WSA error : WSAEPROTONOSUPPORT"); break;
       
    80         case WSAESOCKTNOSUPPORT: qDebug("WSA error : WSAESOCKTNOSUPPORT"); break;
       
    81         case WSAEOPNOTSUPP: qDebug("WSA error : WSAEOPNOTSUPP"); break;
       
    82         case WSAEPFNOSUPPORT: qDebug("WSA error : WSAEPFNOSUPPORT"); break;
       
    83         case WSAEAFNOSUPPORT: qDebug("WSA error : WSAEAFNOSUPPORT"); break;
       
    84         case WSAEADDRINUSE: qDebug("WSA error : WSAEADDRINUSE"); break;
       
    85         case WSAEADDRNOTAVAIL: qDebug("WSA error : WSAEADDRNOTAVAIL"); break;
       
    86         case WSAENETDOWN: qDebug("WSA error : WSAENETDOWN"); break;
       
    87         case WSAENETUNREACH: qDebug("WSA error : WSAENETUNREACH"); break;
       
    88         case WSAENETRESET: qDebug("WSA error : WSAENETRESET"); break;
       
    89         case WSAECONNABORTED: qDebug("WSA error : WSAECONNABORTED"); break;
       
    90         case WSAECONNRESET: qDebug("WSA error : WSAECONNRESET"); break;
       
    91         case WSAENOBUFS: qDebug("WSA error : WSAENOBUFS"); break;
       
    92         case WSAEISCONN: qDebug("WSA error : WSAEISCONN"); break;
       
    93         case WSAENOTCONN: qDebug("WSA error : WSAENOTCONN"); break;
       
    94         case WSAESHUTDOWN: qDebug("WSA error : WSAESHUTDOWN"); break;
       
    95         case WSAETOOMANYREFS: qDebug("WSA error : WSAETOOMANYREFS"); break;
       
    96         case WSAETIMEDOUT: qDebug("WSA error : WSAETIMEDOUT"); break;
       
    97         case WSAECONNREFUSED: qDebug("WSA error : WSAECONNREFUSED"); break;
       
    98         case WSAELOOP: qDebug("WSA error : WSAELOOP"); break;
       
    99         case WSAENAMETOOLONG: qDebug("WSA error : WSAENAMETOOLONG"); break;
       
   100         case WSAEHOSTDOWN: qDebug("WSA error : WSAEHOSTDOWN"); break;
       
   101         case WSAEHOSTUNREACH: qDebug("WSA error : WSAEHOSTUNREACH"); break;
       
   102         case WSAENOTEMPTY: qDebug("WSA error : WSAENOTEMPTY"); break;
       
   103         case WSAEPROCLIM: qDebug("WSA error : WSAEPROCLIM"); break;
       
   104         case WSAEUSERS: qDebug("WSA error : WSAEUSERS"); break;
       
   105         case WSAEDQUOT: qDebug("WSA error : WSAEDQUOT"); break;
       
   106         case WSAESTALE: qDebug("WSA error : WSAESTALE"); break;
       
   107         case WSAEREMOTE: qDebug("WSA error : WSAEREMOTE"); break;
       
   108         case WSAEDISCON: qDebug("WSA error : WSAEDISCON"); break;
       
   109         default: qDebug("WSA error : Unknown"); break;
       
   110     }
       
   111     qErrnoWarning(r, "more details");
       
   112 }
       
   113 
       
   114 /*
       
   115     Returns a human readable representation of the first \a len
       
   116     characters in \a data.
       
   117 */
       
   118 static QByteArray qt_prettyDebug(const char *data, int len, int maxLength)
       
   119 {
       
   120     if (!data) return "(null)";
       
   121     QByteArray out;
       
   122     for (int i = 0; i < len; ++i) {
       
   123         char c = data[i];
       
   124         if (isprint(int(uchar(c)))) {
       
   125             out += c;
       
   126         } else switch (c) {
       
   127         case '\n': out += "\\n"; break;
       
   128         case '\r': out += "\\r"; break;
       
   129         case '\t': out += "\\t"; break;
       
   130         default:
       
   131             QString tmp;
       
   132             tmp.sprintf("\\%o", c);
       
   133             out += tmp.toLatin1().constData();
       
   134         }
       
   135     }
       
   136 
       
   137     if (len < maxLength)
       
   138         out += "...";
       
   139 
       
   140     return out;
       
   141 }
       
   142 
       
   143 
       
   144 #define WS_ERROR_DEBUG(x) verboseWSErrorDebug(x);
       
   145 
       
   146 #else
       
   147 
       
   148 #define WS_ERROR_DEBUG(x) Q_UNUSED(x)
       
   149 
       
   150 #endif
       
   151 
       
   152 #ifndef AF_INET6
       
   153 #define AF_INET6        23              /* Internetwork Version 6 */
       
   154 #endif
       
   155 
       
   156 #ifndef SO_EXCLUSIVEADDRUSE
       
   157 #define SO_EXCLUSIVEADDRUSE ((int)(~SO_REUSEADDR)) /* disallow local address reuse */
       
   158 #endif
       
   159 
       
   160 //###
       
   161 #define QT_SOCKLEN_T int
       
   162 #define QT_SOCKOPTLEN_T int
       
   163 
       
   164 
       
   165 /*
       
   166     Extracts the port and address from a sockaddr, and stores them in
       
   167     \a port and \a addr if they are non-null.
       
   168 */
       
   169 static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt_sockaddr *sa, quint16 *port, QHostAddress *address)
       
   170 {
       
   171 #if !defined (QT_NO_IPV6)
       
   172     if (sa->a.sa_family == AF_INET6) {
       
   173         const qt_sockaddr_in6 *sa6 = &sa->a6;
       
   174         Q_IPV6ADDR tmp;
       
   175         for (int i = 0; i < 16; ++i)
       
   176             tmp.c[i] = sa6->sin6_addr.qt_s6_addr[i];
       
   177         QHostAddress a;
       
   178 	a.setAddress(tmp);
       
   179 	if (address)
       
   180 	    *address = a;
       
   181         if (port)
       
   182 	    WSANtohs(socketDescriptor, sa6->sin6_port, port);
       
   183     } else
       
   184 #endif
       
   185     if (sa->a.sa_family == AF_INET) {
       
   186         const sockaddr_in *sa4 = &sa->a4;
       
   187         unsigned long addr;
       
   188         WSANtohl(socketDescriptor, sa4->sin_addr.s_addr, &addr);
       
   189         QHostAddress a;
       
   190 	a.setAddress(addr);
       
   191 	if (address)
       
   192 	    *address = a;
       
   193         if (port)
       
   194 	    WSANtohs(socketDescriptor, sa4->sin_port, port);
       
   195     }
       
   196 }
       
   197 
       
   198 
       
   199 /*! \internal
       
   200 
       
   201     Sets the port and address to a sockaddr. Requires that sa point to the IPv6 struct if the address is IPv6.
       
   202 */
       
   203 static inline void qt_socket_setPortAndAddress(SOCKET socketDescriptor, sockaddr_in * sockAddrIPv4, qt_sockaddr_in6 * sockAddrIPv6,
       
   204                                                quint16 port, const QHostAddress & address, sockaddr ** sockAddrPtr, QT_SOCKLEN_T *sockAddrSize)
       
   205 {
       
   206 #if !defined(QT_NO_IPV6)
       
   207     if (address.protocol() == QAbstractSocket::IPv6Protocol) {
       
   208         memset(sockAddrIPv6, 0, sizeof(qt_sockaddr_in6));
       
   209         sockAddrIPv6->sin6_family = AF_INET6;
       
   210         WSAHtons(socketDescriptor, port, &(sockAddrIPv6->sin6_port));
       
   211         Q_IPV6ADDR tmp = address.toIPv6Address();
       
   212         memcpy(&(sockAddrIPv6->sin6_addr.qt_s6_addr), &tmp, sizeof(tmp));
       
   213         *sockAddrSize = sizeof(qt_sockaddr_in6);
       
   214         *sockAddrPtr = (struct sockaddr *) sockAddrIPv6;
       
   215     } else
       
   216 #endif
       
   217     if (address.protocol() == QAbstractSocket::IPv4Protocol
       
   218         || address.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
       
   219         memset(sockAddrIPv4, 0, sizeof(sockaddr_in));
       
   220         sockAddrIPv4->sin_family = AF_INET;
       
   221         WSAHtons(socketDescriptor, port, &(sockAddrIPv4->sin_port));
       
   222         WSAHtonl(socketDescriptor, address.toIPv4Address(), &(sockAddrIPv4->sin_addr.s_addr));
       
   223         *sockAddrSize = sizeof(sockaddr_in);
       
   224         *sockAddrPtr = (struct sockaddr *) sockAddrIPv4;
       
   225     } else {
       
   226         // unreachable
       
   227     }
       
   228 }
       
   229 
       
   230 /*! \internal
       
   231 
       
   232 */
       
   233 static inline QAbstractSocket::SocketType qt_socket_getType(int socketDescriptor)
       
   234 {
       
   235     int value = 0;
       
   236     QT_SOCKLEN_T valueSize = sizeof(value);
       
   237     if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, (char *) &value, &valueSize) != 0) {
       
   238         WS_ERROR_DEBUG(WSAGetLastError());
       
   239     } else {
       
   240         if (value == SOCK_STREAM)
       
   241             return QAbstractSocket::TcpSocket;
       
   242         else if (value == SOCK_DGRAM)
       
   243             return QAbstractSocket::UdpSocket;
       
   244     }
       
   245     return QAbstractSocket::UnknownSocketType;
       
   246 }
       
   247 
       
   248 /*! \internal
       
   249 
       
   250 */
       
   251 static inline int qt_socket_getMaxMsgSize(int socketDescriptor)
       
   252 {
       
   253     int value = 0;
       
   254     QT_SOCKLEN_T valueSize = sizeof(value);
       
   255     if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *) &value, &valueSize) != 0) {
       
   256         WS_ERROR_DEBUG(WSAGetLastError());
       
   257     }
       
   258     return value;
       
   259 }
       
   260 
       
   261 QWindowsSockInit::QWindowsSockInit()
       
   262 :   version(0)
       
   263 {
       
   264     //### should we try for 2.2 on all platforms ??
       
   265     WSAData wsadata;
       
   266 
       
   267     // IPv6 requires Winsock v2.0 or better.
       
   268     if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) {
       
   269 	qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed.");
       
   270     } else {
       
   271         version = 0x20;
       
   272     }
       
   273 }
       
   274 
       
   275 QWindowsSockInit::~QWindowsSockInit()
       
   276 {
       
   277     WSACleanup();
       
   278 }
       
   279 
       
   280 // MS Transport Provider IOCTL to control
       
   281 // reporting PORT_UNREACHABLE messages
       
   282 // on UDP sockets via recv/WSARecv/etc.
       
   283 // Path TRUE in input buffer to enable (default if supported),
       
   284 // FALSE to disable.
       
   285 #ifndef SIO_UDP_CONNRESET
       
   286 #  ifndef IOC_VENDOR
       
   287 #    define IOC_VENDOR 0x18000000
       
   288 #  endif
       
   289 #  ifndef _WSAIOW
       
   290 #    define _WSAIOW(x,y) (IOC_IN|(x)|(y))
       
   291 #  endif
       
   292 #  define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
       
   293 #endif
       
   294 
       
   295 bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol socketProtocol)
       
   296 {
       
   297 
       
   298     //### no ip6 support on winsocket 1.1 but we will try not to use this !!!!!!!!!!!!1
       
   299     /*
       
   300     if (winsockVersion < 0x20 && socketProtocol == QAbstractSocket::IPv6Protocol) {
       
   301         //### no ip6 support
       
   302         return -1;
       
   303     }
       
   304     */
       
   305 
       
   306     int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol) ? AF_INET6 : AF_INET;
       
   307     int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
       
   308     // MSDN KB179942 states that on winnt 4 WSA_FLAG_OVERLAPPED is needed if socket is to be non blocking
       
   309     // and recomends alwasy doing it for cross windows version comapablity.
       
   310     SOCKET socket = ::WSASocket(protocol, type, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
       
   311 
       
   312     if (socket == INVALID_SOCKET) {
       
   313         int err = WSAGetLastError();
       
   314         WS_ERROR_DEBUG(err);
       
   315         switch (err) {
       
   316         case WSANOTINITIALISED:
       
   317             //###
       
   318             break;
       
   319         case WSAEAFNOSUPPORT:
       
   320         case WSAESOCKTNOSUPPORT:
       
   321         case WSAEPROTOTYPE:
       
   322         case WSAEINVAL:
       
   323             setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
       
   324             break;
       
   325         case WSAEMFILE:
       
   326         case WSAENOBUFS:
       
   327             setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
       
   328             break;
       
   329         default:
       
   330             break;
       
   331         }
       
   332 
       
   333         return false;
       
   334     }
       
   335 
       
   336 #if !defined(Q_OS_WINCE)
       
   337     // enable new behavior using
       
   338     // SIO_UDP_CONNRESET
       
   339     DWORD dwBytesReturned = 0;
       
   340     int bNewBehavior = 1;
       
   341     if (::WSAIoctl(socket, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior),
       
   342                    NULL, 0, &dwBytesReturned, NULL, NULL) == SOCKET_ERROR) {
       
   343         // not to worry isBogusUdpReadNotification() should handle this otherwise
       
   344         int err = WSAGetLastError();
       
   345         WS_ERROR_DEBUG(err);
       
   346     }
       
   347 #endif
       
   348 
       
   349     socketDescriptor = socket;
       
   350     return true;
       
   351 
       
   352 }
       
   353 
       
   354 /*! \internal
       
   355 
       
   356     Returns the value of the socket option \a opt.
       
   357 */
       
   358 int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) const
       
   359 {
       
   360     Q_Q(const QNativeSocketEngine);
       
   361     if (!q->isValid())
       
   362         return -1;
       
   363 
       
   364     int n = -1;
       
   365     int level = SOL_SOCKET; // default
       
   366 
       
   367     switch (opt) {
       
   368     case QNativeSocketEngine::ReceiveBufferSocketOption:
       
   369         n = SO_RCVBUF;
       
   370         break;
       
   371     case QNativeSocketEngine::SendBufferSocketOption:
       
   372         n = SO_SNDBUF;
       
   373         break;
       
   374     case QNativeSocketEngine::BroadcastSocketOption:
       
   375         n = SO_BROADCAST;
       
   376         break;
       
   377     case QNativeSocketEngine::NonBlockingSocketOption: {
       
   378         unsigned long buf = 0;
       
   379         if (WSAIoctl(socketDescriptor, FIONBIO, 0,0, &buf, sizeof(buf), 0,0,0) == 0)
       
   380             return buf;
       
   381         else
       
   382             return -1;
       
   383         break;
       
   384     }
       
   385     case QNativeSocketEngine::AddressReusable:
       
   386         n = SO_REUSEADDR;
       
   387         break;
       
   388     case QNativeSocketEngine::BindExclusively:
       
   389         n = SO_EXCLUSIVEADDRUSE;
       
   390         break;
       
   391     case QNativeSocketEngine::ReceiveOutOfBandData:
       
   392         n = SO_OOBINLINE;
       
   393         break;
       
   394     case QNativeSocketEngine::LowDelayOption:
       
   395         level = IPPROTO_TCP;
       
   396         n = TCP_NODELAY;
       
   397         break;
       
   398     case QNativeSocketEngine::KeepAliveOption:
       
   399         n = SO_KEEPALIVE;
       
   400         break;
       
   401     }
       
   402 
       
   403     int v = -1;
       
   404     QT_SOCKOPTLEN_T len = sizeof(v);
       
   405     if (getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1)
       
   406         return v;
       
   407     return -1;
       
   408 }
       
   409 
       
   410 
       
   411 /*! \internal
       
   412     Sets the socket option \a opt to \a v.
       
   413 */
       
   414 bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt, int v)
       
   415 {
       
   416     Q_Q(const QNativeSocketEngine);
       
   417     if (!q->isValid())
       
   418         return false;
       
   419 
       
   420     int n = 0;
       
   421     int level = SOL_SOCKET; // default
       
   422 
       
   423     switch (opt) {
       
   424     case QNativeSocketEngine::ReceiveBufferSocketOption:
       
   425         n = SO_RCVBUF;
       
   426         break;
       
   427     case QNativeSocketEngine::SendBufferSocketOption:
       
   428         n = SO_SNDBUF;
       
   429         break;
       
   430     case QNativeSocketEngine::BroadcastSocketOption:
       
   431         n = SO_BROADCAST;
       
   432         break;
       
   433     case QNativeSocketEngine::NonBlockingSocketOption:
       
   434         {
       
   435         unsigned long buf = v;
       
   436         unsigned long outBuf;
       
   437         DWORD sizeWritten = 0;
       
   438         if (::WSAIoctl(socketDescriptor, FIONBIO, &buf, sizeof(unsigned long), &outBuf, sizeof(unsigned long), &sizeWritten, 0,0) == SOCKET_ERROR) {
       
   439             WS_ERROR_DEBUG(WSAGetLastError());
       
   440             return false;
       
   441         }
       
   442         return true;
       
   443         break;
       
   444         }
       
   445     case QNativeSocketEngine::AddressReusable:
       
   446         n = SO_REUSEADDR;
       
   447         break;
       
   448     case QNativeSocketEngine::BindExclusively:
       
   449         n = SO_EXCLUSIVEADDRUSE;
       
   450         break;
       
   451     case QNativeSocketEngine::ReceiveOutOfBandData:
       
   452         n = SO_OOBINLINE;
       
   453         break;
       
   454     case QNativeSocketEngine::LowDelayOption:
       
   455         level = IPPROTO_TCP;
       
   456         n = TCP_NODELAY;
       
   457         break;
       
   458     case QNativeSocketEngine::KeepAliveOption:
       
   459         n = SO_KEEPALIVE;
       
   460         break;
       
   461     }
       
   462 
       
   463     if (::setsockopt(socketDescriptor, level, n, (char*)&v, sizeof(v)) != 0) {
       
   464         WS_ERROR_DEBUG(WSAGetLastError());
       
   465         return false;
       
   466     }
       
   467     return true;
       
   468 }
       
   469 
       
   470 /*!
       
   471     Fetches information about both ends of the connection: whatever is
       
   472     available.
       
   473 */
       
   474 bool QNativeSocketEnginePrivate::fetchConnectionParameters()
       
   475 {
       
   476     localPort = 0;
       
   477     localAddress.clear();
       
   478     peerPort = 0;
       
   479     peerAddress.clear();
       
   480 
       
   481     if (socketDescriptor == -1)
       
   482        return false;
       
   483 
       
   484     qt_sockaddr sa;
       
   485     QT_SOCKLEN_T sockAddrSize = sizeof(sa);
       
   486 
       
   487     // Determine local address
       
   488     memset(&sa, 0, sizeof(sa));
       
   489     if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
       
   490         qt_socket_getPortAndAddress(socketDescriptor, &sa, &localPort, &localAddress);
       
   491         // Determine protocol family
       
   492         switch (sa.a.sa_family) {
       
   493         case AF_INET:
       
   494             socketProtocol = QAbstractSocket::IPv4Protocol;
       
   495             break;
       
   496 #if !defined (QT_NO_IPV6)
       
   497         case AF_INET6:
       
   498             socketProtocol = QAbstractSocket::IPv6Protocol;
       
   499             break;
       
   500 #endif
       
   501         default:
       
   502             socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
       
   503             break;
       
   504         }
       
   505     } else {
       
   506         int err = WSAGetLastError();
       
   507         WS_ERROR_DEBUG(err);
       
   508         if (err == WSAENOTSOCK) {
       
   509             setError(QAbstractSocket::UnsupportedSocketOperationError,
       
   510                 InvalidSocketErrorString);
       
   511             return false;
       
   512         }
       
   513     }
       
   514 
       
   515     memset(&sa, 0, sizeof(sa));
       
   516     if (::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
       
   517         qt_socket_getPortAndAddress(socketDescriptor, &sa, &peerPort, &peerAddress);
       
   518     } else {
       
   519         WS_ERROR_DEBUG(WSAGetLastError());
       
   520     }
       
   521 
       
   522     socketType = qt_socket_getType(socketDescriptor);
       
   523 
       
   524 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   525     QString socketProtocolStr = "UnknownProtocol";
       
   526     if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = "IPv4Protocol";
       
   527     else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = "IPv6Protocol";
       
   528 
       
   529     QString socketTypeStr = "UnknownSocketType";
       
   530     if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = "TcpSocket";
       
   531     else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = "UdpSocket";
       
   532 
       
   533     qDebug("QNativeSocketEnginePrivate::fetchConnectionParameters() localAddress == %s, localPort = %i, peerAddress == %s, peerPort = %i, socketProtocol == %s, socketType == %s", localAddress.toString().toLatin1().constData(), localPort, peerAddress.toString().toLatin1().constData(), peerPort, socketProtocolStr.toLatin1().constData(), socketTypeStr.toLatin1().constData());
       
   534 #endif
       
   535 
       
   536     return true;
       
   537 }
       
   538 
       
   539 
       
   540 bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quint16 port)
       
   541 {
       
   542 
       
   543 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   544     qDebug("QNativeSocketEnginePrivate::nativeConnect() to %s :: %i", address.toString().toLatin1().constData(), port);
       
   545 #endif
       
   546 
       
   547     struct sockaddr_in sockAddrIPv4;
       
   548     qt_sockaddr_in6 sockAddrIPv6;
       
   549     struct sockaddr *sockAddrPtr = 0;
       
   550     QT_SOCKLEN_T sockAddrSize = 0;
       
   551 
       
   552     qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
       
   553 
       
   554     forever {
       
   555         int connectResult = ::WSAConnect(socketDescriptor, sockAddrPtr, sockAddrSize, 0,0,0,0);
       
   556         if (connectResult == SOCKET_ERROR) {
       
   557             int err = WSAGetLastError();
       
   558             WS_ERROR_DEBUG(err);
       
   559 
       
   560             switch (err) {
       
   561             case WSANOTINITIALISED:
       
   562                 //###
       
   563                 break;
       
   564             case WSAEISCONN:
       
   565                 socketState = QAbstractSocket::ConnectedState;
       
   566                 break;
       
   567             case WSAEWOULDBLOCK: {
       
   568                 // If WSAConnect returns WSAEWOULDBLOCK on the second
       
   569                 // connection attempt, we have to check SO_ERROR's
       
   570                 // value to detect ECONNREFUSED. If we don't get
       
   571                 // ECONNREFUSED, we'll have to treat it as an
       
   572                 // unfinished operation.
       
   573                 int value = 0;
       
   574                 QT_SOCKLEN_T valueSize = sizeof(value);
       
   575                 if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) {
       
   576                     if (value == WSAECONNREFUSED) {
       
   577                         setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
       
   578                         socketState = QAbstractSocket::UnconnectedState;
       
   579                         break;
       
   580                     }
       
   581                     if (value == WSAETIMEDOUT) {
       
   582                         setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
       
   583                         socketState = QAbstractSocket::UnconnectedState;
       
   584                         break;
       
   585                     }
       
   586                     if (value == WSAEHOSTUNREACH) {
       
   587                         setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
       
   588                         socketState = QAbstractSocket::UnconnectedState;
       
   589                         break;
       
   590                     }
       
   591                 }
       
   592                 // fall through
       
   593             }
       
   594             case WSAEINPROGRESS:
       
   595                 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
       
   596                 socketState = QAbstractSocket::ConnectingState;
       
   597                 break;
       
   598             case WSAEADDRINUSE:
       
   599                 setError(QAbstractSocket::NetworkError, AddressInuseErrorString);
       
   600                 break;
       
   601             case WSAECONNREFUSED:
       
   602                 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
       
   603                 socketState = QAbstractSocket::UnconnectedState;
       
   604                 break;
       
   605             case WSAETIMEDOUT:
       
   606                 setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
       
   607                 break;
       
   608             case WSAEACCES:
       
   609                 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
       
   610                 socketState = QAbstractSocket::UnconnectedState;
       
   611                 break;
       
   612             case WSAEHOSTUNREACH:
       
   613                 setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
       
   614                 socketState = QAbstractSocket::UnconnectedState;
       
   615                 break;
       
   616             case WSAENETUNREACH:
       
   617                 setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString);
       
   618                 socketState = QAbstractSocket::UnconnectedState;
       
   619                 break;
       
   620             case WSAEINVAL:
       
   621             case WSAEALREADY:
       
   622                 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
       
   623                 break;
       
   624             default:
       
   625                 break;
       
   626             }
       
   627             if (socketState != QAbstractSocket::ConnectedState) {
       
   628 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   629                 qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
       
   630                         address.toString().toLatin1().constData(), port,
       
   631                         socketState == QAbstractSocket::ConnectingState
       
   632                         ? "Connection in progress" : socketErrorString.toLatin1().constData());
       
   633 #endif
       
   634                 return false;
       
   635             }
       
   636         }
       
   637         break;
       
   638     }
       
   639 
       
   640 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   641     qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true",
       
   642            address.toString().toLatin1().constData(), port);
       
   643 #endif
       
   644 
       
   645     socketState = QAbstractSocket::ConnectedState;
       
   646     return true;
       
   647 }
       
   648 
       
   649 
       
   650 bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port)
       
   651 {
       
   652     struct sockaddr_in sockAddrIPv4;
       
   653     qt_sockaddr_in6 sockAddrIPv6;
       
   654     struct sockaddr *sockAddrPtr = 0;
       
   655     QT_SOCKLEN_T sockAddrSize = 0;
       
   656 
       
   657     qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
       
   658 
       
   659 
       
   660     int bindResult = ::bind(socketDescriptor, sockAddrPtr, sockAddrSize);
       
   661     if (bindResult == SOCKET_ERROR) {
       
   662         int err = WSAGetLastError();
       
   663         WS_ERROR_DEBUG(err);
       
   664         switch (err) {
       
   665         case WSANOTINITIALISED:
       
   666             //###
       
   667             break;
       
   668         case WSAEADDRINUSE:
       
   669         case WSAEINVAL:
       
   670             setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
       
   671             break;
       
   672         case WSAEACCES:
       
   673             setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString);
       
   674             break;
       
   675         case WSAEADDRNOTAVAIL:
       
   676             setError(QAbstractSocket::SocketAddressNotAvailableError, AddressNotAvailableErrorString);
       
   677             break;
       
   678         default:
       
   679             break;
       
   680         }
       
   681 
       
   682 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   683         qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
       
   684                address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData());
       
   685 #endif
       
   686 
       
   687         return false;
       
   688     }
       
   689 
       
   690 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   691     qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == true",
       
   692            address.toString().toLatin1().constData(), port);
       
   693 #endif
       
   694     socketState = QAbstractSocket::BoundState;
       
   695     return true;
       
   696 }
       
   697 
       
   698 
       
   699 bool QNativeSocketEnginePrivate::nativeListen(int backlog)
       
   700 {
       
   701     if (::listen(socketDescriptor, backlog) == SOCKET_ERROR) {
       
   702         int err = WSAGetLastError();
       
   703         WS_ERROR_DEBUG(err);
       
   704         switch (err) {
       
   705         case WSANOTINITIALISED:
       
   706             //###
       
   707             break;
       
   708         case WSAEADDRINUSE:
       
   709             setError(QAbstractSocket::AddressInUseError,
       
   710                      PortInuseErrorString);
       
   711             break;
       
   712         default:
       
   713             break;
       
   714         }
       
   715 
       
   716 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   717         qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == false (%s)",
       
   718                backlog, socketErrorString.toLatin1().constData());
       
   719 #endif
       
   720         return false;
       
   721     }
       
   722 
       
   723 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   724     qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == true", backlog);
       
   725 #endif
       
   726 
       
   727     socketState = QAbstractSocket::ListeningState;
       
   728     return true;
       
   729 }
       
   730 
       
   731 int QNativeSocketEnginePrivate::nativeAccept()
       
   732 {
       
   733     int acceptedDescriptor = WSAAccept(socketDescriptor, 0,0,0,0);
       
   734 	if (acceptedDescriptor != -1 && QAbstractEventDispatcher::instance()) {
       
   735 		// Becuase of WSAAsyncSelect() WSAAccept returns a non blocking socket
       
   736 		// with the same attributes as the listening socket including the current
       
   737 		// WSAAsyncSelect(). To be able to change the socket to blocking mode the
       
   738 		// WSAAsyncSelect() call must be cancled.
       
   739 		QSocketNotifier n(acceptedDescriptor, QSocketNotifier::Read);
       
   740 		n.setEnabled(true);
       
   741 		n.setEnabled(false);
       
   742 	}
       
   743 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   744     qDebug("QNativeSocketEnginePrivate::nativeAccept() == %i", acceptedDescriptor);
       
   745 #endif
       
   746     return acceptedDescriptor;
       
   747 }
       
   748 
       
   749 
       
   750 qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
       
   751 {
       
   752     unsigned long  nbytes = 0;
       
   753     unsigned long dummy = 0;
       
   754     DWORD sizeWritten = 0;
       
   755     if (::WSAIoctl(socketDescriptor, FIONREAD, &dummy, sizeof(dummy), &nbytes, sizeof(nbytes), &sizeWritten, 0,0) == SOCKET_ERROR) {
       
   756         WS_ERROR_DEBUG(WSAGetLastError());
       
   757         return -1;
       
   758     }
       
   759 
       
   760     // ioctlsocket sometimes reports 1 byte available for datagrams
       
   761     // while the following recvfrom returns -1 and claims connection
       
   762     // was reset (udp is connectionless). so we peek one byte to
       
   763     // catch this case and return 0 bytes available if recvfrom
       
   764     // fails.
       
   765     if (nbytes == 1 && socketType == QAbstractSocket::UdpSocket) {
       
   766         char c;
       
   767         WSABUF buf;
       
   768         buf.buf = &c;
       
   769         buf.len = sizeof(c);
       
   770         DWORD flags = MSG_PEEK;
       
   771         if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR)
       
   772             return 0;
       
   773     }
       
   774     return nbytes;
       
   775 }
       
   776 
       
   777 
       
   778 bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
       
   779 {
       
   780 #if !defined(Q_OS_WINCE)
       
   781     // Create a sockaddr struct and reset its port number.
       
   782     qt_sockaddr storage;
       
   783     QT_SOCKLEN_T storageSize = sizeof(storage);
       
   784     memset(&storage, 0, storageSize);
       
   785 
       
   786     bool result = false;
       
   787 
       
   788     // Peek 0 bytes into the next message. The size of the message may
       
   789     // well be 0, so we check if there was a sender.
       
   790     char c;
       
   791     WSABUF buf;
       
   792     buf.buf = &c;
       
   793     buf.len = sizeof(c);
       
   794     DWORD available = 0;
       
   795     DWORD flags = MSG_PEEK;
       
   796     int ret = ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags, &storage.a, &storageSize,0,0);
       
   797     int err = WSAGetLastError();
       
   798     if (ret == SOCKET_ERROR && err !=  WSAEMSGSIZE) {
       
   799         WS_ERROR_DEBUG(err);
       
   800         if (err == WSAECONNRESET) {
       
   801             // Discard error message to prevent QAbstractSocket from
       
   802             // getting this message repeatedly after reenabling the
       
   803             // notifiers.
       
   804             flags = 0;
       
   805             ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags,
       
   806                           &storage.a, &storageSize, 0, 0);
       
   807         }
       
   808     } else {
       
   809         // If there's no error, or if our buffer was too small, there must be
       
   810         // a pending datagram.
       
   811         result = true;
       
   812     }
       
   813 
       
   814 #else // Q_OS_WINCE
       
   815     bool result = false;
       
   816     fd_set readS;
       
   817     FD_ZERO(&readS);
       
   818     FD_SET(socketDescriptor, &readS);
       
   819     timeval timeout;
       
   820     timeout.tv_sec = 0;
       
   821     timeout.tv_usec = 5000;
       
   822     int available = ::select(1, &readS, 0, 0, &timeout);
       
   823     result = available > 0 ? true : false;
       
   824 #endif
       
   825 
       
   826 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   827     qDebug("QNativeSocketEnginePrivate::nativeHasPendingDatagrams() == %s",
       
   828            result ? "true" : "false");
       
   829 #endif
       
   830     return result;
       
   831 }
       
   832 
       
   833 
       
   834 qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
       
   835 {
       
   836     qint64 ret = -1;
       
   837 #if !defined(Q_OS_WINCE)
       
   838     int recvResult = 0;
       
   839     DWORD flags;
       
   840     DWORD bufferCount = 5;
       
   841     WSABUF * buf = 0;
       
   842     for (;;) {
       
   843         // the data written to udpMessagePeekBuffer is discarded, so
       
   844         // this function is still reentrant although it might not look
       
   845         // so.
       
   846         static char udpMessagePeekBuffer[8192];
       
   847 
       
   848         buf = new WSABUF[bufferCount];
       
   849         for (DWORD i=0; i<bufferCount; i++) {
       
   850            buf[i].buf = udpMessagePeekBuffer;
       
   851            buf[i].len = sizeof(udpMessagePeekBuffer);
       
   852         }
       
   853         flags = MSG_PEEK;
       
   854         DWORD bytesRead = 0;
       
   855         recvResult = ::WSARecv(socketDescriptor, buf, bufferCount, &bytesRead, &flags, 0,0);
       
   856         int err = WSAGetLastError();
       
   857         if (recvResult != SOCKET_ERROR) {
       
   858             ret = qint64(bytesRead);
       
   859             break;
       
   860         } else if (recvResult == SOCKET_ERROR && err == WSAEMSGSIZE) {
       
   861            bufferCount += 5;
       
   862            delete[] buf;
       
   863         } else if (recvResult == SOCKET_ERROR) {
       
   864             WS_ERROR_DEBUG(err);
       
   865             ret = -1;
       
   866             break;
       
   867         }
       
   868     }
       
   869 
       
   870     if (buf)
       
   871         delete[] buf;
       
   872 
       
   873 #else // Q_OS_WINCE
       
   874     DWORD size = -1;
       
   875     DWORD bytesReturned;
       
   876     int ioResult = WSAIoctl(socketDescriptor, FIONREAD, 0,0, &size, sizeof(size), &bytesReturned, 0, 0);
       
   877     if (ioResult == SOCKET_ERROR) {
       
   878         int err = WSAGetLastError();
       
   879         WS_ERROR_DEBUG(err);
       
   880     } else {
       
   881         ret = qint64(size);
       
   882     }
       
   883 #endif
       
   884 
       
   885 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   886     qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %li", ret);
       
   887 #endif
       
   888 
       
   889     return ret;
       
   890 }
       
   891 
       
   892 
       
   893 qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength,
       
   894                                                       QHostAddress *address, quint16 *port)
       
   895 {
       
   896     qint64 ret = 0;
       
   897 
       
   898     qt_sockaddr aa;
       
   899     memset(&aa, 0, sizeof(aa));
       
   900     QT_SOCKLEN_T sz;
       
   901     sz = sizeof(aa);
       
   902 
       
   903     WSABUF buf;
       
   904     buf.buf = data;
       
   905     buf.len = maxLength;
       
   906 #if !defined(Q_OS_WINCE)
       
   907     buf.buf = data;
       
   908     buf.len = maxLength;
       
   909 #else
       
   910     char tmpChar;
       
   911     buf.buf = data ? data : &tmpChar;
       
   912     buf.len = maxLength;
       
   913 #endif
       
   914 
       
   915     DWORD flags = 0;
       
   916     DWORD bytesRead = 0;
       
   917     int wsaRet = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, &aa.a, &sz,0,0);
       
   918     if (wsaRet == SOCKET_ERROR) {
       
   919         int err = WSAGetLastError();
       
   920         if (err == WSAEMSGSIZE) {
       
   921             // it is ok the buffer was to small if bytesRead is larger than
       
   922             // maxLength then assume bytes read is really maxLenth
       
   923             ret = qint64(bytesRead) > maxLength ? maxLength : qint64(bytesRead);
       
   924         } else {
       
   925             WS_ERROR_DEBUG(err);
       
   926             setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
       
   927             ret = -1;
       
   928         }
       
   929     } else {
       
   930         ret = qint64(bytesRead);
       
   931     }
       
   932 
       
   933     qt_socket_getPortAndAddress(socketDescriptor, &aa, port, address);
       
   934 
       
   935 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   936     qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %li, %s, %i) == %li",
       
   937            data, qt_prettyDebug(data, qMin<qint64>(ret, 16), ret).data(), maxLength,
       
   938            address ? address->toString().toLatin1().constData() : "(nil)",
       
   939            port ? *port : 0, ret);
       
   940 #endif
       
   941 
       
   942     return ret;
       
   943 }
       
   944 
       
   945 
       
   946 qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len,
       
   947                                                    const QHostAddress &address, quint16 port)
       
   948 {
       
   949     qint64 ret = -1;
       
   950     struct sockaddr_in sockAddrIPv4;
       
   951     qt_sockaddr_in6 sockAddrIPv6;
       
   952     struct sockaddr *sockAddrPtr = 0;
       
   953     QT_SOCKLEN_T sockAddrSize = 0;
       
   954 
       
   955     qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
       
   956 
       
   957     WSABUF buf;
       
   958 #if !defined(Q_OS_WINCE)
       
   959     buf.buf = len ? (char*)data : 0;
       
   960 #else
       
   961     char tmp;
       
   962     buf.buf = len ? (char*)data : &tmp;
       
   963 #endif
       
   964     buf.len = len;
       
   965     DWORD flags = 0;
       
   966     DWORD bytesSent = 0;
       
   967     if (::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, sockAddrPtr, sockAddrSize, 0,0) ==  SOCKET_ERROR) {
       
   968         int err = WSAGetLastError();
       
   969         WS_ERROR_DEBUG(err);
       
   970         switch (err) {
       
   971         case WSAEMSGSIZE:
       
   972             setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
       
   973             break;
       
   974         default:
       
   975             setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
       
   976             break;
       
   977         }
       
   978         ret = -1;
       
   979     } else {
       
   980         ret = qint64(bytesSent);
       
   981     }
       
   982 
       
   983 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
   984     qDebug("QNativeSocketEnginePrivate::nativeSendDatagram(%p \"%s\", %li, \"%s\", %i) == %li", data,
       
   985            qt_prettyDebug(data, qMin<qint64>(len, 16), len).data(), 0, address.toString().toLatin1().constData(),
       
   986            port, ret);
       
   987 #endif
       
   988 
       
   989     return ret;
       
   990 }
       
   991 
       
   992 
       
   993 qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
       
   994 {
       
   995     Q_Q(QNativeSocketEngine);
       
   996     qint64 ret = 0;
       
   997     // don't send more than 49152 per call to WSASendTo to avoid getting a WSAENOBUFS
       
   998     for (;;) {
       
   999         qint64 bytesToSend = qMin<qint64>(49152, len - ret);
       
  1000         WSABUF buf;
       
  1001         buf.buf = (char*)data + ret;
       
  1002         buf.len = bytesToSend;
       
  1003         DWORD flags = 0;
       
  1004         DWORD bytesWritten = 0;
       
  1005 
       
  1006         int socketRet = ::WSASend(socketDescriptor, &buf, 1, &bytesWritten, flags, 0,0);
       
  1007 
       
  1008         ret += qint64(bytesWritten);
       
  1009 
       
  1010         if (socketRet != SOCKET_ERROR) {
       
  1011             if (ret == len)
       
  1012                 break;
       
  1013             else
       
  1014                 continue;
       
  1015         } else if (WSAGetLastError() == WSAEWOULDBLOCK) {
       
  1016             break;
       
  1017         } else {
       
  1018             int err = WSAGetLastError();
       
  1019             WS_ERROR_DEBUG(err);
       
  1020             switch (err) {
       
  1021             case WSAECONNRESET:
       
  1022             case WSAECONNABORTED:
       
  1023                 ret = -1;
       
  1024                 setError(QAbstractSocket::NetworkError, WriteErrorString);
       
  1025                 q->close();
       
  1026                 break;
       
  1027             default:
       
  1028                 break;
       
  1029             }
       
  1030             break;
       
  1031         }
       
  1032     }
       
  1033 
       
  1034 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
  1035     qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %li) == %li",
       
  1036            data, qt_prettyDebug(data, qMin((int)ret, 16), (int)ret).data(), (int)len, (int)ret);
       
  1037 #endif
       
  1038 
       
  1039     return ret;
       
  1040 }
       
  1041 
       
  1042 qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxLength)
       
  1043 {
       
  1044     qint64 ret = -1;
       
  1045     WSABUF buf;
       
  1046     buf.buf = data;
       
  1047     buf.len = maxLength;
       
  1048     DWORD flags = 0;
       
  1049     DWORD bytesRead = 0;
       
  1050 #if defined(Q_OS_WINCE)
       
  1051     WSASetLastError(0);
       
  1052 #endif
       
  1053     if (::WSARecv(socketDescriptor, &buf, 1, &bytesRead, &flags, 0,0) ==  SOCKET_ERROR) {
       
  1054         int err = WSAGetLastError();
       
  1055         WS_ERROR_DEBUG(err);
       
  1056         switch (err) {
       
  1057         case WSAEWOULDBLOCK:
       
  1058             ret = -2;
       
  1059             break;
       
  1060         case WSAEBADF:
       
  1061         case WSAEINVAL:
       
  1062             setError(QAbstractSocket::NetworkError, ReadErrorString);
       
  1063             break;
       
  1064         case WSAECONNRESET:
       
  1065         case WSAECONNABORTED:
       
  1066             // for tcp sockets this will be handled in QNativeSocketEngine::read
       
  1067             ret = 0;
       
  1068             break;
       
  1069         default:
       
  1070             break;
       
  1071         }
       
  1072     } else {
       
  1073         if (WSAGetLastError() == WSAEWOULDBLOCK)
       
  1074             ret = -2;
       
  1075         else
       
  1076             ret = qint64(bytesRead);
       
  1077     }
       
  1078 
       
  1079 #if defined (QNATIVESOCKETENGINE_DEBUG)
       
  1080     if (ret != -2) {
       
  1081         qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %l) == %li",
       
  1082                data, qt_prettyDebug(data, qMin((int)bytesRead, 16), (int)bytesRead).data(), (int)maxLength, (int)ret);
       
  1083     } else {
       
  1084         qDebug("QNativeSocketEnginePrivate::nativeRead(%p, %l) == -2 (WOULD BLOCK)",
       
  1085                data, int(maxLength));
       
  1086     }
       
  1087 #endif
       
  1088 
       
  1089     return ret;
       
  1090 }
       
  1091 
       
  1092 int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const
       
  1093 {
       
  1094     bool readEnabled = selectForRead && readNotifier && readNotifier->isEnabled();
       
  1095     if (readEnabled)
       
  1096         readNotifier->setEnabled(false);
       
  1097     
       
  1098     fd_set fds;
       
  1099 
       
  1100     int ret = 0;
       
  1101 
       
  1102     memset(&fds, 0, sizeof(fd_set));
       
  1103     fds.fd_count = 1;
       
  1104     fds.fd_array[0] = socketDescriptor;
       
  1105 
       
  1106     struct timeval tv;
       
  1107     tv.tv_sec = timeout / 1000;
       
  1108     tv.tv_usec = (timeout % 1000) * 1000;
       
  1109 
       
  1110     if (selectForRead)
       
  1111         ret = select(0, &fds, 0, 0, timeout < 0 ? 0 : &tv);
       
  1112     else
       
  1113         ret = select(0, 0, &fds, 0, timeout < 0 ? 0 : &tv);
       
  1114 
       
  1115     if (readEnabled)
       
  1116         readNotifier->setEnabled(true);
       
  1117 
       
  1118     return ret;
       
  1119 }
       
  1120 
       
  1121 int QNativeSocketEnginePrivate::nativeSelect(int timeout,
       
  1122                                       bool checkRead, bool checkWrite,
       
  1123                                       bool *selectForRead, bool *selectForWrite) const
       
  1124 {
       
  1125     bool readEnabled = checkRead && readNotifier && readNotifier->isEnabled();
       
  1126     if (readEnabled)
       
  1127         readNotifier->setEnabled(false);
       
  1128     
       
  1129     fd_set fdread;
       
  1130     fd_set fdwrite;
       
  1131 
       
  1132     int ret = 0;
       
  1133 
       
  1134     memset(&fdread, 0, sizeof(fd_set));
       
  1135     if (checkRead) {
       
  1136         fdread.fd_count = 1;
       
  1137         fdread.fd_array[0] = socketDescriptor;
       
  1138     }
       
  1139     memset(&fdwrite, 0, sizeof(fd_set));
       
  1140     if (checkWrite) {
       
  1141         fdwrite.fd_count = 1;
       
  1142         fdwrite.fd_array[0] = socketDescriptor;
       
  1143     }
       
  1144 
       
  1145     struct timeval tv;
       
  1146     tv.tv_sec = timeout / 1000;
       
  1147     tv.tv_usec = (timeout % 1000) * 1000;
       
  1148 
       
  1149 #if !defined(Q_OS_WINCE)
       
  1150     ret = select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
       
  1151 #else
       
  1152     ret = select(1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
       
  1153 #endif
       
  1154     if (readEnabled)
       
  1155         readNotifier->setEnabled(true);
       
  1156 
       
  1157     if (ret <= 0)
       
  1158         return ret;
       
  1159 
       
  1160     *selectForRead = FD_ISSET(socketDescriptor, &fdread);
       
  1161     *selectForWrite = FD_ISSET(socketDescriptor, &fdwrite);
       
  1162 
       
  1163     return ret;
       
  1164 }
       
  1165 
       
  1166 void QNativeSocketEnginePrivate::nativeClose()
       
  1167 {
       
  1168 #if defined (QTCPSOCKETENGINE_DEBUG)
       
  1169     qDebug("QNativeSocketEnginePrivate::nativeClose()");
       
  1170 #endif
       
  1171     linger l = {1, 0};
       
  1172     ::setsockopt(socketDescriptor, SOL_SOCKET, SO_DONTLINGER, (char*)&l, sizeof(l));
       
  1173     ::closesocket(socketDescriptor);
       
  1174 }
       
  1175 
       
  1176 QT_END_NAMESPACE