source: trunk/src/network/socket/qnativesocketengine_win.cpp@ 846

Last change on this file since 846 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 39.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtNetwork module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include <winsock2.h>
43
44#include "qnativesocketengine_p.h"
45
46#include <qabstracteventdispatcher.h>
47#include <qsocketnotifier.h>
48#include <qdebug.h>
49#include <qdatetime.h>
50
51//#define QNATIVESOCKETENGINE_DEBUG
52#if defined(QNATIVESOCKETENGINE_DEBUG)
53# include <qstring.h>
54# include <qbytearray.h>
55#endif
56
57QT_BEGIN_NAMESPACE
58
59#if defined(QNATIVESOCKETENGINE_DEBUG)
60
61void verboseWSErrorDebug(int r)
62{
63 switch (r) {
64 case WSANOTINITIALISED : qDebug("WSA error : WSANOTINITIALISED"); break;
65 case WSAEINTR: qDebug("WSA error : WSAEINTR"); break;
66 case WSAEBADF: qDebug("WSA error : WSAEBADF"); break;
67 case WSAEACCES: qDebug("WSA error : WSAEACCES"); break;
68 case WSAEFAULT: qDebug("WSA error : WSAEFAULT"); break;
69 case WSAEINVAL: qDebug("WSA error : WSAEINVAL"); break;
70 case WSAEMFILE: qDebug("WSA error : WSAEMFILE"); break;
71 case WSAEWOULDBLOCK: qDebug("WSA error : WSAEWOULDBLOCK"); break;
72 case WSAEINPROGRESS: qDebug("WSA error : WSAEINPROGRESS"); break;
73 case WSAEALREADY: qDebug("WSA error : WSAEALREADY"); break;
74 case WSAENOTSOCK: qDebug("WSA error : WSAENOTSOCK"); break;
75 case WSAEDESTADDRREQ: qDebug("WSA error : WSAEDESTADDRREQ"); break;
76 case WSAEMSGSIZE: qDebug("WSA error : WSAEMSGSIZE"); break;
77 case WSAEPROTOTYPE: qDebug("WSA error : WSAEPROTOTYPE"); break;
78 case WSAENOPROTOOPT: qDebug("WSA error : WSAENOPROTOOPT"); break;
79 case WSAEPROTONOSUPPORT: qDebug("WSA error : WSAEPROTONOSUPPORT"); break;
80 case WSAESOCKTNOSUPPORT: qDebug("WSA error : WSAESOCKTNOSUPPORT"); break;
81 case WSAEOPNOTSUPP: qDebug("WSA error : WSAEOPNOTSUPP"); break;
82 case WSAEPFNOSUPPORT: qDebug("WSA error : WSAEPFNOSUPPORT"); break;
83 case WSAEAFNOSUPPORT: qDebug("WSA error : WSAEAFNOSUPPORT"); break;
84 case WSAEADDRINUSE: qDebug("WSA error : WSAEADDRINUSE"); break;
85 case WSAEADDRNOTAVAIL: qDebug("WSA error : WSAEADDRNOTAVAIL"); break;
86 case WSAENETDOWN: qDebug("WSA error : WSAENETDOWN"); break;
87 case WSAENETUNREACH: qDebug("WSA error : WSAENETUNREACH"); break;
88 case WSAENETRESET: qDebug("WSA error : WSAENETRESET"); break;
89 case WSAECONNABORTED: qDebug("WSA error : WSAECONNABORTED"); break;
90 case WSAECONNRESET: qDebug("WSA error : WSAECONNRESET"); break;
91 case WSAENOBUFS: qDebug("WSA error : WSAENOBUFS"); break;
92 case WSAEISCONN: qDebug("WSA error : WSAEISCONN"); break;
93 case WSAENOTCONN: qDebug("WSA error : WSAENOTCONN"); break;
94 case WSAESHUTDOWN: qDebug("WSA error : WSAESHUTDOWN"); break;
95 case WSAETOOMANYREFS: qDebug("WSA error : WSAETOOMANYREFS"); break;
96 case WSAETIMEDOUT: qDebug("WSA error : WSAETIMEDOUT"); break;
97 case WSAECONNREFUSED: qDebug("WSA error : WSAECONNREFUSED"); break;
98 case WSAELOOP: qDebug("WSA error : WSAELOOP"); break;
99 case WSAENAMETOOLONG: qDebug("WSA error : WSAENAMETOOLONG"); break;
100 case WSAEHOSTDOWN: qDebug("WSA error : WSAEHOSTDOWN"); break;
101 case WSAEHOSTUNREACH: qDebug("WSA error : WSAEHOSTUNREACH"); break;
102 case WSAENOTEMPTY: qDebug("WSA error : WSAENOTEMPTY"); break;
103 case WSAEPROCLIM: qDebug("WSA error : WSAEPROCLIM"); break;
104 case WSAEUSERS: qDebug("WSA error : WSAEUSERS"); break;
105 case WSAEDQUOT: qDebug("WSA error : WSAEDQUOT"); break;
106 case WSAESTALE: qDebug("WSA error : WSAESTALE"); break;
107 case WSAEREMOTE: qDebug("WSA error : WSAEREMOTE"); break;
108 case WSAEDISCON: qDebug("WSA error : WSAEDISCON"); break;
109 default: qDebug("WSA error : Unknown"); break;
110 }
111 qErrnoWarning(r, "more details");
112}
113
114/*
115 Returns a human readable representation of the first \a len
116 characters in \a data.
117*/
118static QByteArray qt_prettyDebug(const char *data, int len, int maxLength)
119{
120 if (!data) return "(null)";
121 QByteArray out;
122 for (int i = 0; i < len; ++i) {
123 char c = data[i];
124 if (isprint(int(uchar(c)))) {
125 out += c;
126 } else switch (c) {
127 case '\n': out += "\\n"; break;
128 case '\r': out += "\\r"; break;
129 case '\t': out += "\\t"; break;
130 default:
131 QString tmp;
132 tmp.sprintf("\\%o", c);
133 out += tmp.toLatin1().constData();
134 }
135 }
136
137 if (len < maxLength)
138 out += "...";
139
140 return out;
141}
142
143
144#define WS_ERROR_DEBUG(x) verboseWSErrorDebug(x);
145
146#else
147
148#define WS_ERROR_DEBUG(x) Q_UNUSED(x)
149
150#endif
151
152#ifndef AF_INET6
153#define AF_INET6 23 /* Internetwork Version 6 */
154#endif
155
156#ifndef SO_EXCLUSIVEADDRUSE
157#define SO_EXCLUSIVEADDRUSE ((int)(~SO_REUSEADDR)) /* disallow local address reuse */
158#endif
159
160//###
161#define QT_SOCKLEN_T int
162#define QT_SOCKOPTLEN_T int
163
164
165/*
166 Extracts the port and address from a sockaddr, and stores them in
167 \a port and \a addr if they are non-null.
168*/
169static inline void qt_socket_getPortAndAddress(SOCKET socketDescriptor, const qt_sockaddr *sa, quint16 *port, QHostAddress *address)
170{
171#if !defined (QT_NO_IPV6)
172 if (sa->a.sa_family == AF_INET6) {
173 const qt_sockaddr_in6 *sa6 = &sa->a6;
174 Q_IPV6ADDR tmp;
175 for (int i = 0; i < 16; ++i)
176 tmp.c[i] = sa6->sin6_addr.qt_s6_addr[i];
177 QHostAddress a;
178 a.setAddress(tmp);
179 if (address)
180 *address = a;
181 if (port)
182 WSANtohs(socketDescriptor, sa6->sin6_port, port);
183 } else
184#endif
185 if (sa->a.sa_family == AF_INET) {
186 const sockaddr_in *sa4 = &sa->a4;
187 unsigned long addr;
188 WSANtohl(socketDescriptor, sa4->sin_addr.s_addr, &addr);
189 QHostAddress a;
190 a.setAddress(addr);
191 if (address)
192 *address = a;
193 if (port)
194 WSANtohs(socketDescriptor, sa4->sin_port, port);
195 }
196}
197
198
199/*! \internal
200
201 Sets the port and address to a sockaddr. Requires that sa point to the IPv6 struct if the address is IPv6.
202*/
203static inline void qt_socket_setPortAndAddress(SOCKET socketDescriptor, sockaddr_in * sockAddrIPv4, qt_sockaddr_in6 * sockAddrIPv6,
204 quint16 port, const QHostAddress & address, sockaddr ** sockAddrPtr, QT_SOCKLEN_T *sockAddrSize)
205{
206#if !defined(QT_NO_IPV6)
207 if (address.protocol() == QAbstractSocket::IPv6Protocol) {
208 memset(sockAddrIPv6, 0, sizeof(qt_sockaddr_in6));
209 sockAddrIPv6->sin6_family = AF_INET6;
210 sockAddrIPv6->sin6_scope_id = address.scopeId().toInt();
211 WSAHtons(socketDescriptor, port, &(sockAddrIPv6->sin6_port));
212 Q_IPV6ADDR tmp = address.toIPv6Address();
213 memcpy(&(sockAddrIPv6->sin6_addr.qt_s6_addr), &tmp, sizeof(tmp));
214 *sockAddrSize = sizeof(qt_sockaddr_in6);
215 *sockAddrPtr = (struct sockaddr *) sockAddrIPv6;
216 } else
217#endif
218 if (address.protocol() == QAbstractSocket::IPv4Protocol
219 || address.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol) {
220 memset(sockAddrIPv4, 0, sizeof(sockaddr_in));
221 sockAddrIPv4->sin_family = AF_INET;
222 WSAHtons(socketDescriptor, port, &(sockAddrIPv4->sin_port));
223 WSAHtonl(socketDescriptor, address.toIPv4Address(), &(sockAddrIPv4->sin_addr.s_addr));
224 *sockAddrSize = sizeof(sockaddr_in);
225 *sockAddrPtr = (struct sockaddr *) sockAddrIPv4;
226 } else {
227 // unreachable
228 }
229}
230
231/*! \internal
232
233*/
234static inline QAbstractSocket::SocketType qt_socket_getType(int socketDescriptor)
235{
236 int value = 0;
237 QT_SOCKLEN_T valueSize = sizeof(value);
238 if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, (char *) &value, &valueSize) != 0) {
239 WS_ERROR_DEBUG(WSAGetLastError());
240 } else {
241 if (value == SOCK_STREAM)
242 return QAbstractSocket::TcpSocket;
243 else if (value == SOCK_DGRAM)
244 return QAbstractSocket::UdpSocket;
245 }
246 return QAbstractSocket::UnknownSocketType;
247}
248
249/*! \internal
250
251*/
252static inline int qt_socket_getMaxMsgSize(int socketDescriptor)
253{
254 int value = 0;
255 QT_SOCKLEN_T valueSize = sizeof(value);
256 if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *) &value, &valueSize) != 0) {
257 WS_ERROR_DEBUG(WSAGetLastError());
258 }
259 return value;
260}
261
262QWindowsSockInit::QWindowsSockInit()
263: version(0)
264{
265 //### should we try for 2.2 on all platforms ??
266 WSAData wsadata;
267
268 // IPv6 requires Winsock v2.0 or better.
269 if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) {
270 qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed.");
271 } else {
272 version = 0x20;
273 }
274}
275
276QWindowsSockInit::~QWindowsSockInit()
277{
278 WSACleanup();
279}
280
281// MS Transport Provider IOCTL to control
282// reporting PORT_UNREACHABLE messages
283// on UDP sockets via recv/WSARecv/etc.
284// Path TRUE in input buffer to enable (default if supported),
285// FALSE to disable.
286#ifndef SIO_UDP_CONNRESET
287# ifndef IOC_VENDOR
288# define IOC_VENDOR 0x18000000
289# endif
290# ifndef _WSAIOW
291# define _WSAIOW(x,y) (IOC_IN|(x)|(y))
292# endif
293# define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
294#endif
295
296bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol socketProtocol)
297{
298
299 //### no ip6 support on winsocket 1.1 but we will try not to use this !!!!!!!!!!!!1
300 /*
301 if (winsockVersion < 0x20 && socketProtocol == QAbstractSocket::IPv6Protocol) {
302 //### no ip6 support
303 return -1;
304 }
305 */
306
307 int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol) ? AF_INET6 : AF_INET;
308 int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
309 // MSDN KB179942 states that on winnt 4 WSA_FLAG_OVERLAPPED is needed if socket is to be non blocking
310 // and recomends alwasy doing it for cross windows version comapablity.
311 SOCKET socket = ::WSASocket(protocol, type, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
312
313 if (socket == INVALID_SOCKET) {
314 int err = WSAGetLastError();
315 WS_ERROR_DEBUG(err);
316 switch (err) {
317 case WSANOTINITIALISED:
318 //###
319 break;
320 case WSAEAFNOSUPPORT:
321 case WSAESOCKTNOSUPPORT:
322 case WSAEPROTOTYPE:
323 case WSAEINVAL:
324 setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
325 break;
326 case WSAEMFILE:
327 case WSAENOBUFS:
328 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
329 break;
330 default:
331 break;
332 }
333
334 return false;
335 }
336
337#if !defined(Q_OS_WINCE)
338 // enable new behavior using
339 // SIO_UDP_CONNRESET
340 DWORD dwBytesReturned = 0;
341 int bNewBehavior = 1;
342 if (::WSAIoctl(socket, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior),
343 NULL, 0, &dwBytesReturned, NULL, NULL) == SOCKET_ERROR) {
344 // not to worry isBogusUdpReadNotification() should handle this otherwise
345 int err = WSAGetLastError();
346 WS_ERROR_DEBUG(err);
347 }
348#endif
349
350 socketDescriptor = socket;
351 return true;
352
353}
354
355/*! \internal
356
357 Returns the value of the socket option \a opt.
358*/
359int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) const
360{
361 Q_Q(const QNativeSocketEngine);
362 if (!q->isValid())
363 return -1;
364
365 int n = -1;
366 int level = SOL_SOCKET; // default
367
368 switch (opt) {
369 case QNativeSocketEngine::ReceiveBufferSocketOption:
370 n = SO_RCVBUF;
371 break;
372 case QNativeSocketEngine::SendBufferSocketOption:
373 n = SO_SNDBUF;
374 break;
375 case QNativeSocketEngine::BroadcastSocketOption:
376 n = SO_BROADCAST;
377 break;
378 case QNativeSocketEngine::NonBlockingSocketOption: {
379 unsigned long buf = 0;
380 if (WSAIoctl(socketDescriptor, FIONBIO, 0,0, &buf, sizeof(buf), 0,0,0) == 0)
381 return buf;
382 else
383 return -1;
384 break;
385 }
386 case QNativeSocketEngine::AddressReusable:
387 n = SO_REUSEADDR;
388 break;
389 case QNativeSocketEngine::BindExclusively:
390 n = SO_EXCLUSIVEADDRUSE;
391 break;
392 case QNativeSocketEngine::ReceiveOutOfBandData:
393 n = SO_OOBINLINE;
394 break;
395 case QNativeSocketEngine::LowDelayOption:
396 level = IPPROTO_TCP;
397 n = TCP_NODELAY;
398 break;
399 case QNativeSocketEngine::KeepAliveOption:
400 n = SO_KEEPALIVE;
401 break;
402 }
403
404 int v = -1;
405 QT_SOCKOPTLEN_T len = sizeof(v);
406 if (getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1)
407 return v;
408 return -1;
409}
410
411
412/*! \internal
413 Sets the socket option \a opt to \a v.
414*/
415bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt, int v)
416{
417 Q_Q(const QNativeSocketEngine);
418 if (!q->isValid())
419 return false;
420
421 int n = 0;
422 int level = SOL_SOCKET; // default
423
424 switch (opt) {
425 case QNativeSocketEngine::ReceiveBufferSocketOption:
426 n = SO_RCVBUF;
427 break;
428 case QNativeSocketEngine::SendBufferSocketOption:
429 n = SO_SNDBUF;
430 break;
431 case QNativeSocketEngine::BroadcastSocketOption:
432 n = SO_BROADCAST;
433 break;
434 case QNativeSocketEngine::NonBlockingSocketOption:
435 {
436 unsigned long buf = v;
437 unsigned long outBuf;
438 DWORD sizeWritten = 0;
439 if (::WSAIoctl(socketDescriptor, FIONBIO, &buf, sizeof(unsigned long), &outBuf, sizeof(unsigned long), &sizeWritten, 0,0) == SOCKET_ERROR) {
440 WS_ERROR_DEBUG(WSAGetLastError());
441 return false;
442 }
443 return true;
444 break;
445 }
446 case QNativeSocketEngine::AddressReusable:
447 n = SO_REUSEADDR;
448 break;
449 case QNativeSocketEngine::BindExclusively:
450 n = SO_EXCLUSIVEADDRUSE;
451 break;
452 case QNativeSocketEngine::ReceiveOutOfBandData:
453 n = SO_OOBINLINE;
454 break;
455 case QNativeSocketEngine::LowDelayOption:
456 level = IPPROTO_TCP;
457 n = TCP_NODELAY;
458 break;
459 case QNativeSocketEngine::KeepAliveOption:
460 n = SO_KEEPALIVE;
461 break;
462 }
463
464 if (::setsockopt(socketDescriptor, level, n, (char*)&v, sizeof(v)) != 0) {
465 WS_ERROR_DEBUG(WSAGetLastError());
466 return false;
467 }
468 return true;
469}
470
471/*!
472 Fetches information about both ends of the connection: whatever is
473 available.
474*/
475bool QNativeSocketEnginePrivate::fetchConnectionParameters()
476{
477 localPort = 0;
478 localAddress.clear();
479 peerPort = 0;
480 peerAddress.clear();
481
482 if (socketDescriptor == -1)
483 return false;
484
485 qt_sockaddr sa;
486 QT_SOCKLEN_T sockAddrSize = sizeof(sa);
487
488 // Determine local address
489 memset(&sa, 0, sizeof(sa));
490 if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
491 qt_socket_getPortAndAddress(socketDescriptor, &sa, &localPort, &localAddress);
492 // Determine protocol family
493 switch (sa.a.sa_family) {
494 case AF_INET:
495 socketProtocol = QAbstractSocket::IPv4Protocol;
496 break;
497#if !defined (QT_NO_IPV6)
498 case AF_INET6:
499 socketProtocol = QAbstractSocket::IPv6Protocol;
500 break;
501#endif
502 default:
503 socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
504 break;
505 }
506 } else {
507 int err = WSAGetLastError();
508 WS_ERROR_DEBUG(err);
509 if (err == WSAENOTSOCK) {
510 setError(QAbstractSocket::UnsupportedSocketOperationError,
511 InvalidSocketErrorString);
512 return false;
513 }
514 }
515
516 memset(&sa, 0, sizeof(sa));
517 if (::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
518 qt_socket_getPortAndAddress(socketDescriptor, &sa, &peerPort, &peerAddress);
519 } else {
520 WS_ERROR_DEBUG(WSAGetLastError());
521 }
522
523 socketType = qt_socket_getType(socketDescriptor);
524
525#if defined (QNATIVESOCKETENGINE_DEBUG)
526 QString socketProtocolStr = "UnknownProtocol";
527 if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = "IPv4Protocol";
528 else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = "IPv6Protocol";
529
530 QString socketTypeStr = "UnknownSocketType";
531 if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = "TcpSocket";
532 else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = "UdpSocket";
533
534 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());
535#endif
536
537 return true;
538}
539
540
541bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &address, quint16 port)
542{
543
544#if defined (QNATIVESOCKETENGINE_DEBUG)
545 qDebug("QNativeSocketEnginePrivate::nativeConnect() to %s :: %i", address.toString().toLatin1().constData(), port);
546#endif
547
548 struct sockaddr_in sockAddrIPv4;
549 qt_sockaddr_in6 sockAddrIPv6;
550 struct sockaddr *sockAddrPtr = 0;
551 QT_SOCKLEN_T sockAddrSize = 0;
552
553 qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
554
555 forever {
556 int connectResult = ::WSAConnect(socketDescriptor, sockAddrPtr, sockAddrSize, 0,0,0,0);
557 if (connectResult == SOCKET_ERROR) {
558 int err = WSAGetLastError();
559 WS_ERROR_DEBUG(err);
560
561 switch (err) {
562 case WSANOTINITIALISED:
563 //###
564 break;
565 case WSAEISCONN:
566 socketState = QAbstractSocket::ConnectedState;
567 break;
568 case WSAEWOULDBLOCK: {
569 // If WSAConnect returns WSAEWOULDBLOCK on the second
570 // connection attempt, we have to check SO_ERROR's
571 // value to detect ECONNREFUSED. If we don't get
572 // ECONNREFUSED, we'll have to treat it as an
573 // unfinished operation.
574 int value = 0;
575 QT_SOCKLEN_T valueSize = sizeof(value);
576 if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_ERROR, (char *) &value, &valueSize) == 0) {
577 if (value == WSAECONNREFUSED) {
578 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
579 socketState = QAbstractSocket::UnconnectedState;
580 break;
581 }
582 if (value == WSAETIMEDOUT) {
583 setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
584 socketState = QAbstractSocket::UnconnectedState;
585 break;
586 }
587 if (value == WSAEHOSTUNREACH) {
588 setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
589 socketState = QAbstractSocket::UnconnectedState;
590 break;
591 }
592 }
593 // fall through
594 }
595 case WSAEINPROGRESS:
596 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
597 socketState = QAbstractSocket::ConnectingState;
598 break;
599 case WSAEADDRINUSE:
600 setError(QAbstractSocket::NetworkError, AddressInuseErrorString);
601 break;
602 case WSAECONNREFUSED:
603 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
604 socketState = QAbstractSocket::UnconnectedState;
605 break;
606 case WSAETIMEDOUT:
607 setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
608 break;
609 case WSAEACCES:
610 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
611 socketState = QAbstractSocket::UnconnectedState;
612 break;
613 case WSAEHOSTUNREACH:
614 setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
615 socketState = QAbstractSocket::UnconnectedState;
616 break;
617 case WSAENETUNREACH:
618 setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString);
619 socketState = QAbstractSocket::UnconnectedState;
620 break;
621 case WSAEINVAL:
622 case WSAEALREADY:
623 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
624 break;
625 default:
626 break;
627 }
628 if (socketState != QAbstractSocket::ConnectedState) {
629#if defined (QNATIVESOCKETENGINE_DEBUG)
630 qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
631 address.toString().toLatin1().constData(), port,
632 socketState == QAbstractSocket::ConnectingState
633 ? "Connection in progress" : socketErrorString.toLatin1().constData());
634#endif
635 return false;
636 }
637 }
638 break;
639 }
640
641#if defined (QNATIVESOCKETENGINE_DEBUG)
642 qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true",
643 address.toString().toLatin1().constData(), port);
644#endif
645
646 socketState = QAbstractSocket::ConnectedState;
647 return true;
648}
649
650
651bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port)
652{
653 struct sockaddr_in sockAddrIPv4;
654 qt_sockaddr_in6 sockAddrIPv6;
655 struct sockaddr *sockAddrPtr = 0;
656 QT_SOCKLEN_T sockAddrSize = 0;
657
658 qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
659
660
661 int bindResult = ::bind(socketDescriptor, sockAddrPtr, sockAddrSize);
662 if (bindResult == SOCKET_ERROR) {
663 int err = WSAGetLastError();
664 WS_ERROR_DEBUG(err);
665 switch (err) {
666 case WSANOTINITIALISED:
667 //###
668 break;
669 case WSAEADDRINUSE:
670 case WSAEINVAL:
671 setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
672 break;
673 case WSAEACCES:
674 setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString);
675 break;
676 case WSAEADDRNOTAVAIL:
677 setError(QAbstractSocket::SocketAddressNotAvailableError, AddressNotAvailableErrorString);
678 break;
679 default:
680 break;
681 }
682
683#if defined (QNATIVESOCKETENGINE_DEBUG)
684 qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
685 address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData());
686#endif
687
688 return false;
689 }
690
691#if defined (QNATIVESOCKETENGINE_DEBUG)
692 qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == true",
693 address.toString().toLatin1().constData(), port);
694#endif
695 socketState = QAbstractSocket::BoundState;
696 return true;
697}
698
699
700bool QNativeSocketEnginePrivate::nativeListen(int backlog)
701{
702 if (::listen(socketDescriptor, backlog) == SOCKET_ERROR) {
703 int err = WSAGetLastError();
704 WS_ERROR_DEBUG(err);
705 switch (err) {
706 case WSANOTINITIALISED:
707 //###
708 break;
709 case WSAEADDRINUSE:
710 setError(QAbstractSocket::AddressInUseError,
711 PortInuseErrorString);
712 break;
713 default:
714 break;
715 }
716
717#if defined (QNATIVESOCKETENGINE_DEBUG)
718 qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == false (%s)",
719 backlog, socketErrorString.toLatin1().constData());
720#endif
721 return false;
722 }
723
724#if defined (QNATIVESOCKETENGINE_DEBUG)
725 qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == true", backlog);
726#endif
727
728 socketState = QAbstractSocket::ListeningState;
729 return true;
730}
731
732int QNativeSocketEnginePrivate::nativeAccept()
733{
734 int acceptedDescriptor = WSAAccept(socketDescriptor, 0,0,0,0);
735 if (acceptedDescriptor != -1 && QAbstractEventDispatcher::instance()) {
736 // Because of WSAAsyncSelect() WSAAccept returns a non blocking socket
737 // with the same attributes as the listening socket including the current
738 // WSAAsyncSelect(). To be able to change the socket to blocking mode the
739 // WSAAsyncSelect() call must be cancled.
740 QSocketNotifier n(acceptedDescriptor, QSocketNotifier::Read);
741 n.setEnabled(true);
742 n.setEnabled(false);
743 }
744#if defined (QNATIVESOCKETENGINE_DEBUG)
745 qDebug("QNativeSocketEnginePrivate::nativeAccept() == %i", acceptedDescriptor);
746#endif
747 return acceptedDescriptor;
748}
749
750
751qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
752{
753 unsigned long nbytes = 0;
754 unsigned long dummy = 0;
755 DWORD sizeWritten = 0;
756 if (::WSAIoctl(socketDescriptor, FIONREAD, &dummy, sizeof(dummy), &nbytes, sizeof(nbytes), &sizeWritten, 0,0) == SOCKET_ERROR) {
757 WS_ERROR_DEBUG(WSAGetLastError());
758 return -1;
759 }
760
761 // ioctlsocket sometimes reports 1 byte available for datagrams
762 // while the following recvfrom returns -1 and claims connection
763 // was reset (udp is connectionless). so we peek one byte to
764 // catch this case and return 0 bytes available if recvfrom
765 // fails.
766 if (nbytes == 1 && socketType == QAbstractSocket::UdpSocket) {
767 char c;
768 WSABUF buf;
769 buf.buf = &c;
770 buf.len = sizeof(c);
771 DWORD flags = MSG_PEEK;
772 if (::WSARecvFrom(socketDescriptor, &buf, 1, 0, &flags, 0,0,0,0) == SOCKET_ERROR)
773 return 0;
774 }
775 return nbytes;
776}
777
778
779bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
780{
781#if !defined(Q_OS_WINCE)
782 // Create a sockaddr struct and reset its port number.
783 qt_sockaddr storage;
784 QT_SOCKLEN_T storageSize = sizeof(storage);
785 memset(&storage, 0, storageSize);
786
787 bool result = false;
788
789 // Peek 0 bytes into the next message. The size of the message may
790 // well be 0, so we check if there was a sender.
791 char c;
792 WSABUF buf;
793 buf.buf = &c;
794 buf.len = sizeof(c);
795 DWORD available = 0;
796 DWORD flags = MSG_PEEK;
797 int ret = ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags, &storage.a, &storageSize,0,0);
798 int err = WSAGetLastError();
799 if (ret == SOCKET_ERROR && err != WSAEMSGSIZE) {
800 WS_ERROR_DEBUG(err);
801 if (err == WSAECONNRESET) {
802 // Discard error message to prevent QAbstractSocket from
803 // getting this message repeatedly after reenabling the
804 // notifiers.
805 flags = 0;
806 ::WSARecvFrom(socketDescriptor, &buf, 1, &available, &flags,
807 &storage.a, &storageSize, 0, 0);
808 }
809 } else {
810 // If there's no error, or if our buffer was too small, there must be
811 // a pending datagram.
812 result = true;
813 }
814
815#else // Q_OS_WINCE
816 bool result = false;
817 fd_set readS;
818 FD_ZERO(&readS);
819 FD_SET(socketDescriptor, &readS);
820 timeval timeout;
821 timeout.tv_sec = 0;
822 timeout.tv_usec = 5000;
823 int available = ::select(1, &readS, 0, 0, &timeout);
824 result = available > 0 ? true : false;
825#endif
826
827#if defined (QNATIVESOCKETENGINE_DEBUG)
828 qDebug("QNativeSocketEnginePrivate::nativeHasPendingDatagrams() == %s",
829 result ? "true" : "false");
830#endif
831 return result;
832}
833
834
835qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
836{
837 qint64 ret = -1;
838#if !defined(Q_OS_WINCE)
839 int recvResult = 0;
840 DWORD flags;
841 DWORD bufferCount = 5;
842 WSABUF * buf = 0;
843 for (;;) {
844 // the data written to udpMessagePeekBuffer is discarded, so
845 // this function is still reentrant although it might not look
846 // so.
847 static char udpMessagePeekBuffer[8192];
848
849 buf = new WSABUF[bufferCount];
850 for (DWORD i=0; i<bufferCount; i++) {
851 buf[i].buf = udpMessagePeekBuffer;
852 buf[i].len = sizeof(udpMessagePeekBuffer);
853 }
854 flags = MSG_PEEK;
855 DWORD bytesRead = 0;
856 recvResult = ::WSARecv(socketDescriptor, buf, bufferCount, &bytesRead, &flags, 0,0);
857 int err = WSAGetLastError();
858 if (recvResult != SOCKET_ERROR) {
859 ret = qint64(bytesRead);
860 break;
861 } else if (recvResult == SOCKET_ERROR && err == WSAEMSGSIZE) {
862 bufferCount += 5;
863 delete[] buf;
864 } else if (recvResult == SOCKET_ERROR) {
865 WS_ERROR_DEBUG(err);
866 ret = -1;
867 break;
868 }
869 }
870
871 if (buf)
872 delete[] buf;
873
874#else // Q_OS_WINCE
875 DWORD size = -1;
876 DWORD bytesReturned;
877 int ioResult = WSAIoctl(socketDescriptor, FIONREAD, 0,0, &size, sizeof(size), &bytesReturned, 0, 0);
878 if (ioResult == SOCKET_ERROR) {
879 int err = WSAGetLastError();
880 WS_ERROR_DEBUG(err);
881 } else {
882 ret = qint64(size);
883 }
884#endif
885
886#if defined (QNATIVESOCKETENGINE_DEBUG)
887 qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %li", ret);
888#endif
889
890 return ret;
891}
892
893
894qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength,
895 QHostAddress *address, quint16 *port)
896{
897 qint64 ret = 0;
898
899 qt_sockaddr aa;
900 memset(&aa, 0, sizeof(aa));
901 QT_SOCKLEN_T sz;
902 sz = sizeof(aa);
903
904 WSABUF buf;
905 buf.buf = data;
906 buf.len = maxLength;
907#if !defined(Q_OS_WINCE)
908 buf.buf = data;
909 buf.len = maxLength;
910#else
911 char tmpChar;
912 buf.buf = data ? data : &tmpChar;
913 buf.len = maxLength;
914#endif
915
916 DWORD flags = 0;
917 DWORD bytesRead = 0;
918 int wsaRet = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, &aa.a, &sz,0,0);
919 if (wsaRet == SOCKET_ERROR) {
920 int err = WSAGetLastError();
921 if (err == WSAEMSGSIZE) {
922 // it is ok the buffer was to small if bytesRead is larger than
923 // maxLength then assume bytes read is really maxLenth
924 ret = qint64(bytesRead) > maxLength ? maxLength : qint64(bytesRead);
925 } else {
926 WS_ERROR_DEBUG(err);
927 setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
928 ret = -1;
929 }
930 } else {
931 ret = qint64(bytesRead);
932 }
933
934 qt_socket_getPortAndAddress(socketDescriptor, &aa, port, address);
935
936#if defined (QNATIVESOCKETENGINE_DEBUG)
937 qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %li, %s, %i) == %li",
938 data, qt_prettyDebug(data, qMin<qint64>(ret, 16), ret).data(), maxLength,
939 address ? address->toString().toLatin1().constData() : "(nil)",
940 port ? *port : 0, ret);
941#endif
942
943 return ret;
944}
945
946
947qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len,
948 const QHostAddress &address, quint16 port)
949{
950 qint64 ret = -1;
951 struct sockaddr_in sockAddrIPv4;
952 qt_sockaddr_in6 sockAddrIPv6;
953 struct sockaddr *sockAddrPtr = 0;
954 QT_SOCKLEN_T sockAddrSize = 0;
955
956 qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize);
957
958 WSABUF buf;
959#if !defined(Q_OS_WINCE)
960 buf.buf = len ? (char*)data : 0;
961#else
962 char tmp;
963 buf.buf = len ? (char*)data : &tmp;
964#endif
965 buf.len = len;
966 DWORD flags = 0;
967 DWORD bytesSent = 0;
968 if (::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, sockAddrPtr, sockAddrSize, 0,0) == SOCKET_ERROR) {
969 int err = WSAGetLastError();
970 WS_ERROR_DEBUG(err);
971 switch (err) {
972 case WSAEMSGSIZE:
973 setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
974 break;
975 default:
976 setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
977 break;
978 }
979 ret = -1;
980 } else {
981 ret = qint64(bytesSent);
982 }
983
984#if defined (QNATIVESOCKETENGINE_DEBUG)
985 qDebug("QNativeSocketEnginePrivate::nativeSendDatagram(%p \"%s\", %li, \"%s\", %i) == %li", data,
986 qt_prettyDebug(data, qMin<qint64>(len, 16), len).data(), 0, address.toString().toLatin1().constData(),
987 port, ret);
988#endif
989
990 return ret;
991}
992
993
994qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
995{
996 Q_Q(QNativeSocketEngine);
997 qint64 ret = 0;
998 qint64 bytesToSend = len;
999
1000 for (;;) {
1001 WSABUF buf;
1002 buf.buf = (char*)data + ret;
1003 buf.len = bytesToSend;
1004 DWORD flags = 0;
1005 DWORD bytesWritten = 0;
1006
1007 int socketRet = ::WSASend(socketDescriptor, &buf, 1, &bytesWritten, flags, 0,0);
1008
1009 ret += qint64(bytesWritten);
1010
1011 int err;
1012 if (socketRet != SOCKET_ERROR) {
1013 if (ret == len)
1014 break;
1015 else
1016 continue;
1017 } else if ((err = WSAGetLastError()) == WSAEWOULDBLOCK) {
1018 break;
1019 } else if (err == WSAENOBUFS) {
1020 // this function used to not send more than 49152 per call to WSASendTo
1021 // to avoid getting a WSAENOBUFS. However this is a performance regression
1022 // and we think it only appears with old windows versions. We now handle the
1023 // WSAENOBUFS and hope it never appears anyway.
1024 // just go on, the next loop run we will try a smaller number
1025 } else {
1026 WS_ERROR_DEBUG(err);
1027 switch (err) {
1028 case WSAECONNRESET:
1029 case WSAECONNABORTED:
1030 ret = -1;
1031 setError(QAbstractSocket::NetworkError, WriteErrorString);
1032 q->close();
1033 break;
1034 default:
1035 break;
1036 }
1037 break;
1038 }
1039
1040 // for next send:
1041 bytesToSend = qMin<qint64>(49152, len - ret);
1042 }
1043
1044#if defined (QNATIVESOCKETENGINE_DEBUG)
1045 qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %li) == %li",
1046 data, qt_prettyDebug(data, qMin((int)ret, 16), (int)ret).data(), (int)len, (int)ret);
1047#endif
1048
1049 return ret;
1050}
1051
1052qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxLength)
1053{
1054 qint64 ret = -1;
1055 WSABUF buf;
1056 buf.buf = data;
1057 buf.len = maxLength;
1058 DWORD flags = 0;
1059 DWORD bytesRead = 0;
1060#if defined(Q_OS_WINCE)
1061 WSASetLastError(0);
1062#endif
1063 if (::WSARecv(socketDescriptor, &buf, 1, &bytesRead, &flags, 0,0) == SOCKET_ERROR) {
1064 int err = WSAGetLastError();
1065 WS_ERROR_DEBUG(err);
1066 switch (err) {
1067 case WSAEWOULDBLOCK:
1068 ret = -2;
1069 break;
1070 case WSAEBADF:
1071 case WSAEINVAL:
1072 //error string is now set in read(), not here in nativeRead()
1073 break;
1074 case WSAECONNRESET:
1075 case WSAECONNABORTED:
1076 // for tcp sockets this will be handled in QNativeSocketEngine::read
1077 ret = 0;
1078 break;
1079 default:
1080 break;
1081 }
1082 } else {
1083 if (WSAGetLastError() == WSAEWOULDBLOCK)
1084 ret = -2;
1085 else
1086 ret = qint64(bytesRead);
1087 }
1088
1089#if defined (QNATIVESOCKETENGINE_DEBUG)
1090 if (ret != -2) {
1091 qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %l) == %li",
1092 data, qt_prettyDebug(data, qMin((int)bytesRead, 16), (int)bytesRead).data(), (int)maxLength, (int)ret);
1093 } else {
1094 qDebug("QNativeSocketEnginePrivate::nativeRead(%p, %l) == -2 (WOULD BLOCK)",
1095 data, int(maxLength));
1096 }
1097#endif
1098
1099 return ret;
1100}
1101
1102int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const
1103{
1104 bool readEnabled = selectForRead && readNotifier && readNotifier->isEnabled();
1105 if (readEnabled)
1106 readNotifier->setEnabled(false);
1107
1108 fd_set fds;
1109
1110 int ret = 0;
1111
1112 memset(&fds, 0, sizeof(fd_set));
1113 fds.fd_count = 1;
1114 fds.fd_array[0] = socketDescriptor;
1115
1116 struct timeval tv;
1117 tv.tv_sec = timeout / 1000;
1118 tv.tv_usec = (timeout % 1000) * 1000;
1119
1120 if (selectForRead) {
1121 ret = select(0, &fds, 0, 0, timeout < 0 ? 0 : &tv);
1122 } else {
1123 // select for write
1124
1125 // Windows needs this to report errors when connecting a socket ...
1126 fd_set fdexception;
1127 FD_ZERO(&fdexception);
1128 FD_SET(socketDescriptor, &fdexception);
1129
1130 ret = select(0, 0, &fds, &fdexception, timeout < 0 ? 0 : &tv);
1131
1132 // ... but if it is actually set, pretend it did not happen
1133 if (ret > 0 && FD_ISSET(socketDescriptor, &fdexception))
1134 ret--;
1135 }
1136
1137 if (readEnabled)
1138 readNotifier->setEnabled(true);
1139
1140 return ret;
1141}
1142
1143int QNativeSocketEnginePrivate::nativeSelect(int timeout,
1144 bool checkRead, bool checkWrite,
1145 bool *selectForRead, bool *selectForWrite) const
1146{
1147 bool readEnabled = checkRead && readNotifier && readNotifier->isEnabled();
1148 if (readEnabled)
1149 readNotifier->setEnabled(false);
1150
1151 fd_set fdread;
1152 fd_set fdwrite;
1153 fd_set fdexception;
1154
1155 int ret = 0;
1156
1157 memset(&fdread, 0, sizeof(fd_set));
1158 if (checkRead) {
1159 fdread.fd_count = 1;
1160 fdread.fd_array[0] = socketDescriptor;
1161 }
1162 memset(&fdwrite, 0, sizeof(fd_set));
1163 FD_ZERO(&fdexception);
1164 if (checkWrite) {
1165 fdwrite.fd_count = 1;
1166 fdwrite.fd_array[0] = socketDescriptor;
1167
1168 // Windows needs this to report errors when connecting a socket
1169 FD_SET(socketDescriptor, &fdexception);
1170 }
1171
1172 struct timeval tv;
1173 tv.tv_sec = timeout / 1000;
1174 tv.tv_usec = (timeout % 1000) * 1000;
1175
1176#if !defined(Q_OS_WINCE)
1177 ret = select(socketDescriptor + 1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv);
1178#else
1179 ret = select(1, &fdread, &fdwrite, &fdexception, timeout < 0 ? 0 : &tv);
1180#endif
1181
1182 //... but if it is actually set, pretend it did not happen
1183 if (ret > 0 && FD_ISSET(socketDescriptor, &fdexception))
1184 ret--;
1185
1186 if (readEnabled)
1187 readNotifier->setEnabled(true);
1188
1189 if (ret <= 0)
1190 return ret;
1191
1192 *selectForRead = FD_ISSET(socketDescriptor, &fdread);
1193 *selectForWrite = FD_ISSET(socketDescriptor, &fdwrite);
1194
1195 return ret;
1196}
1197
1198void QNativeSocketEnginePrivate::nativeClose()
1199{
1200#if defined (QTCPSOCKETENGINE_DEBUG)
1201 qDebug("QNativeSocketEnginePrivate::nativeClose()");
1202#endif
1203 // We were doing a setsockopt here before with SO_DONTLINGER. (However with kind of wrong
1204 // usage of parameters, it wants a BOOL but we used a struct and pretended it to be bool).
1205 // We don't think setting this option should be done here, if a user wants it she/he can
1206 // do it manually with socketDescriptor()/setSocketDescriptor();
1207 ::closesocket(socketDescriptor);
1208}
1209
1210QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.