75 QAbstractSocket::NetworkLayerProtocol socketProtocol,
int &level,
int &n)
81 case QNativeSocketEngine::NonBlockingSocketOption:
82 case QNativeSocketEngine::BindExclusively:
83 case QNativeSocketEngine::MaxStreamsSocketOption:
86 case QNativeSocketEngine::BindInterfaceIndex:
89 case QNativeSocketEngine::BroadcastSocketOption:
92 case QNativeSocketEngine::ReceiveBufferSocketOption:
95 case QNativeSocketEngine::SendBufferSocketOption:
98 case QNativeSocketEngine::AddressReusable:
101 case QNativeSocketEngine::ReceiveOutOfBandData:
104 case QNativeSocketEngine::LowDelayOption:
108 case QNativeSocketEngine::KeepAliveOption:
111 case QNativeSocketEngine::MulticastTtlOption:
112 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
113 level = IPPROTO_IPV6;
114 n = IPV6_MULTICAST_HOPS;
118 n = IP_MULTICAST_TTL;
121 case QNativeSocketEngine::MulticastLoopbackOption:
122 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
123 level = IPPROTO_IPV6;
124 n = IPV6_MULTICAST_LOOP;
128 n = IP_MULTICAST_LOOP;
131 case QNativeSocketEngine::TypeOfServiceOption:
132 if (socketProtocol == QAbstractSocket::IPv4Protocol) {
137 case QNativeSocketEngine::ReceivePacketInformation:
138 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
139 level = IPPROTO_IPV6;
140 n = IPV6_RECVPKTINFO;
141 }
else if (socketProtocol == QAbstractSocket::IPv4Protocol) {
145#elif defined(IP_RECVDSTADDR)
152 case QNativeSocketEngine::ReceiveHopLimit:
153 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
154 level = IPPROTO_IPV6;
155 n = IPV6_RECVHOPLIMIT;
156 }
else if (socketProtocol == QAbstractSocket::IPv4Protocol) {
164 case QNativeSocketEngine::PathMtuInformation:
165 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
167 level = IPPROTO_IPV6;
186 QAbstractSocket::NetworkLayerProtocol &socketProtocol)
189 int protocol = (socketType == QAbstractSocket::SctpSocket) ? IPPROTO_SCTP : 0;
191 if (socketType == QAbstractSocket::SctpSocket) {
192 setError(QAbstractSocket::UnsupportedSocketOperationError,
193 ProtocolUnsupportedErrorString);
194#if defined (QNATIVESOCKETENGINE_DEBUG)
195 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d): unsupported protocol",
196 socketType, socketProtocol);
202 int domain = (socketProtocol == QAbstractSocket::IPv6Protocol
203 || socketProtocol == QAbstractSocket::AnyIPProtocol) ?
AF_INET6 : AF_INET;
204 int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
206 int socket = qt_safe_socket(domain, type, protocol, O_NONBLOCK);
207 if (socket < 0 && socketProtocol == QAbstractSocket::AnyIPProtocol && errno == EAFNOSUPPORT) {
209 socket = qt_safe_socket(domain, type, protocol, O_NONBLOCK);
210 socketProtocol = QAbstractSocket::IPv4Protocol;
216 case EPROTONOSUPPORT:
219 setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
225 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
228 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
234#if defined (QNATIVESOCKETENGINE_DEBUG)
235 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d) == false (%s)",
236 socketType, socketProtocol,
245 const int ipv6only = 0;
246 [[maybe_unused]]
const int ret = ::setsockopt(socket, IPPROTO_IPV6,
IPV6_V6ONLY,
247 &ipv6only,
sizeof(ipv6only));
248#if defined (QNATIVESOCKETENGINE_DEBUG)
250 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d): "
251 "failed to set IPV6_V6ONLY to %d.",
252 socketType, socketProtocol, ipv6only);
257#if defined (QNATIVESOCKETENGINE_DEBUG)
258 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d) == true",
259 socketType, socketProtocol);
262 socketDescriptor = socket;
263 this->socketProtocol = socketProtocol;
264 this->socketType = socketType;
273 Q_Q(
const QNativeSocketEngine);
279 case QNativeSocketEngine::BindExclusively:
280 case QNativeSocketEngine::NonBlockingSocketOption:
281 case QNativeSocketEngine::BroadcastSocketOption:
283 case QNativeSocketEngine::MaxStreamsSocketOption: {
285 sctp_initmsg sctpInitMsg;
286 QT_SOCKOPTLEN_T sctpInitMsgSize =
sizeof(sctpInitMsg);
287 if (::getsockopt(socketDescriptor, SOL_SCTP, SCTP_INITMSG, &sctpInitMsg,
288 &sctpInitMsgSize) == 0)
289 return int(qMin(sctpInitMsg.sinit_num_ostreams, sctpInitMsg.sinit_max_instreams));
294 case QNativeSocketEngine::PathMtuInformation:
295#if defined(IPV6_PATHMTU
) && !defined(IPV6_MTU
)
298 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
300 QT_SOCKOPTLEN_T len =
sizeof(mtuinfo);
301 if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_PATHMTU, &mtuinfo, &len) == 0)
302 return int(mtuinfo.ip6m_mtu);
314 QT_SOCKOPTLEN_T len =
sizeof(v);
316 convertToLevelAndOption(opt, socketProtocol, level, n);
317 if (n != -1 && ::getsockopt(socketDescriptor, level, n, (
char *) &v, &len) != -1)
318 return len == 1 ? qFromUnaligned<quint8>(&v) : v;
329 Q_Q(QNativeSocketEngine);
335 case QNativeSocketEngine::NonBlockingSocketOption: {
337#if !defined(Q_OS_VXWORKS)
338 int flags = ::fcntl(socketDescriptor, F_GETFL, 0);
340#ifdef QNATIVESOCKETENGINE_DEBUG
341 perror(
"QNativeSocketEnginePrivate::setOption(): fcntl(F_GETFL) failed");
345 if (::fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) {
346#ifdef QNATIVESOCKETENGINE_DEBUG
347 perror(
"QNativeSocketEnginePrivate::setOption(): fcntl(F_SETFL) failed");
354 if (qt_safe_ioctl(socketDescriptor, FIONBIO, &onoff) < 0) {
356#ifdef QNATIVESOCKETENGINE_DEBUG
357 perror(
"QNativeSocketEnginePrivate::setOption(): ioctl(FIONBIO, 1) failed");
364 case QNativeSocketEngine::BindExclusively:
367 case QNativeSocketEngine::MaxStreamsSocketOption: {
369 sctp_initmsg sctpInitMsg;
370 QT_SOCKOPTLEN_T sctpInitMsgSize =
sizeof(sctpInitMsg);
371 if (::getsockopt(socketDescriptor, SOL_SCTP, SCTP_INITMSG, &sctpInitMsg,
372 &sctpInitMsgSize) == 0) {
373 sctpInitMsg.sinit_num_ostreams = sctpInitMsg.sinit_max_instreams = uint16_t(v);
374 return ::setsockopt(socketDescriptor, SOL_SCTP, SCTP_INITMSG, &sctpInitMsg,
375 sctpInitMsgSize) == 0;
380 case QNativeSocketEngine::BindInterfaceIndex: {
381#if defined(SO_BINDTOIFINDEX
)
382 return ::setsockopt(socketDescriptor, SOL_SOCKET, SO_BINDTOIFINDEX,
384#elif defined(IPV6_BOUND_IF) && defined(IP_BOUND_IF)
386 if (socketProtocol == QAbstractSocket::IPv6Protocol
387 || socketProtocol == QAbstractSocket::AnyIPProtocol) {
388 return ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_BOUND_IF, &v,
sizeof(v)) == 0;
390 return ::setsockopt(socketDescriptor, IPPROTO_IP, IP_BOUND_IF, &v,
sizeof(v)) == 0;
392#elif defined(SO_BINDTODEVICE) && QT_CONFIG(networkinterface)
394 const QByteArray name = QNetworkInterfaceManager::interfaceNameFromIndex(v).toLatin1();
395 return ::setsockopt(socketDescriptor, SOL_SOCKET, SO_BINDTODEVICE,
396 name.data(), socklen_t(name.size())) == 0;
406 convertToLevelAndOption(opt, socketProtocol, level, n);
407#if defined(SO_REUSEPORT
) && !defined(Q_OS_LINUX)
408 if (opt == QNativeSocketEngine::AddressReusable) {
412 if (socketType == QAbstractSocket::UdpSocket)
419 return ::setsockopt(socketDescriptor, level, n, (
char *) &v,
sizeof(v)) == 0;
424#ifdef QNATIVESOCKETENGINE_DEBUG
425 qDebug() <<
"QNativeSocketEnginePrivate::nativeConnect() " << socketDescriptor;
429 QT_SOCKLEN_T sockAddrSize;
430 setPortAndAddress(port, addr, &aa, &sockAddrSize);
432 int connectResult = qt_safe_connect(socketDescriptor, &aa.a, sockAddrSize);
433#if defined (QNATIVESOCKETENGINE_DEBUG)
436 if (connectResult == -1) {
439 socketState = QAbstractSocket::ConnectedState;
444 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
445 socketState = QAbstractSocket::UnconnectedState;
448 setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
451 setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
452 socketState = QAbstractSocket::UnconnectedState;
455 setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString);
456 socketState = QAbstractSocket::UnconnectedState;
459 setError(QAbstractSocket::NetworkError, AddressInuseErrorString);
463 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
464 socketState = QAbstractSocket::ConnectingState;
467 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
471 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
472 socketState = QAbstractSocket::UnconnectedState;
478 socketState = QAbstractSocket::UnconnectedState;
484 if (socketState != QAbstractSocket::ConnectedState) {
485#if defined (QNATIVESOCKETENGINE_DEBUG)
486 qDebug(
"QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
487 addr.toString().toLatin1().constData(), port,
488 socketState == QAbstractSocket::ConnectingState
489 ?
"Connection in progress" : strerror(ecopy));
495#if defined (QNATIVESOCKETENGINE_DEBUG)
496 qDebug(
"QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true",
497 addr.toString().toLatin1().constData(), port);
500 socketState = QAbstractSocket::ConnectedState;
507 QT_SOCKLEN_T sockAddrSize;
508 setPortAndAddress(port, address, &aa, &sockAddrSize);
513 if (address.protocol() == QAbstractSocket::IPv6Protocol)
516 ::setsockopt(socketDescriptor, IPPROTO_IPV6,
IPV6_V6ONLY, (
char*)&ipv6only,
sizeof(ipv6only) );
520 int bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
521 if (bindResult < 0 && errno == EAFNOSUPPORT && address.protocol() == QAbstractSocket::AnyIPProtocol) {
523 aa.a4.sin_family = AF_INET;
524 aa.a4.sin_port = htons(port);
525 aa.a4.sin_addr.s_addr = htonl(address.toIPv4Address());
526 sockAddrSize =
sizeof(aa.a4);
527 bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
530 if (bindResult < 0) {
531#if defined (QNATIVESOCKETENGINE_DEBUG)
536 setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
539 setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString);
542 setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString);
545 setError(QAbstractSocket::SocketAddressNotAvailableError, AddressNotAvailableErrorString);
551#if defined (QNATIVESOCKETENGINE_DEBUG)
552 qDebug(
"QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
553 address.toString().toLatin1().constData(), port, strerror(ecopy));
559#if defined (QNATIVESOCKETENGINE_DEBUG)
560 qDebug(
"QNativeSocketEnginePrivate::nativeBind(%s, %i) == true",
561 address.toString().toLatin1().constData(), port);
563 socketState = QAbstractSocket::BoundState;
599 int acceptedDescriptor = qt_safe_accept(socketDescriptor,
nullptr,
nullptr);
600 if (acceptedDescriptor == -1) {
604 setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidSocketErrorString);
607 setError(QAbstractSocket::NetworkError, RemoteHostClosedErrorString);
611 setError(QAbstractSocket::SocketResourceError, NotSocketErrorString);
613 case EPROTONOSUPPORT:
614#if !defined(Q_OS_OPENBSD)
619 setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
625 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
629 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
631#if EAGAIN
!= EWOULDBLOCK
635 setError(QAbstractSocket::TemporaryError, TemporaryErrorString);
638 setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString);
643 return qintptr(acceptedDescriptor);
651 const QHostAddress &groupAddress,
652 const QNetworkInterface &interface)
662 if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) {
663 level = IPPROTO_IPV6;
666 sockArgSize =
sizeof(mreq6);
667 memset(&mreq6, 0,
sizeof(mreq6));
668 Q_IPV6ADDR ip6 = groupAddress.toIPv6Address();
669 memcpy(&mreq6.ipv6mr_multiaddr, &ip6,
sizeof(ip6));
670 mreq6.ipv6mr_interface = interface.index();
671 }
else if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
675 sockArgSize =
sizeof(mreq4);
676 memset(&mreq4, 0,
sizeof(mreq4));
677 mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address());
679 if (interface.isValid()) {
680 const QList<QNetworkAddressEntry> addressEntries = interface.addressEntries();
682 for (
const QNetworkAddressEntry &entry : addressEntries) {
683 const QHostAddress ip = entry.ip();
684 if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
685 mreq4.imr_interface.s_addr = htonl(ip.toIPv4Address());
691 d->setError(QAbstractSocket::NetworkError,
692 QNativeSocketEnginePrivate::NetworkUnreachableErrorString);
696 mreq4.imr_interface.s_addr = INADDR_ANY;
700 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
701 QNativeSocketEnginePrivate::ProtocolUnsupportedErrorString);
705 int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize);
709 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
710 QNativeSocketEnginePrivate::OperationUnsupportedErrorString);
713 d->setError(QAbstractSocket::SocketAddressNotAvailableError,
714 QNativeSocketEnginePrivate::AddressNotAvailableErrorString);
717 d->setError(QAbstractSocket::UnknownSocketError,
718 QNativeSocketEnginePrivate::UnknownSocketErrorString);
748 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
750 QT_SOCKOPTLEN_T sizeofv =
sizeof(v);
751 if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, &sizeofv) == -1)
752 return QNetworkInterface();
753 return QNetworkInterface::interfaceFromIndex(v);
756#if defined(Q_OS_SOLARIS)
757 struct in_addr v = { 0, 0, 0, 0};
759 struct in_addr v = { 0 };
761 QT_SOCKOPTLEN_T sizeofv =
sizeof(v);
762 if (::getsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, &sizeofv) == -1)
763 return QNetworkInterface();
764 if (v.s_addr != 0 && sizeofv >= QT_SOCKOPTLEN_T(
sizeof(v))) {
765 QHostAddress ipv4(ntohl(v.s_addr));
766 QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
767 for (
int i = 0; i < ifaces.size(); ++i) {
768 const QNetworkInterface &iface = ifaces.at(i);
769 QList<QNetworkAddressEntry> entries = iface.addressEntries();
770 for (
int j = 0; j < entries.size(); ++j) {
771 const QNetworkAddressEntry &entry = entries.at(j);
772 if (entry.ip() == ipv4)
777 return QNetworkInterface();
782 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
783 uint v = iface.index();
784 return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v,
sizeof(v)) != -1);
788 if (iface.isValid()) {
789 QList<QNetworkAddressEntry> entries = iface.addressEntries();
790 for (
int i = 0; i < entries.size(); ++i) {
791 const QNetworkAddressEntry &entry = entries.at(i);
792 const QHostAddress &ip = entry.ip();
793 if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
794 v.s_addr = htonl(ip.toIPv4Address());
795 int r = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v,
sizeof(v));
803 v.s_addr = INADDR_ANY;
804 return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v,
sizeof(v)) != -1);
852 ssize_t recvResult = -1;
856 QT_EINTR_LOOP(recvResult, ::recv(socketDescriptor, &c, 1, MSG_PEEK | MSG_TRUNC));
857#elif defined(SO_NREAD)
860 socklen_t valuelen =
sizeof(value);
861 recvResult = getsockopt(socketDescriptor, SOL_SOCKET, SO_NREAD, &value, &valuelen);
862 if (recvResult != -1)
864#elif defined(Q_OS_VXWORKS)
867 int ioctlResult = ::ioctl(socketDescriptor, FIONREAD, &available);
868 if (ioctlResult != -1)
869 recvResult = available;
875 char udpMessagePeekBuffer[1500];
879 memset(&msg, 0,
sizeof(msg));
882 vec.iov_base = udpMessagePeekBuffer;
883 vec.iov_len =
sizeof(udpMessagePeekBuffer);
889 recvResult = ::recvmsg(socketDescriptor, &msg, MSG_PEEK);
890 if (recvResult == -1 && errno == EINTR)
894 if ((msg.msg_flags & MSG_TRUNC) == 0)
898 msg.msg_iovlen *= 16;
899 if (msg.msg_iov != &vec)
900 delete[] msg.msg_iov;
901 msg.msg_iov =
new struct iovec[msg.msg_iovlen];
902 std::fill_n(msg.msg_iov, msg.msg_iovlen, vec);
905 if (msg.msg_iov != &vec)
906 delete[] msg.msg_iov;
909#if defined (QNATIVESOCKETENGINE_DEBUG)
910 qDebug(
"QNativeSocketEnginePrivate::nativePendingDatagramSize() == %zd", recvResult);
913 return qint64(recvResult);
917 QAbstractSocketEngine::PacketHeaderOptions options)
920 quintptr cbuf[(CMSG_SPACE(
sizeof(
struct in6_pktinfo)) + CMSG_SPACE(
sizeof(
int))
921#if !defined(IP_PKTINFO
) && defined(IP_RECVIF) && defined(Q_OS_BSD4)
922 + CMSG_SPACE(
sizeof(sockaddr_dl))
925 + CMSG_SPACE(
sizeof(
struct sctp_sndrcvinfo))
927 +
sizeof(quintptr) - 1) /
sizeof(quintptr)];
933 memset(&msg, 0,
sizeof(msg));
934 memset(&aa, 0,
sizeof(aa));
937 vec.iov_base = maxSize ? data : &c;
938 vec.iov_len = maxSize ? maxSize : 1;
941 if (options & QAbstractSocketEngine::WantDatagramSender) {
943 msg.msg_namelen =
sizeof(aa);
945 if (options & (QAbstractSocketEngine::WantDatagramHopLimit | QAbstractSocketEngine::WantDatagramDestination
946 | QAbstractSocketEngine::WantStreamNumber)) {
947 msg.msg_control = cbuf;
948 msg.msg_controllen =
sizeof(cbuf);
951 ssize_t recvResult = 0;
953 recvResult = ::recvmsg(socketDescriptor, &msg, 0);
954 }
while (recvResult == -1 && errno == EINTR);
956 if (recvResult == -1) {
958#if defined(EWOULDBLOCK
) && EWOULDBLOCK
!= EAGAIN
966 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
969 setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
973 }
else if (options != QAbstractSocketEngine::WantNone) {
975 qt_socket_getPortAndAddress(&aa, &header->senderPort, &header->senderAddress);
976 header->destinationPort = localPort;
977 header->endOfRecord = (msg.msg_flags & MSG_EOR) != 0;
980 struct cmsghdr *cmsgptr;
982 QT_WARNING_DISABLE_CLANG(
"-Wsign-compare")
983 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr !=
nullptr;
984 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
986 if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO
987 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in6_pktinfo))) {
988 in6_pktinfo *info =
reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
990 header->destinationAddress.setAddress(
reinterpret_cast<quint8 *>(&info->ipi6_addr));
991 header->ifindex = info->ipi6_ifindex;
993 header->destinationAddress.setScopeId(QString::number(info->ipi6_ifindex));
997 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO
998 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in_pktinfo))) {
999 in_pktinfo *info =
reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr));
1001 header->destinationAddress.setAddress(ntohl(info->ipi_addr.s_addr));
1002 header->ifindex = info->ipi_ifindex;
1005# ifdef IP_RECVDSTADDR
1006 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVDSTADDR
1007 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in_addr))) {
1008 in_addr *addr =
reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr));
1010 header->destinationAddress.setAddress(ntohl(addr->s_addr));
1013# if defined(IP_RECVIF) && defined(Q_OS_BSD4)
1014 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVIF
1015 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(sockaddr_dl))) {
1016 sockaddr_dl *sdl =
reinterpret_cast<sockaddr_dl *>(CMSG_DATA(cmsgptr));
1017 header->ifindex = sdl->sdl_index;
1022 if (cmsgptr->cmsg_len == CMSG_LEN(
sizeof(
int))
1023 && ((cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT)
1024 || (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TTL))) {
1025 static_assert(
sizeof(header->hopLimit) ==
sizeof(
int));
1026 memcpy(&header->hopLimit, CMSG_DATA(cmsgptr),
sizeof(header->hopLimit));
1030 if (cmsgptr->cmsg_level == IPPROTO_SCTP && cmsgptr->cmsg_type == SCTP_SNDRCV
1031 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(sctp_sndrcvinfo))) {
1032 sctp_sndrcvinfo *rcvInfo =
reinterpret_cast<sctp_sndrcvinfo *>(CMSG_DATA(cmsgptr));
1034 header->streamNumber =
int(rcvInfo->sinfo_stream);
1040#if defined (QNATIVESOCKETENGINE_DEBUG)
1041 qDebug(
"QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli",
1042 data, QtDebugUtils::toPrintable(data, recvResult, 16).constData(), maxSize,
1043 (recvResult != -1 && options != QAbstractSocketEngine::WantNone)
1044 ? header->senderAddress.toString().toLatin1().constData() :
"(unknown)",
1045 (recvResult != -1 && options != QAbstractSocketEngine::WantNone)
1046 ? header->senderPort : 0, (qint64) recvResult);
1049 return qint64((maxSize || recvResult < 0) ? recvResult : Q_INT64_C(0));
1055 quintptr cbuf[(CMSG_SPACE(
sizeof(
struct in6_pktinfo)) + CMSG_SPACE(
sizeof(
int))
1057 + CMSG_SPACE(
sizeof(
struct sctp_sndrcvinfo))
1059 +
sizeof(quintptr) - 1) /
sizeof(quintptr)];
1061 struct cmsghdr *cmsgptr =
reinterpret_cast<
struct cmsghdr *>(cbuf);
1066 memset(&msg, 0,
sizeof(msg));
1067 memset(&aa, 0,
sizeof(aa));
1068 vec.iov_base =
const_cast<
char *>(data);
1072 msg.msg_control = &cbuf;
1074 if (header.destinationPort != 0) {
1075 msg.msg_name = &aa.a;
1076 setPortAndAddress(header.destinationPort, header.destinationAddress,
1077 &aa, &msg.msg_namelen);
1080 if (msg.msg_namelen ==
sizeof(aa.a6)) {
1081 if (header.hopLimit != -1) {
1082 msg.msg_controllen += CMSG_SPACE(
sizeof(
int));
1083 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(
int));
1084 cmsgptr->cmsg_level = IPPROTO_IPV6;
1085 cmsgptr->cmsg_type = IPV6_HOPLIMIT;
1086 memcpy(CMSG_DATA(cmsgptr), &header.hopLimit,
sizeof(
int));
1087 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(
int)));
1089 if (header.ifindex != 0 || !header.senderAddress.isNull()) {
1090 struct in6_pktinfo *data =
reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
1091 memset(data, 0,
sizeof(*data));
1092 msg.msg_controllen += CMSG_SPACE(
sizeof(*data));
1093 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(*data));
1094 cmsgptr->cmsg_level = IPPROTO_IPV6;
1095 cmsgptr->cmsg_type = IPV6_PKTINFO;
1096 data->ipi6_ifindex = header.ifindex;
1098 QIPv6Address tmp = header.senderAddress.toIPv6Address();
1099 memcpy(&data->ipi6_addr, &tmp,
sizeof(tmp));
1100 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1103 if (header.hopLimit != -1) {
1104 msg.msg_controllen += CMSG_SPACE(
sizeof(
int));
1105 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(
int));
1106 cmsgptr->cmsg_level = IPPROTO_IP;
1107 cmsgptr->cmsg_type = IP_TTL;
1108 memcpy(CMSG_DATA(cmsgptr), &header.hopLimit,
sizeof(
int));
1109 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(
int)));
1112#if defined(IP_PKTINFO
) || defined(IP_SENDSRCADDR)
1113 if (header.ifindex != 0 || !header.senderAddress.isNull()) {
1115 struct in_pktinfo *data =
reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr));
1116 memset(data, 0,
sizeof(*data));
1117 cmsgptr->cmsg_type = IP_PKTINFO;
1118 data->ipi_ifindex = header.ifindex;
1119 data->ipi_addr.s_addr = htonl(header.senderAddress.toIPv4Address());
1120# elif defined(IP_SENDSRCADDR)
1121 struct in_addr *data =
reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr));
1122 cmsgptr->cmsg_type = IP_SENDSRCADDR;
1123 data->s_addr = htonl(header.senderAddress.toIPv4Address());
1125 cmsgptr->cmsg_level = IPPROTO_IP;
1126 msg.msg_controllen += CMSG_SPACE(
sizeof(*data));
1127 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(*data));
1128 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1134 if (header.streamNumber != -1) {
1135 struct sctp_sndrcvinfo *data =
reinterpret_cast<sctp_sndrcvinfo *>(CMSG_DATA(cmsgptr));
1136 memset(data, 0,
sizeof(*data));
1137 msg.msg_controllen += CMSG_SPACE(
sizeof(sctp_sndrcvinfo));
1138 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(sctp_sndrcvinfo));
1139 cmsgptr->cmsg_level = IPPROTO_SCTP;
1140 cmsgptr->cmsg_type = SCTP_SNDRCV;
1141 data->sinfo_stream = uint16_t(header.streamNumber);
1142 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1146 if (msg.msg_controllen == 0)
1147 msg.msg_control =
nullptr;
1148 ssize_t sentBytes = qt_safe_sendmsg(socketDescriptor, &msg, 0);
1150 if (sentBytes < 0) {
1152#if defined(EWOULDBLOCK
) && EWOULDBLOCK
!= EAGAIN
1159 setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
1162 setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString);
1165 setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
1169#if defined (QNATIVESOCKETENGINE_DEBUG)
1170 qDebug(
"QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data,
1171 QtDebugUtils::toPrintable(data, len, 16).constData(), len,
1172 header.destinationAddress.toString().toLatin1().constData(),
1173 header.destinationPort, (qint64) sentBytes);
1176 return qint64(sentBytes);
1182 localAddress.clear();
1184 peerAddress.clear();
1185 inboundStreamCount = outboundStreamCount = 0;
1187 if (socketDescriptor == -1)
1191 QT_SOCKLEN_T sockAddrSize =
sizeof(sa);
1194 memset(&sa, 0,
sizeof(sa));
1195 if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
1196 qt_socket_getPortAndAddress(&sa, &localPort, &localAddress);
1199 switch (sa.a.sa_family) {
1201 socketProtocol = QAbstractSocket::IPv4Protocol;
1204 socketProtocol = QAbstractSocket::IPv6Protocol;
1207 socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
1211 }
else if (errno == EBADF) {
1212 setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidSocketErrorString);
1222 socklen_t optlen =
sizeof(ipv6only);
1223 if (socketProtocol == QAbstractSocket::IPv6Protocol
1224 && (localAddress == QHostAddress::AnyIPv4 || localAddress == QHostAddress::AnyIPv6)
1225 && !getsockopt(socketDescriptor, IPPROTO_IPV6,
IPV6_V6ONLY, (
char*)&ipv6only, &optlen )) {
1226 if (optlen !=
sizeof(ipv6only))
1227 qWarning(
"unexpected size of IPV6_V6ONLY socket option");
1229 socketProtocol = QAbstractSocket::AnyIPProtocol;
1230 localAddress = QHostAddress::Any;
1236 bool connected = ::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0;
1238 qt_socket_getPortAndAddress(&sa, &peerPort, &peerAddress);
1239 inboundStreamCount = outboundStreamCount = 1;
1244 QT_SOCKOPTLEN_T valueSize =
sizeof(
int);
1245 if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, &value, &valueSize) == 0) {
1246 if (value == SOCK_STREAM) {
1247 socketType = QAbstractSocket::TcpSocket;
1249 if (option(QNativeSocketEngine::MaxStreamsSocketOption) != -1) {
1250 socketType = QAbstractSocket::SctpSocket;
1252 sctp_status sctpStatus;
1253 QT_SOCKOPTLEN_T sctpStatusSize =
sizeof(sctpStatus);
1254 sctp_event_subscribe sctpEvents;
1256 memset(&sctpEvents, 0,
sizeof(sctpEvents));
1257 sctpEvents.sctp_data_io_event = 1;
1258 if (::getsockopt(socketDescriptor, SOL_SCTP, SCTP_STATUS, &sctpStatus,
1259 &sctpStatusSize) == 0 &&
1260 ::setsockopt(socketDescriptor, SOL_SCTP, SCTP_EVENTS, &sctpEvents,
1261 sizeof(sctpEvents)) == 0) {
1262 inboundStreamCount =
int(sctpStatus.sstat_instrms);
1263 outboundStreamCount =
int(sctpStatus.sstat_outstrms);
1265 setError(QAbstractSocket::UnsupportedSocketOperationError,
1266 InvalidSocketErrorString);
1272 }
else if (value == SOCK_DGRAM) {
1273 socketType = QAbstractSocket::UdpSocket;
1274#ifdef SOCK_SEQPACKET
1275 }
else if (value == SOCK_SEQPACKET) {
1283 socketType = QAbstractSocket::TcpSocket;
1286 socketType = QAbstractSocket::UnknownSocketType;
1289#if defined (QNATIVESOCKETENGINE_DEBUG)
1290 QString socketProtocolStr = QStringLiteral(
"UnknownProtocol");
1291 if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = QStringLiteral(
"IPv4Protocol");
1292 else if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) socketProtocolStr = QStringLiteral(
"IPv6Protocol");
1294 QString socketTypeStr = QStringLiteral(
"UnknownSocketType");
1295 if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = QStringLiteral(
"TcpSocket");
1296 else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = QStringLiteral(
"UdpSocket");
1297 else if (socketType == QAbstractSocket::SctpSocket) socketTypeStr = QStringLiteral(
"SctpSocket");
1299 qDebug(
"QNativeSocketEnginePrivate::fetchConnectionParameters() local == %s:%i,"
1300 " peer == %s:%i, socket == %s - %s, inboundStreamCount == %i, outboundStreamCount == %i",
1301 localAddress.toString().toLatin1().constData(), localPort,
1302 peerAddress.toString().toLatin1().constData(), peerPort,socketTypeStr.toLatin1().constData(),
1303 socketProtocolStr.toLatin1().constData(), inboundStreamCount, outboundStreamCount);