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