Windows native socket: handle WSAENETRESET the same as WSAECONNRESET
[qt:qt.git] / src / network / socket / qnativesocketengine_win.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <winsock2.h>
43 #include <ws2tcpip.h>
44
45 #include "qnativesocketengine_p.h"
46
47 #include <qabstracteventdispatcher.h>
48 #include <qsocketnotifier.h>
49 #include <qdebug.h>
50 #include <qdatetime.h>
51 #include <qnetworkinterface.h>
52
53 //#define QNATIVESOCKETENGINE_DEBUG
54 #if defined(QNATIVESOCKETENGINE_DEBUG)
55 #   include <qstring.h>
56 #   include <qbytearray.h>
57 #endif
58
59 QT_BEGIN_NAMESPACE
60
61 #if defined(QNATIVESOCKETENGINE_DEBUG)
62
63 void verboseWSErrorDebug(int r)
64 {
65     switch (r) {
66         case WSANOTINITIALISED : qDebug("WSA error : WSANOTINITIALISED"); break;
67         case WSAEINTR: qDebug("WSA error : WSAEINTR"); break;
68         case WSAEBADF: qDebug("WSA error : WSAEBADF"); break;
69         case WSAEACCES: qDebug("WSA error : WSAEACCES"); break;
70         case WSAEFAULT: qDebug("WSA error : WSAEFAULT"); break;
71         case WSAEINVAL: qDebug("WSA error : WSAEINVAL"); break;
72         case WSAEMFILE: qDebug("WSA error : WSAEMFILE"); break;
73         case WSAEWOULDBLOCK: qDebug("WSA error : WSAEWOULDBLOCK"); break;
74         case WSAEINPROGRESS: qDebug("WSA error : WSAEINPROGRESS"); break;
75         case WSAEALREADY: qDebug("WSA error : WSAEALREADY"); break;
76         case WSAENOTSOCK: qDebug("WSA error : WSAENOTSOCK"); break;
77         case WSAEDESTADDRREQ: qDebug("WSA error : WSAEDESTADDRREQ"); break;
78         case WSAEMSGSIZE: qDebug("WSA error : WSAEMSGSIZE"); break;
79         case WSAEPROTOTYPE: qDebug("WSA error : WSAEPROTOTYPE"); break;
80         case WSAENOPROTOOPT: qDebug("WSA error : WSAENOPROTOOPT"); break;
81         case WSAEPROTONOSUPPORT: qDebug("WSA error : WSAEPROTONOSUPPORT"); break;
82         case WSAESOCKTNOSUPPORT: qDebug("WSA error : WSAESOCKTNOSUPPORT"); break;
83         case WSAEOPNOTSUPP: qDebug("WSA error : WSAEOPNOTSUPP"); break;
84         case WSAEPFNOSUPPORT: qDebug("WSA error : WSAEPFNOSUPPORT"); break;
85         case WSAEAFNOSUPPORT: qDebug("WSA error : WSAEAFNOSUPPORT"); break;
86         case WSAEADDRINUSE: qDebug("WSA error : WSAEADDRINUSE"); break;
87         case WSAEADDRNOTAVAIL: qDebug("WSA error : WSAEADDRNOTAVAIL"); break;
88         case WSAENETDOWN: qDebug("WSA error : WSAENETDOWN"); break;
89         case WSAENETUNREACH: qDebug("WSA error : WSAENETUNREACH"); break;
90         case WSAENETRESET: qDebug("WSA error : WSAENETRESET"); break;
91         case WSAECONNABORTED: qDebug("WSA error : WSAECONNABORTED"); break;
92         case WSAECONNRESET: qDebug("WSA error : WSAECONNRESET"); break;
93         case WSAENOBUFS: qDebug("WSA error : WSAENOBUFS"); break;
94         case WSAEISCONN: qDebug("WSA error : WSAEISCONN"); break;
95         case WSAENOTCONN: qDebug("WSA error : WSAENOTCONN"); break;
96         case WSAESHUTDOWN: qDebug("WSA error : WSAESHUTDOWN"); break;
97         case WSAETOOMANYREFS: qDebug("WSA error : WSAETOOMANYREFS"); break;
98         case WSAETIMEDOUT: qDebug("WSA error : WSAETIMEDOUT"); break;
99         case WSAECONNREFUSED: qDebug("WSA error : WSAECONNREFUSED"); break;
100         case WSAELOOP: qDebug("WSA error : WSAELOOP"); break;
101         case WSAENAMETOOLONG: qDebug("WSA error : WSAENAMETOOLONG"); break;
102         case WSAEHOSTDOWN: qDebug("WSA error : WSAEHOSTDOWN"); break;
103         case WSAEHOSTUNREACH: qDebug("WSA error : WSAEHOSTUNREACH"); break;
104         case WSAENOTEMPTY: qDebug("WSA error : WSAENOTEMPTY"); break;
105         case WSAEPROCLIM: qDebug("WSA error : WSAEPROCLIM"); break;
106         case WSAEUSERS: qDebug("WSA error : WSAEUSERS"); break;
107         case WSAEDQUOT: qDebug("WSA error : WSAEDQUOT"); break;
108         case WSAESTALE: qDebug("WSA error : WSAESTALE"); break;
109         case WSAEREMOTE: qDebug("WSA error : WSAEREMOTE"); break;
110         case WSAEDISCON: qDebug("WSA error : WSAEDISCON"); break;
111         default: qDebug("WSA error : Unknown"); break;
112     }
113     qErrnoWarning(r, "more details");
114 }
115
116 /*
117     Returns a human readable representation of the first \a len
118     characters in \a data.
119 */
120 static QByteArray qt_prettyDebug(const char *data, int len, int maxLength)
121 {
122     if (!data) return "(null)";
123     QByteArray out;
124     for (int i = 0; i < len; ++i) {
125         char c = data[i];
126         if (isprint(int(uchar(c)))) {
127             out += c;
128         } else switch (c) {
129         case '\n': out += "\\n"; break;
130         case '\r': out += "\\r"; break;
131         case '\t': out += "\\t"; break;
132         default:
133             QString tmp;
134             tmp.sprintf("\\%o", c);
135             out += tmp.toLatin1().constData();
136         }
137     }
138
139     if (len < maxLength)
140         out += "...";
141
142     return out;
143 }
144
145
146 #define WS_ERROR_DEBUG(x) verboseWSErrorDebug(x);
147
148 #else
149
150 #define WS_ERROR_DEBUG(x) Q_UNUSED(x)
151
152 #endif
153
154 #ifndef AF_INET6
155 #define AF_INET6        23              /* Internetwork Version 6 */
156 #endif
157
158 #ifndef SO_EXCLUSIVEADDRUSE
159 #define SO_EXCLUSIVEADDRUSE ((int)(~SO_REUSEADDR)) /* disallow local address reuse */
160 #endif
161
162 //###
163 #define QT_SOCKLEN_T int
164 #define QT_SOCKOPTLEN_T int
165
166
167 /*
168     Extracts the port and address from a sockaddr, and stores them in
169     \a port and \a addr if they are non-null.
170 */
171 static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt_sockaddr *sa, quint16 *port, QHostAddress *address)
172 {
173 #if !defined (QT_NO_IPV6)
174     if (sa->a.sa_family == AF_INET6) {
175         const qt_sockaddr_in6 *sa6 = &sa->a6;
176         Q_IPV6ADDR tmp;
177         for (int i = 0; i < 16; ++i)
178             tmp.c[i] = sa6->sin6_addr.qt_s6_addr[i];
179         if (address) {
180             QHostAddress a;
181             a.setAddress(tmp);
182             a.setScopeId(QString::number(sa6->sin6_scope_id));
183             *address = a;
184         }
185         if (port)
186             WSANtohs(socketDescriptor, sa6->sin6_port, port);
187     } else
188 #endif
189     if (sa->a.sa_family == AF_INET) {
190         const sockaddr_in *sa4 = &sa->a4;
191         unsigned long addr;
192         WSANtohl(socketDescriptor, sa4->sin_addr.s_addr, &addr);
193         QHostAddress a;
194         a.setAddress(addr);
195         if (address)
196             *address = a;
197         if (port)
198             WSANtohs(socketDescriptor, sa4->sin_port, port);
199     }
200 }
201
202
203 /*! \internal
204
205     Sets the port and address to a sockaddr. Requires that sa point to the IPv6 struct if the address is IPv6.
206 */
207 static inline void qt_socket_setPortAndAddress(SOCKET socketDescriptor, sockaddr_in * sockAddrIPv4, qt_sockaddr_in6 * sockAddrIPv6,
208                                                quint16 port, const QHostAddress & address, sockaddr ** sockAddrPtr, QT_SOCKLEN_T *sockAddrSize)
209 {
210 #if !defined(QT_NO_IPV6)
211     if (address.protocol() == QAbstractSocket::IPv6Protocol) {
212         memset(sockAddrIPv6, 0, sizeof(qt_sockaddr_in6));
213         sockAddrIPv6->sin6_family = AF_INET6;
214         sockAddrIPv6->sin6_scope_id = address.scopeId().toInt();
215         WSAHtons(socketDescriptor, port, &(sockAddrIPv6->sin6_port));
216         Q_IPV6ADDR tmp = address.toIPv6Address();
217         memcpy(&(sockAddrIPv6->sin6_addr.qt_s6_addr), &tmp, sizeof(tmp));
218         *sockAddrSize = sizeof(qt_sockaddr_in6);
219         *sockAddrPtr = (struct sockaddr *) sockAddrIPv6;
220     } else
221 #endif
222     if (address.protocol() == QAbstractSocket::IPv4Protocol
223         || address.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
224         memset(sockAddrIPv4, 0, sizeof(sockaddr_in));
225         sockAddrIPv4->sin_family = AF_INET;
226         WSAHtons(socketDescriptor, port, &(sockAddrIPv4->sin_port));
227         WSAHtonl(socketDescriptor, address.toIPv4Address(), &(sockAddrIPv4->sin_addr.s_addr));
228         *sockAddrSize = sizeof(sockaddr_in);
229         *sockAddrPtr = (struct sockaddr *) sockAddrIPv4;
230     } else {
231         // unreachable
232     }
233 }
234
235 /*! \internal
236
237 */
238 static inline QAbstractSocket::SocketType qt_socket_getType(int socketDescriptor)
239 {
240     int value = 0;
241     QT_SOCKLEN_T valueSize = sizeof(value);
242     if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, (char *) &value, &valueSize) != 0) {
243         WS_ERROR_DEBUG(WSAGetLastError());
244     } else {
245         if (value == SOCK_STREAM)
246             return QAbstractSocket::TcpSocket;
247         else if (value == SOCK_DGRAM)
248             return QAbstractSocket::UdpSocket;
249     }
250     return QAbstractSocket::UnknownSocketType;
251 }
252
253 /*! \internal
254
255 */
256 static inline int qt_socket_getMaxMsgSize(int socketDescriptor)
257 {
258     int value = 0;
259     QT_SOCKLEN_T valueSize = sizeof(value);
260     if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *) &value, &valueSize) != 0) {
261         WS_ERROR_DEBUG(WSAGetLastError());
262     }
263     return value;
264 }
265
266 QWindowsSockInit::QWindowsSockInit()
267 :   version(0)
268 {
269     //### should we try for 2.2 on all platforms ??
270     WSAData wsadata;
271
272     // IPv6 requires Winsock v2.0 or better.
273     if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) {
274         qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed.");
275     } else {
276         version = 0x20;
277     }
278 }
279
280 QWindowsSockInit::~QWindowsSockInit()
281 {
282     WSACleanup();
283 }
284
285 // MS Transport Provider IOCTL to control
286 // reporting PORT_UNREACHABLE messages
287 // on UDP sockets via recv/WSARecv/etc.
288 // Path TRUE in input buffer to enable (default if supported),
289 // FALSE to disable.
290 #ifndef SIO_UDP_CONNRESET
291 #  ifndef IOC_VENDOR
292 #    define IOC_VENDOR 0x18000000
293 #  endif
294 #  ifndef _WSAIOW
295 #    define _WSAIOW(x,y) (IOC_IN|(x)|(y))
296 #  endif
297 #  define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
298 #endif
299
300 bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol socketProtocol)
301 {
302
303     //### no ip6 support on winsocket 1.1 but we will try not to use this !!!!!!!!!!!!1
304     /*
305     if (winsockVersion < 0x20 && socketProtocol == QAbstractSocket::IPv6Protocol) {
306         //### no ip6 support
307         return -1;
308     }
309     */
310
311     int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol) ? AF_INET6 : AF_INET;
312     int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
313     // MSDN KB179942 states that on winnt 4 WSA_FLAG_OVERLAPPED is needed if socket is to be non blocking
314     // and recomends alwasy doing it for cross windows version comapablity.
315     SOCKET socket = ::WSASocket(protocol, type, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
316
317     if (socket == INVALID_SOCKET) {
318         int err = WSAGetLastError();
319         WS_ERROR_DEBUG(err);
320         switch (err) {
321         case WSANOTINITIALISED:
322             //###
323             break;
324         case WSAEAFNOSUPPORT:
325         case WSAESOCKTNOSUPPORT:
326         case WSAEPROTOTYPE:
327         case WSAEINVAL:
328             setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
329             break;
330         case WSAEMFILE:
331         case WSAENOBUFS:
332             setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
333             break;
334         default:
335             break;
336         }
337
338         return false;
339     }
340
341 #if !defined(Q_OS_WINCE)
342     if (socketType == QAbstractSocket::UdpSocket) {
343         // enable new behavior using
344         // SIO_UDP_CONNRESET
345         DWORD dwBytesReturned = 0;
346         int bNewBehavior = 1;
347         if (::WSAIoctl(socket, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior),
348                        NULL, 0, &dwBytesReturned, NULL, NULL) == SOCKET_ERROR) {
349             // not to worry isBogusUdpReadNotification() should handle this otherwise
350             int err = WSAGetLastError();
351             WS_ERROR_DEBUG(err);
352         }
353     }
354 #endif
355
356     socketDescriptor = socket;
357     return true;
358
359 }
360
361 /*! \internal
362
363     Returns the value of the socket option \a opt.
364 */
365 int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) const
366 {
367     Q_Q(const QNativeSocketEngine);
368     if (!q->isValid())
369         return -1;
370
371     int n = -1;
372     int level = SOL_SOCKET; // default
373
374     switch (opt) {
375     case QNativeSocketEngine::ReceiveBufferSocketOption:
376         n = SO_RCVBUF;
377         break;
378     case QNativeSocketEngine::SendBufferSocketOption:
379         n = SO_SNDBUF;
380         break;
381     case QNativeSocketEngine::BroadcastSocketOption:
382         n = SO_BROADCAST;
383         break;
384     case QNativeSocketEngine::NonBlockingSocketOption: {
385         unsigned long buf = 0;
386         if (WSAIoctl(socketDescriptor, FIONBIO, 0,0, &buf, sizeof(buf), 0,0,0) == 0)
387             return buf;
388         else
389             return -1;
390         break;
391     }
392     case QNativeSocketEngine::AddressReusable:
393         n = SO_REUSEADDR;
394         break;
395     case QNativeSocketEngine::BindExclusively:
396         n = SO_EXCLUSIVEADDRUSE;
397         break;
398     case QNativeSocketEngine::ReceiveOutOfBandData:
399         n = SO_OOBINLINE;
400         break;
401     case QNativeSocketEngine::LowDelayOption:
402         level = IPPROTO_TCP;
403         n = TCP_NODELAY;
404         break;
405     case QNativeSocketEngine::KeepAliveOption:
406         n = SO_KEEPALIVE;
407         break;
408     case QNativeSocketEngine::MulticastTtlOption:
409 #ifndef QT_NO_IPV6
410         if (socketProtocol == QAbstractSocket::IPv6Protocol) {
411             level = IPPROTO_IPV6;
412             n = IPV6_MULTICAST_HOPS;
413         } else
414 #endif
415         {
416             level = IPPROTO_IP;
417             n = IP_MULTICAST_TTL;
418         }
419         break;
420     case QNativeSocketEngine::MulticastLoopbackOption:
421 #ifndef QT_NO_IPV6
422         if (socketProtocol == QAbstractSocket::IPv6Protocol) {
423             level = IPPROTO_IPV6;
424             n = IPV6_MULTICAST_LOOP;
425         } else
426 #endif
427         {
428             level = IPPROTO_IP;
429             n = IP_MULTICAST_LOOP;
430         }
431         break;
432     }
433
434 #if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
435 #error code assumes windows is little endian
436 #endif
437     int v = 0; //note: windows doesn't write to all bytes if the option type is smaller than int
438     QT_SOCKOPTLEN_T len = sizeof(v);
439     if (getsockopt(socketDescriptor, level, n, (char *) &v, &len) == 0)
440         return v;
441     WS_ERROR_DEBUG(WSAGetLastError());
442     return -1;
443 }
444
445
446 /*! \internal
447     Sets the socket option \a opt to \a v.
448 */
449 bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt, int v)
450 {
451     Q_Q(const QNativeSocketEngine);
452     if (!q->isValid())
453         return false;
454
455     int n = 0;
456     int level = SOL_SOCKET; // default
457
458     switch (opt) {
459     case QNativeSocketEngine::ReceiveBufferSocketOption:
460         n = SO_RCVBUF;
461         break;
462     case QNativeSocketEngine::SendBufferSocketOption:
463         n = SO_SNDBUF;
464         break;
465     case QNativeSocketEngine::BroadcastSocketOption:
466         n = SO_BROADCAST;
467         break;
468     case QNativeSocketEngine::NonBlockingSocketOption:
469         {
470         unsigned long buf = v;
471         unsigned long outBuf;
472         DWORD sizeWritten = 0;
473         if (::WSAIoctl(socketDescriptor, FIONBIO, &buf, sizeof(unsigned long), &outBuf, sizeof(unsigned long), &sizeWritten, 0,0) == SOCKET_ERROR) {
474             WS_ERROR_DEBUG(WSAGetLastError());
475             return false;
476         }
477         return true;
478         break;
479         }
480     case QNativeSocketEngine::AddressReusable:
481         n = SO_REUSEADDR;
482         break;
483     case QNativeSocketEngine::BindExclusively:
484         n = SO_EXCLUSIVEADDRUSE;
485         break;
486     case QNativeSocketEngine::ReceiveOutOfBandData:
487         n = SO_OOBINLINE;
488         break;
489     case QNativeSocketEngine::LowDelayOption:
490         level = IPPROTO_TCP;
491         n = TCP_NODELAY;
492         break;
493     case QNativeSocketEngine::KeepAliveOption:
494         n = SO_KEEPALIVE;
495         break;
496     case QNativeSocketEngine::MulticastTtlOption:
497 #ifndef QT_NO_IPV6
498         if (socketProtocol == QAbstractSocket::IPv6Protocol) {
499             level = IPPROTO_IPV6;
500             n = IPV6_MULTICAST_HOPS;
501         } else
502 #endif
503         {
504             level = IPPROTO_IP;
505             n = IP_MULTICAST_TTL;
506         }
507         break;
508     case QNativeSocketEngine::MulticastLoopbackOption:
509 #ifndef QT_NO_IPV6
510         if (socketProtocol == QAbstractSocket::IPv6Protocol) {
511             level = IPPROTO_IPV6;
512             n = IPV6_MULTICAST_LOOP;
513         } else
514 #endif
515         {
516             level = IPPROTO_IP;
517             n = IP_MULTICAST_LOOP;
518         }
519         break;
520     }
521
522     if (::setsockopt(socketDescriptor, level, n, (char*)&v, sizeof(v)) != 0) {
523         WS_ERROR_DEBUG(WSAGetLastError());
524         return false;
525     }
526     return true;
527 }
528
529 /*!
530     Fetches information about both ends of the connection: whatever is
531     available.
532 */
533 bool QNativeSocketEnginePrivate::fetchConnectionParameters()
534 {
535     localPort = 0;
536     localAddress.clear();
537     peerPort = 0;
538     peerAddress.clear();
539
540     if (socketDescriptor == -1)
541        return false;
542
543     qt_sockaddr sa;
544     QT_SOCKLEN_T sockAddrSize = sizeof(sa);
545
546     // Determine local address
547     memset(&sa, 0, sizeof(sa));
548     if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
549         qt_socket_getPortAndAddress(socketDescriptor, &sa, &localPort, &localAddress);
550         // Determine protocol family
551         switch (sa.a.sa_family) {
552         case AF_INET:
553             socketProtocol = QAbstractSocket::IPv4Protocol;
554             break;
555 #if !defined (QT_NO_IPV6)
556         case AF_INET6:
557             socketProtocol = QAbstractSocket::IPv6Protocol;
558             break;
559 #endif
560         default:
561             socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
562             break;
563         }
564     } else {
565         int err = WSAGetLastError();
566         WS_ERROR_DEBUG(err);
567         if (err == WSAENOTSOCK) {
568             setError(QAbstractSocket::UnsupportedSocketOperationError,
569                 InvalidSocketErrorString);
570             return false;
571         }
572     }
573
574     memset(&sa, 0, sizeof(sa));
575     if (::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
576         qt_socket_getPortAndAddress(socketDescriptor, &sa, &peerPort, &peerAddress);
577     } else {
578         WS_ERROR_DEBUG(WSAGetLastError());
579     }
580
581     socketType = qt_socket_getType(socketDescriptor);
582
583 #if defined (QNATIVESOCKETENGINE_DEBUG)
584     QString socketProtocolStr = "UnknownProtocol";
585     if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = "IPv4Protocol";
586     else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = "IPv6Protocol";
587
588     QString socketTypeStr = "UnknownSocketType";
589     if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = "TcpSocket";
590     else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = "UdpSocket";
591
592     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());
593 #endif
594
595     return true;
596 }
597
598
599 bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quint16 port)
600 {
601
602 #if defined (QNATIVESOCKETENGINE_DEBUG)
603     qDebug("QNativeSocketEnginePrivate::nativeConnect() to %s :: %i", address.toString().toLatin1().constData(), port);
604 #endif
605
606     struct sockaddr_in sockAddrIPv4;
607     qt_sockaddr_in6 sockAddrIPv6;
608     struct sockaddr *sockAddrPtr = 0;
609     QT_SOCKLEN_T sockAddrSize = 0;
610
611     qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
612
613     forever {
614         int connectResult = ::WSAConnect(socketDescriptor, sockAddrPtr, sockAddrSize, 0,0,0,0);
615         if (connectResult == SOCKET_ERROR) {
616             int err = WSAGetLastError();
617             WS_ERROR_DEBUG(err);
618
619             switch (err) {
620             case WSANOTINITIALISED:
621                 //###
622                 break;
623             case WSAEISCONN:
624                 socketState = QAbstractSocket::ConnectedState;
625                 break;
626             case WSAEWOULDBLOCK: {
627                 // If WSAConnect returns WSAEWOULDBLOCK on the second
628                 // connection attempt, we have to check SO_ERROR's
629                 // value to detect ECONNREFUSED. If we don't get
630                 // ECONNREFUSED, we'll have to treat it as an
631                 // unfinished operation.
632                 int value = 0;
633                 QT_SOCKLEN_T valueSize = sizeof(value);
634                 if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) {
635                     if (value == WSAECONNREFUSED) {
636                         setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
637                         socketState = QAbstractSocket::UnconnectedState;
638                         break;
639                     }
640                     if (value == WSAETIMEDOUT) {
641                         setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
642                         socketState = QAbstractSocket::UnconnectedState;
643                         break;
644                     }
645                     if (value == WSAEHOSTUNREACH) {
646                         setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
647                         socketState = QAbstractSocket::UnconnectedState;
648                         break;
649                     }
650                     if (value == WSAEADDRNOTAVAIL) {
651                         setError(QAbstractSocket::NetworkError, AddressNotAvailableErrorString);
652                         socketState = QAbstractSocket::UnconnectedState;
653                         break;
654                     }
655                 }
656                 // fall through
657             }
658             case WSAEINPROGRESS:
659                 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
660                 socketState = QAbstractSocket::ConnectingState;
661                 break;
662             case WSAEADDRINUSE:
663                 setError(QAbstractSocket::NetworkError, AddressInuseErrorString);
664                 break;
665             case WSAECONNREFUSED:
666                 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
667                 socketState = QAbstractSocket::UnconnectedState;
668                 break;
669             case WSAETIMEDOUT:
670                 setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
671                 break;
672             case WSAEACCES:
673                 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
674                 socketState = QAbstractSocket::UnconnectedState;
675                 break;
676             case WSAEHOSTUNREACH:
677                 setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
678                 socketState = QAbstractSocket::UnconnectedState;
679                 break;
680             case WSAENETUNREACH:
681                 setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString);
682                 socketState = QAbstractSocket::UnconnectedState;
683                 break;
684             case WSAEINVAL:
685             case WSAEALREADY:
686                 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
687                 break;
688             default:
689                 break;
690             }
691             if (socketState != QAbstractSocket::ConnectedState) {
692 #if defined (QNATIVESOCKETENGINE_DEBUG)
693                 qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
694                         address.toString().toLatin1().constData(), port,
695                         socketState == QAbstractSocket::ConnectingState
696                         ? "Connection in progress" : socketErrorString.toLatin1().constData());
697 #endif
698                 return false;
699             }
700         }
701         break;
702     }
703
704 #if defined (QNATIVESOCKETENGINE_DEBUG)
705     qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true",
706            address.toString().toLatin1().constData(), port);
707 #endif
708
709     socketState = QAbstractSocket::ConnectedState;
710     return true;
711 }
712
713
714 bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &a, quint16 port)
715 {
716     QHostAddress address = a;
717     switch (address.protocol()) {
718     case QAbstractSocket::IPv6Protocol:
719         if (address.toIPv6Address()[0] == 0xff) {
720             // binding to a multicast address
721             address = QHostAddress(QHostAddress::AnyIPv6);
722         }
723         break;
724     case QAbstractSocket::IPv4Protocol:
725         if ((address.toIPv4Address() & 0xffff0000) == 0xefff0000) {
726             // binding to a multicast address
727             address = QHostAddress(QHostAddress::Any);
728         }
729         break;
730     default:
731         break;
732     }
733
734     struct sockaddr_in sockAddrIPv4;
735     qt_sockaddr_in6 sockAddrIPv6;
736     struct sockaddr *sockAddrPtr = 0;
737     QT_SOCKLEN_T sockAddrSize = 0;
738
739     qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
740
741
742     int bindResult = ::bind(socketDescriptor, sockAddrPtr, sockAddrSize);
743     if (bindResult == SOCKET_ERROR) {
744         int err = WSAGetLastError();
745         WS_ERROR_DEBUG(err);
746         switch (err) {
747         case WSANOTINITIALISED:
748             //###
749             break;
750         case WSAEADDRINUSE:
751         case WSAEINVAL:
752             setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
753             break;
754         case WSAEACCES:
755             setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString);
756             break;
757         case WSAEADDRNOTAVAIL:
758             setError(QAbstractSocket::SocketAddressNotAvailableError, AddressNotAvailableErrorString);
759             break;
760         default:
761             break;
762         }
763
764 #if defined (QNATIVESOCKETENGINE_DEBUG)
765         qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
766                address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData());
767 #endif
768
769         return false;
770     }
771
772 #if defined (QNATIVESOCKETENGINE_DEBUG)
773     qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == true",
774            address.toString().toLatin1().constData(), port);
775 #endif
776     socketState = QAbstractSocket::BoundState;
777     return true;
778 }
779
780
781 bool QNativeSocketEnginePrivate::nativeListen(int backlog)
782 {
783     if (::listen(socketDescriptor, backlog) == SOCKET_ERROR) {
784         int err = WSAGetLastError();
785         WS_ERROR_DEBUG(err);
786         switch (err) {
787         case WSANOTINITIALISED:
788             //###
789             break;
790         case WSAEADDRINUSE:
791             setError(QAbstractSocket::AddressInUseError,
792                      PortInuseErrorString);
793             break;
794         default:
795             break;
796         }
797
798 #if defined (QNATIVESOCKETENGINE_DEBUG)
799         qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == false (%s)",
800                backlog, socketErrorString.toLatin1().constData());
801 #endif
802         return false;
803     }
804
805 #if defined (QNATIVESOCKETENGINE_DEBUG)
806     qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == true", backlog);
807 #endif
808
809     socketState = QAbstractSocket::ListeningState;
810     return true;
811 }
812
813 int QNativeSocketEnginePrivate::nativeAccept()
814 {
815     int acceptedDescriptor = WSAAccept(socketDescriptor, 0,0,0,0);
816         if (acceptedDescriptor != -1 && QAbstractEventDispatcher::instance()) {
817                 // Because of WSAAsyncSelect() WSAAccept returns a non blocking socket
818                 // with the same attributes as the listening socket including the current
819                 // WSAAsyncSelect(). To be able to change the socket to blocking mode the
820                 // WSAAsyncSelect() call must be cancled.
821                 QSocketNotifier n(acceptedDescriptor, QSocketNotifier::Read);
822                 n.setEnabled(true);
823                 n.setEnabled(false);
824         }
825 #if defined (QNATIVESOCKETENGINE_DEBUG)
826     qDebug("QNativeSocketEnginePrivate::nativeAccept() == %i", acceptedDescriptor);
827 #endif
828     return acceptedDescriptor;
829 }
830
831 static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d,
832                                       int how6,
833                                       int how4,
834                                       const QHostAddress &groupAddress,
835                                       const QNetworkInterface &iface)
836 {
837     int level = 0;
838     int sockOpt = 0;
839     char *sockArg;
840     int sockArgSize;
841
842     struct ip_mreq mreq4;
843 #ifndef QT_NO_IPV6
844     struct ipv6_mreq mreq6;
845
846     if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) {
847         level = IPPROTO_IPV6;
848         sockOpt = how6;
849         sockArg = reinterpret_cast<char *>(&mreq6);
850         sockArgSize = sizeof(mreq6);
851         memset(&mreq6, 0, sizeof(mreq6));
852         Q_IPV6ADDR ip6 = groupAddress.toIPv6Address();
853         memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6));
854         mreq6.ipv6mr_interface = iface.index();
855     } else
856 #endif
857     if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
858         level = IPPROTO_IP;
859         sockOpt = how4;
860         sockArg = reinterpret_cast<char *>(&mreq4);
861         sockArgSize = sizeof(mreq4);
862         memset(&mreq4, 0, sizeof(mreq4));
863         mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address());
864
865         if (iface.isValid()) {
866             QList<QNetworkAddressEntry> addressEntries = iface.addressEntries();
867             if (!addressEntries.isEmpty()) {
868                 QHostAddress firstIP = addressEntries.first().ip();
869                 mreq4.imr_interface.s_addr = htonl(firstIP.toIPv4Address());
870             } else {
871                 d->setError(QAbstractSocket::NetworkError,
872                             QNativeSocketEnginePrivate::NetworkUnreachableErrorString);
873                 return false;
874             }
875         } else {
876             mreq4.imr_interface.s_addr = INADDR_ANY;
877         }
878     } else {
879         // unreachable
880         d->setError(QAbstractSocket::UnsupportedSocketOperationError,
881                     QNativeSocketEnginePrivate::ProtocolUnsupportedErrorString);
882         return false;
883     }
884
885     int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize);
886     if (res == -1) {
887         d->setError(QAbstractSocket::UnsupportedSocketOperationError,
888                     QNativeSocketEnginePrivate::OperationUnsupportedErrorString);
889         return false;
890     }
891     return true;
892 }
893
894 bool QNativeSocketEnginePrivate::nativeJoinMulticastGroup(const QHostAddress &groupAddress,
895                                                           const QNetworkInterface &iface)
896 {
897     return multicastMembershipHelper(this,
898 #ifndef QT_NO_IPV6
899                                      IPV6_JOIN_GROUP,
900 #else
901                                      0,
902 #endif
903                                      IP_ADD_MEMBERSHIP,
904                                      groupAddress,
905                                      iface);
906 }
907
908 bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &groupAddress,
909                                                            const QNetworkInterface &iface)
910 {
911     return multicastMembershipHelper(this,
912 #ifndef QT_NO_IPV6
913                                      IPV6_LEAVE_GROUP,
914 #else
915                                      0,
916 #endif
917                                      IP_DROP_MEMBERSHIP,
918                                      groupAddress,
919                                      iface);
920 }
921
922 QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const
923 {
924 #ifndef QT_NO_IPV6
925     if (socketProtocol == QAbstractSocket::IPv6Protocol) {
926         uint v;
927         QT_SOCKOPTLEN_T sizeofv = sizeof(v);
928         if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &v, &sizeofv) == -1)
929             return QNetworkInterface();
930         return QNetworkInterface::interfaceFromIndex(v);
931     }
932 #endif
933
934     struct in_addr v;
935     v.s_addr = 0;
936     QT_SOCKOPTLEN_T sizeofv = sizeof(v);
937     if (::getsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, &sizeofv) == -1)
938         return QNetworkInterface();
939     if (v.s_addr != 0 && sizeofv >= QT_SOCKOPTLEN_T(sizeof(v))) {
940         QHostAddress ipv4(ntohl(v.s_addr));
941         QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
942         for (int i = 0; i < ifaces.count(); ++i) {
943             const QNetworkInterface &iface = ifaces.at(i);
944             if (!(iface.flags() & QNetworkInterface::CanMulticast))
945                 continue;
946             QList<QNetworkAddressEntry> entries = iface.addressEntries();
947             for (int j = 0; j < entries.count(); ++j) {
948                 const QNetworkAddressEntry &entry = entries.at(j);
949                 if (entry.ip() == ipv4)
950                     return iface;
951             }
952         }
953     }
954     return QNetworkInterface();
955 }
956
957 bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInterface &iface)
958 {
959 #ifndef QT_NO_IPV6
960     if (socketProtocol == QAbstractSocket::IPv6Protocol) {
961         uint v = iface.isValid() ? iface.index() : 0;
962         return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &v, sizeof(v)) != -1);
963     }
964 #endif
965
966     struct in_addr v;
967     if (iface.isValid()) {
968         QList<QNetworkAddressEntry> entries = iface.addressEntries();
969         for (int i = 0; i < entries.count(); ++i) {
970             const QNetworkAddressEntry &entry = entries.at(i);
971             const QHostAddress &ip = entry.ip();
972             if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
973                 v.s_addr = htonl(ip.toIPv4Address());
974                 int r = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, sizeof(v));
975                 if (r != -1)
976                     return true;
977             }
978         }
979         return false;
980     }
981
982     v.s_addr = INADDR_ANY;
983     return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, sizeof(v)) != -1);
984 }
985
986 qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
987 {
988     unsigned long  nbytes = 0;
989     unsigned long dummy = 0;
990     DWORD sizeWritten = 0;
991     if (::WSAIoctl(socketDescriptor, FIONREAD, &dummy, sizeof(dummy), &nbytes, sizeof(nbytes), &sizeWritten, 0,0) == SOCKET_ERROR) {
992         WS_ERROR_DEBUG(WSAGetLastError());
993         return -1;
994     }
995
996     // ioctlsocket sometimes reports 1 byte available for datagrams
997     // while the following recvfrom returns -1 and claims connection
998     // was reset (udp is connectionless). so we peek one byte to
999     // catch this case and return 0 bytes available if recvfrom
1000     // fails.
1001     if (nbytes == 1 && socketType == QAbstractSocket::UdpSocket) {
1002         char c;
1003         WSABUF buf;
1004         buf.buf = &c;
1005         buf.len = sizeof(c);
1006         DWORD flags = MSG_PEEK;
1007         if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR)
1008             return 0;
1009     }
1010     return nbytes;
1011 }
1012
1013
1014 bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
1015 {
1016 #if !defined(Q_OS_WINCE)
1017     // Create a sockaddr struct and reset its port number.
1018     qt_sockaddr storage;
1019     QT_SOCKLEN_T storageSize = sizeof(storage);
1020     memset(&storage, 0, storageSize);
1021
1022     bool result = false;
1023
1024     // Peek 0 bytes into the next message. The size of the message may
1025     // well be 0, so we check if there was a sender.
1026     char c;
1027     WSABUF buf;
1028     buf.buf = &c;
1029     buf.len = sizeof(c);
1030     DWORD available = 0;
1031     DWORD flags = MSG_PEEK;
1032     int ret = ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags, &storage.a, &storageSize,0,0);
1033     int err = WSAGetLastError();
1034     if (ret == SOCKET_ERROR && err !=  WSAEMSGSIZE) {
1035         WS_ERROR_DEBUG(err);
1036         if (err == WSAECONNRESET || err == WSAENETRESET) {
1037             // Discard error message to prevent QAbstractSocket from
1038             // getting this message repeatedly after reenabling the
1039             // notifiers.
1040             flags = 0;
1041             ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags,
1042                           &storage.a, &storageSize, 0, 0);
1043         }
1044     } else {
1045         // If there's no error, or if our buffer was too small, there must be
1046         // a pending datagram.
1047         result = true;
1048     }
1049
1050 #else // Q_OS_WINCE
1051     bool result = false;
1052     fd_set readS;
1053     FD_ZERO(&readS);
1054     FD_SET((SOCKET)socketDescriptor, &readS);
1055     timeval timeout;
1056     timeout.tv_sec = 0;
1057     timeout.tv_usec = 5000;
1058     int available = ::select(1, &readS, 0, 0, &timeout);
1059     result = available > 0 ? true : false;
1060 #endif
1061
1062 #if defined (QNATIVESOCKETENGINE_DEBUG)
1063     qDebug("QNativeSocketEnginePrivate::nativeHasPendingDatagrams() == %s",
1064            result ? "true" : "false");
1065 #endif
1066     return result;
1067 }
1068
1069
1070 qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
1071 {
1072     qint64 ret = -1;
1073 #if !defined(Q_OS_WINCE)
1074     int recvResult = 0;
1075     DWORD flags;
1076     DWORD bufferCount = 5;
1077     WSABUF * buf = 0;
1078     for (;;) {
1079         // the data written to udpMessagePeekBuffer is discarded, so
1080         // this function is still reentrant although it might not look
1081         // so.
1082         static char udpMessagePeekBuffer[8192];
1083
1084         buf = new WSABUF[bufferCount];
1085         for (DWORD i=0; i<bufferCount; i++) {
1086            buf[i].buf = udpMessagePeekBuffer;
1087            buf[i].len = sizeof(udpMessagePeekBuffer);
1088         }
1089         flags = MSG_PEEK;
1090         DWORD bytesRead = 0;
1091         recvResult = ::WSARecv(socketDescriptor, buf, bufferCount, &bytesRead, &flags, 0,0);
1092         int err = WSAGetLastError();
1093         if (recvResult != SOCKET_ERROR) {
1094             ret = qint64(bytesRead);
1095             break;
1096         } else if (recvResult == SOCKET_ERROR && err == WSAEMSGSIZE) {
1097            bufferCount += 5;
1098            delete[] buf;
1099         } else if (recvResult == SOCKET_ERROR) {
1100             WS_ERROR_DEBUG(err);
1101             ret = -1;
1102             break;
1103         }
1104     }
1105
1106     if (buf)
1107         delete[] buf;
1108
1109 #else // Q_OS_WINCE
1110     DWORD size = -1;
1111     DWORD bytesReturned;
1112     int ioResult = WSAIoctl(socketDescriptor, FIONREAD, 0,0, &size, sizeof(size), &bytesReturned, 0, 0);
1113     if (ioResult == SOCKET_ERROR) {
1114         int err = WSAGetLastError();
1115         WS_ERROR_DEBUG(err);
1116     } else {
1117         ret = qint64(size);
1118     }
1119 #endif
1120
1121 #if defined (QNATIVESOCKETENGINE_DEBUG)
1122     qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %li", ret);
1123 #endif
1124
1125     return ret;
1126 }
1127
1128
1129 qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength,
1130                                                       QHostAddress *address, quint16 *port)
1131 {
1132     qint64 ret = 0;
1133
1134     qt_sockaddr aa;
1135     memset(&aa, 0, sizeof(aa));
1136     QT_SOCKLEN_T sz;
1137     sz = sizeof(aa);
1138
1139     WSABUF buf;
1140     buf.buf = data;
1141     buf.len = maxLength;
1142 #if !defined(Q_OS_WINCE)
1143     buf.buf = data;
1144     buf.len = maxLength;
1145 #else
1146     char tmpChar;
1147     buf.buf = data ? data : &tmpChar;
1148     buf.len = maxLength;
1149 #endif
1150
1151     DWORD flags = 0;
1152     DWORD bytesRead = 0;
1153     int wsaRet = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, &aa.a, &sz,0,0);
1154     if (wsaRet == SOCKET_ERROR) {
1155         int err = WSAGetLastError();
1156         if (err == WSAEMSGSIZE) {
1157             // it is ok the buffer was to small if bytesRead is larger than
1158             // maxLength then assume bytes read is really maxLenth
1159             ret = qint64(bytesRead) > maxLength ? maxLength : qint64(bytesRead);
1160         } else {
1161             WS_ERROR_DEBUG(err);
1162             setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
1163             ret = -1;
1164         }
1165     } else {
1166         ret = qint64(bytesRead);
1167     }
1168
1169     qt_socket_getPortAndAddress(socketDescriptor, &aa, port, address);
1170
1171 #if defined (QNATIVESOCKETENGINE_DEBUG)
1172     qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %li, %s, %i) == %li",
1173            data, qt_prettyDebug(data, qMin<qint64>(ret, 16), ret).data(), maxLength,
1174            address ? address->toString().toLatin1().constData() : "(nil)",
1175            port ? *port : 0, ret);
1176 #endif
1177
1178     return ret;
1179 }
1180
1181
1182 qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len,
1183                                                    const QHostAddress &address, quint16 port)
1184 {
1185     qint64 ret = -1;
1186     struct sockaddr_in sockAddrIPv4;
1187     qt_sockaddr_in6 sockAddrIPv6;
1188     struct sockaddr *sockAddrPtr = 0;
1189     QT_SOCKLEN_T sockAddrSize = 0;
1190
1191     qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
1192
1193     WSABUF buf;
1194 #if !defined(Q_OS_WINCE)
1195     buf.buf = len ? (char*)data : 0;
1196 #else
1197     char tmp;
1198     buf.buf = len ? (char*)data : &tmp;
1199 #endif
1200     buf.len = len;
1201     DWORD flags = 0;
1202     DWORD bytesSent = 0;
1203     if (::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, sockAddrPtr, sockAddrSize, 0,0) ==  SOCKET_ERROR) {
1204         int err = WSAGetLastError();
1205         WS_ERROR_DEBUG(err);
1206         switch (err) {
1207         case WSAEMSGSIZE:
1208             setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
1209             break;
1210         default:
1211             setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
1212             break;
1213         }
1214         ret = -1;
1215     } else {
1216         ret = qint64(bytesSent);
1217     }
1218
1219 #if defined (QNATIVESOCKETENGINE_DEBUG)
1220     qDebug("QNativeSocketEnginePrivate::nativeSendDatagram(%p \"%s\", %li, \"%s\", %i) == %li", data,
1221            qt_prettyDebug(data, qMin<qint64>(len, 16), len).data(), 0, address.toString().toLatin1().constData(),
1222            port, ret);
1223 #endif
1224
1225     return ret;
1226 }
1227
1228
1229 qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
1230 {
1231     Q_Q(QNativeSocketEngine);
1232     qint64 ret = 0;
1233     qint64 bytesToSend = len;
1234
1235     for (;;) {
1236         WSABUF buf;
1237         buf.buf = (char*)data + ret;
1238         buf.len = bytesToSend;
1239         DWORD flags = 0;
1240         DWORD bytesWritten = 0;
1241
1242         int socketRet = ::WSASend(socketDescriptor, &buf, 1, &bytesWritten, flags, 0,0);
1243
1244         ret += qint64(bytesWritten);
1245
1246         int err;
1247         if (socketRet != SOCKET_ERROR) {
1248             if (ret == len)
1249                 break;
1250             else
1251                 continue;
1252         } else if ((err = WSAGetLastError()) == WSAEWOULDBLOCK) {
1253             break;
1254         } else if (err == WSAENOBUFS) {
1255             // this function used to not send more than 49152 per call to WSASendTo
1256             // to avoid getting a WSAENOBUFS. However this is a performance regression
1257             // and we think it only appears with old windows versions. We now handle the
1258             // WSAENOBUFS and hope it never appears anyway.
1259             // just go on, the next loop run we will try a smaller number
1260         } else {
1261             WS_ERROR_DEBUG(err);
1262             switch (err) {
1263             case WSAECONNRESET:
1264             case WSAECONNABORTED:
1265                 ret = -1;
1266                 setError(QAbstractSocket::NetworkError, WriteErrorString);
1267                 q->close();
1268                 break;
1269             default:
1270                 break;
1271             }
1272             break;
1273         }
1274
1275         // for next send:
1276         bytesToSend = qMin<qint64>(49152, len - ret);
1277     }
1278
1279 #if defined (QNATIVESOCKETENGINE_DEBUG)
1280     qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %li) == %li",
1281            data, qt_prettyDebug(data, qMin((int)ret, 16), (int)ret).data(), (int)len, (int)ret);
1282 #endif
1283
1284     return ret;
1285 }
1286
1287 qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxLength)
1288 {
1289     qint64 ret = -1;
1290     WSABUF buf;
1291     buf.buf = data;
1292     buf.len = maxLength;
1293     DWORD flags = 0;
1294     DWORD bytesRead = 0;
1295 #if defined(Q_OS_WINCE)
1296     WSASetLastError(0);
1297 #endif
1298     if (::WSARecv(socketDescriptor, &buf, 1, &bytesRead, &flags, 0,0) ==  SOCKET_ERROR) {
1299         int err = WSAGetLastError();
1300         WS_ERROR_DEBUG(err);
1301         switch (err) {
1302         case WSAEWOULDBLOCK:
1303             ret = -2;
1304             break;
1305         case WSAEBADF:
1306         case WSAEINVAL:
1307             //error string is now set in read(), not here in nativeRead()
1308             break;
1309         case WSAECONNRESET:
1310         case WSAECONNABORTED:
1311             // for tcp sockets this will be handled in QNativeSocketEngine::read
1312             ret = 0;
1313             break;
1314         default:
1315             break;
1316         }
1317     } else {
1318         if (WSAGetLastError() == WSAEWOULDBLOCK)
1319             ret = -2;
1320         else
1321             ret = qint64(bytesRead);
1322     }
1323
1324 #if defined (QNATIVESOCKETENGINE_DEBUG)
1325     if (ret != -2) {
1326         qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %l) == %li",
1327                data, qt_prettyDebug(data, qMin((int)bytesRead, 16), (int)bytesRead).data(), (int)maxLength, (int)ret);
1328     } else {
1329         qDebug("QNativeSocketEnginePrivate::nativeRead(%p, %l) == -2 (WOULD BLOCK)",
1330                data, int(maxLength));
1331     }
1332 #endif
1333
1334     return ret;
1335 }
1336
1337 int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const
1338 {
1339     bool readEnabled = selectForRead && readNotifier && readNotifier->isEnabled();
1340     if (readEnabled)
1341         readNotifier->setEnabled(false);
1342     
1343     fd_set fds;
1344
1345     int ret = 0;
1346
1347     memset(&fds, 0, sizeof(fd_set));
1348     fds.fd_count = 1;
1349     fds.fd_array[0] = (SOCKET)socketDescriptor;
1350
1351     struct timeval tv;
1352     tv.tv_sec = timeout / 1000;
1353     tv.tv_usec = (timeout % 1000) * 1000;
1354
1355     if (selectForRead) {
1356         ret = select(0, &fds, 0, 0, timeout < 0 ? 0 : &tv);
1357     } else {
1358         // select for write
1359
1360         // Windows needs this to report errors when connecting a socket ...
1361         fd_set fdexception;
1362         FD_ZERO(&fdexception);
1363         FD_SET((SOCKET)socketDescriptor, &fdexception);
1364
1365         ret = select(0, 0, &fds, &fdexception, timeout < 0 ? 0 : &tv);
1366
1367         // ... but if it is actually set, pretend it did not happen
1368         if (ret > 0 && FD_ISSET((SOCKET)socketDescriptor, &fdexception))
1369             ret--;
1370     }
1371
1372     if (readEnabled)
1373         readNotifier->setEnabled(true);
1374
1375     return ret;
1376 }
1377
1378 int QNativeSocketEnginePrivate::nativeSelect(int timeout,
1379                                       bool checkRead, bool checkWrite,
1380                                       bool *selectForRead, bool *selectForWrite) const
1381 {
1382     bool readEnabled = checkRead && readNotifier && readNotifier->isEnabled();
1383     if (readEnabled)
1384         readNotifier->setEnabled(false);
1385
1386     fd_set fdread;
1387     fd_set fdwrite;
1388     fd_set fdexception;
1389
1390     int ret = 0;
1391
1392     memset(&fdread, 0, sizeof(fd_set));
1393     if (checkRead) {
1394         fdread.fd_count = 1;
1395         fdread.fd_array[0] = (SOCKET)socketDescriptor;
1396     }
1397     memset(&fdwrite, 0, sizeof(fd_set));
1398     FD_ZERO(&fdexception);
1399     if (checkWrite) {
1400         fdwrite.fd_count = 1;
1401         fdwrite.fd_array[0] = (SOCKET)socketDescriptor;
1402
1403         // Windows needs this to report errors when connecting a socket
1404         FD_SET((SOCKET)socketDescriptor, &fdexception);
1405     }
1406
1407     struct timeval tv;
1408     tv.tv_sec = timeout / 1000;
1409     tv.tv_usec = (timeout % 1000) * 1000;
1410
1411 #if !defined(Q_OS_WINCE)
1412     ret = select(socketDescriptor + 1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv);
1413 #else
1414     ret = select(1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv);
1415 #endif
1416
1417      //... but if it is actually set, pretend it did not happen
1418     if (ret > 0 && FD_ISSET((SOCKET)socketDescriptor, &fdexception))
1419         ret--;
1420
1421     if (readEnabled)
1422         readNotifier->setEnabled(true);
1423
1424     if (ret <= 0)
1425         return ret;
1426
1427     *selectForRead = FD_ISSET((SOCKET)socketDescriptor, &fdread);
1428     *selectForWrite = FD_ISSET((SOCKET)socketDescriptor, &fdwrite);
1429
1430     return ret;
1431 }
1432
1433 void QNativeSocketEnginePrivate::nativeClose()
1434 {
1435 #if defined (QTCPSOCKETENGINE_DEBUG)
1436     qDebug("QNativeSocketEnginePrivate::nativeClose()");
1437 #endif
1438     // We were doing a setsockopt here before with SO_DONTLINGER. (However with kind of wrong
1439     // usage of parameters, it wants a BOOL but we used a struct and pretended it to be bool).
1440     // We don't think setting this option should be done here, if a user wants it she/he can
1441      // do it manually with socketDescriptor()/setSocketDescriptor();
1442     ::closesocket(socketDescriptor);
1443 }
1444
1445 QT_END_NAMESPACE