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