1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
45 #include "qnativesocketengine_p.h"
47 #include <qabstracteventdispatcher.h>
48 #include <qsocketnotifier.h>
50 #include <qdatetime.h>
51 #include <qnetworkinterface.h>
53 //#define QNATIVESOCKETENGINE_DEBUG
54 #if defined(QNATIVESOCKETENGINE_DEBUG)
56 # include <qbytearray.h>
61 #if defined(QNATIVESOCKETENGINE_DEBUG)
63 void verboseWSErrorDebug(int 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;
113 qErrnoWarning(r, "more details");
117 Returns a human readable representation of the first \a len
118 characters in \a data.
120 static QByteArray qt_prettyDebug(const char *data, int len, int maxLength)
122 if (!data) return "(null)";
124 for (int i = 0; i < len; ++i) {
126 if (isprint(int(uchar(c)))) {
129 case '\n': out += "\\n"; break;
130 case '\r': out += "\\r"; break;
131 case '\t': out += "\\t"; break;
134 tmp.sprintf("\\%o", c);
135 out += tmp.toLatin1().constData();
146 #define WS_ERROR_DEBUG(x) verboseWSErrorDebug(x);
150 #define WS_ERROR_DEBUG(x) Q_UNUSED(x)
155 #define AF_INET6 23 /* Internetwork Version 6 */
158 #ifndef SO_EXCLUSIVEADDRUSE
159 #define SO_EXCLUSIVEADDRUSE ((int)(~SO_REUSEADDR)) /* disallow local address reuse */
163 Extracts the port and address from a sockaddr, and stores them in
164 \a port and \a addr if they are non-null.
166 static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt_sockaddr *sa, quint16 *port, QHostAddress *address)
168 if (sa->a.sa_family == AF_INET6) {
169 const qt_sockaddr_in6 *sa6 = &sa->a6;
171 for (int i = 0; i < 16; ++i)
172 tmp.c[i] = sa6->sin6_addr.qt_s6_addr[i];
176 a.setScopeId(QString::number(sa6->sin6_scope_id));
180 WSANtohs(socketDescriptor, sa6->sin6_port, port);
183 if (sa->a.sa_family == AF_INET) {
184 const sockaddr_in *sa4 = &sa->a4;
186 WSANtohl(socketDescriptor, sa4->sin_addr.s_addr, &addr);
192 WSANtohs(socketDescriptor, sa4->sin_port, port);
199 Sets the port and address to a sockaddr. Requires that sa point to the IPv6 struct if the address is IPv6.
201 void QNativeSocketEnginePrivate::setPortAndAddress(sockaddr_in * sockAddrIPv4, qt_sockaddr_in6 * sockAddrIPv6,
202 quint16 port, const QHostAddress & address, sockaddr ** sockAddrPtr, QT_SOCKLEN_T *sockAddrSize)
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;
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;
235 static inline QAbstractSocket::SocketType qt_socket_getType(qintptr socketDescriptor)
238 QT_SOCKLEN_T valueSize = sizeof(value);
239 if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, (char *) &value, &valueSize) != 0) {
240 WS_ERROR_DEBUG(WSAGetLastError());
242 if (value == SOCK_STREAM)
243 return QAbstractSocket::TcpSocket;
244 else if (value == SOCK_DGRAM)
245 return QAbstractSocket::UdpSocket;
247 return QAbstractSocket::UnknownSocketType;
253 static inline int qt_socket_getMaxMsgSize(qintptr socketDescriptor)
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());
263 QWindowsSockInit::QWindowsSockInit()
266 //### should we try for 2.2 on all platforms ??
269 // IPv6 requires Winsock v2.0 or better.
270 if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) {
271 qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed.");
277 QWindowsSockInit::~QWindowsSockInit()
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),
287 #ifndef SIO_UDP_CONNRESET
289 # define IOC_VENDOR 0x18000000
292 # define _WSAIOW(x,y) (IOC_IN|(x)|(y))
294 # define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
297 bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol socketProtocol)
300 //### no ip6 support on winsocket 1.1 but we will try not to use this !!!!!!!!!!!!1
302 if (winsockVersion < 0x20 && socketProtocol == QAbstractSocket::IPv6Protocol) {
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);
316 if (socket == INVALID_SOCKET) {
317 int err = WSAGetLastError();
320 case WSANOTINITIALISED:
323 case WSAEAFNOSUPPORT:
324 case WSAESOCKTNOSUPPORT:
327 setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
331 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
340 #if !defined(Q_OS_WINCE)
341 if (socketType == QAbstractSocket::UdpSocket) {
342 // enable new behavior using
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();
355 socketDescriptor = socket;
362 Returns the value of the socket option \a opt.
364 int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) const
366 Q_Q(const QNativeSocketEngine);
371 int level = SOL_SOCKET; // default
374 case QNativeSocketEngine::ReceiveBufferSocketOption:
377 case QNativeSocketEngine::SendBufferSocketOption:
380 case QNativeSocketEngine::BroadcastSocketOption:
383 case QNativeSocketEngine::NonBlockingSocketOption: {
384 unsigned long buf = 0;
385 if (WSAIoctl(socketDescriptor, FIONBIO, 0,0, &buf, sizeof(buf), 0,0,0) == 0)
391 case QNativeSocketEngine::AddressReusable:
394 case QNativeSocketEngine::BindExclusively:
395 n = SO_EXCLUSIVEADDRUSE;
397 case QNativeSocketEngine::ReceiveOutOfBandData:
400 case QNativeSocketEngine::LowDelayOption:
404 case QNativeSocketEngine::KeepAliveOption:
407 case QNativeSocketEngine::MulticastTtlOption:
409 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
410 level = IPPROTO_IPV6;
411 n = IPV6_MULTICAST_HOPS;
415 n = IP_MULTICAST_TTL;
418 case QNativeSocketEngine::MulticastLoopbackOption:
419 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
420 level = IPPROTO_IPV6;
421 n = IPV6_MULTICAST_LOOP;
425 n = IP_MULTICAST_LOOP;
428 case QNativeSocketEngine::TypeOfServiceOption:
433 #if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
434 #error code assumes windows is little endian
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)
440 WS_ERROR_DEBUG(WSAGetLastError());
446 Sets the socket option \a opt to \a v.
448 bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt, int v)
450 Q_Q(const QNativeSocketEngine);
455 int level = SOL_SOCKET; // default
458 case QNativeSocketEngine::ReceiveBufferSocketOption:
461 case QNativeSocketEngine::SendBufferSocketOption:
464 case QNativeSocketEngine::BroadcastSocketOption:
467 case QNativeSocketEngine::NonBlockingSocketOption:
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());
479 case QNativeSocketEngine::AddressReusable:
482 case QNativeSocketEngine::BindExclusively:
483 n = SO_EXCLUSIVEADDRUSE;
485 case QNativeSocketEngine::ReceiveOutOfBandData:
488 case QNativeSocketEngine::LowDelayOption:
492 case QNativeSocketEngine::KeepAliveOption:
495 case QNativeSocketEngine::MulticastTtlOption:
496 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
497 level = IPPROTO_IPV6;
498 n = IPV6_MULTICAST_HOPS;
502 n = IP_MULTICAST_TTL;
505 case QNativeSocketEngine::MulticastLoopbackOption:
506 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
507 level = IPPROTO_IPV6;
508 n = IPV6_MULTICAST_LOOP;
512 n = IP_MULTICAST_LOOP;
515 case QNativeSocketEngine::TypeOfServiceOption:
520 if (::setsockopt(socketDescriptor, level, n, (char*)&v, sizeof(v)) != 0) {
521 WS_ERROR_DEBUG(WSAGetLastError());
528 Fetches information about both ends of the connection: whatever is
531 bool QNativeSocketEnginePrivate::fetchConnectionParameters()
534 localAddress.clear();
538 if (socketDescriptor == -1)
542 QT_SOCKLEN_T sockAddrSize = sizeof(sa);
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) {
551 socketProtocol = QAbstractSocket::IPv4Protocol;
554 socketProtocol = QAbstractSocket::IPv6Protocol;
557 socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
561 int err = WSAGetLastError();
563 if (err == WSAENOTSOCK) {
564 setError(QAbstractSocket::UnsupportedSocketOperationError,
565 InvalidSocketErrorString);
570 #if defined (IPV6_V6ONLY)
571 // determine if local address is dual mode
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 )) {
578 socketProtocol = QAbstractSocket::AnyIPProtocol;
579 localAddress = QHostAddress::Any;
584 memset(&sa, 0, sizeof(sa));
585 if (::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
586 qt_socket_getPortAndAddress(socketDescriptor, &sa, &peerPort, &peerAddress);
588 WS_ERROR_DEBUG(WSAGetLastError());
591 socketType = qt_socket_getType(socketDescriptor);
593 #if defined (QNATIVESOCKETENGINE_DEBUG)
594 QString socketProtocolStr = "UnknownProtocol";
595 if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = "IPv4Protocol";
596 else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = "IPv6Protocol";
598 QString socketTypeStr = "UnknownSocketType";
599 if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = "TcpSocket";
600 else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = "UdpSocket";
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());
609 bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quint16 port)
612 #if defined (QNATIVESOCKETENGINE_DEBUG)
613 qDebug("QNativeSocketEnginePrivate::nativeConnect() to %s :: %i", address.toString().toLatin1().constData(), port);
616 struct sockaddr_in sockAddrIPv4;
617 qt_sockaddr_in6 sockAddrIPv6;
618 struct sockaddr *sockAddrPtr = 0;
619 QT_SOCKLEN_T sockAddrSize = 0;
621 setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
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) {
628 ipv6only = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
634 int connectResult = ::WSAConnect(socketDescriptor, sockAddrPtr, sockAddrSize, 0,0,0,0);
635 if (connectResult == SOCKET_ERROR) {
636 int err = WSAGetLastError();
640 case WSANOTINITIALISED:
644 socketState = QAbstractSocket::ConnectedState;
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.
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;
660 if (value == WSAETIMEDOUT) {
661 setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
662 socketState = QAbstractSocket::UnconnectedState;
665 if (value == WSAEHOSTUNREACH) {
666 setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
667 socketState = QAbstractSocket::UnconnectedState;
670 if (value == WSAEADDRNOTAVAIL) {
671 setError(QAbstractSocket::NetworkError, AddressNotAvailableErrorString);
672 socketState = QAbstractSocket::UnconnectedState;
679 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
680 socketState = QAbstractSocket::ConnectingState;
683 setError(QAbstractSocket::NetworkError, AddressInuseErrorString);
685 case WSAECONNREFUSED:
686 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
687 socketState = QAbstractSocket::UnconnectedState;
690 setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
693 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
694 socketState = QAbstractSocket::UnconnectedState;
696 case WSAEHOSTUNREACH:
697 setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
698 socketState = QAbstractSocket::UnconnectedState;
701 setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString);
702 socketState = QAbstractSocket::UnconnectedState;
706 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
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());
724 #if defined (QNATIVESOCKETENGINE_DEBUG)
725 qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true",
726 address.toString().toLatin1().constData(), port);
729 socketState = QAbstractSocket::ConnectedState;
734 bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &a, quint16 port)
736 QHostAddress address = a;
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);
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) {
748 ipv6only = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
754 case QAbstractSocket::IPv4Protocol:
755 if ((address.toIPv4Address() & 0xffff0000) == 0xefff0000) {
756 // binding to a multicast address
757 address = QHostAddress(QHostAddress::AnyIPv4);
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) );
766 address = QHostAddress(QHostAddress::AnyIPv4); //xp/WS2003 and earlier don't support dual stack, so bind to IPv4
772 struct sockaddr_in sockAddrIPv4;
773 qt_sockaddr_in6 sockAddrIPv6;
774 struct sockaddr *sockAddrPtr = 0;
775 QT_SOCKLEN_T sockAddrSize = 0;
777 setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
780 int bindResult = ::bind(socketDescriptor, sockAddrPtr, sockAddrSize);
781 if (bindResult == SOCKET_ERROR) {
782 int err = WSAGetLastError();
785 case WSANOTINITIALISED:
790 setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
793 setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString);
795 case WSAEADDRNOTAVAIL:
796 setError(QAbstractSocket::SocketAddressNotAvailableError, AddressNotAvailableErrorString);
802 #if defined (QNATIVESOCKETENGINE_DEBUG)
803 qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
804 address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData());
811 localAddress = address;
813 #if defined (QNATIVESOCKETENGINE_DEBUG)
814 qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == true",
815 address.toString().toLatin1().constData(), port);
817 socketState = QAbstractSocket::BoundState;
822 bool QNativeSocketEnginePrivate::nativeListen(int backlog)
824 if (::listen(socketDescriptor, backlog) == SOCKET_ERROR) {
825 int err = WSAGetLastError();
828 case WSANOTINITIALISED:
832 setError(QAbstractSocket::AddressInUseError,
833 PortInuseErrorString);
839 #if defined (QNATIVESOCKETENGINE_DEBUG)
840 qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == false (%s)",
841 backlog, socketErrorString.toLatin1().constData());
846 #if defined (QNATIVESOCKETENGINE_DEBUG)
847 qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == true", backlog);
850 socketState = QAbstractSocket::ListeningState;
854 int QNativeSocketEnginePrivate::nativeAccept()
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);
866 #if defined (QNATIVESOCKETENGINE_DEBUG)
867 qDebug("QNativeSocketEnginePrivate::nativeAccept() == %i", acceptedDescriptor);
869 return acceptedDescriptor;
872 static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d,
875 const QHostAddress &groupAddress,
876 const QNetworkInterface &iface)
883 struct ip_mreq mreq4;
884 struct ipv6_mreq mreq6;
886 if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) {
887 level = IPPROTO_IPV6;
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();
897 if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
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());
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());
911 d->setError(QAbstractSocket::NetworkError,
912 QNativeSocketEnginePrivate::NetworkUnreachableErrorString);
916 mreq4.imr_interface.s_addr = INADDR_ANY;
920 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
921 QNativeSocketEnginePrivate::ProtocolUnsupportedErrorString);
925 int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize);
927 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
928 QNativeSocketEnginePrivate::OperationUnsupportedErrorString);
934 bool QNativeSocketEnginePrivate::nativeJoinMulticastGroup(const QHostAddress &groupAddress,
935 const QNetworkInterface &iface)
937 return multicastMembershipHelper(this,
944 bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &groupAddress,
945 const QNetworkInterface &iface)
947 return multicastMembershipHelper(this,
954 QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const
956 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
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);
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))
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)
984 return QNetworkInterface();
987 bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInterface &iface)
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);
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));
1011 v.s_addr = INADDR_ANY;
1012 return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, sizeof(v)) != -1);
1015 qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
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());
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
1030 if (nbytes == 1 && socketType == QAbstractSocket::UdpSocket) {
1034 buf.len = sizeof(c);
1035 DWORD flags = MSG_PEEK;
1036 if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR)
1043 bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
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);
1051 bool result = false;
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.
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
1070 ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags,
1071 &storage.a, &storageSize, 0, 0);
1074 // If there's no error, or if our buffer was too small, there must be
1075 // a pending datagram.
1080 bool result = false;
1083 FD_SET((SOCKET)socketDescriptor, &readS);
1086 timeout.tv_usec = 5000;
1087 int available = ::select(1, &readS, 0, 0, &timeout);
1088 result = available > 0 ? true : false;
1091 #if defined (QNATIVESOCKETENGINE_DEBUG)
1092 qDebug("QNativeSocketEnginePrivate::nativeHasPendingDatagrams() == %s",
1093 result ? "true" : "false");
1099 qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
1102 #if !defined(Q_OS_WINCE)
1105 DWORD bufferCount = 5;
1108 // the data written to udpMessagePeekBuffer is discarded, so
1109 // this function is still reentrant although it might not look
1111 static char udpMessagePeekBuffer[8192];
1113 buf = new WSABUF[bufferCount];
1114 for (DWORD i=0; i<bufferCount; i++) {
1115 buf[i].buf = udpMessagePeekBuffer;
1116 buf[i].len = sizeof(udpMessagePeekBuffer);
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);
1125 } else if (recvResult == SOCKET_ERROR && err == WSAEMSGSIZE) {
1128 } else if (recvResult == SOCKET_ERROR) {
1129 WS_ERROR_DEBUG(err);
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);
1150 #if defined (QNATIVESOCKETENGINE_DEBUG)
1151 qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %li", ret);
1158 qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength,
1159 QHostAddress *address, quint16 *port)
1164 memset(&aa, 0, sizeof(aa));
1170 buf.len = maxLength;
1171 #if !defined(Q_OS_WINCE)
1173 buf.len = maxLength;
1176 buf.buf = data ? data : &tmpChar;
1177 buf.len = maxLength;
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);
1190 WS_ERROR_DEBUG(err);
1191 setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
1195 ret = qint64(bytesRead);
1198 qt_socket_getPortAndAddress(socketDescriptor, &aa, port, address);
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);
1211 qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len,
1212 const QHostAddress &address, quint16 port)
1215 struct sockaddr_in sockAddrIPv4;
1216 qt_sockaddr_in6 sockAddrIPv6;
1217 struct sockaddr *sockAddrPtr = 0;
1218 QT_SOCKLEN_T sockAddrSize = 0;
1220 setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
1223 #if !defined(Q_OS_WINCE)
1224 buf.buf = len ? (char*)data : 0;
1227 buf.buf = len ? (char*)data : &tmp;
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);
1237 setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
1240 setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
1245 ret = qint64(bytesSent);
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(),
1258 qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
1260 Q_Q(QNativeSocketEngine);
1262 qint64 bytesToSend = len;
1266 buf.buf = (char*)data + ret;
1267 buf.len = bytesToSend;
1269 DWORD bytesWritten = 0;
1271 int socketRet = ::WSASend(socketDescriptor, &buf, 1, &bytesWritten, flags, 0,0);
1273 ret += qint64(bytesWritten);
1276 if (socketRet != SOCKET_ERROR) {
1281 } else if ((err = WSAGetLastError()) == WSAEWOULDBLOCK) {
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
1290 WS_ERROR_DEBUG(err);
1293 case WSAECONNABORTED:
1295 setError(QAbstractSocket::NetworkError, WriteErrorString);
1305 bytesToSend = qMin<qint64>(49152, len - ret);
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);
1316 qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxLength)
1321 buf.len = maxLength;
1323 DWORD bytesRead = 0;
1324 #if defined(Q_OS_WINCE)
1327 if (::WSARecv(socketDescriptor, &buf, 1, &bytesRead, &flags, 0,0) == SOCKET_ERROR) {
1328 int err = WSAGetLastError();
1329 WS_ERROR_DEBUG(err);
1331 case WSAEWOULDBLOCK:
1336 //error string is now set in read(), not here in nativeRead()
1339 case WSAECONNABORTED:
1340 // for tcp sockets this will be handled in QNativeSocketEngine::read
1347 if (WSAGetLastError() == WSAEWOULDBLOCK)
1350 ret = qint64(bytesRead);
1353 #if defined (QNATIVESOCKETENGINE_DEBUG)
1355 qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %li) == %li",
1356 data, qt_prettyDebug(data, qMin((int)bytesRead, 16), (int)bytesRead).data(), (int)maxLength, (int)ret);
1358 qDebug("QNativeSocketEnginePrivate::nativeRead(%p, %li) == -2 (WOULD BLOCK)",
1359 data, int(maxLength));
1366 int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const
1368 bool readEnabled = selectForRead && readNotifier && readNotifier->isEnabled();
1370 readNotifier->setEnabled(false);
1376 memset(&fds, 0, sizeof(fd_set));
1378 fds.fd_array[0] = (SOCKET)socketDescriptor;
1381 tv.tv_sec = timeout / 1000;
1382 tv.tv_usec = (timeout % 1000) * 1000;
1384 if (selectForRead) {
1385 ret = select(0, &fds, 0, 0, timeout < 0 ? 0 : &tv);
1389 // Windows needs this to report errors when connecting a socket ...
1391 FD_ZERO(&fdexception);
1392 FD_SET((SOCKET)socketDescriptor, &fdexception);
1394 ret = select(0, 0, &fds, &fdexception, timeout < 0 ? 0 : &tv);
1396 // ... but if it is actually set, pretend it did not happen
1397 if (ret > 0 && FD_ISSET((SOCKET)socketDescriptor, &fdexception))
1402 readNotifier->setEnabled(true);
1407 int QNativeSocketEnginePrivate::nativeSelect(int timeout,
1408 bool checkRead, bool checkWrite,
1409 bool *selectForRead, bool *selectForWrite) const
1411 bool readEnabled = checkRead && readNotifier && readNotifier->isEnabled();
1413 readNotifier->setEnabled(false);
1421 memset(&fdread, 0, sizeof(fd_set));
1423 fdread.fd_count = 1;
1424 fdread.fd_array[0] = (SOCKET)socketDescriptor;
1426 memset(&fdwrite, 0, sizeof(fd_set));
1427 FD_ZERO(&fdexception);
1429 fdwrite.fd_count = 1;
1430 fdwrite.fd_array[0] = (SOCKET)socketDescriptor;
1432 // Windows needs this to report errors when connecting a socket
1433 FD_SET((SOCKET)socketDescriptor, &fdexception);
1437 tv.tv_sec = timeout / 1000;
1438 tv.tv_usec = (timeout % 1000) * 1000;
1440 #if !defined(Q_OS_WINCE)
1441 ret = select(socketDescriptor + 1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv);
1443 ret = select(1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv);
1446 //... but if it is actually set, pretend it did not happen
1447 if (ret > 0 && FD_ISSET((SOCKET)socketDescriptor, &fdexception))
1451 readNotifier->setEnabled(true);
1456 *selectForRead = FD_ISSET((SOCKET)socketDescriptor, &fdread);
1457 *selectForWrite = FD_ISSET((SOCKET)socketDescriptor, &fdwrite);
1462 void QNativeSocketEnginePrivate::nativeClose()
1464 #if defined (QTCPSOCKETENGINE_DEBUG)
1465 qDebug("QNativeSocketEnginePrivate::nativeClose()");
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);