Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qnativesocketengine_win.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
6#include <winsock2.h>
7#include <ws2tcpip.h>
8
10
11#include <qabstracteventdispatcher.h>
12#include <qsocketnotifier.h>
13#include <qdebug.h>
14#include <qdatetime.h>
15#include <qnetworkinterface.h>
16#include <qoperatingsystemversion.h>
17#include <qvarlengtharray.h>
18
19#include <algorithm>
20#include <chrono>
21
22//#define QNATIVESOCKETENGINE_DEBUG
23#if defined(QNATIVESOCKETENGINE_DEBUG)
24#include <private/qdebug_p.h>
25#endif
26
28
29//Some distributions of mingw (including 4.7.2 from mingw.org) are missing this from headers.
30//Also microsoft headers don't include it when building on XP and earlier.
31#ifndef IPV6_V6ONLY
32#define IPV6_V6ONLY 27
33#endif
34#ifndef IP_HOPLIMIT
35#define IP_HOPLIMIT 21 // Receive packet hop limit.
36#endif
37#ifndef TCP_KEEPIDLE
38#define TCP_KEEPIDLE 3
39#endif
40#ifndef TCP_KEEPINTVL
41#define TCP_KEEPINTVL 17
42#endif
43#ifndef TCP_KEEPCNT
44#define TCP_KEEPCNT 16
45#endif
46
47#if defined(QNATIVESOCKETENGINE_DEBUG)
48
49void verboseWSErrorDebug(int r)
50{
51 switch (r) {
52 case WSANOTINITIALISED : qDebug("WSA error : WSANOTINITIALISED"); break;
53 case WSAEINTR: qDebug("WSA error : WSAEINTR"); break;
54 case WSAEBADF: qDebug("WSA error : WSAEBADF"); break;
55 case WSAEACCES: qDebug("WSA error : WSAEACCES"); break;
56 case WSAEFAULT: qDebug("WSA error : WSAEFAULT"); break;
57 case WSAEINVAL: qDebug("WSA error : WSAEINVAL"); break;
58 case WSAEMFILE: qDebug("WSA error : WSAEMFILE"); break;
59 case WSAEWOULDBLOCK: qDebug("WSA error : WSAEWOULDBLOCK"); break;
60 case WSAEINPROGRESS: qDebug("WSA error : WSAEINPROGRESS"); break;
61 case WSAEALREADY: qDebug("WSA error : WSAEALREADY"); break;
62 case WSAENOTSOCK: qDebug("WSA error : WSAENOTSOCK"); break;
63 case WSAEDESTADDRREQ: qDebug("WSA error : WSAEDESTADDRREQ"); break;
64 case WSAEMSGSIZE: qDebug("WSA error : WSAEMSGSIZE"); break;
65 case WSAEPROTOTYPE: qDebug("WSA error : WSAEPROTOTYPE"); break;
66 case WSAENOPROTOOPT: qDebug("WSA error : WSAENOPROTOOPT"); break;
67 case WSAEPROTONOSUPPORT: qDebug("WSA error : WSAEPROTONOSUPPORT"); break;
68 case WSAESOCKTNOSUPPORT: qDebug("WSA error : WSAESOCKTNOSUPPORT"); break;
69 case WSAEOPNOTSUPP: qDebug("WSA error : WSAEOPNOTSUPP"); break;
70 case WSAEPFNOSUPPORT: qDebug("WSA error : WSAEPFNOSUPPORT"); break;
71 case WSAEAFNOSUPPORT: qDebug("WSA error : WSAEAFNOSUPPORT"); break;
72 case WSAEADDRINUSE: qDebug("WSA error : WSAEADDRINUSE"); break;
73 case WSAEADDRNOTAVAIL: qDebug("WSA error : WSAEADDRNOTAVAIL"); break;
74 case WSAENETDOWN: qDebug("WSA error : WSAENETDOWN"); break;
75 case WSAENETUNREACH: qDebug("WSA error : WSAENETUNREACH"); break;
76 case WSAENETRESET: qDebug("WSA error : WSAENETRESET"); break;
77 case WSAECONNABORTED: qDebug("WSA error : WSAECONNABORTED"); break;
78 case WSAECONNRESET: qDebug("WSA error : WSAECONNRESET"); break;
79 case WSAENOBUFS: qDebug("WSA error : WSAENOBUFS"); break;
80 case WSAEISCONN: qDebug("WSA error : WSAEISCONN"); break;
81 case WSAENOTCONN: qDebug("WSA error : WSAENOTCONN"); break;
82 case WSAESHUTDOWN: qDebug("WSA error : WSAESHUTDOWN"); break;
83 case WSAETOOMANYREFS: qDebug("WSA error : WSAETOOMANYREFS"); break;
84 case WSAETIMEDOUT: qDebug("WSA error : WSAETIMEDOUT"); break;
85 case WSAECONNREFUSED: qDebug("WSA error : WSAECONNREFUSED"); break;
86 case WSAELOOP: qDebug("WSA error : WSAELOOP"); break;
87 case WSAENAMETOOLONG: qDebug("WSA error : WSAENAMETOOLONG"); break;
88 case WSAEHOSTDOWN: qDebug("WSA error : WSAEHOSTDOWN"); break;
89 case WSAEHOSTUNREACH: qDebug("WSA error : WSAEHOSTUNREACH"); break;
90 case WSAENOTEMPTY: qDebug("WSA error : WSAENOTEMPTY"); break;
91 case WSAEPROCLIM: qDebug("WSA error : WSAEPROCLIM"); break;
92 case WSAEUSERS: qDebug("WSA error : WSAEUSERS"); break;
93 case WSAEDQUOT: qDebug("WSA error : WSAEDQUOT"); break;
94 case WSAESTALE: qDebug("WSA error : WSAESTALE"); break;
95 case WSAEREMOTE: qDebug("WSA error : WSAEREMOTE"); break;
96 case WSAEDISCON: qDebug("WSA error : WSAEDISCON"); break;
97 default: qDebug("WSA error : Unknown"); break;
98 }
99 qErrnoWarning(r, "more details");
100}
101
102#define WS_ERROR_DEBUG(x) verboseWSErrorDebug(x)
103
104#else
105
106#define WS_ERROR_DEBUG(x) Q_UNUSED(x)
107
108#endif
109
110#ifndef AF_INET6
111#define AF_INET6 23 /* Internetwork Version 6 */
112#endif
113
114#ifndef SO_EXCLUSIVEADDRUSE
115#define SO_EXCLUSIVEADDRUSE ((int)(~SO_REUSEADDR)) /* disallow local address reuse */
116#endif
117
118/*
119 Extracts the port and address from a sockaddr, and stores them in
120 \a port and \a addr if they are non-null.
121*/
122static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt_sockaddr *sa, quint16 *port, QHostAddress *address)
123{
124 if (sa->a.sa_family == AF_INET6) {
125 const sockaddr_in6 *sa6 = &sa->a6;
126 Q_IPV6ADDR tmp;
127 for (int i = 0; i < 16; ++i)
128 tmp.c[i] = sa6->sin6_addr.s6_addr[i];
129 if (address) {
130 QHostAddress a;
131 a.setAddress(tmp);
132 if (sa6->sin6_scope_id)
133 a.setScopeId(QString::number(sa6->sin6_scope_id));
134 *address = a;
135 }
136 if (port)
137 WSANtohs(socketDescriptor, sa6->sin6_port, port);
138 } else
139
140 if (sa->a.sa_family == AF_INET) {
141 const sockaddr_in *sa4 = &sa->a4;
142 unsigned long addr;
143 WSANtohl(socketDescriptor, sa4->sin_addr.s_addr, &addr);
144 QHostAddress a;
145 a.setAddress(addr);
146 if (address)
147 *address = a;
148 if (port)
149 WSANtohs(socketDescriptor, sa4->sin_port, port);
150 }
151}
152
153static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt,
154 QAbstractSocket::NetworkLayerProtocol socketProtocol, int &level, int &n)
155{
156 n = -1;
157 level = SOL_SOCKET; // default
158
159 switch (opt) {
160 case QNativeSocketEngine::NonBlockingSocketOption: // WSAIoctl
161 case QNativeSocketEngine::TypeOfServiceOption: // not supported
162 case QNativeSocketEngine::MaxStreamsSocketOption:
163 Q_UNREACHABLE();
164
165 case QNativeSocketEngine::BindInterfaceIndex:
166 Q_UNREACHABLE(); // handled directly in setOption()
167
168 case QNativeSocketEngine::ReceiveBufferSocketOption:
169 n = SO_RCVBUF;
170 break;
171 case QNativeSocketEngine::SendBufferSocketOption:
172 n = SO_SNDBUF;
173 break;
174 case QNativeSocketEngine::BroadcastSocketOption:
175 n = SO_BROADCAST;
176 break;
177 case QNativeSocketEngine::AddressReusable:
178 n = SO_REUSEADDR;
179 break;
180 case QNativeSocketEngine::BindExclusively:
182 break;
183 case QNativeSocketEngine::ReceiveOutOfBandData:
184 n = SO_OOBINLINE;
185 break;
186 case QNativeSocketEngine::LowDelayOption:
187 level = IPPROTO_TCP;
188 n = TCP_NODELAY;
189 break;
190 case QNativeSocketEngine::KeepAliveOption:
191 n = SO_KEEPALIVE;
192 break;
193 case QNativeSocketEngine::MulticastTtlOption:
194 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
195 level = IPPROTO_IPV6;
196 n = IPV6_MULTICAST_HOPS;
197 } else
198 {
199 level = IPPROTO_IP;
200 n = IP_MULTICAST_TTL;
201 }
202 break;
203 case QNativeSocketEngine::MulticastLoopbackOption:
204 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
205 level = IPPROTO_IPV6;
206 n = IPV6_MULTICAST_LOOP;
207 } else
208 {
209 level = IPPROTO_IP;
210 n = IP_MULTICAST_LOOP;
211 }
212 break;
213 case QNativeSocketEngine::ReceivePacketInformation:
214 Q_UNREACHABLE(); // handled in setOption() directly now
215 break;
216 case QNativeSocketEngine::ReceiveHopLimit:
217 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
218 level = IPPROTO_IPV6;
219 n = IPV6_HOPLIMIT;
220 } else if (socketProtocol == QAbstractSocket::IPv4Protocol) {
221 level = IPPROTO_IP;
222 n = IP_HOPLIMIT;
223 }
224 break;
225
226 case QAbstractSocketEngine::PathMtuInformation:
227 break; // not supported on Windows
228 case QNativeSocketEngine::KeepAliveIdleOption:
229 level = IPPROTO_TCP;
230 n = TCP_KEEPIDLE; // defined in ws2ipdef.h
231 break;
232 case QNativeSocketEngine::KeepAliveIntervalOption:
233 level = IPPROTO_TCP;
234 n = TCP_KEEPINTVL; // defined in ws2ipdef.h
235 break;
236 case QNativeSocketEngine::KeepAliveCountOption:
237 level = IPPROTO_TCP;
238 n = TCP_KEEPCNT; // defined in ws2ipdef.h
239 break;
240 }
241}
242
243/*! \internal
244
245*/
246static inline QAbstractSocket::SocketType qt_socket_getType(qintptr socketDescriptor)
247{
248 int value = 0;
249 QT_SOCKLEN_T valueSize = sizeof(value);
250 if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE,
251 reinterpret_cast<char *>(&value), &valueSize) != 0) {
252 WS_ERROR_DEBUG(WSAGetLastError());
253 } else {
254 if (value == SOCK_STREAM)
255 return QAbstractSocket::TcpSocket;
256 else if (value == SOCK_DGRAM)
257 return QAbstractSocket::UdpSocket;
258 }
259 return QAbstractSocket::UnknownSocketType;
260}
261
262// MS Transport Provider IOCTL to control
263// reporting PORT_UNREACHABLE messages
264// on UDP sockets via recv/WSARecv/etc.
265// Path TRUE in input buffer to enable (default if supported),
266// FALSE to disable.
267#ifndef SIO_UDP_CONNRESET
268# ifndef IOC_VENDOR
269# define IOC_VENDOR 0x18000000
270# endif
271# ifndef _WSAIOW
272# define _WSAIOW(x,y) (IOC_IN|(x)|(y))
273# endif
274# define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
275#endif
276
277bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol)
278{
279 //### SCTP not implemented
280 if (socketType == QAbstractSocket::SctpSocket) {
281 setError(QAbstractSocket::UnsupportedSocketOperationError,
282 ProtocolUnsupportedErrorString);
283 return false;
284 }
285
286 //Windows XP and 2003 support IPv6 but not dual stack sockets
287 int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol
288 || (socketProtocol == QAbstractSocket::AnyIPProtocol)) ? AF_INET6 : AF_INET;
289 int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
290
291 // MSDN KB179942 states that on winnt 4 WSA_FLAG_OVERLAPPED is needed if socket is to be non
292 // blocking and recommends always doing it for cross-windows-version compatibility.
293
294 // WSA_FLAG_NO_HANDLE_INHERIT is atomic (like linux O_CLOEXEC)
295#ifndef WSA_FLAG_NO_HANDLE_INHERIT
296#define WSA_FLAG_NO_HANDLE_INHERIT 0x80
297#endif
298
299 SOCKET socket = ::WSASocket(protocol, type, 0, NULL, 0, WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED);
300 if (socket == INVALID_SOCKET) {
301 int err = WSAGetLastError();
302 WS_ERROR_DEBUG(err);
303 switch (err) {
304 case WSANOTINITIALISED:
305 //###
306 break;
307 case WSAEAFNOSUPPORT:
308 case WSAESOCKTNOSUPPORT:
309 case WSAEPROTOTYPE:
310 case WSAEINVAL:
311 setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
312 break;
313 case WSAEMFILE:
314 case WSAENOBUFS:
315 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
316 break;
317 default:
318 break;
319 }
320
321 return false;
322 }
323
324 if (socketType == QAbstractSocket::UdpSocket) {
325 // enable new behavior using
326 // SIO_UDP_CONNRESET
327 DWORD dwBytesReturned = 0;
328 int bNewBehavior = 1;
329 if (::WSAIoctl(socket, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior),
330 NULL, 0, &dwBytesReturned, NULL, NULL) == SOCKET_ERROR) {
331 // not to worry isBogusUdpReadNotification() should handle this otherwise
332 int err = WSAGetLastError();
333 WS_ERROR_DEBUG(err);
334 }
335 }
336
337 // get the pointer to sendmsg and recvmsg
338 DWORD bytesReturned;
339 GUID recvmsgguid = WSAID_WSARECVMSG;
340 if (WSAIoctl(socket, SIO_GET_EXTENSION_FUNCTION_POINTER,
341 &recvmsgguid, sizeof(recvmsgguid),
342 &recvmsg, sizeof(recvmsg), &bytesReturned, NULL, NULL) == SOCKET_ERROR)
343 recvmsg = 0;
344
345 GUID sendmsgguid = WSAID_WSASENDMSG;
346 if (WSAIoctl(socket, SIO_GET_EXTENSION_FUNCTION_POINTER,
347 &sendmsgguid, sizeof(sendmsgguid),
348 &sendmsg, sizeof(sendmsg), &bytesReturned, NULL, NULL) == SOCKET_ERROR)
349 sendmsg = 0;
350
351 // Attempt to enable dual-stack
352 if (protocol == AF_INET6) {
353 int ipv6only = 0;
354 ::setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY,
355 reinterpret_cast<char *>(&ipv6only), sizeof(ipv6only));
356 }
357
358 socketDescriptor = socket;
359 this->socketProtocol = socketProtocol;
360 this->socketType = socketType;
361
362 // Make the socket nonblocking.
363 if (!setOption(QAbstractSocketEngine::NonBlockingSocketOption, 1)) {
364 setError(QAbstractSocket::UnsupportedSocketOperationError, NonBlockingInitFailedErrorString);
365 q_func()->close();
366 return false;
367 }
368
369 return true;
370}
371
372/*! \internal
373
374 Returns the value of the socket option \a opt.
375*/
376int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) const
377{
378 Q_Q(const QNativeSocketEngine);
379 if (!q->isValid())
380 return -1;
381
382 // handle non-getsockopt
383 switch (opt) {
384 case QNativeSocketEngine::NonBlockingSocketOption: {
385 unsigned long buf = 0;
386 if (WSAIoctl(socketDescriptor, FIONBIO, 0,0, &buf, sizeof(buf), 0,0,0) == 0)
387 return buf;
388 else
389 return -1;
390 break;
391 }
392 case QNativeSocketEngine::TypeOfServiceOption:
393 case QNativeSocketEngine::MaxStreamsSocketOption:
394 return -1;
395
396 default:
397 break;
398 }
399
400#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
401#error code assumes windows is little endian
402#endif
403 int n, level;
404 int v = 0; //note: windows doesn't write to all bytes if the option type is smaller than int
405 QT_SOCKOPTLEN_T len = sizeof(v);
406
407 convertToLevelAndOption(opt, socketProtocol, level, n);
408 if (n != -1) {
409 if (getsockopt(socketDescriptor, level, n, (char *) &v, &len) == 0)
410 return v;
411 WS_ERROR_DEBUG(WSAGetLastError());
412 }
413 return -1;
414}
415
416
417/*! \internal
418 Sets the socket option \a opt to \a v.
419*/
420bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt, int v)
421{
422 Q_Q(const QNativeSocketEngine);
423 if (!q->isValid())
424 return false;
425
426 // handle non-setsockopt options
427 switch (opt) {
428 case QNativeSocketEngine::SendBufferSocketOption:
429 // see QTBUG-30478 SO_SNDBUF should not be used on Vista or later
430 return false;
431 case QNativeSocketEngine::NonBlockingSocketOption:
432 {
433 unsigned long buf = v;
434 unsigned long outBuf;
435 DWORD sizeWritten = 0;
436 if (::WSAIoctl(socketDescriptor, FIONBIO, &buf, sizeof(unsigned long), &outBuf, sizeof(unsigned long), &sizeWritten, 0,0) == SOCKET_ERROR) {
437 WS_ERROR_DEBUG(WSAGetLastError());
438 return false;
439 }
440 return true;
441 }
442 case QNativeSocketEngine::TypeOfServiceOption:
443 case QNativeSocketEngine::MaxStreamsSocketOption:
444 return false;
445
446 case QNativeSocketEngine::ReceivePacketInformation: {
447 if (socketProtocol == QAbstractSocket::IPv6Protocol
448 || socketProtocol == QAbstractSocket::AnyIPProtocol) {
449 // set the IPv6 option
450 if (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_PKTINFO,
451 reinterpret_cast<char *>(&v), sizeof(v)) != 0) {
452 WS_ERROR_DEBUG(WSAGetLastError());
453 return false;
454 }
455 }
456 // Try to set the IPv4 option in any case, but fail only if the
457 // protocol is IPv4
458 if (::setsockopt(socketDescriptor, IPPROTO_IP, IP_PKTINFO,
459 reinterpret_cast<char *>(&v), sizeof(v)) != 0) {
460 if (socketProtocol == QAbstractSocket::IPv4Protocol) {
461 WS_ERROR_DEBUG(WSAGetLastError());
462 return false;
463 }
464 }
465 return true;
466 }
467
468 case QNativeSocketEngine::BindInterfaceIndex: {
469 int ret = 0;
470 if (socketProtocol == QAbstractSocket::IPv6Protocol
471 || socketProtocol == QAbstractSocket::AnyIPProtocol) {
472 // IPv6 - uses host byte order
473 // Bind outgoing datagrams to the interface
474 if (!ret) {
475 ret = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_UNICAST_IF,
476 reinterpret_cast<char *>(&v), sizeof(v));
477 }
478 if (!ret) {
479 ret = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF,
480 reinterpret_cast<char *>(&v), sizeof(v));
481 }
482 // Bind incoming datagrams to the interface
483 if (!ret) {
484 const int enable = 1;
485 ret = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_IFLIST,
486 reinterpret_cast<const char *>(&enable), sizeof(enable));
487 if (!ret) {
488 ret = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_ADD_IFLIST,
489 reinterpret_cast<char *>(&v), sizeof(v));
490 }
491 }
492 }
493 bool result = !ret;
494 if (result) {
495 // Try to set the IPv4 options unconditionally, but ignore
496 // the result if the protocol is not IPv4-only
497
498 // IPv4 - uses network byte order
499 int netIdx = htonl(v);
500 // Bind outgoing datagrams to the interface
501 if (!ret) {
502 ret = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_UNICAST_IF,
503 reinterpret_cast<char *>(&netIdx), sizeof(netIdx));
504 }
505 if (!ret) {
506 ret = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF,
507 reinterpret_cast<char *>(&netIdx), sizeof(netIdx));
508 }
509 // Bind incoming datagrams to the interface
510 if (!ret) {
511 const int enable = 1;
512 ret = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_IFLIST,
513 reinterpret_cast<const char *>(&enable), sizeof(enable));
514 if (!ret) {
515 // uses host byte order here
516 ret = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_ADD_IFLIST,
517 reinterpret_cast<char *>(&v), sizeof(v));
518 }
519 }
520 if (socketProtocol == QAbstractSocket::IPv4Protocol)
521 result = !ret;
522 }
523 return result;
524 }
525
526 default:
527 break;
528 }
529
530 int n, level;
531 convertToLevelAndOption(opt, socketProtocol, level, n);
532 if (n == -1)
533 return false;
534 if (::setsockopt(socketDescriptor, level, n, (char*)&v, sizeof(v)) != 0) {
535 WS_ERROR_DEBUG(WSAGetLastError());
536 return false;
537 }
538 return true;
539}
540
541/*!
542 \class QNativeSocketEnginePrivate
543 \internal
544*/
545
546/*!
547 Fetches information about both ends of the connection: whatever is
548 available.
549*/
551{
552 localPort = 0;
553 localAddress.clear();
554 peerPort = 0;
555 peerAddress.clear();
556 inboundStreamCount = outboundStreamCount = 0;
557
558 if (socketDescriptor == -1)
559 return false;
560
561 qt_sockaddr sa;
562 QT_SOCKLEN_T sockAddrSize = sizeof(sa);
563
564 // Determine local address
565 memset(&sa, 0, sizeof(sa));
566 if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
567 qt_socket_getPortAndAddress(socketDescriptor, &sa, &localPort, &localAddress);
568 // Determine protocol family
569 switch (sa.a.sa_family) {
570 case AF_INET:
571 socketProtocol = QAbstractSocket::IPv4Protocol;
572 break;
573 case AF_INET6:
574 socketProtocol = QAbstractSocket::IPv6Protocol;
575 break;
576 default:
577 socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
578 break;
579 }
580 } else {
581 int err = WSAGetLastError();
582 WS_ERROR_DEBUG(err);
583 if (err == WSAENOTSOCK) {
584 setError(QAbstractSocket::UnsupportedSocketOperationError,
585 InvalidSocketErrorString);
586 return false;
587 }
588 }
589
590 // determine if local address is dual mode
591 DWORD ipv6only = 0;
592 QT_SOCKOPTLEN_T optlen = sizeof(ipv6only);
593 if (localAddress == QHostAddress::AnyIPv6
594 && !getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, &optlen )) {
595 if (!ipv6only) {
596 socketProtocol = QAbstractSocket::AnyIPProtocol;
597 localAddress = QHostAddress::Any;
598 }
599 }
600
601 // Some Windows kernels return a v4-mapped QHostAddress::AnyIPv4 as a
602 // local address of the socket which bound on both IPv4 and IPv6 interfaces.
603 // This address does not match to any special address and should not be used
604 // to send the data. So, replace it with QHostAddress::Any.
605 const uchar ipv6MappedNet[] = {0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 0,0,0,0};
606 if (localAddress.isInSubnet(QHostAddress(ipv6MappedNet), 128 - 32)) {
607 bool ok = false;
608 const quint32 localIPv4 = localAddress.toIPv4Address(&ok);
609 if (ok && localIPv4 == INADDR_ANY) {
610 socketProtocol = QAbstractSocket::AnyIPProtocol;
611 localAddress = QHostAddress::Any;
612 }
613 }
614
615 memset(&sa, 0, sizeof(sa));
616 if (::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
617 qt_socket_getPortAndAddress(socketDescriptor, &sa, &peerPort, &peerAddress);
618 inboundStreamCount = outboundStreamCount = 1;
619 } else {
620 WS_ERROR_DEBUG(WSAGetLastError());
621 }
622
623 socketType = qt_socket_getType(socketDescriptor);
624
625#if defined (QNATIVESOCKETENGINE_DEBUG)
626 QString socketProtocolStr = QStringLiteral("UnknownProtocol");
627 if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = QStringLiteral("IPv4Protocol");
628 else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = QStringLiteral("IPv6Protocol");
629
630 QString socketTypeStr = QStringLiteral("UnknownSocketType");
631 if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = QStringLiteral("TcpSocket");
632 else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = QStringLiteral("UdpSocket");
633
634 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());
635#endif
636
637 return true;
638}
639
640
642{
643 Q_ASSERT(d);
644 switch (error) {
645 case WSAEISCONN:
646 d->socketState = QAbstractSocket::ConnectedState;
647 break;
648 case WSAEHOSTUNREACH:
649 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::HostUnreachableErrorString);
650 d->socketState = QAbstractSocket::UnconnectedState;
651 break;
652 case WSAEADDRNOTAVAIL:
653 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::AddressNotAvailableErrorString);
654 d->socketState = QAbstractSocket::UnconnectedState;
655 break;
656 case WSAEINPROGRESS:
657 d->setError(QAbstractSocket::UnfinishedSocketOperationError, QNativeSocketEnginePrivate::InvalidSocketErrorString);
658 d->socketState = QAbstractSocket::ConnectingState;
659 break;
660 case WSAEADDRINUSE:
661 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::AddressInuseErrorString);
662 break;
663 case WSAECONNREFUSED:
664 d->setError(QAbstractSocket::ConnectionRefusedError, QNativeSocketEnginePrivate::ConnectionRefusedErrorString);
665 d->socketState = QAbstractSocket::UnconnectedState;
666 break;
667 case WSAETIMEDOUT:
668 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::ConnectionTimeOutErrorString);
669 d->socketState = QAbstractSocket::UnconnectedState;
670 break;
671 case WSAEACCES:
672 d->setError(QAbstractSocket::SocketAccessError, QNativeSocketEnginePrivate::AccessErrorString);
673 d->socketState = QAbstractSocket::UnconnectedState;
674 break;
675 case WSAENETUNREACH:
676 d->setError(QAbstractSocket::NetworkError, QNativeSocketEnginePrivate::NetworkUnreachableErrorString);
677 d->socketState = QAbstractSocket::UnconnectedState;
678 break;
679 case WSAEINVAL:
680 case WSAEALREADY:
681 d->setError(QAbstractSocket::UnfinishedSocketOperationError, QNativeSocketEnginePrivate::InvalidSocketErrorString);
682 break;
683 default:
684 break;
685 }
686}
687
688bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quint16 port)
689{
690
691#if defined (QNATIVESOCKETENGINE_DEBUG)
692 qDebug("QNativeSocketEnginePrivate::nativeConnect() to %s :: %i", address.toString().toLatin1().constData(), port);
693#endif
694
695 qt_sockaddr aa;
696 QT_SOCKLEN_T sockAddrSize = 0;
697
698 setPortAndAddress(port, address, &aa, &sockAddrSize);
699
700 if ((socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) && address.toIPv4Address()) {
701 //IPV6_V6ONLY option must be cleared to connect to a V4 mapped address
702 DWORD ipv6only = 0;
703 ipv6only = ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
704 }
705
706 forever {
707 int connectResult = ::WSAConnect(socketDescriptor, &aa.a, sockAddrSize, 0,0,0,0);
708 if (connectResult == SOCKET_ERROR) {
709 int err = WSAGetLastError();
710 WS_ERROR_DEBUG(err);
711
712 switch (err) {
713 case WSANOTINITIALISED:
714 //###
715 break;
716 case WSAEWOULDBLOCK: {
717 // If WSAConnect returns WSAEWOULDBLOCK on the second
718 // connection attempt, we have to check SO_ERROR's
719 // value to detect ECONNREFUSED. If we don't get
720 // ECONNREFUSED, we'll have to treat it as an
721 // unfinished operation.
722 int value = 0;
723 QT_SOCKLEN_T valueSize = sizeof(value);
724 bool tryAgain = false;
725 bool errorDetected = false;
726 int tries = 0;
727 do {
728 if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) {
729 if (value != NOERROR) {
730 WS_ERROR_DEBUG(value);
731 errorDetected = true;
732 // MSDN says getsockopt with SO_ERROR clears the error, but it's not actually cleared
733 // and this can affect all subsequent WSAConnect attempts, so clear it now.
734 const int val = NO_ERROR;
735 ::setsockopt(socketDescriptor, SOL_SOCKET, SO_ERROR, reinterpret_cast<const char*>(&val), sizeof val);
736 } else {
737 // When we get WSAEWOULDBLOCK the outcome was not known, so a
738 // NOERROR might indicate that the result of the operation
739 // is still unknown. We try again to increase the chance that we did
740 // get the correct result.
741 tryAgain = !tryAgain;
742 }
743 setErrorFromWSAError(value, this);
744 }
745 tries++;
746 } while (tryAgain && (tries < 2));
747
748 if (errorDetected)
749 break;
750 // fall through to unfinished operation error handling
751 err = WSAEINPROGRESS;
752 Q_FALLTHROUGH();
753 }
754
755 default:
756 setErrorFromWSAError(err, this);
757 break;
758 }
759 if (socketState != QAbstractSocket::ConnectedState) {
760#if defined (QNATIVESOCKETENGINE_DEBUG)
761 qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
762 address.toString().toLatin1().constData(), port,
763 socketState == QAbstractSocket::ConnectingState
764 ? "Connection in progress" : socketErrorString.toLatin1().constData());
765#endif
766 return false;
767 }
768 }
769 break;
770 }
771
772#if defined (QNATIVESOCKETENGINE_DEBUG)
773 qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true",
774 address.toString().toLatin1().constData(), port);
775#endif
776
777 socketState = QAbstractSocket::ConnectedState;
778 return true;
779}
780
781
782bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &a, quint16 port)
783{
784 QHostAddress address = a;
785 if (address.protocol() == QAbstractSocket::IPv4Protocol) {
786 if ((address.toIPv4Address() & 0xffff0000) == 0xefff0000) {
787 // binding to a multicast address
788 address = QHostAddress(QHostAddress::AnyIPv4);
789 }
790 }
791
792 qt_sockaddr aa;
793 QT_SOCKLEN_T sockAddrSize = 0;
794 setPortAndAddress(port, address, &aa, &sockAddrSize);
795
796 if (aa.a.sa_family == AF_INET6) {
797 // The default may change in future, so set it explicitly
798 int ipv6only = 0;
799 if (address.protocol() == QAbstractSocket::IPv6Protocol)
800 ipv6only = 1;
801 ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only) );
802 }
803
804
805 int bindResult = ::bind(socketDescriptor, &aa.a, sockAddrSize);
806 if (bindResult == SOCKET_ERROR && WSAGetLastError() == WSAEAFNOSUPPORT
807 && address.protocol() == QAbstractSocket::AnyIPProtocol) {
808 // retry with v4
809 aa.a4.sin_family = AF_INET;
810 aa.a4.sin_port = htons(port);
811 aa.a4.sin_addr.s_addr = htonl(address.toIPv4Address());
812 sockAddrSize = sizeof(aa.a4);
813 bindResult = ::bind(socketDescriptor, &aa.a, sockAddrSize);
814 }
815 if (bindResult == SOCKET_ERROR) {
816 int err = WSAGetLastError();
817 WS_ERROR_DEBUG(err);
818 switch (err) {
819 case WSANOTINITIALISED:
820 //###
821 break;
822 case WSAEADDRINUSE:
823 case WSAEINVAL:
824 setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
825 break;
826 case WSAEACCES:
827 setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString);
828 break;
829 case WSAEADDRNOTAVAIL:
830 setError(QAbstractSocket::SocketAddressNotAvailableError, AddressNotAvailableErrorString);
831 break;
832 default:
833 break;
834 }
835
836#if defined (QNATIVESOCKETENGINE_DEBUG)
837 qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
838 address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData());
839#endif
840
841 return false;
842 }
843
844#if defined (QNATIVESOCKETENGINE_DEBUG)
845 qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == true",
846 address.toString().toLatin1().constData(), port);
847#endif
848 socketState = QAbstractSocket::BoundState;
849 return true;
850}
851
852
854{
855 if (::listen(socketDescriptor, backlog) == SOCKET_ERROR) {
856 int err = WSAGetLastError();
857 WS_ERROR_DEBUG(err);
858 switch (err) {
859 case WSANOTINITIALISED:
860 //###
861 break;
862 case WSAEADDRINUSE:
863 setError(QAbstractSocket::AddressInUseError,
864 PortInuseErrorString);
865 break;
866 default:
867 break;
868 }
869
870#if defined (QNATIVESOCKETENGINE_DEBUG)
871 qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == false (%s)",
872 backlog, socketErrorString.toLatin1().constData());
873#endif
874 return false;
875 }
876
877#if defined (QNATIVESOCKETENGINE_DEBUG)
878 qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == true", backlog);
879#endif
880
881 socketState = QAbstractSocket::ListeningState;
882 return true;
883}
884
886{
887 SOCKET acceptedDescriptor = WSAAccept(socketDescriptor, 0,0,0,0);
888 if (acceptedDescriptor == INVALID_SOCKET) {
889 int err = WSAGetLastError();
890 switch (err) {
891 case WSAEACCES:
892 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
893 break;
894 case WSAECONNREFUSED:
895 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
896 break;
897 case WSAECONNRESET:
898 setError(QAbstractSocket::NetworkError, RemoteHostClosedErrorString);
899 break;
900 case WSAENETDOWN:
901 setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString);
902 break;
903 case WSAENOTSOCK:
904 setError(QAbstractSocket::SocketResourceError, NotSocketErrorString);
905 break;
906 case WSAEINVAL:
907 case WSAEOPNOTSUPP:
908 setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
909 break;
910 case WSAEFAULT:
911 case WSAEMFILE:
912 case WSAENOBUFS:
913 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
914 break;
915 case WSAEWOULDBLOCK:
916 setError(QAbstractSocket::TemporaryError, TemporaryErrorString);
917 break;
918 default:
919 setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString);
920 break;
921 }
922 } else if (acceptedDescriptor != INVALID_SOCKET && QAbstractEventDispatcher::instance()) {
923 // Because of WSAAsyncSelect() WSAAccept returns a non blocking socket
924 // with the same attributes as the listening socket including the current
925 // WSAAsyncSelect(). To be able to change the socket to blocking mode the
926 // WSAAsyncSelect() call must be canceled.
927 QSocketNotifier n(acceptedDescriptor, QSocketNotifier::Read);
928 n.setEnabled(true);
929 n.setEnabled(false);
930 }
931#if defined (QNATIVESOCKETENGINE_DEBUG)
932 qDebug("QNativeSocketEnginePrivate::nativeAccept() == %lld", qint64(acceptedDescriptor));
933#endif
934 return qintptr(acceptedDescriptor);
935}
936
938 int how6,
939 int how4,
940 const QHostAddress &groupAddress,
941 const QNetworkInterface &iface)
942{
943 int level = 0;
944 int sockOpt = 0;
945 char *sockArg;
946 int sockArgSize;
947
948 struct ip_mreq mreq4;
949 struct ipv6_mreq mreq6;
950
951 if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) {
952 level = IPPROTO_IPV6;
953 sockOpt = how6;
954 sockArg = reinterpret_cast<char *>(&mreq6);
955 sockArgSize = sizeof(mreq6);
956 memset(&mreq6, 0, sizeof(mreq6));
957 Q_IPV6ADDR ip6 = groupAddress.toIPv6Address();
958 memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6));
959 mreq6.ipv6mr_interface = iface.index();
960 } else if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
961 level = IPPROTO_IP;
962 sockOpt = how4;
963 sockArg = reinterpret_cast<char *>(&mreq4);
964 sockArgSize = sizeof(mreq4);
965 memset(&mreq4, 0, sizeof(mreq4));
966 mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address());
967
968 if (iface.isValid()) {
969 const QList<QNetworkAddressEntry> addressEntries = iface.addressEntries();
970 bool found = false;
971 for (const QNetworkAddressEntry &entry : addressEntries) {
972 const QHostAddress ip = entry.ip();
973 if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
974 mreq4.imr_interface.s_addr = htonl(ip.toIPv4Address());
975 found = true;
976 break;
977 }
978 }
979 if (!found) {
980 d->setError(QAbstractSocket::NetworkError,
982 return false;
983 }
984 } else {
985 mreq4.imr_interface.s_addr = INADDR_ANY;
986 }
987 } else {
988 // unreachable
989 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
991 return false;
992 }
993
994 int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize);
995 if (res == -1) {
996 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
998 return false;
999 }
1000 return true;
1001}
1002
1003bool QNativeSocketEnginePrivate::nativeJoinMulticastGroup(const QHostAddress &groupAddress,
1004 const QNetworkInterface &iface)
1005{
1006 return multicastMembershipHelper(this,
1007 IPV6_JOIN_GROUP,
1008 IP_ADD_MEMBERSHIP,
1009 groupAddress,
1010 iface);
1011}
1012
1013bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &groupAddress,
1014 const QNetworkInterface &iface)
1015{
1016 return multicastMembershipHelper(this,
1017 IPV6_LEAVE_GROUP,
1018 IP_DROP_MEMBERSHIP,
1019 groupAddress,
1020 iface);
1021}
1022
1024{
1025 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
1026 uint v;
1027 QT_SOCKOPTLEN_T sizeofv = sizeof(v);
1028 if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &v, &sizeofv) == -1)
1029 return QNetworkInterface();
1030 return QNetworkInterface::interfaceFromIndex(v);
1031 }
1032
1033 struct in_addr v;
1034 v.s_addr = 0;
1035 QT_SOCKOPTLEN_T sizeofv = sizeof(v);
1036 if (::getsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, &sizeofv) == -1)
1037 return QNetworkInterface();
1038 if (v.s_addr != 0 && sizeofv >= QT_SOCKOPTLEN_T(sizeof(v))) {
1039 QHostAddress ipv4(ntohl(v.s_addr));
1040 QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
1041 for (int i = 0; i < ifaces.count(); ++i) {
1042 const QNetworkInterface &iface = ifaces.at(i);
1043 if (!(iface.flags() & QNetworkInterface::CanMulticast))
1044 continue;
1045 QList<QNetworkAddressEntry> entries = iface.addressEntries();
1046 for (int j = 0; j < entries.count(); ++j) {
1047 const QNetworkAddressEntry &entry = entries.at(j);
1048 if (entry.ip() == ipv4)
1049 return iface;
1050 }
1051 }
1052 }
1053 return QNetworkInterface();
1054}
1055
1056bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInterface &iface)
1057{
1058
1059 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
1060 uint v = iface.isValid() ? iface.index() : 0;
1061 return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *) &v, sizeof(v)) != -1);
1062 }
1063
1064 struct in_addr v;
1065 if (iface.isValid()) {
1066 QList<QNetworkAddressEntry> entries = iface.addressEntries();
1067 for (int i = 0; i < entries.count(); ++i) {
1068 const QNetworkAddressEntry &entry = entries.at(i);
1069 const QHostAddress &ip = entry.ip();
1070 if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
1071 v.s_addr = htonl(ip.toIPv4Address());
1072 int r = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, sizeof(v));
1073 if (r != -1)
1074 return true;
1075 }
1076 }
1077 return false;
1078 }
1079
1080 v.s_addr = INADDR_ANY;
1081 return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, (char *) &v, sizeof(v)) != -1);
1082}
1083
1085{
1086 unsigned long nbytes = 0;
1087 unsigned long dummy = 0;
1088 DWORD sizeWritten = 0;
1089 if (::WSAIoctl(socketDescriptor, FIONREAD, &dummy, sizeof(dummy), &nbytes, sizeof(nbytes), &sizeWritten, 0,0) == SOCKET_ERROR) {
1090 WS_ERROR_DEBUG(WSAGetLastError());
1091 return -1;
1092 }
1093
1094 // ioctlsocket sometimes reports 1 byte available for datagrams
1095 // while the following recvfrom returns -1 and claims connection
1096 // was reset (udp is connectionless). so we peek one byte to
1097 // catch this case and return 0 bytes available if recvfrom
1098 // fails.
1099 if (nbytes == 1 && socketType == QAbstractSocket::UdpSocket) {
1100 char c;
1101 WSABUF buf;
1102 buf.buf = &c;
1103 buf.len = sizeof(c);
1104 DWORD bytesReceived;
1105 DWORD flags = MSG_PEEK;
1106 if (::WSARecvFrom(socketDescriptor, &buf, 1, &bytesReceived, &flags, 0,0,0,0) == SOCKET_ERROR) {
1107 int err = WSAGetLastError();
1108 if (err != WSAECONNRESET && err != WSAENETRESET)
1109 return 0;
1110 } else {
1111 return bytesReceived;
1112 }
1113 }
1114 return nbytes;
1115}
1116
1117
1119{
1120 // Create a sockaddr struct and reset its port number.
1121 qt_sockaddr storage;
1122 QT_SOCKLEN_T storageSize = sizeof(storage);
1123 memset(&storage, 0, storageSize);
1124
1125 bool result = false;
1126
1127 // Peek 0 bytes into the next message. The size of the message may
1128 // well be 0, so we check if there was a sender.
1129 char c;
1130 WSABUF buf;
1131 buf.buf = &c;
1132 buf.len = sizeof(c);
1133 DWORD available = 0;
1134 DWORD flags = MSG_PEEK;
1135 int ret = ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags, &storage.a, &storageSize,0,0);
1136 int err = WSAGetLastError();
1137 if (ret == SOCKET_ERROR && err != WSAEMSGSIZE) {
1138 WS_ERROR_DEBUG(err);
1139 result = (err == WSAECONNRESET || err == WSAENETRESET);
1140 } else {
1141 // If there's no error, or if our buffer was too small, there must be
1142 // a pending datagram.
1143 result = true;
1144 }
1145
1146#if defined (QNATIVESOCKETENGINE_DEBUG)
1147 qDebug("QNativeSocketEnginePrivate::nativeHasPendingDatagrams() == %s",
1148 result ? "true" : "false");
1149#endif
1150 return result;
1151}
1152
1153
1155{
1156 qint64 ret = -1;
1157 int recvResult = 0;
1158 DWORD flags;
1159 // We increase the amount we peek by 2048 * 5 on each iteration
1160 // Grabs most cases fast and early.
1161 char udpMessagePeekBuffer[2048];
1162 const int increments = 5;
1163 QVarLengthArray<WSABUF, 10> buf;
1164 for (;;) {
1165 buf.reserve(buf.size() + increments);
1166 std::fill_n(std::back_inserter(buf), increments, WSABUF{sizeof(udpMessagePeekBuffer), udpMessagePeekBuffer});
1167
1168 flags = MSG_PEEK;
1169 DWORD bytesRead = 0;
1170 recvResult = ::WSARecv(socketDescriptor, buf.data(), DWORD(buf.size()), &bytesRead, &flags, nullptr, nullptr);
1171 int err = WSAGetLastError();
1172 if (recvResult != SOCKET_ERROR) {
1173 ret = qint64(bytesRead);
1174 break;
1175 } else {
1176 switch (err) {
1177 case WSAEMSGSIZE:
1178 continue;
1179 case WSAECONNRESET:
1180 case WSAENETRESET:
1181 ret = 0;
1182 break;
1183 default:
1184 WS_ERROR_DEBUG(err);
1185 ret = -1;
1186 break;
1187 }
1188 break;
1189 }
1190 }
1191
1192#if defined (QNATIVESOCKETENGINE_DEBUG)
1193 qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %lli", ret);
1194#endif
1195
1196 return ret;
1197}
1198
1199qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength, QIpPacketHeader *header,
1200 QAbstractSocketEngine::PacketHeaderOptions options)
1201{
1202 union {
1203 char cbuf[WSA_CMSG_SPACE(sizeof(struct in6_pktinfo)) + WSA_CMSG_SPACE(sizeof(int))];
1204 WSACMSGHDR align; // only to ensure alignment
1205 };
1206 WSAMSG msg;
1207 WSABUF buf;
1208 qt_sockaddr aa;
1209 char c;
1210 memset(&msg, 0, sizeof(msg));
1211 memset(&aa, 0, sizeof(aa));
1212
1213 // we need to receive at least one byte, even if our user isn't interested in it
1214 buf.buf = maxLength ? data : &c;
1215 buf.len = maxLength ? maxLength : 1;
1216 msg.lpBuffers = &buf;
1217 msg.dwBufferCount = 1;
1218 msg.name = reinterpret_cast<LPSOCKADDR>(&aa);
1219 msg.namelen = sizeof(aa);
1220 msg.Control.buf = cbuf;
1221 msg.Control.len = sizeof(cbuf);
1222
1223 DWORD flags = 0;
1224 DWORD bytesRead = 0;
1225 qint64 ret;
1226
1227 if (recvmsg)
1228 ret = recvmsg(socketDescriptor, &msg, &bytesRead, 0,0);
1229 else
1230 ret = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, msg.name, &msg.namelen,0,0);
1231 if (ret == SOCKET_ERROR) {
1232 int err = WSAGetLastError();
1233 if (err == WSAEMSGSIZE) {
1234 // it is ok the buffer was to small if bytesRead is larger than
1235 // maxLength then assume bytes read is really maxLenth
1236 ret = qint64(bytesRead) > maxLength ? maxLength : qint64(bytesRead);
1237 if (options & QNativeSocketEngine::WantDatagramSender)
1238 qt_socket_getPortAndAddress(socketDescriptor, &aa, &header->senderPort, &header->senderAddress);
1239 } else {
1240 WS_ERROR_DEBUG(err);
1241 switch (err) {
1242 case WSAENETRESET:
1243 setError(QAbstractSocket::NetworkError, NetworkDroppedConnectionErrorString);
1244 break;
1245 case WSAECONNRESET:
1246 setError(QAbstractSocket::ConnectionRefusedError, ConnectionResetErrorString);
1247 break;
1248 default:
1249 setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
1250 break;
1251 }
1252 ret = -1;
1253 if (header)
1254 header->clear();
1255 }
1256 } else {
1257 ret = qint64(bytesRead);
1258 if (options & QNativeSocketEngine::WantDatagramSender)
1259 qt_socket_getPortAndAddress(socketDescriptor, &aa, &header->senderPort, &header->senderAddress);
1260 }
1261
1262 if (ret != -1 && recvmsg && options != QAbstractSocketEngine::WantNone) {
1263 // get the ancillary data
1264 header->destinationPort = localPort;
1265 WSACMSGHDR *cmsgptr;
1266 for (cmsgptr = WSA_CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
1267 cmsgptr = WSA_CMSG_NXTHDR(&msg, cmsgptr)) {
1268 if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO
1269 && cmsgptr->cmsg_len >= WSA_CMSG_LEN(sizeof(in6_pktinfo))) {
1270 in6_pktinfo *info = reinterpret_cast<in6_pktinfo *>(WSA_CMSG_DATA(cmsgptr));
1271
1272 header->destinationAddress.setAddress(reinterpret_cast<quint8 *>(&info->ipi6_addr));
1273 header->ifindex = info->ipi6_ifindex;
1274 if (header->ifindex)
1275 header->destinationAddress.setScopeId(QString::number(info->ipi6_ifindex));
1276 }
1277 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO
1278 && cmsgptr->cmsg_len >= WSA_CMSG_LEN(sizeof(in_pktinfo))) {
1279 in_pktinfo *info = reinterpret_cast<in_pktinfo *>(WSA_CMSG_DATA(cmsgptr));
1280 u_long addr;
1281 WSANtohl(socketDescriptor, info->ipi_addr.s_addr, &addr);
1282 header->destinationAddress.setAddress(addr);
1283 header->ifindex = info->ipi_ifindex;
1284 }
1285
1286 if (cmsgptr->cmsg_len == WSA_CMSG_LEN(sizeof(int))
1287 && ((cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT)
1288 || (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TTL))) {
1289 header->hopLimit = *reinterpret_cast<int *>(WSA_CMSG_DATA(cmsgptr));
1290 }
1291 }
1292 }
1293
1294#if defined (QNATIVESOCKETENGINE_DEBUG)
1295 bool printSender = (ret != -1 && (options & QNativeSocketEngine::WantDatagramSender) != 0);
1296 qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli",
1297 data, QtDebugUtils::toPrintable(data, ret, 16).constData(), maxLength,
1298 printSender ? header->senderAddress.toString().toLatin1().constData() : "(unknown)",
1299 printSender ? header->senderPort : 0, ret);
1300#endif
1301
1302 return ret;
1303}
1304
1305
1306qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len,
1307 const QIpPacketHeader &header)
1308{
1309 union {
1310 char cbuf[WSA_CMSG_SPACE(sizeof(struct in6_pktinfo)) + WSA_CMSG_SPACE(sizeof(int))];
1311 WSACMSGHDR align; // ensures alignment
1312 };
1313 WSACMSGHDR *cmsgptr = &align;
1314 WSAMSG msg;
1315 WSABUF buf;
1316 qt_sockaddr aa;
1317
1318 memset(&msg, 0, sizeof(msg));
1319 memset(&aa, 0, sizeof(aa));
1320 buf.buf = len ? (char*)data : 0;
1321 msg.lpBuffers = &buf;
1322 msg.dwBufferCount = 1;
1323 msg.name = &aa.a;
1324 buf.len = len;
1325
1326 setPortAndAddress(header.destinationPort, header.destinationAddress, &aa, &msg.namelen);
1327
1328 uint oldIfIndex = 0;
1329 bool mustSetIpv6MulticastIf = false;
1330
1331 if (msg.namelen == sizeof(aa.a6)) {
1332 // sending IPv6
1333 if (header.hopLimit != -1) {
1334 msg.Control.len += WSA_CMSG_SPACE(sizeof(int));
1335 cmsgptr->cmsg_len = WSA_CMSG_LEN(sizeof(int));
1336 cmsgptr->cmsg_level = IPPROTO_IPV6;
1337 cmsgptr->cmsg_type = IPV6_HOPLIMIT;
1338 memcpy(WSA_CMSG_DATA(cmsgptr), &header.hopLimit, sizeof(int));
1339 cmsgptr = reinterpret_cast<WSACMSGHDR *>(reinterpret_cast<char *>(cmsgptr)
1340 + WSA_CMSG_SPACE(sizeof(int)));
1341 }
1342 if (!header.senderAddress.isNull()) {
1343 struct in6_pktinfo *data = reinterpret_cast<in6_pktinfo *>(WSA_CMSG_DATA(cmsgptr));
1344 memset(data, 0, sizeof(*data));
1345 msg.Control.len += WSA_CMSG_SPACE(sizeof(*data));
1346 cmsgptr->cmsg_len = WSA_CMSG_LEN(sizeof(*data));
1347 cmsgptr->cmsg_level = IPPROTO_IPV6;
1348 cmsgptr->cmsg_type = IPV6_PKTINFO;
1349 data->ipi6_ifindex = header.ifindex;
1350
1351 Q_IPV6ADDR tmp = header.senderAddress.toIPv6Address();
1352 memcpy(&data->ipi6_addr, &tmp, sizeof(tmp));
1353 cmsgptr = reinterpret_cast<WSACMSGHDR *>(reinterpret_cast<char *>(cmsgptr)
1354 + WSA_CMSG_SPACE(sizeof(*data)));
1355 } else if (header.ifindex != 0) {
1356 // Unlike other operating systems, setting the interface index in the in6_pktinfo
1357 // structure above and leaving the ipi6_addr set to :: will cause the packets to be
1358 // sent with source address ::. So we have to use IPV6_MULTICAST_IF, which MSDN is
1359 // quite clear that "This option does not change the default interface for receiving
1360 // IPv6 multicast traffic."
1361 QT_SOCKOPTLEN_T len = sizeof(oldIfIndex);
1362 if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1363 reinterpret_cast<char *>(&oldIfIndex), &len) == -1
1364 || ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1365 reinterpret_cast<const char *>(&header.ifindex), sizeof(header.ifindex)) == -1) {
1366 setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
1367 return -1;
1368 }
1369 mustSetIpv6MulticastIf = true;
1370 }
1371 } else {
1372 // sending IPv4
1373 if (header.hopLimit != -1) {
1374 msg.Control.len += WSA_CMSG_SPACE(sizeof(int));
1375 cmsgptr->cmsg_len = WSA_CMSG_LEN(sizeof(int));
1376 cmsgptr->cmsg_level = IPPROTO_IP;
1377 cmsgptr->cmsg_type = IP_TTL;
1378 memcpy(WSA_CMSG_DATA(cmsgptr), &header.hopLimit, sizeof(int));
1379 cmsgptr = reinterpret_cast<WSACMSGHDR *>(reinterpret_cast<char *>(cmsgptr)
1380 + WSA_CMSG_SPACE(sizeof(int)));
1381 }
1382 if (header.ifindex != 0 || !header.senderAddress.isNull()) {
1383 struct in_pktinfo *data = reinterpret_cast<in_pktinfo *>(WSA_CMSG_DATA(cmsgptr));
1384 memset(data, 0, sizeof(*data));
1385 msg.Control.len += WSA_CMSG_SPACE(sizeof(*data));
1386 cmsgptr->cmsg_len = WSA_CMSG_LEN(sizeof(*data));
1387 cmsgptr->cmsg_level = IPPROTO_IP;
1388 cmsgptr->cmsg_type = IP_PKTINFO;
1389 data->ipi_ifindex = header.ifindex;
1390 WSAHtonl(socketDescriptor, header.senderAddress.toIPv4Address(), &data->ipi_addr.s_addr);
1391 cmsgptr = reinterpret_cast<WSACMSGHDR *>(reinterpret_cast<char *>(cmsgptr)
1392 + WSA_CMSG_SPACE(sizeof(*data)));
1393 }
1394 }
1395
1396 if (msg.Control.len != 0)
1397 msg.Control.buf = cbuf;
1398
1399 DWORD flags = 0;
1400 DWORD bytesSent = 0;
1401 qint64 ret = -1;
1402 if (sendmsg) {
1403 ret = sendmsg(socketDescriptor, &msg, flags, &bytesSent, 0,0);
1404 } else {
1405 ret = ::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, msg.name, msg.namelen, 0,0);
1406 }
1407 if (ret == SOCKET_ERROR) {
1408 int err = WSAGetLastError();
1409 WS_ERROR_DEBUG(err);
1410 switch (err) {
1411 case WSAEMSGSIZE:
1412 setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
1413 break;
1414 default:
1415 setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
1416 break;
1417 }
1418 ret = -1;
1419 } else {
1420 ret = qint64(bytesSent);
1421 }
1422
1423 if (mustSetIpv6MulticastIf) {
1424 // undo what we did above
1425 ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF,
1426 reinterpret_cast<char *>(&oldIfIndex), sizeof(oldIfIndex));
1427 }
1428
1429#if defined (QNATIVESOCKETENGINE_DEBUG)
1430 qDebug("QNativeSocketEnginePrivate::nativeSendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli",
1431 data, QtDebugUtils::toPrintable(data, len, 16).constData(), len,
1432 header.destinationAddress.toString().toLatin1().constData(),
1433 header.destinationPort, ret);
1434#endif
1435
1436 return ret;
1437}
1438
1439
1440qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
1441{
1442 Q_Q(QNativeSocketEngine);
1443 qint64 ret = 0;
1444 qint64 bytesToSend = len;
1445
1446 for (;;) {
1447 WSABUF buf;
1448 buf.buf = const_cast<char*>(data) + ret;
1449 buf.len = bytesToSend;
1450 DWORD flags = 0;
1451 DWORD bytesWritten = 0;
1452
1453 int socketRet = ::WSASend(socketDescriptor, &buf, 1, &bytesWritten, flags, 0,0);
1454
1455 ret += qint64(bytesWritten);
1456
1457 int err;
1458 if (socketRet != SOCKET_ERROR) {
1459 if (ret == len || bytesToSend != qint64(bytesWritten))
1460 break;
1461 } else if ((err = WSAGetLastError()) == WSAEWOULDBLOCK) {
1462 break;
1463 } else if (err == WSAENOBUFS) {
1464 // this function used to not send more than 49152 per call to WSASendTo
1465 // to avoid getting a WSAENOBUFS. However this is a performance regression
1466 // and we think it only appears with old windows versions. We now handle the
1467 // WSAENOBUFS and hope it never appears anyway.
1468 // just go on, the next loop run we will try a smaller number
1469 } else {
1470 WS_ERROR_DEBUG(err);
1471 switch (err) {
1472 case WSAECONNRESET:
1473 case WSAECONNABORTED:
1474 ret = -1;
1475 setError(QAbstractSocket::NetworkError, WriteErrorString);
1476 q->close();
1477 break;
1478 default:
1479 break;
1480 }
1481 break;
1482 }
1483
1484 // for next send:
1485 bytesToSend = qMin<qint64>(49152, len - ret);
1486 }
1487
1488#if defined (QNATIVESOCKETENGINE_DEBUG)
1489 qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %lli) == %lli",
1490 data, QtDebugUtils::toPrintable(data, ret, 16).constData(), len, ret);
1491#endif
1492
1493 return ret;
1494}
1495
1496qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxLength)
1497{
1498 qint64 ret = -1;
1499 WSABUF buf;
1500 buf.buf = data;
1501 buf.len = maxLength;
1502 DWORD flags = 0;
1503 DWORD bytesRead = 0;
1504 if (::WSARecv(socketDescriptor, &buf, 1, &bytesRead, &flags, 0,0) == SOCKET_ERROR) {
1505 int err = WSAGetLastError();
1506 WS_ERROR_DEBUG(err);
1507 switch (err) {
1508 case WSAEWOULDBLOCK:
1509 ret = -2;
1510 break;
1511 case WSAEBADF:
1512 case WSAEINVAL:
1513 //error string is now set in read(), not here in nativeRead()
1514 break;
1515 case WSAECONNRESET:
1516 case WSAECONNABORTED:
1517 // for tcp sockets this will be handled in QNativeSocketEngine::read
1518 ret = 0;
1519 break;
1520 default:
1521 break;
1522 }
1523 } else {
1524 if (WSAGetLastError() == WSAEWOULDBLOCK)
1525 ret = -2;
1526 else
1527 ret = qint64(bytesRead);
1528 }
1529
1530#if defined (QNATIVESOCKETENGINE_DEBUG)
1531 if (ret != -2) {
1532 qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %lli) == %lli", data,
1533 QtDebugUtils::toPrintable(data, bytesRead, 16).constData(), maxLength, ret);
1534 } else {
1535 qDebug("QNativeSocketEnginePrivate::nativeRead(%p, %lli) == -2 (WOULD BLOCK)",
1536 data, maxLength);
1537 }
1538#endif
1539
1540 return ret;
1541}
1542
1543inline timeval durationToTimeval(std::chrono::nanoseconds dur) noexcept
1544{
1545 using namespace std::chrono;
1546 const auto secs = duration_cast<seconds>(dur);
1547 const auto frac = duration_cast<microseconds>(dur - secs);
1548 struct timeval tval;
1549 tval.tv_sec = secs.count();
1550 tval.tv_usec = frac.count();
1551 return tval;
1552}
1553
1554int QNativeSocketEnginePrivate::nativeSelect(QDeadlineTimer deadline, bool selectForRead) const
1555{
1556 bool readEnabled = selectForRead && readNotifier && readNotifier->isEnabled();
1557 if (readEnabled)
1558 readNotifier->setEnabled(false);
1559
1560 fd_set fds;
1561
1562 int ret = 0;
1563
1564 memset(&fds, 0, sizeof(fd_set));
1565 fds.fd_count = 1;
1566 fds.fd_array[0] = (SOCKET)socketDescriptor;
1567
1568 struct timeval tv = durationToTimeval(deadline.remainingTimeAsDuration());
1569
1570 if (selectForRead) {
1571 ret = select(0, &fds, 0, 0, &tv);
1572 } else {
1573 // select for write
1574
1575 // Windows needs this to report errors when connecting a socket ...
1576 fd_set fdexception;
1577 FD_ZERO(&fdexception);
1578 FD_SET((SOCKET)socketDescriptor, &fdexception);
1579
1580 ret = select(0, 0, &fds, &fdexception, &tv);
1581
1582 // ... but if it is actually set, pretend it did not happen
1583 if (ret > 0 && FD_ISSET((SOCKET)socketDescriptor, &fdexception))
1584 ret--;
1585 }
1586
1587 if (readEnabled)
1588 readNotifier->setEnabled(true);
1589
1590 return ret;
1591}
1592
1593int QNativeSocketEnginePrivate::nativeSelect(QDeadlineTimer deadline,
1594 bool checkRead, bool checkWrite,
1595 bool *selectForRead, bool *selectForWrite) const
1596{
1597 bool readEnabled = checkRead && readNotifier && readNotifier->isEnabled();
1598 if (readEnabled)
1599 readNotifier->setEnabled(false);
1600
1601 fd_set fdread;
1602 fd_set fdwrite;
1603 fd_set fdexception;
1604
1605 int ret = 0;
1606
1607 memset(&fdread, 0, sizeof(fd_set));
1608 if (checkRead) {
1609 fdread.fd_count = 1;
1610 fdread.fd_array[0] = (SOCKET)socketDescriptor;
1611 }
1612 memset(&fdwrite, 0, sizeof(fd_set));
1613 FD_ZERO(&fdexception);
1614 if (checkWrite) {
1615 fdwrite.fd_count = 1;
1616 fdwrite.fd_array[0] = (SOCKET)socketDescriptor;
1617
1618 // Windows needs this to report errors when connecting a socket
1619 FD_SET((SOCKET)socketDescriptor, &fdexception);
1620 }
1621
1622 struct timeval tv = durationToTimeval(deadline.remainingTimeAsDuration());
1623
1624 ret = select(socketDescriptor + 1, &fdread, &fdwrite, &fdexception, &tv);
1625
1626 //... but if it is actually set, pretend it did not happen
1627 if (ret > 0 && FD_ISSET((SOCKET)socketDescriptor, &fdexception))
1628 ret--;
1629
1630 if (readEnabled)
1631 readNotifier->setEnabled(true);
1632
1633 if (ret <= 0)
1634 return ret;
1635
1636 *selectForRead = FD_ISSET((SOCKET)socketDescriptor, &fdread);
1637 *selectForWrite = FD_ISSET((SOCKET)socketDescriptor, &fdwrite);
1638
1639 return ret;
1640}
1641
1643{
1644#if defined (QTCPSOCKETENGINE_DEBUG)
1645 qDebug("QNativeSocketEnginePrivate::nativeClose()");
1646#endif
1647 // We were doing a setsockopt here before with SO_DONTLINGER. (However with kind of wrong
1648 // usage of parameters, it wants a BOOL but we used a struct and pretended it to be bool).
1649 // We don't think setting this option should be done here, if a user wants it she/he can
1650 // do it manually with socketDescriptor()/setSocketDescriptor();
1651 ::closesocket(socketDescriptor);
1652}
1653
1654QT_END_NAMESPACE
bool createNewSocket(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol &protocol)
QNetworkInterface nativeMulticastInterface() const
qint64 nativeWrite(const char *data, qint64 length)
int option(QNativeSocketEngine::SocketOption option) const
bool nativeJoinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface)
bool setOption(QNativeSocketEngine::SocketOption option, int value)
bool nativeSetMulticastInterface(const QNetworkInterface &iface)
bool fetchConnectionParameters()
Fetches information about both ends of the connection: whatever is available.
bool nativeBind(const QHostAddress &address, quint16 port)
qint64 nativeSendDatagram(const char *data, qint64 length, const QIpPacketHeader &header)
bool nativeConnect(const QHostAddress &address, quint16 port)
bool nativeLeaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface)
qint64 nativeRead(char *data, qint64 maxLength)
qint64 nativeReceiveDatagram(char *data, qint64 maxLength, QIpPacketHeader *header, QAbstractSocketEngine::PacketHeaderOptions options)
Combined button and popup list for selecting options.
#define SO_EXCLUSIVEADDRUSE
static void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt_sockaddr *sa, quint16 *port, QHostAddress *address)
#define TCP_KEEPCNT
static void convertToLevelAndOption(QNativeSocketEngine::SocketOption opt, QAbstractSocket::NetworkLayerProtocol socketProtocol, int &level, int &n)
#define _WSAIOW(x, y)
static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d, int how6, int how4, const QHostAddress &groupAddress, const QNetworkInterface &iface)
#define SIO_UDP_CONNRESET
#define IPV6_V6ONLY
static void setErrorFromWSAError(int error, QNativeSocketEnginePrivate *d)
#define WSA_FLAG_NO_HANDLE_INHERIT
timeval durationToTimeval(std::chrono::nanoseconds dur) noexcept
#define WS_ERROR_DEBUG(x)
static QAbstractSocket::SocketType qt_socket_getType(qintptr socketDescriptor)
#define TCP_KEEPINTVL
#define IP_HOPLIMIT
#define AF_INET6
#define TCP_KEEPIDLE
#define IOC_VENDOR