1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
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 The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 //#define QNATIVESOCKETENGINE_DEBUG
43 #include "qnativesocketengine_p.h"
44 #include "private/qnet_unix_p.h"
45 #include "qiodevice.h"
46 #include "qhostaddress.h"
47 #include "qelapsedtimer.h"
48 #include "qvarlengtharray.h"
49 #include "qnetworkinterface.h"
50 #include <time.h>
51 #include <errno.h>
52 #include <fcntl.h>
53 #ifndef QT_NO_IPV6IFNAME
54 #include <net/if.h>
55 #endif
56 #ifndef QT_NO_IPV6IFNAME
57 #include <net/if.h>
58 #endif
59 #ifdef QT_LINUXBASE
60 #include <arpa/inet.h>
61 #endif
62
63 #if defined QNATIVESOCKETENGINE_DEBUG
64 #include <qstring.h>
65 #include <ctype.h>
66 #endif
67
68 #include <netinet/tcp.h>
69
70 QT_BEGIN_NAMESPACE
71
72 #if defined QNATIVESOCKETENGINE_DEBUG
73
74 /*
75 Returns a human readable representation of the first \a len
76 characters in \a data.
77 */
qt_prettyDebug(const char * data,int len,int maxSize)78 static QByteArray qt_prettyDebug(const char *data, int len, int maxSize)
79 {
80 if (!data) return "(null)";
81 QByteArray out;
82 for (int i = 0; i < len; ++i) {
83 char c = data[i];
84 if (isprint(c)) {
85 out += c;
86 } else switch (c) {
87 case '\n': out += "\\n"; break;
88 case '\r': out += "\\r"; break;
89 case '\t': out += "\\t"; break;
90 default:
91 QString tmp;
92 tmp.sprintf("\\%o", c);
93 out += tmp.toLatin1();
94 }
95 }
96
97 if (len < maxSize)
98 out += "...";
99
100 return out;
101 }
102 #endif
103
104 /*
105 Extracts the port and address from a sockaddr, and stores them in
106 \a port and \a addr if they are non-null.
107 */
qt_socket_getPortAndAddress(const qt_sockaddr * s,quint16 * port,QHostAddress * addr)108 static inline void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *port, QHostAddress *addr)
109 {
110 #if !defined(QT_NO_IPV6)
111 if (s->a.sa_family == AF_INET6) {
112 Q_IPV6ADDR tmp;
113 memcpy(&tmp, &s->a6.sin6_addr, sizeof(tmp));
114 if (addr) {
115 QHostAddress tmpAddress;
116 tmpAddress.setAddress(tmp);
117 *addr = tmpAddress;
118 #ifndef QT_NO_IPV6IFNAME
119 char scopeid[IFNAMSIZ];
120 if (::if_indextoname(s->a6.sin6_scope_id, scopeid)) {
121 addr->setScopeId(QLatin1String(scopeid));
122 } else
123 #endif
124 addr->setScopeId(QString::number(s->a6.sin6_scope_id));
125 }
126 if (port)
127 *port = ntohs(s->a6.sin6_port);
128 return;
129 }
130 #endif
131 if (port)
132 *port = ntohs(s->a4.sin_port);
133 if (addr) {
134 QHostAddress tmpAddress;
135 tmpAddress.setAddress(ntohl(s->a4.sin_addr.s_addr));
136 *addr = tmpAddress;
137 }
138 }
139
140 /*! \internal
141
142 Creates and returns a new socket descriptor of type \a socketType
143 and \a socketProtocol. Returns -1 on failure.
144 */
createNewSocket(QAbstractSocket::SocketType socketType,QAbstractSocket::NetworkLayerProtocol socketProtocol)145 bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType,
146 QAbstractSocket::NetworkLayerProtocol socketProtocol)
147 {
148 #ifndef QT_NO_IPV6
149 int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol) ? AF_INET6 : AF_INET;
150 #else
151 Q_UNUSED(socketProtocol);
152 int protocol = AF_INET;
153 #endif
154 int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
155
156 int socket = qt_safe_socket(protocol, type, 0);
157
158 if (socket <= 0) {
159 switch (errno) {
160 case EPROTONOSUPPORT:
161 case EAFNOSUPPORT:
162 case EINVAL:
163 setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
164 break;
165 case ENFILE:
166 case EMFILE:
167 case ENOBUFS:
168 case ENOMEM:
169 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
170 break;
171 case EACCES:
172 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
173 break;
174 default:
175 break;
176 }
177
178 return false;
179 }
180
181 socketDescriptor = socket;
182 return true;
183 }
184
185 /*
186 Returns the value of the socket option \a opt.
187 */
option(QNativeSocketEngine::SocketOption opt) const188 int QNativeSocketEnginePrivate::option(QNativeSocketEngine::SocketOption opt) const
189 {
190 Q_Q(const QNativeSocketEngine);
191 if (!q->isValid())
192 return -1;
193
194 int n = -1;
195 int level = SOL_SOCKET; // default
196
197 switch (opt) {
198 case QNativeSocketEngine::ReceiveBufferSocketOption:
199 n = SO_RCVBUF;
200 break;
201 case QNativeSocketEngine::SendBufferSocketOption:
202 n = SO_SNDBUF;
203 break;
204 case QNativeSocketEngine::NonBlockingSocketOption:
205 break;
206 case QNativeSocketEngine::BroadcastSocketOption:
207 break;
208 case QNativeSocketEngine::AddressReusable:
209 n = SO_REUSEADDR;
210 break;
211 case QNativeSocketEngine::BindExclusively:
212 return true;
213 case QNativeSocketEngine::ReceiveOutOfBandData:
214 n = SO_OOBINLINE;
215 break;
216 case QNativeSocketEngine::LowDelayOption:
217 level = IPPROTO_TCP;
218 n = TCP_NODELAY;
219 break;
220 case QNativeSocketEngine::KeepAliveOption:
221 n = SO_KEEPALIVE;
222 break;
223 case QNativeSocketEngine::MulticastTtlOption:
224 #ifndef QT_NO_IPV6
225 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
226 level = IPPROTO_IPV6;
227 n = IPV6_MULTICAST_HOPS;
228 } else
229 #endif
230 {
231 level = IPPROTO_IP;
232 n = IP_MULTICAST_TTL;
233 }
234 break;
235 case QNativeSocketEngine::MulticastLoopbackOption:
236 #ifndef QT_NO_IPV6
237 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
238 level = IPPROTO_IPV6;
239 n = IPV6_MULTICAST_LOOP;
240 } else
241 #endif
242 {
243 level = IPPROTO_IP;
244 n = IP_MULTICAST_LOOP;
245 }
246 break;
247 }
248
249 int v = -1;
250 QT_SOCKOPTLEN_T len = sizeof(v);
251 if (::getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1)
252 return v;
253
254 return -1;
255 }
256
257
258 /*
259 Sets the socket option \a opt to \a v.
260 */
setOption(QNativeSocketEngine::SocketOption opt,int v)261 bool QNativeSocketEnginePrivate::setOption(QNativeSocketEngine::SocketOption opt, int v)
262 {
263 Q_Q(QNativeSocketEngine);
264 if (!q->isValid())
265 return false;
266
267 int n = 0;
268 int level = SOL_SOCKET; // default
269
270 switch (opt) {
271 case QNativeSocketEngine::ReceiveBufferSocketOption:
272 n = SO_RCVBUF;
273 break;
274 case QNativeSocketEngine::SendBufferSocketOption:
275 n = SO_SNDBUF;
276 break;
277 case QNativeSocketEngine::BroadcastSocketOption:
278 n = SO_BROADCAST;
279 break;
280 case QNativeSocketEngine::NonBlockingSocketOption: {
281 // Make the socket nonblocking.
282 #if !defined(Q_OS_VXWORKS)
283 int flags = ::fcntl(socketDescriptor, F_GETFL, 0);
284 if (flags == -1) {
285 #ifdef QNATIVESOCKETENGINE_DEBUG
286 perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_GETFL) failed");
287 #endif
288 return false;
289 }
290 if (::fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) {
291 #ifdef QNATIVESOCKETENGINE_DEBUG
292 perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_SETFL) failed");
293 #endif
294 return false;
295 }
296 #else // Q_OS_VXWORKS
297 int onoff = 1;
298
299 if (qt_safe_ioctl(socketDescriptor, FIONBIO, &onoff) < 0) {
300
301 #ifdef QNATIVESOCKETENGINE_DEBUG
302 perror("QNativeSocketEnginePrivate::setOption(): ioctl(FIONBIO, 1) failed");
303 #endif
304 return false;
305 }
306 #endif // Q_OS_VXWORKS
307 return true;
308 }
309 case QNativeSocketEngine::AddressReusable:
310 #if defined(SO_REUSEPORT)
311 // on OS X, SO_REUSEADDR isn't sufficient to allow multiple binds to the
312 // same port (which is useful for multicast UDP). SO_REUSEPORT is, but
313 // we most definitely do not want to use this for TCP. See QTBUG-6305.
314 if (socketType == QAbstractSocket::UdpSocket)
315 n = SO_REUSEPORT;
316 else
317 n = SO_REUSEADDR;
318 #else
319 n = SO_REUSEADDR;
320 #endif
321 break;
322 case QNativeSocketEngine::BindExclusively:
323 return true;
324 case QNativeSocketEngine::ReceiveOutOfBandData:
325 n = SO_OOBINLINE;
326 break;
327 case QNativeSocketEngine::LowDelayOption:
328 level = IPPROTO_TCP;
329 n = TCP_NODELAY;
330 break;
331 case QNativeSocketEngine::KeepAliveOption:
332 n = SO_KEEPALIVE;
333 break;
334 case QNativeSocketEngine::MulticastTtlOption:
335 #ifndef QT_NO_IPV6
336 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
337 level = IPPROTO_IPV6;
338 n = IPV6_MULTICAST_HOPS;
339 } else
340 #endif
341 {
342 level = IPPROTO_IP;
343 n = IP_MULTICAST_TTL;
344 }
345 break;
346 case QNativeSocketEngine::MulticastLoopbackOption:
347 #ifndef QT_NO_IPV6
348 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
349 level = IPPROTO_IPV6;
350 n = IPV6_MULTICAST_LOOP;
351 } else
352 #endif
353 {
354 level = IPPROTO_IP;
355 n = IP_MULTICAST_LOOP;
356 }
357 break;
358 }
359
360 return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0;
361 }
362
nativeConnect(const QHostAddress & addr,quint16 port)363 bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16 port)
364 {
365 #ifdef QNATIVESOCKETENGINE_DEBUG
366 qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor);
367 #endif
368
369 struct sockaddr_in sockAddrIPv4;
370 struct sockaddr *sockAddrPtr = 0;
371 QT_SOCKLEN_T sockAddrSize = 0;
372
373 #if !defined(QT_NO_IPV6)
374 struct sockaddr_in6 sockAddrIPv6;
375
376 if (addr.protocol() == QAbstractSocket::IPv6Protocol) {
377 memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
378 sockAddrIPv6.sin6_family = AF_INET6;
379 sockAddrIPv6.sin6_port = htons(port);
380
381 QString scopeid = addr.scopeId();
382 bool ok;
383 sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok);
384 #ifndef QT_NO_IPV6IFNAME
385 if (!ok)
386 sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1());
387 #endif
388 Q_IPV6ADDR ip6 = addr.toIPv6Address();
389 memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6));
390
391 sockAddrSize = sizeof(sockAddrIPv6);
392 sockAddrPtr = (struct sockaddr *) &sockAddrIPv6;
393 } else
394 #if 0
395 {}
396 #endif
397 #endif
398 if (addr.protocol() == QAbstractSocket::IPv4Protocol) {
399 memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
400 sockAddrIPv4.sin_family = AF_INET;
401 sockAddrIPv4.sin_port = htons(port);
402 sockAddrIPv4.sin_addr.s_addr = htonl(addr.toIPv4Address());
403
404 sockAddrSize = sizeof(sockAddrIPv4);
405 sockAddrPtr = (struct sockaddr *) &sockAddrIPv4;
406 } else {
407 // unreachable
408 }
409
410 int connectResult = qt_safe_connect(socketDescriptor, sockAddrPtr, sockAddrSize);
411 if (connectResult == -1) {
412 switch (errno) {
413 case EISCONN:
414 socketState = QAbstractSocket::ConnectedState;
415 break;
416 case ECONNREFUSED:
417 case EINVAL:
418 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
419 socketState = QAbstractSocket::UnconnectedState;
420 break;
421 case ETIMEDOUT:
422 setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
423 break;
424 case EHOSTUNREACH:
425 setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
426 socketState = QAbstractSocket::UnconnectedState;
427 break;
428 case ENETUNREACH:
429 setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString);
430 socketState = QAbstractSocket::UnconnectedState;
431 break;
432 case EADDRINUSE:
433 setError(QAbstractSocket::NetworkError, AddressInuseErrorString);
434 break;
435 case EINPROGRESS:
436 case EALREADY:
437 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
438 socketState = QAbstractSocket::ConnectingState;
439 break;
440 case EAGAIN:
441 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
442 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
443 break;
444 case EACCES:
445 case EPERM:
446 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
447 socketState = QAbstractSocket::UnconnectedState;
448 break;
449 case EAFNOSUPPORT:
450 case EBADF:
451 case EFAULT:
452 case ENOTSOCK:
453 socketState = QAbstractSocket::UnconnectedState;
454 default:
455 break;
456 }
457
458 if (socketState != QAbstractSocket::ConnectedState) {
459 #if defined (QNATIVESOCKETENGINE_DEBUG)
460 qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
461 addr.toString().toLatin1().constData(), port,
462 socketState == QAbstractSocket::ConnectingState
463 ? "Connection in progress" : socketErrorString.toLatin1().constData());
464 #endif
465 return false;
466 }
467 }
468
469 #if defined (QNATIVESOCKETENGINE_DEBUG)
470 qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true",
471 addr.toString().toLatin1().constData(), port);
472 #endif
473
474 socketState = QAbstractSocket::ConnectedState;
475 return true;
476 }
477
nativeBind(const QHostAddress & address,quint16 port)478 bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 port)
479 {
480 struct sockaddr_in sockAddrIPv4;
481 struct sockaddr *sockAddrPtr = 0;
482 QT_SOCKLEN_T sockAddrSize = 0;
483
484 #if !defined(QT_NO_IPV6)
485 struct sockaddr_in6 sockAddrIPv6;
486
487 if (address.protocol() == QAbstractSocket::IPv6Protocol) {
488 memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
489 sockAddrIPv6.sin6_family = AF_INET6;
490 sockAddrIPv6.sin6_port = htons(port);
491 #ifndef QT_NO_IPV6IFNAME
492 sockAddrIPv6.sin6_scope_id = ::if_nametoindex(address.scopeId().toLatin1().data());
493 #else
494 sockAddrIPv6.sin6_scope_id = address.scopeId().toInt();
495 #endif
496 Q_IPV6ADDR tmp = address.toIPv6Address();
497 memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
498 sockAddrSize = sizeof(sockAddrIPv6);
499 sockAddrPtr = (struct sockaddr *) &sockAddrIPv6;
500 } else
501 #endif
502 if (address.protocol() == QAbstractSocket::IPv4Protocol) {
503 memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
504 sockAddrIPv4.sin_family = AF_INET;
505 sockAddrIPv4.sin_port = htons(port);
506 sockAddrIPv4.sin_addr.s_addr = htonl(address.toIPv4Address());
507 sockAddrSize = sizeof(sockAddrIPv4);
508 sockAddrPtr = (struct sockaddr *) &sockAddrIPv4;
509 } else {
510 // unreachable
511 }
512
513 int bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize);
514
515 if (bindResult < 0) {
516 switch(errno) {
517 case EADDRINUSE:
518 setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
519 break;
520 case EACCES:
521 setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString);
522 break;
523 case EINVAL:
524 setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString);
525 break;
526 case EADDRNOTAVAIL:
527 setError(QAbstractSocket::SocketAddressNotAvailableError, AddressNotAvailableErrorString);
528 break;
529 default:
530 break;
531 }
532
533 #if defined (QNATIVESOCKETENGINE_DEBUG)
534 qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
535 address.toString().toLatin1().constData(), port, socketErrorString.toLatin1().constData());
536 #endif
537
538 return false;
539 }
540
541 #if defined (QNATIVESOCKETENGINE_DEBUG)
542 qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == true",
543 address.toString().toLatin1().constData(), port);
544 #endif
545 socketState = QAbstractSocket::BoundState;
546 return true;
547 }
548
nativeListen(int backlog)549 bool QNativeSocketEnginePrivate::nativeListen(int backlog)
550 {
551 if (qt_safe_listen(socketDescriptor, backlog) < 0) {
552 switch (errno) {
553 case EADDRINUSE:
554 setError(QAbstractSocket::AddressInUseError,
555 PortInuseErrorString);
556 break;
557 default:
558 break;
559 }
560
561 #if defined (QNATIVESOCKETENGINE_DEBUG)
562 qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == false (%s)",
563 backlog, socketErrorString.toLatin1().constData());
564 #endif
565 return false;
566 }
567
568 #if defined (QNATIVESOCKETENGINE_DEBUG)
569 qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == true", backlog);
570 #endif
571
572 socketState = QAbstractSocket::ListeningState;
573 return true;
574 }
575
nativeAccept()576 int QNativeSocketEnginePrivate::nativeAccept()
577 {
578 int acceptedDescriptor = qt_safe_accept(socketDescriptor, 0, 0);
579
580 return acceptedDescriptor;
581 }
582
583 #ifndef QT_NO_NETWORKINTERFACE
584
multicastMembershipHelper(QNativeSocketEnginePrivate * d,int how6,int how4,const QHostAddress & groupAddress,const QNetworkInterface & interface)585 static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d,
586 int how6,
587 int how4,
588 const QHostAddress &groupAddress,
589 const QNetworkInterface &interface)
590 {
591 int level = 0;
592 int sockOpt = 0;
593 void *sockArg;
594 int sockArgSize;
595
596 ip_mreq mreq4;
597 #ifndef QT_NO_IPV6
598 ipv6_mreq mreq6;
599
600 if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) {
601 level = IPPROTO_IPV6;
602 sockOpt = how6;
603 sockArg = &mreq6;
604 sockArgSize = sizeof(mreq6);
605 memset(&mreq6, 0, sizeof(mreq6));
606 Q_IPV6ADDR ip6 = groupAddress.toIPv6Address();
607 memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6));
608 mreq6.ipv6mr_interface = interface.index();
609 } else
610 #endif
611 if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
612 level = IPPROTO_IP;
613 sockOpt = how4;
614 sockArg = &mreq4;
615 sockArgSize = sizeof(mreq4);
616 memset(&mreq4, 0, sizeof(mreq4));
617 mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address());
618
619 if (interface.isValid()) {
620 QList<QNetworkAddressEntry> addressEntries = interface.addressEntries();
621 if (!addressEntries.isEmpty()) {
622 QHostAddress firstIP = addressEntries.first().ip();
623 mreq4.imr_interface.s_addr = htonl(firstIP.toIPv4Address());
624 } else {
625 d->setError(QAbstractSocket::NetworkError,
626 QNativeSocketEnginePrivate::NetworkUnreachableErrorString);
627 return false;
628 }
629 } else {
630 mreq4.imr_interface.s_addr = INADDR_ANY;
631 }
632 } else {
633 // unreachable
634 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
635 QNativeSocketEnginePrivate::ProtocolUnsupportedErrorString);
636 return false;
637 }
638
639 int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize);
640 if (res == -1) {
641 switch (errno) {
642 case ENOPROTOOPT:
643 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
644 QNativeSocketEnginePrivate::OperationUnsupportedErrorString);
645 break;
646 case EADDRNOTAVAIL:
647 d->setError(QAbstractSocket::SocketAddressNotAvailableError,
648 QNativeSocketEnginePrivate::AddressNotAvailableErrorString);
649 break;
650 default:
651 d->setError(QAbstractSocket::UnknownSocketError,
652 QNativeSocketEnginePrivate::UnknownSocketErrorString);
653 break;
654 }
655 return false;
656 }
657 return true;
658 }
659
nativeJoinMulticastGroup(const QHostAddress & groupAddress,const QNetworkInterface & interface)660 bool QNativeSocketEnginePrivate::nativeJoinMulticastGroup(const QHostAddress &groupAddress,
661 const QNetworkInterface &interface)
662 {
663 return multicastMembershipHelper(this,
664 #ifndef QT_NO_IPV6
665 IPV6_JOIN_GROUP,
666 #else
667 0,
668 #endif
669 IP_ADD_MEMBERSHIP,
670 groupAddress,
671 interface);
672 }
673
nativeLeaveMulticastGroup(const QHostAddress & groupAddress,const QNetworkInterface & interface)674 bool QNativeSocketEnginePrivate::nativeLeaveMulticastGroup(const QHostAddress &groupAddress,
675 const QNetworkInterface &interface)
676 {
677 return multicastMembershipHelper(this,
678 #ifndef QT_NO_IPV6
679 IPV6_LEAVE_GROUP,
680 #else
681 0,
682 #endif
683 IP_DROP_MEMBERSHIP,
684 groupAddress,
685 interface);
686 }
687
nativeMulticastInterface() const688 QNetworkInterface QNativeSocketEnginePrivate::nativeMulticastInterface() const
689 {
690 #ifndef QT_NO_IPV6
691 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
692 uint v;
693 QT_SOCKOPTLEN_T sizeofv = sizeof(v);
694 if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, &sizeofv) == -1)
695 return QNetworkInterface();
696 return QNetworkInterface::interfaceFromIndex(v);
697 }
698 #endif
699
700 struct in_addr v = { 0 };
701 QT_SOCKOPTLEN_T sizeofv = sizeof(v);
702 if (::getsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, &sizeofv) == -1)
703 return QNetworkInterface();
704 if (v.s_addr != 0 && sizeofv >= sizeof(v)) {
705 QHostAddress ipv4(ntohl(v.s_addr));
706 QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
707 for (int i = 0; i < ifaces.count(); ++i) {
708 const QNetworkInterface &iface = ifaces.at(i);
709 QList<QNetworkAddressEntry> entries = iface.addressEntries();
710 for (int j = 0; j < entries.count(); ++j) {
711 const QNetworkAddressEntry &entry = entries.at(j);
712 if (entry.ip() == ipv4)
713 return iface;
714 }
715 }
716 }
717 return QNetworkInterface();
718 }
719
nativeSetMulticastInterface(const QNetworkInterface & iface)720 bool QNativeSocketEnginePrivate::nativeSetMulticastInterface(const QNetworkInterface &iface)
721 {
722 #ifndef QT_NO_IPV6
723 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
724 uint v = iface.index();
725 return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, sizeof(v)) != -1);
726 }
727 #endif
728
729 struct in_addr v;
730 if (iface.isValid()) {
731 QList<QNetworkAddressEntry> entries = iface.addressEntries();
732 for (int i = 0; i < entries.count(); ++i) {
733 const QNetworkAddressEntry &entry = entries.at(i);
734 const QHostAddress &ip = entry.ip();
735 if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
736 v.s_addr = htonl(ip.toIPv4Address());
737 int r = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, sizeof(v));
738 if (r != -1)
739 return true;
740 }
741 }
742 return false;
743 }
744
745 v.s_addr = INADDR_ANY;
746 return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, sizeof(v)) != -1);
747 }
748
749 #endif // QT_NO_NETWORKINTERFACE
750
nativeBytesAvailable() const751 qint64 QNativeSocketEnginePrivate::nativeBytesAvailable() const
752 {
753 int nbytes = 0;
754 // gives shorter than true amounts on Unix domain sockets.
755 qint64 available = 0;
756 if (qt_safe_ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
757 available = (qint64) nbytes;
758
759 #if defined (QNATIVESOCKETENGINE_DEBUG)
760 qDebug("QNativeSocketEnginePrivate::nativeBytesAvailable() == %lli", available);
761 #endif
762 return available;
763 }
764
nativeHasPendingDatagrams() const765 bool QNativeSocketEnginePrivate::nativeHasPendingDatagrams() const
766 {
767 // Create a sockaddr struct and reset its port number.
768 qt_sockaddr storage;
769 QT_SOCKLEN_T storageSize = sizeof(storage);
770 memset(&storage, 0, storageSize);
771
772 // Peek 0 bytes into the next message. The size of the message may
773 // well be 0, so we can't check recvfrom's return value.
774 ssize_t readBytes;
775 do {
776 char c;
777 readBytes = ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, &storage.a, &storageSize);
778 } while (readBytes == -1 && errno == EINTR);
779
780 // If there's no error, or if our buffer was too small, there must be a
781 // pending datagram.
782 bool result = (readBytes != -1) || errno == EMSGSIZE;
783
784 #if defined (QNATIVESOCKETENGINE_DEBUG)
785 qDebug("QNativeSocketEnginePrivate::nativeHasPendingDatagrams() == %s",
786 result ? "true" : "false");
787 #endif
788 return result;
789 }
790
nativePendingDatagramSize() const791 qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
792 {
793 QVarLengthArray<char, 8192> udpMessagePeekBuffer(8192);
794 ssize_t recvResult = -1;
795
796 for (;;) {
797 // the data written to udpMessagePeekBuffer is discarded, so
798 // this function is still reentrant although it might not look
799 // so.
800 recvResult = ::recv(socketDescriptor, udpMessagePeekBuffer.data(),
801 udpMessagePeekBuffer.size(), MSG_PEEK);
802 if (recvResult == -1 && errno == EINTR)
803 continue;
804
805 if (recvResult != (ssize_t) udpMessagePeekBuffer.size())
806 break;
807
808 udpMessagePeekBuffer.resize(udpMessagePeekBuffer.size() * 2);
809 }
810
811 #if defined (QNATIVESOCKETENGINE_DEBUG)
812 qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %i", recvResult);
813 #endif
814
815 return qint64(recvResult);
816 }
817
nativeReceiveDatagram(char * data,qint64 maxSize,QHostAddress * address,quint16 * port)818 qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize,
819 QHostAddress *address, quint16 *port)
820 {
821 qt_sockaddr aa;
822 memset(&aa, 0, sizeof(aa));
823 QT_SOCKLEN_T sz;
824 sz = sizeof(aa);
825
826 ssize_t recvFromResult = 0;
827 do {
828 char c;
829 recvFromResult = ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1,
830 0, &aa.a, &sz);
831 } while (recvFromResult == -1 && errno == EINTR);
832
833 if (recvFromResult == -1) {
834 setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
835 } else if (port || address) {
836 qt_socket_getPortAndAddress(&aa, port, address);
837 }
838
839 #if defined (QNATIVESOCKETENGINE_DEBUG)
840 qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli",
841 data, qt_prettyDebug(data, qMin(recvFromResult, ssize_t(16)), recvFromResult).data(), maxSize,
842 address ? address->toString().toLatin1().constData() : "(nil)",
843 port ? *port : 0, (qint64) recvFromResult);
844 #endif
845
846 return qint64(maxSize ? recvFromResult : recvFromResult == -1 ? -1 : 0);
847 }
848
nativeSendDatagram(const char * data,qint64 len,const QHostAddress & host,quint16 port)849 qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len,
850 const QHostAddress &host, quint16 port)
851 {
852 struct sockaddr_in sockAddrIPv4;
853 struct sockaddr *sockAddrPtr = 0;
854 QT_SOCKLEN_T sockAddrSize = 0;
855
856 #if !defined(QT_NO_IPV6)
857 struct sockaddr_in6 sockAddrIPv6;
858 if (host.protocol() == QAbstractSocket::IPv6Protocol) {
859 memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
860 sockAddrIPv6.sin6_family = AF_INET6;
861 sockAddrIPv6.sin6_port = htons(port);
862
863 Q_IPV6ADDR tmp = host.toIPv6Address();
864 memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
865 QString scopeid = host.scopeId();
866 bool ok;
867 sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok);
868 #ifndef QT_NO_IPV6IFNAME
869 if (!ok)
870 sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1());
871 #endif
872 sockAddrSize = sizeof(sockAddrIPv6);
873 sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
874 } else
875 #endif
876 if (host.protocol() == QAbstractSocket::IPv4Protocol) {
877 memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
878 sockAddrIPv4.sin_family = AF_INET;
879 sockAddrIPv4.sin_port = htons(port);
880 sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address());
881 sockAddrSize = sizeof(sockAddrIPv4);
882 sockAddrPtr = (struct sockaddr *)&sockAddrIPv4;
883 }
884
885 ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len,
886 0, sockAddrPtr, sockAddrSize);
887
888 if (sentBytes < 0) {
889 switch (errno) {
890 case EMSGSIZE:
891 setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
892 break;
893 default:
894 setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
895 }
896 }
897
898 #if defined (QNATIVESOCKETENGINE_DEBUG)
899 qDebug("QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data,
900 qt_prettyDebug(data, qMin<int>(len, 16), len).data(), len, host.toString().toLatin1().constData(),
901 port, (qint64) sentBytes);
902 #endif
903
904 return qint64(sentBytes);
905 }
906
fetchConnectionParameters()907 bool QNativeSocketEnginePrivate::fetchConnectionParameters()
908 {
909 localPort = 0;
910 localAddress.clear();
911 peerPort = 0;
912 peerAddress.clear();
913
914 if (socketDescriptor == -1)
915 return false;
916
917 qt_sockaddr sa;
918 QT_SOCKLEN_T sockAddrSize = sizeof(sa);
919
920 // Determine local address
921 memset(&sa, 0, sizeof(sa));
922 if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
923 qt_socket_getPortAndAddress(&sa, &localPort, &localAddress);
924
925 // Determine protocol family
926 switch (sa.a.sa_family) {
927 case AF_INET:
928 socketProtocol = QAbstractSocket::IPv4Protocol;
929 break;
930 #if !defined (QT_NO_IPV6)
931 case AF_INET6:
932 socketProtocol = QAbstractSocket::IPv6Protocol;
933 break;
934 #endif
935 default:
936 socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
937 break;
938 }
939
940 } else if (errno == EBADF) {
941 setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidSocketErrorString);
942 return false;
943 }
944
945 // Determine the remote address
946 if (!::getpeername(socketDescriptor, &sa.a, &sockAddrSize))
947 qt_socket_getPortAndAddress(&sa, &peerPort, &peerAddress);
948
949 // Determine the socket type (UDP/TCP)
950 int value = 0;
951 QT_SOCKOPTLEN_T valueSize = sizeof(int);
952 if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, &value, &valueSize) == 0) {
953 if (value == SOCK_STREAM)
954 socketType = QAbstractSocket::TcpSocket;
955 else if (value == SOCK_DGRAM)
956 socketType = QAbstractSocket::UdpSocket;
957 else
958 socketType = QAbstractSocket::UnknownSocketType;
959 }
960 #if defined (QNATIVESOCKETENGINE_DEBUG)
961 QString socketProtocolStr = "UnknownProtocol";
962 if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = "IPv4Protocol";
963 else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = "IPv6Protocol";
964
965 QString socketTypeStr = "UnknownSocketType";
966 if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = "TcpSocket";
967 else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = "UdpSocket";
968
969 qDebug("QNativeSocketEnginePrivate::fetchConnectionParameters() local == %s:%i,"
970 " peer == %s:%i, socket == %s - %s",
971 localAddress.toString().toLatin1().constData(), localPort,
972 peerAddress.toString().toLatin1().constData(), peerPort,socketTypeStr.toLatin1().constData(),
973 socketProtocolStr.toLatin1().constData());
974 #endif
975 return true;
976 }
977
nativeClose()978 void QNativeSocketEnginePrivate::nativeClose()
979 {
980 #if defined (QNATIVESOCKETENGINE_DEBUG)
981 qDebug("QNativeSocketEngine::nativeClose()");
982 #endif
983
984 qt_safe_close(socketDescriptor);
985 }
986
nativeWrite(const char * data,qint64 len)987 qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len)
988 {
989 Q_Q(QNativeSocketEngine);
990
991 ssize_t writtenBytes;
992 writtenBytes = qt_safe_write_nosignal(socketDescriptor, data, len);
993
994 if (writtenBytes < 0) {
995 switch (errno) {
996 case EPIPE:
997 case ECONNRESET:
998 writtenBytes = -1;
999 setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString);
1000 q->close();
1001 break;
1002 case EAGAIN:
1003 writtenBytes = 0;
1004 break;
1005 case EMSGSIZE:
1006 setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
1007 break;
1008 default:
1009 break;
1010 }
1011 }
1012
1013 #if defined (QNATIVESOCKETENGINE_DEBUG)
1014 qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %llu) == %i",
1015 data, qt_prettyDebug(data, qMin((int) len, 16),
1016 (int) len).data(), len, (int) writtenBytes);
1017 #endif
1018
1019 return qint64(writtenBytes);
1020 }
1021 /*
1022 */
nativeRead(char * data,qint64 maxSize)1023 qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize)
1024 {
1025 Q_Q(QNativeSocketEngine);
1026 if (!q->isValid()) {
1027 qWarning("QNativeSocketEngine::nativeRead: Invalid socket");
1028 return -1;
1029 }
1030
1031 ssize_t r = 0;
1032 r = qt_safe_read(socketDescriptor, data, maxSize);
1033
1034 if (r < 0) {
1035 r = -1;
1036 switch (errno) {
1037 #if EWOULDBLOCK-0 && EWOULDBLOCK != EAGAIN
1038 case EWOULDBLOCK:
1039 #endif
1040 case EAGAIN:
1041 // No data was available for reading
1042 r = -2;
1043 break;
1044 case EBADF:
1045 case EINVAL:
1046 case EIO:
1047 //error string is now set in read(), not here in nativeRead()
1048 break;
1049 case ECONNRESET:
1050 #if defined(Q_OS_VXWORKS)
1051 case ESHUTDOWN:
1052 #endif
1053 r = 0;
1054 break;
1055 default:
1056 break;
1057 }
1058 }
1059
1060 #if defined (QNATIVESOCKETENGINE_DEBUG)
1061 qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %llu) == %i",
1062 data, qt_prettyDebug(data, qMin(r, ssize_t(16)), r).data(),
1063 maxSize, r);
1064 #endif
1065
1066 return qint64(r);
1067 }
1068
nativeSelect(int timeout,bool selectForRead) const1069 int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const
1070 {
1071 fd_set fds;
1072 FD_ZERO(&fds);
1073 FD_SET(socketDescriptor, &fds);
1074
1075 struct timeval tv;
1076 tv.tv_sec = timeout / 1000;
1077 tv.tv_usec = (timeout % 1000) * 1000;
1078
1079 int retval;
1080 if (selectForRead)
1081 retval = qt_safe_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv);
1082 else
1083 retval = qt_safe_select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv);
1084
1085 return retval;
1086 }
1087
nativeSelect(int timeout,bool checkRead,bool checkWrite,bool * selectForRead,bool * selectForWrite) const1088 int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite,
1089 bool *selectForRead, bool *selectForWrite) const
1090 {
1091 fd_set fdread;
1092 FD_ZERO(&fdread);
1093 if (checkRead)
1094 FD_SET(socketDescriptor, &fdread);
1095
1096 fd_set fdwrite;
1097 FD_ZERO(&fdwrite);
1098 if (checkWrite)
1099 FD_SET(socketDescriptor, &fdwrite);
1100
1101 struct timeval tv;
1102 tv.tv_sec = timeout / 1000;
1103 tv.tv_usec = (timeout % 1000) * 1000;
1104
1105 int ret;
1106 ret = qt_safe_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
1107
1108 if (ret <= 0)
1109 return ret;
1110 *selectForRead = FD_ISSET(socketDescriptor, &fdread);
1111 *selectForWrite = FD_ISSET(socketDescriptor, &fdwrite);
1112
1113 return ret;
1114 }
1115
1116 QT_END_NAMESPACE
1117