Qt 4.8
qnativesocketengine_unix.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 //#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 
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 */
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 */
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
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 
150 {
151 #ifndef QT_NO_IPV6
152  int protocol = (socketProtocol == QAbstractSocket::IPv6Protocol) ? AF_INET6 : AF_INET;
153 #else
154  Q_UNUSED(socketProtocol);
155  int protocol = AF_INET;
156 #endif
157  int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
158 
159  int socket = qt_safe_socket(protocol, type, 0);
160 
161  if (socket <= 0) {
162  switch (errno) {
163  case EPROTONOSUPPORT:
164  case EAFNOSUPPORT:
165  case EINVAL:
167  break;
168  case ENFILE:
169  case EMFILE:
170  case ENOBUFS:
171  case ENOMEM:
173  break;
174  case EACCES:
176  break;
177  default:
178  break;
179  }
180 
181  return false;
182  }
183 
184  socketDescriptor = socket;
185  return true;
186 }
187 
188 /*
189  Returns the value of the socket option \a opt.
190 */
192 {
193  Q_Q(const QNativeSocketEngine);
194  if (!q->isValid())
195  return -1;
196 
197  int n = -1;
198  int level = SOL_SOCKET; // default
199 
200  switch (opt) {
202  n = SO_RCVBUF;
203  break;
205  n = SO_SNDBUF;
206  break;
208  break;
210  break;
212  n = SO_REUSEADDR;
213  break;
215  return true;
217  n = SO_OOBINLINE;
218  break;
220  level = IPPROTO_TCP;
221  n = TCP_NODELAY;
222  break;
224  n = SO_KEEPALIVE;
225  break;
227 #ifndef QT_NO_IPV6
229  level = IPPROTO_IPV6;
230  n = IPV6_MULTICAST_HOPS;
231  } else
232 #endif
233  {
234  level = IPPROTO_IP;
235  n = IP_MULTICAST_TTL;
236  }
237  break;
239 #ifndef QT_NO_IPV6
241  level = IPPROTO_IPV6;
242  n = IPV6_MULTICAST_LOOP;
243  } else
244 #endif
245  {
246  level = IPPROTO_IP;
247  n = IP_MULTICAST_LOOP;
248  }
249  break;
250  }
251 
252  int v = -1;
253  QT_SOCKOPTLEN_T len = sizeof(v);
254  if (::getsockopt(socketDescriptor, level, n, (char *) &v, &len) != -1)
255  return v;
256 
257  return -1;
258 }
259 
260 
261 /*
262  Sets the socket option \a opt to \a v.
263 */
265 {
267  if (!q->isValid())
268  return false;
269 
270  int n = 0;
271  int level = SOL_SOCKET; // default
272 
273  switch (opt) {
275  n = SO_RCVBUF;
276  break;
278  n = SO_SNDBUF;
279  break;
281  n = SO_BROADCAST;
282  break;
284  // Make the socket nonblocking.
285 #if !defined(Q_OS_VXWORKS)
286  int flags = ::fcntl(socketDescriptor, F_GETFL, 0);
287  if (flags == -1) {
288 #ifdef QNATIVESOCKETENGINE_DEBUG
289  perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_GETFL) failed");
290 #endif
291  return false;
292  }
293  if (::fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) {
294 #ifdef QNATIVESOCKETENGINE_DEBUG
295  perror("QNativeSocketEnginePrivate::setOption(): fcntl(F_SETFL) failed");
296 #endif
297  return false;
298  }
299 #else // Q_OS_VXWORKS
300  int onoff = 1;
301 
302  if (qt_safe_ioctl(socketDescriptor, FIONBIO, &onoff) < 0) {
303 
304 #ifdef QNATIVESOCKETENGINE_DEBUG
305  perror("QNativeSocketEnginePrivate::setOption(): ioctl(FIONBIO, 1) failed");
306 #endif
307  return false;
308  }
309 #endif // Q_OS_VXWORKS
310  return true;
311  }
313 #if defined(SO_REUSEPORT)
314  // on OS X, SO_REUSEADDR isn't sufficient to allow multiple binds to the
315  // same port (which is useful for multicast UDP). SO_REUSEPORT is, but
316  // we most definitely do not want to use this for TCP. See QTBUG-6305.
318  n = SO_REUSEPORT;
319  else
320  n = SO_REUSEADDR;
321 #else
322  n = SO_REUSEADDR;
323 #endif
324  break;
326  return true;
328  n = SO_OOBINLINE;
329  break;
331  level = IPPROTO_TCP;
332  n = TCP_NODELAY;
333  break;
335  n = SO_KEEPALIVE;
336  break;
338 #ifndef QT_NO_IPV6
340  level = IPPROTO_IPV6;
341  n = IPV6_MULTICAST_HOPS;
342  } else
343 #endif
344  {
345  level = IPPROTO_IP;
346  n = IP_MULTICAST_TTL;
347  }
348  break;
350 #ifndef QT_NO_IPV6
352  level = IPPROTO_IPV6;
353  n = IPV6_MULTICAST_LOOP;
354  } else
355 #endif
356  {
357  level = IPPROTO_IP;
358  n = IP_MULTICAST_LOOP;
359  }
360  break;
361  }
362 
363  return ::setsockopt(socketDescriptor, level, n, (char *) &v, sizeof(v)) == 0;
364 }
365 
367 {
368 #ifdef QNATIVESOCKETENGINE_DEBUG
369  qDebug("QNativeSocketEnginePrivate::nativeConnect() : %d ", socketDescriptor);
370 #endif
371 
372  struct sockaddr_in sockAddrIPv4;
373  struct sockaddr *sockAddrPtr = 0;
374  QT_SOCKLEN_T sockAddrSize = 0;
375 
376 #if !defined(QT_NO_IPV6)
377  struct sockaddr_in6 sockAddrIPv6;
378 
379  if (addr.protocol() == QAbstractSocket::IPv6Protocol) {
380  memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
381  sockAddrIPv6.sin6_family = AF_INET6;
382  sockAddrIPv6.sin6_port = htons(port);
383 
384  QString scopeid = addr.scopeId();
385  bool ok;
386  sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok);
387 #ifndef QT_NO_IPV6IFNAME
388  if (!ok)
389  sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1());
390 #endif
391  Q_IPV6ADDR ip6 = addr.toIPv6Address();
392  memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6));
393 
394  sockAddrSize = sizeof(sockAddrIPv6);
395  sockAddrPtr = (struct sockaddr *) &sockAddrIPv6;
396  } else
397 #if 0
398  {}
399 #endif
400 #endif
401  if (addr.protocol() == QAbstractSocket::IPv4Protocol) {
402  memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
403  sockAddrIPv4.sin_family = AF_INET;
404  sockAddrIPv4.sin_port = htons(port);
405  sockAddrIPv4.sin_addr.s_addr = htonl(addr.toIPv4Address());
406 
407  sockAddrSize = sizeof(sockAddrIPv4);
408  sockAddrPtr = (struct sockaddr *) &sockAddrIPv4;
409  } else {
410  // unreachable
411  }
412 
413  int connectResult = qt_safe_connect(socketDescriptor, sockAddrPtr, sockAddrSize);
414  if (connectResult == -1) {
415  switch (errno) {
416  case EISCONN:
418  break;
419  case ECONNREFUSED:
420  case EINVAL:
423  break;
424  case ETIMEDOUT:
426  break;
427  case EHOSTUNREACH:
430  break;
431  case ENETUNREACH:
434  break;
435  case EADDRINUSE:
437  break;
438  case EINPROGRESS:
439  case EALREADY:
442  break;
443  case EAGAIN:
446  break;
447  case EACCES:
448  case EPERM:
451  break;
452  case EAFNOSUPPORT:
453  case EBADF:
454  case EFAULT:
455  case ENOTSOCK:
457  default:
458  break;
459  }
460 
462 #if defined (QNATIVESOCKETENGINE_DEBUG)
463  qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
464  addr.toString().toLatin1().constData(), port,
466  ? "Connection in progress" : socketErrorString.toLatin1().constData());
467 #endif
468  return false;
469  }
470  }
471 
472 #if defined (QNATIVESOCKETENGINE_DEBUG)
473  qDebug("QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true",
474  addr.toString().toLatin1().constData(), port);
475 #endif
476 
478  return true;
479 }
480 
482 {
483  struct sockaddr_in sockAddrIPv4;
484  struct sockaddr *sockAddrPtr = 0;
485  QT_SOCKLEN_T sockAddrSize = 0;
486 
487 #if !defined(QT_NO_IPV6)
488  struct sockaddr_in6 sockAddrIPv6;
489 
490  if (address.protocol() == QAbstractSocket::IPv6Protocol) {
491  memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
492  sockAddrIPv6.sin6_family = AF_INET6;
493  sockAddrIPv6.sin6_port = htons(port);
494 #ifndef QT_NO_IPV6IFNAME
495  sockAddrIPv6.sin6_scope_id = ::if_nametoindex(address.scopeId().toLatin1().data());
496 #else
497  sockAddrIPv6.sin6_scope_id = address.scopeId().toInt();
498 #endif
499  Q_IPV6ADDR tmp = address.toIPv6Address();
500  memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
501  sockAddrSize = sizeof(sockAddrIPv6);
502  sockAddrPtr = (struct sockaddr *) &sockAddrIPv6;
503  } else
504 #endif
505  if (address.protocol() == QAbstractSocket::IPv4Protocol) {
506  memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
507  sockAddrIPv4.sin_family = AF_INET;
508  sockAddrIPv4.sin_port = htons(port);
509  sockAddrIPv4.sin_addr.s_addr = htonl(address.toIPv4Address());
510  sockAddrSize = sizeof(sockAddrIPv4);
511  sockAddrPtr = (struct sockaddr *) &sockAddrIPv4;
512  } else {
513  // unreachable
514  }
515 
516  int bindResult = QT_SOCKET_BIND(socketDescriptor, sockAddrPtr, sockAddrSize);
517 
518  if (bindResult < 0) {
519  switch(errno) {
520  case EADDRINUSE:
522  break;
523  case EACCES:
525  break;
526  case EINVAL:
528  break;
529  case EADDRNOTAVAIL:
531  break;
532  default:
533  break;
534  }
535 
536 #if defined (QNATIVESOCKETENGINE_DEBUG)
537  qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
539 #endif
540 
541  return false;
542  }
543 
544 #if defined (QNATIVESOCKETENGINE_DEBUG)
545  qDebug("QNativeSocketEnginePrivate::nativeBind(%s, %i) == true",
546  address.toString().toLatin1().constData(), port);
547 #endif
549  return true;
550 }
551 
553 {
554  if (qt_safe_listen(socketDescriptor, backlog) < 0) {
555  switch (errno) {
556  case EADDRINUSE:
559  break;
560  default:
561  break;
562  }
563 
564 #if defined (QNATIVESOCKETENGINE_DEBUG)
565  qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == false (%s)",
566  backlog, socketErrorString.toLatin1().constData());
567 #endif
568  return false;
569  }
570 
571 #if defined (QNATIVESOCKETENGINE_DEBUG)
572  qDebug("QNativeSocketEnginePrivate::nativeListen(%i) == true", backlog);
573 #endif
574 
576  return true;
577 }
578 
580 {
581  int acceptedDescriptor = qt_safe_accept(socketDescriptor, 0, 0);
582 
583  return acceptedDescriptor;
584 }
585 
586 #ifndef QT_NO_NETWORKINTERFACE
587 
589  int how6,
590  int how4,
591  const QHostAddress &groupAddress,
592  const QNetworkInterface &interface)
593 {
594  int level = 0;
595  int sockOpt = 0;
596  void *sockArg;
597  int sockArgSize;
598 
599  ip_mreq mreq4;
600 #ifndef QT_NO_IPV6
601  ipv6_mreq mreq6;
602 
603  if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) {
604  level = IPPROTO_IPV6;
605  sockOpt = how6;
606  sockArg = &mreq6;
607  sockArgSize = sizeof(mreq6);
608  memset(&mreq6, 0, sizeof(mreq6));
609  Q_IPV6ADDR ip6 = groupAddress.toIPv6Address();
610  memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6));
611  mreq6.ipv6mr_interface = interface.index();
612  } else
613 #endif
614  if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
615  level = IPPROTO_IP;
616  sockOpt = how4;
617  sockArg = &mreq4;
618  sockArgSize = sizeof(mreq4);
619  memset(&mreq4, 0, sizeof(mreq4));
620  mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address());
621 
622  if (interface.isValid()) {
623  QList<QNetworkAddressEntry> addressEntries = interface.addressEntries();
624  if (!addressEntries.isEmpty()) {
625  QHostAddress firstIP = addressEntries.first().ip();
626  mreq4.imr_interface.s_addr = htonl(firstIP.toIPv4Address());
627  } else {
630  return false;
631  }
632  } else {
633  mreq4.imr_interface.s_addr = INADDR_ANY;
634  }
635  } else {
636  // unreachable
639  return false;
640  }
641 
642  int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize);
643  if (res == -1) {
644  switch (errno) {
645  case ENOPROTOOPT:
648  break;
649  case EADDRNOTAVAIL:
652  break;
653  default:
656  break;
657  }
658  return false;
659  }
660  return true;
661 }
662 
664  const QNetworkInterface &interface)
665 {
666  return multicastMembershipHelper(this,
667 #ifndef QT_NO_IPV6
668  IPV6_JOIN_GROUP,
669 #else
670  0,
671 #endif
672  IP_ADD_MEMBERSHIP,
673  groupAddress,
674  interface);
675 }
676 
678  const QNetworkInterface &interface)
679 {
680  return multicastMembershipHelper(this,
681 #ifndef QT_NO_IPV6
682  IPV6_LEAVE_GROUP,
683 #else
684  0,
685 #endif
686  IP_DROP_MEMBERSHIP,
687  groupAddress,
688  interface);
689 }
690 
692 {
693 #ifndef QT_NO_IPV6
695  uint v;
696  QT_SOCKOPTLEN_T sizeofv = sizeof(v);
697  if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, &sizeofv) == -1)
698  return QNetworkInterface();
700  }
701 #endif
702 
703  struct in_addr v = { 0 };
704  QT_SOCKOPTLEN_T sizeofv = sizeof(v);
705  if (::getsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, &sizeofv) == -1)
706  return QNetworkInterface();
707  if (v.s_addr != 0 && sizeofv >= sizeof(v)) {
708  QHostAddress ipv4(ntohl(v.s_addr));
710  for (int i = 0; i < ifaces.count(); ++i) {
711  const QNetworkInterface &iface = ifaces.at(i);
713  for (int j = 0; j < entries.count(); ++j) {
714  const QNetworkAddressEntry &entry = entries.at(j);
715  if (entry.ip() == ipv4)
716  return iface;
717  }
718  }
719  }
720  return QNetworkInterface();
721 }
722 
724 {
725 #ifndef QT_NO_IPV6
727  uint v = iface.index();
728  return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, sizeof(v)) != -1);
729  }
730 #endif
731 
732  struct in_addr v;
733  if (iface.isValid()) {
735  for (int i = 0; i < entries.count(); ++i) {
736  const QNetworkAddressEntry &entry = entries.at(i);
737  const QHostAddress &ip = entry.ip();
739  v.s_addr = htonl(ip.toIPv4Address());
740  int r = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, sizeof(v));
741  if (r != -1)
742  return true;
743  }
744  }
745  return false;
746  }
747 
748  v.s_addr = INADDR_ANY;
749  return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, sizeof(v)) != -1);
750 }
751 
752 #endif // QT_NO_NETWORKINTERFACE
753 
755 {
756  int nbytes = 0;
757  // gives shorter than true amounts on Unix domain sockets.
758  qint64 available = 0;
759  if (qt_safe_ioctl(socketDescriptor, FIONREAD, (char *) &nbytes) >= 0)
760  available = (qint64) nbytes;
761 
762 #if defined (QNATIVESOCKETENGINE_DEBUG)
763  qDebug("QNativeSocketEnginePrivate::nativeBytesAvailable() == %lli", available);
764 #endif
765  return available;
766 }
767 
769 {
770  // Create a sockaddr struct and reset its port number.
771  qt_sockaddr storage;
772  QT_SOCKLEN_T storageSize = sizeof(storage);
773  memset(&storage, 0, storageSize);
774 
775  // Peek 0 bytes into the next message. The size of the message may
776  // well be 0, so we can't check recvfrom's return value.
777  ssize_t readBytes;
778  do {
779  char c;
780  readBytes = ::recvfrom(socketDescriptor, &c, 1, MSG_PEEK, &storage.a, &storageSize);
781  } while (readBytes == -1 && errno == EINTR);
782 
783  // If there's no error, or if our buffer was too small, there must be a
784  // pending datagram.
785  bool result = (readBytes != -1) || errno == EMSGSIZE;
786 
787 #if defined (QNATIVESOCKETENGINE_DEBUG)
788  qDebug("QNativeSocketEnginePrivate::nativeHasPendingDatagrams() == %s",
789  result ? "true" : "false");
790 #endif
791  return result;
792 }
793 
795 {
796  QVarLengthArray<char, 8192> udpMessagePeekBuffer(8192);
797  ssize_t recvResult = -1;
798 
799  for (;;) {
800  // the data written to udpMessagePeekBuffer is discarded, so
801  // this function is still reentrant although it might not look
802  // so.
803  recvResult = ::recv(socketDescriptor, udpMessagePeekBuffer.data(),
804  udpMessagePeekBuffer.size(), MSG_PEEK);
805  if (recvResult == -1 && errno == EINTR)
806  continue;
807 
808  if (recvResult != (ssize_t) udpMessagePeekBuffer.size())
809  break;
810 
811  udpMessagePeekBuffer.resize(udpMessagePeekBuffer.size() * 2);
812  }
813 
814 #if defined (QNATIVESOCKETENGINE_DEBUG)
815  qDebug("QNativeSocketEnginePrivate::nativePendingDatagramSize() == %i", recvResult);
816 #endif
817 
818  return qint64(recvResult);
819 }
820 
822  QHostAddress *address, quint16 *port)
823 {
824  qt_sockaddr aa;
825  memset(&aa, 0, sizeof(aa));
826  QT_SOCKLEN_T sz;
827  sz = sizeof(aa);
828 
829  ssize_t recvFromResult = 0;
830  do {
831  char c;
832  recvFromResult = ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1,
833  0, &aa.a, &sz);
834  } while (recvFromResult == -1 && errno == EINTR);
835 
836  if (recvFromResult == -1) {
838  } else if (port || address) {
839  qt_socket_getPortAndAddress(&aa, port, address);
840  }
841 
842 #if defined (QNATIVESOCKETENGINE_DEBUG)
843  qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli",
844  data, qt_prettyDebug(data, qMin(recvFromResult, ssize_t(16)), recvFromResult).data(), maxSize,
845  address ? address->toString().toLatin1().constData() : "(nil)",
846  port ? *port : 0, (qint64) recvFromResult);
847 #endif
848 
849  return qint64(maxSize ? recvFromResult : recvFromResult == -1 ? -1 : 0);
850 }
851 
853  const QHostAddress &host, quint16 port)
854 {
855  struct sockaddr_in sockAddrIPv4;
856  struct sockaddr *sockAddrPtr = 0;
857  QT_SOCKLEN_T sockAddrSize = 0;
858 
859 #if !defined(QT_NO_IPV6)
860  struct sockaddr_in6 sockAddrIPv6;
861  if (host.protocol() == QAbstractSocket::IPv6Protocol) {
862  memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
863  sockAddrIPv6.sin6_family = AF_INET6;
864  sockAddrIPv6.sin6_port = htons(port);
865 
866  Q_IPV6ADDR tmp = host.toIPv6Address();
867  memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
868  QString scopeid = host.scopeId();
869  bool ok;
870  sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok);
871 #ifndef QT_NO_IPV6IFNAME
872  if (!ok)
873  sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1());
874 #endif
875  sockAddrSize = sizeof(sockAddrIPv6);
876  sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
877  } else
878 #endif
879  if (host.protocol() == QAbstractSocket::IPv4Protocol) {
880  memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
881  sockAddrIPv4.sin_family = AF_INET;
882  sockAddrIPv4.sin_port = htons(port);
883  sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address());
884  sockAddrSize = sizeof(sockAddrIPv4);
885  sockAddrPtr = (struct sockaddr *)&sockAddrIPv4;
886  }
887 
888  ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len,
889  0, sockAddrPtr, sockAddrSize);
890 
891  if (sentBytes < 0) {
892  switch (errno) {
893  case EMSGSIZE:
895  break;
896  default:
898  }
899  }
900 
901 #if defined (QNATIVESOCKETENGINE_DEBUG)
902  qDebug("QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data,
903  qt_prettyDebug(data, qMin<int>(len, 16), len).data(), len, host.toString().toLatin1().constData(),
904  port, (qint64) sentBytes);
905 #endif
906 
907  return qint64(sentBytes);
908 }
909 
911 {
912  localPort = 0;
914  peerPort = 0;
915  peerAddress.clear();
916 
917  if (socketDescriptor == -1)
918  return false;
919 
920  qt_sockaddr sa;
921  QT_SOCKLEN_T sockAddrSize = sizeof(sa);
922 
923  // Determine local address
924  memset(&sa, 0, sizeof(sa));
925  if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
927 
928  // Determine protocol family
929  switch (sa.a.sa_family) {
930  case AF_INET:
932  break;
933 #if !defined (QT_NO_IPV6)
934  case AF_INET6:
936  break;
937 #endif
938  default:
940  break;
941  }
942 
943  } else if (errno == EBADF) {
945  return false;
946  }
947 
948  // Determine the remote address
949  if (!::getpeername(socketDescriptor, &sa.a, &sockAddrSize))
951 
952  // Determine the socket type (UDP/TCP)
953  int value = 0;
954  QT_SOCKOPTLEN_T valueSize = sizeof(int);
955  if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, &value, &valueSize) == 0) {
956  if (value == SOCK_STREAM)
958  else if (value == SOCK_DGRAM)
960  else
962  }
963 #if defined (QNATIVESOCKETENGINE_DEBUG)
964  QString socketProtocolStr = "UnknownProtocol";
965  if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = "IPv4Protocol";
966  else if (socketProtocol == QAbstractSocket::IPv6Protocol) socketProtocolStr = "IPv6Protocol";
967 
968  QString socketTypeStr = "UnknownSocketType";
969  if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = "TcpSocket";
970  else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = "UdpSocket";
971 
972  qDebug("QNativeSocketEnginePrivate::fetchConnectionParameters() local == %s:%i,"
973  " peer == %s:%i, socket == %s - %s",
976  socketProtocolStr.toLatin1().constData());
977 #endif
978  return true;
979 }
980 
982 {
983 #if defined (QNATIVESOCKETENGINE_DEBUG)
984  qDebug("QNativeSocketEngine::nativeClose()");
985 #endif
986 
988 }
989 
991 {
993 
994  ssize_t writtenBytes;
995  writtenBytes = qt_safe_write_nosignal(socketDescriptor, data, len);
996 
997  if (writtenBytes < 0) {
998  switch (errno) {
999  case EPIPE:
1000  case ECONNRESET:
1001  writtenBytes = -1;
1003  q->close();
1004  break;
1005  case EAGAIN:
1006  writtenBytes = 0;
1007  break;
1008  case EMSGSIZE:
1010  break;
1011  default:
1012  break;
1013  }
1014  }
1015 
1016 #if defined (QNATIVESOCKETENGINE_DEBUG)
1017  qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %llu) == %i",
1018  data, qt_prettyDebug(data, qMin((int) len, 16),
1019  (int) len).data(), len, (int) writtenBytes);
1020 #endif
1021 
1022  return qint64(writtenBytes);
1023 }
1024 /*
1025 */
1027 {
1029  if (!q->isValid()) {
1030  qWarning("QNativeSocketEngine::nativeRead: Invalid socket");
1031  return -1;
1032  }
1033 
1034  ssize_t r = 0;
1035  r = qt_safe_read(socketDescriptor, data, maxSize);
1036 
1037  if (r < 0) {
1038  r = -1;
1039  switch (errno) {
1040 #if EWOULDBLOCK-0 && EWOULDBLOCK != EAGAIN
1041  case EWOULDBLOCK:
1042 #endif
1043  case EAGAIN:
1044  // No data was available for reading
1045  r = -2;
1046  break;
1047  case EBADF:
1048  case EINVAL:
1049  case EIO:
1050  //error string is now set in read(), not here in nativeRead()
1051  break;
1052  case ECONNRESET:
1053 #if defined(Q_OS_VXWORKS)
1054  case ESHUTDOWN:
1055 #endif
1056  r = 0;
1057  break;
1058  default:
1059  break;
1060  }
1061  }
1062 
1063 #if defined (QNATIVESOCKETENGINE_DEBUG)
1064  qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %llu) == %i",
1065  data, qt_prettyDebug(data, qMin(r, ssize_t(16)), r).data(),
1066  maxSize, r);
1067 #endif
1068 
1069  return qint64(r);
1070 }
1071 
1072 int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const
1073 {
1074  fd_set fds;
1075  FD_ZERO(&fds);
1076  FD_SET(socketDescriptor, &fds);
1077 
1078  struct timeval tv;
1079  tv.tv_sec = timeout / 1000;
1080  tv.tv_usec = (timeout % 1000) * 1000;
1081 
1082  int retval;
1083  if (selectForRead)
1084  retval = qt_safe_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv);
1085  else
1086  retval = qt_safe_select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv);
1087 
1088  return retval;
1089 }
1090 
1091 int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite,
1092  bool *selectForRead, bool *selectForWrite) const
1093 {
1094  fd_set fdread;
1095  FD_ZERO(&fdread);
1096  if (checkRead)
1097  FD_SET(socketDescriptor, &fdread);
1098 
1099  fd_set fdwrite;
1100  FD_ZERO(&fdwrite);
1101  if (checkWrite)
1102  FD_SET(socketDescriptor, &fdwrite);
1103 
1104  struct timeval tv;
1105  tv.tv_sec = timeout / 1000;
1106  tv.tv_usec = (timeout % 1000) * 1000;
1107 
1108  int ret;
1109  ret = qt_safe_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
1110 
1111  if (ret <= 0)
1112  return ret;
1113  *selectForRead = FD_ISSET(socketDescriptor, &fdread);
1114  *selectForWrite = FD_ISSET(socketDescriptor, &fdwrite);
1115 
1116  return ret;
1117 }
1118 
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.
void resize(int size)
double d
Definition: qnumeric_p.h:62
static void qt_socket_getPortAndAddress(const qt_sockaddr *s, quint16 *port, QHostAddress *addr)
QString scopeId() const
Returns the scope ID of an IPv6 address.
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.
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
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
#define QT_SOCKOPTLEN_T
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
struct qt_in6_addr sin6_addr
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.
static int qt_safe_close(int fd)
Definition: qcore_unix_p.h:297
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.
static int qt_safe_ioctl(int sockfd, int request, T arg)
Definition: qnet_unix_p.h:167
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
#define QT_SOCKLEN_T
#define Q_Q(Class)
Definition: qglobal.h:2483
Q_CORE_EXPORT void qDebug(const char *,...)
void clear()
Sets the host address to 0.0.0.0.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static int qt_safe_connect(int sockfd, const struct sockaddr *addr, QT_SOCKLEN_T addrlen)
Definition: qnet_unix_p.h:145
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
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
QAbstractSocket::SocketType socketType
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)
int fcntl(int, int,...)
QAbstractSocket::NetworkLayerProtocol protocol() const
Returns the network layer protocol of the host address.
void setAddress(quint32 ip4Addr)
Set the IPv4 address specified by ip4Addr.
int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, const struct timeval *orig_timeout)
Definition: qcore_unix.cpp:73
static int qt_safe_socket(int domain, int type, int protocol, int flags=0)
Definition: qnet_unix_p.h:83
static int qt_safe_sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *to, QT_SOCKLEN_T tolen)
Definition: qnet_unix_p.h:187
static int qt_safe_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *addrlen, int flags=0)
Definition: qnet_unix_p.h:111
qt_sockaddr_in6 a6
static QList< QNetworkInterface > allInterfaces()
Returns a listing of all the network interfaces found on the host machine.
QAbstractSocket::SocketState socketState
void setError(QAbstractSocket::SocketError error, ErrorString errorString) const
Sets the error and error string if not set already.
bool nativeBind(const QHostAddress &address, quint16 port)
int index() const
Returns the interface system index, if known.
static int qt_safe_listen(int s, int backlog)
Definition: qnet_unix_p.h:140
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
bool nativeLeaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface)
static qint64 qt_safe_write_nosignal(int fd, const void *data, qint64 len)
Definition: qcore_unix_p.h:291
QList< QNetworkAddressEntry > addressEntries() const
Returns the list of IP addresses that this interface possesses along with their associated netmasks a...
QAbstractSocket::NetworkLayerProtocol socketProtocol
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
The QNetworkAddressEntry class stores one IP address supported by a network interface, along with its associated netmask and broadcast address.
static qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
Definition: qcore_unix_p.h:273
int size() const
int errno
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.
static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d, int how6, int how4, const QHostAddress &groupAddress, const QNetworkInterface &interface)
#define AF_INET6
qint64 nativeRead(char *data, qint64 maxLength)