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