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) {
148 case QNativeSocketEngine::ReceiveHopLimit:
149 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
150 level = IPPROTO_IPV6;
151 n = IPV6_RECVHOPLIMIT;
152 }
else if (socketProtocol == QAbstractSocket::IPv4Protocol) {
160 case QNativeSocketEngine::PathMtuInformation:
161 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
163 level = IPPROTO_IPV6;
182 QAbstractSocket::NetworkLayerProtocol &socketProtocol)
185 int protocol = (socketType == QAbstractSocket::SctpSocket) ? IPPROTO_SCTP : 0;
187 if (socketType == QAbstractSocket::SctpSocket) {
188 setError(QAbstractSocket::UnsupportedSocketOperationError,
189 ProtocolUnsupportedErrorString);
190#if defined (QNATIVESOCKETENGINE_DEBUG)
191 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d): unsupported protocol",
192 socketType, socketProtocol);
198 int domain = (socketProtocol == QAbstractSocket::IPv6Protocol
199 || socketProtocol == QAbstractSocket::AnyIPProtocol) ?
AF_INET6 : AF_INET;
200 int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
202 int socket = qt_safe_socket(domain, type, protocol, O_NONBLOCK);
203 if (socket < 0 && socketProtocol == QAbstractSocket::AnyIPProtocol && errno == EAFNOSUPPORT) {
205 socket = qt_safe_socket(domain, type, protocol, O_NONBLOCK);
206 socketProtocol = QAbstractSocket::IPv4Protocol;
212 case EPROTONOSUPPORT:
215 setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
221 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
224 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
230#if defined (QNATIVESOCKETENGINE_DEBUG)
231 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d) == false (%s)",
232 socketType, socketProtocol,
241 const int ipv6only = 0;
242 [[maybe_unused]]
const int ret = ::setsockopt(socket, IPPROTO_IPV6,
IPV6_V6ONLY,
243 &ipv6only,
sizeof(ipv6only));
244#if defined (QNATIVESOCKETENGINE_DEBUG)
246 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d): "
247 "failed to set IPV6_V6ONLY to %d.",
248 socketType, socketProtocol, ipv6only);
253#if defined (QNATIVESOCKETENGINE_DEBUG)
254 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d) == true",
255 socketType, socketProtocol);
258 socketDescriptor = socket;
259 this->socketProtocol = socketProtocol;
260 this->socketType = socketType;
269 Q_Q(
const QNativeSocketEngine);
275 case QNativeSocketEngine::BindExclusively:
276 case QNativeSocketEngine::NonBlockingSocketOption:
277 case QNativeSocketEngine::BroadcastSocketOption:
279 case QNativeSocketEngine::MaxStreamsSocketOption: {
281 sctp_initmsg sctpInitMsg;
282 QT_SOCKOPTLEN_T sctpInitMsgSize =
sizeof(sctpInitMsg);
283 if (::getsockopt(socketDescriptor, SOL_SCTP, SCTP_INITMSG, &sctpInitMsg,
284 &sctpInitMsgSize) == 0)
285 return int(qMin(sctpInitMsg.sinit_num_ostreams, sctpInitMsg.sinit_max_instreams));
290 case QNativeSocketEngine::PathMtuInformation:
291#if defined(IPV6_PATHMTU
) && !defined(IPV6_MTU
)
294 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
296 QT_SOCKOPTLEN_T len =
sizeof(mtuinfo);
297 if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_PATHMTU, &mtuinfo, &len) == 0)
298 return int(mtuinfo.ip6m_mtu);
310 QT_SOCKOPTLEN_T len =
sizeof(v);
312 convertToLevelAndOption(opt, socketProtocol, level, n);
313 if (n != -1 && ::getsockopt(socketDescriptor, level, n, (
char *) &v, &len) != -1)
314 return len == 1 ? qFromUnaligned<quint8>(&v) : v;
325#ifdef QNATIVESOCKETENGINE_DEBUG
326# define perrorDebug(msg) perror("QNativeSocketEnginePrivate::setOption(): " msg)
328# define perrorDebug(msg) (void)0
330 Q_Q(QNativeSocketEngine);
336 case QNativeSocketEngine::NonBlockingSocketOption: {
338#if !defined(Q_OS_VXWORKS)
339 int flags = ::fcntl(socketDescriptor, F_GETFL, 0);
344 if (::fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) {
349 if (qt_safe_ioctl(socketDescriptor, FIONBIO, &v) < 0) {
350 perrorDebug(
"ioctl(FIONBIO, 1) failed");
356 case QNativeSocketEngine::BindExclusively:
359 case QNativeSocketEngine::ReceivePacketInformation:
360 if (socketProtocol == QAbstractSocket::IPv4Protocol) {
361#if !defined(IP_PKTINFO
) && defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
364 r += ::setsockopt(socketDescriptor, IPPROTO_IP, IP_RECVDSTADDR, &v,
sizeof(v));
365 r += ::setsockopt(socketDescriptor, IPPROTO_IP, IP_RECVIF, &v,
sizeof(v));
371 case QNativeSocketEngine::MaxStreamsSocketOption: {
373 sctp_initmsg sctpInitMsg;
374 QT_SOCKOPTLEN_T sctpInitMsgSize =
sizeof(sctpInitMsg);
375 if (::getsockopt(socketDescriptor, SOL_SCTP, SCTP_INITMSG, &sctpInitMsg,
376 &sctpInitMsgSize) == 0) {
377 sctpInitMsg.sinit_num_ostreams = sctpInitMsg.sinit_max_instreams = uint16_t(v);
378 return ::setsockopt(socketDescriptor, SOL_SCTP, SCTP_INITMSG, &sctpInitMsg,
379 sctpInitMsgSize) == 0;
384 case QNativeSocketEngine::BindInterfaceIndex: {
385#if defined(SO_BINDTOIFINDEX
)
386 return ::setsockopt(socketDescriptor, SOL_SOCKET, SO_BINDTOIFINDEX,
388#elif defined(IPV6_BOUND_IF) && defined(IP_BOUND_IF)
390 if (socketProtocol == QAbstractSocket::IPv6Protocol
391 || socketProtocol == QAbstractSocket::AnyIPProtocol) {
392 return ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_BOUND_IF, &v,
sizeof(v)) == 0;
394 return ::setsockopt(socketDescriptor, IPPROTO_IP, IP_BOUND_IF, &v,
sizeof(v)) == 0;
396#elif defined(SO_BINDTODEVICE) && QT_CONFIG(networkinterface)
398 const QByteArray name = QNetworkInterfaceManager::interfaceNameFromIndex(v).toLatin1();
399 return ::setsockopt(socketDescriptor, SOL_SOCKET, SO_BINDTODEVICE,
400 name.data(), socklen_t(name.size())) == 0;
410 convertToLevelAndOption(opt, socketProtocol, level, n);
411#if defined(SO_REUSEPORT
) && !defined(Q_OS_LINUX)
412 if (opt == QNativeSocketEngine::AddressReusable) {
416 if (socketType == QAbstractSocket::UdpSocket)
423 return ::setsockopt(socketDescriptor, level, n, (
char *) &v,
sizeof(v)) == 0;
429#ifdef QNATIVESOCKETENGINE_DEBUG
430 qDebug() <<
"QNativeSocketEnginePrivate::nativeConnect() " << socketDescriptor;
434 QT_SOCKLEN_T sockAddrSize;
435 setPortAndAddress(port, addr, &aa, &sockAddrSize);
437 int connectResult = qt_safe_connect(socketDescriptor, &aa.a, sockAddrSize);
438#if defined (QNATIVESOCKETENGINE_DEBUG)
441 if (connectResult == -1) {
444 socketState = QAbstractSocket::ConnectedState;
449 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
450 socketState = QAbstractSocket::UnconnectedState;
453 setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
456 setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
457 socketState = QAbstractSocket::UnconnectedState;
460 setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString);
461 socketState = QAbstractSocket::UnconnectedState;
464 setError(QAbstractSocket::NetworkError, AddressInuseErrorString);
468 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
469 socketState = QAbstractSocket::ConnectingState;
472 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
476 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
477 socketState = QAbstractSocket::UnconnectedState;
483 socketState = QAbstractSocket::UnconnectedState;
489 if (socketState != QAbstractSocket::ConnectedState) {
490#if defined (QNATIVESOCKETENGINE_DEBUG)
491 qDebug(
"QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
492 addr.toString().toLatin1().constData(), port,
493 socketState == QAbstractSocket::ConnectingState
494 ?
"Connection in progress" : strerror(ecopy));
500#if defined (QNATIVESOCKETENGINE_DEBUG)
501 qDebug(
"QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true",
502 addr.toString().toLatin1().constData(), port);
505 socketState = QAbstractSocket::ConnectedState;
512 QT_SOCKLEN_T sockAddrSize;
513 setPortAndAddress(port, address, &aa, &sockAddrSize);
518 if (address.protocol() == QAbstractSocket::IPv6Protocol)
521 ::setsockopt(socketDescriptor, IPPROTO_IPV6,
IPV6_V6ONLY, (
char*)&ipv6only,
sizeof(ipv6only) );
525 int bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
526 if (bindResult < 0 && errno == EAFNOSUPPORT && address.protocol() == QAbstractSocket::AnyIPProtocol) {
528 aa.a4.sin_family = AF_INET;
529 aa.a4.sin_port = htons(port);
530 aa.a4.sin_addr.s_addr = htonl(address.toIPv4Address());
531 sockAddrSize =
sizeof(aa.a4);
532 bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
535 if (bindResult < 0) {
536#if defined (QNATIVESOCKETENGINE_DEBUG)
541 setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
544 setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString);
547 setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString);
550 setError(QAbstractSocket::SocketAddressNotAvailableError, AddressNotAvailableErrorString);
556#if defined (QNATIVESOCKETENGINE_DEBUG)
557 qDebug(
"QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
558 address.toString().toLatin1().constData(), port, strerror(ecopy));
564#if defined (QNATIVESOCKETENGINE_DEBUG)
565 qDebug(
"QNativeSocketEnginePrivate::nativeBind(%s, %i) == true",
566 address.toString().toLatin1().constData(), port);
568 socketState = QAbstractSocket::BoundState;
604 int acceptedDescriptor = qt_safe_accept(socketDescriptor,
nullptr,
nullptr);
605 if (acceptedDescriptor == -1) {
609 setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidSocketErrorString);
612 setError(QAbstractSocket::NetworkError, RemoteHostClosedErrorString);
616 setError(QAbstractSocket::SocketResourceError, NotSocketErrorString);
618 case EPROTONOSUPPORT:
619#if !defined(Q_OS_OPENBSD)
624 setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
630 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
634 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
636#if EAGAIN
!= EWOULDBLOCK
640 setError(QAbstractSocket::TemporaryError, TemporaryErrorString);
643 setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString);
648 return qintptr(acceptedDescriptor);
656 const QHostAddress &groupAddress,
657 const QNetworkInterface &interface)
667 if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) {
668 level = IPPROTO_IPV6;
671 sockArgSize =
sizeof(mreq6);
672 memset(&mreq6, 0,
sizeof(mreq6));
673 Q_IPV6ADDR ip6 = groupAddress.toIPv6Address();
674 memcpy(&mreq6.ipv6mr_multiaddr, &ip6,
sizeof(ip6));
675 mreq6.ipv6mr_interface = interface.index();
676 }
else if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
680 sockArgSize =
sizeof(mreq4);
681 memset(&mreq4, 0,
sizeof(mreq4));
682 mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address());
684 if (interface.isValid()) {
685 const QList<QNetworkAddressEntry> addressEntries = interface.addressEntries();
687 for (
const QNetworkAddressEntry &entry : addressEntries) {
688 const QHostAddress ip = entry.ip();
689 if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
690 mreq4.imr_interface.s_addr = htonl(ip.toIPv4Address());
696 d->setError(QAbstractSocket::NetworkError,
697 QNativeSocketEnginePrivate::NetworkUnreachableErrorString);
701 mreq4.imr_interface.s_addr = INADDR_ANY;
705 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
706 QNativeSocketEnginePrivate::ProtocolUnsupportedErrorString);
710 int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize);
714 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
715 QNativeSocketEnginePrivate::OperationUnsupportedErrorString);
718 d->setError(QAbstractSocket::SocketAddressNotAvailableError,
719 QNativeSocketEnginePrivate::AddressNotAvailableErrorString);
722 d->setError(QAbstractSocket::UnknownSocketError,
723 QNativeSocketEnginePrivate::UnknownSocketErrorString);
753 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
755 QT_SOCKOPTLEN_T sizeofv =
sizeof(v);
756 if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, &sizeofv) == -1)
757 return QNetworkInterface();
758 return QNetworkInterface::interfaceFromIndex(v);
761#if defined(Q_OS_SOLARIS)
762 struct in_addr v = { 0, 0, 0, 0};
764 struct in_addr v = { 0 };
766 QT_SOCKOPTLEN_T sizeofv =
sizeof(v);
767 if (::getsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, &sizeofv) == -1)
768 return QNetworkInterface();
769 if (v.s_addr != 0 && sizeofv >= QT_SOCKOPTLEN_T(
sizeof(v))) {
770 QHostAddress ipv4(ntohl(v.s_addr));
771 QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
772 for (
int i = 0; i < ifaces.size(); ++i) {
773 const QNetworkInterface &iface = ifaces.at(i);
774 QList<QNetworkAddressEntry> entries = iface.addressEntries();
775 for (
int j = 0; j < entries.size(); ++j) {
776 const QNetworkAddressEntry &entry = entries.at(j);
777 if (entry.ip() == ipv4)
782 return QNetworkInterface();
787 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
788 uint v = iface.index();
789 return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v,
sizeof(v)) != -1);
793 if (iface.isValid()) {
794 QList<QNetworkAddressEntry> entries = iface.addressEntries();
795 for (
int i = 0; i < entries.size(); ++i) {
796 const QNetworkAddressEntry &entry = entries.at(i);
797 const QHostAddress &ip = entry.ip();
798 if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
799 v.s_addr = htonl(ip.toIPv4Address());
800 int r = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v,
sizeof(v));
808 v.s_addr = INADDR_ANY;
809 return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v,
sizeof(v)) != -1);
857 ssize_t recvResult = -1;
861 QT_EINTR_LOOP(recvResult, ::recv(socketDescriptor, &c, 1, MSG_PEEK | MSG_TRUNC));
862#elif defined(SO_NREAD)
865 socklen_t valuelen =
sizeof(value);
866 recvResult = getsockopt(socketDescriptor, SOL_SOCKET, SO_NREAD, &value, &valuelen);
867 if (recvResult != -1)
869#elif defined(Q_OS_VXWORKS)
872 int ioctlResult = ::ioctl(socketDescriptor, FIONREAD, &available);
873 if (ioctlResult != -1)
874 recvResult = available;
880 char udpMessagePeekBuffer[1500];
884 memset(&msg, 0,
sizeof(msg));
887 vec.iov_base = udpMessagePeekBuffer;
888 vec.iov_len =
sizeof(udpMessagePeekBuffer);
894 recvResult = ::recvmsg(socketDescriptor, &msg, MSG_PEEK);
895 if (recvResult == -1 && errno == EINTR)
899 if ((msg.msg_flags & MSG_TRUNC) == 0)
903 msg.msg_iovlen *= 16;
904 if (msg.msg_iov != &vec)
905 delete[] msg.msg_iov;
906 msg.msg_iov =
new struct iovec[msg.msg_iovlen];
907 std::fill_n(msg.msg_iov, msg.msg_iovlen, vec);
910 if (msg.msg_iov != &vec)
911 delete[] msg.msg_iov;
914#if defined (QNATIVESOCKETENGINE_DEBUG)
915 qDebug(
"QNativeSocketEnginePrivate::nativePendingDatagramSize() == %zd", recvResult);
918 return qint64(recvResult);
922 QAbstractSocketEngine::PacketHeaderOptions options)
925 quintptr cbuf[(CMSG_SPACE(
sizeof(
struct in6_pktinfo)) + CMSG_SPACE(
sizeof(
int))
926#if !defined(IP_PKTINFO
) && defined(IP_RECVIF) && defined(AF_LINK)
927 + CMSG_SPACE(
sizeof(sockaddr_dl))
930 + CMSG_SPACE(
sizeof(
struct sctp_sndrcvinfo))
932 +
sizeof(quintptr) - 1) /
sizeof(quintptr)];
938 memset(&msg, 0,
sizeof(msg));
939 memset(&aa, 0,
sizeof(aa));
942 vec.iov_base = maxSize ? data : &c;
943 vec.iov_len = maxSize ? maxSize : 1;
946 if (options & QAbstractSocketEngine::WantDatagramSender) {
948 msg.msg_namelen =
sizeof(aa);
950 if (options & (QAbstractSocketEngine::WantDatagramHopLimit | QAbstractSocketEngine::WantDatagramDestination
951 | QAbstractSocketEngine::WantStreamNumber)) {
952 msg.msg_control = cbuf;
953 msg.msg_controllen =
sizeof(cbuf);
956 ssize_t recvResult = 0;
958 recvResult = ::recvmsg(socketDescriptor, &msg, 0);
959 }
while (recvResult == -1 && errno == EINTR);
961 if (recvResult == -1) {
963#if defined(EWOULDBLOCK
) && EWOULDBLOCK
!= EAGAIN
971 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
974 setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
978 }
else if (options != QAbstractSocketEngine::WantNone) {
980 qt_socket_getPortAndAddress(&aa, &header->senderPort, &header->senderAddress);
981 header->destinationPort = localPort;
982 header->endOfRecord = (msg.msg_flags & MSG_EOR) != 0;
985 struct cmsghdr *cmsgptr;
987 QT_WARNING_DISABLE_CLANG(
"-Wsign-compare")
988 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr !=
nullptr;
989 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
991 if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO
992 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in6_pktinfo))) {
993 in6_pktinfo *info =
reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
995 header->destinationAddress.setAddress(
reinterpret_cast<quint8 *>(&info->ipi6_addr));
996 header->ifindex = info->ipi6_ifindex;
998 header->destinationAddress.setScopeId(QString::number(info->ipi6_ifindex));
1002 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO
1003 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in_pktinfo))) {
1004 in_pktinfo *info =
reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr));
1006 header->destinationAddress.setAddress(ntohl(info->ipi_addr.s_addr));
1007 header->ifindex = info->ipi_ifindex;
1010# ifdef IP_RECVDSTADDR
1011 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVDSTADDR
1012 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in_addr))) {
1013 in_addr *addr =
reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr));
1015 header->destinationAddress.setAddress(ntohl(addr->s_addr));
1018# if defined(IP_RECVIF) && defined(AF_LINK)
1019 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVIF
1020 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(sockaddr_dl))) {
1021 sockaddr_dl *sdl =
reinterpret_cast<sockaddr_dl *>(CMSG_DATA(cmsgptr));
1022 header->ifindex = sdl->sdl_index;
1027 if (cmsgptr->cmsg_len == CMSG_LEN(
sizeof(
int))
1028 && ((cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT)
1029 || (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TTL))) {
1030 static_assert(
sizeof(header->hopLimit) ==
sizeof(
int));
1031 memcpy(&header->hopLimit, CMSG_DATA(cmsgptr),
sizeof(header->hopLimit));
1035 if (cmsgptr->cmsg_level == IPPROTO_SCTP && cmsgptr->cmsg_type == SCTP_SNDRCV
1036 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(sctp_sndrcvinfo))) {
1037 sctp_sndrcvinfo *rcvInfo =
reinterpret_cast<sctp_sndrcvinfo *>(CMSG_DATA(cmsgptr));
1039 header->streamNumber =
int(rcvInfo->sinfo_stream);
1045#if defined (QNATIVESOCKETENGINE_DEBUG)
1046 qDebug(
"QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli",
1047 data, QtDebugUtils::toPrintable(data, recvResult, 16).constData(), maxSize,
1048 (recvResult != -1 && options != QAbstractSocketEngine::WantNone)
1049 ? header->senderAddress.toString().toLatin1().constData() :
"(unknown)",
1050 (recvResult != -1 && options != QAbstractSocketEngine::WantNone)
1051 ? header->senderPort : 0, (qint64) recvResult);
1054 return qint64((maxSize || recvResult < 0) ? recvResult : Q_INT64_C(0));
1060 quintptr cbuf[(CMSG_SPACE(
sizeof(
struct in6_pktinfo)) + CMSG_SPACE(
sizeof(
int))
1062 + CMSG_SPACE(
sizeof(
struct sctp_sndrcvinfo))
1064 +
sizeof(quintptr) - 1) /
sizeof(quintptr)];
1066 struct cmsghdr *cmsgptr =
reinterpret_cast<
struct cmsghdr *>(cbuf);
1071 memset(&msg, 0,
sizeof(msg));
1072 memset(&aa, 0,
sizeof(aa));
1073 vec.iov_base =
const_cast<
char *>(data);
1077 msg.msg_control = &cbuf;
1079 if (header.destinationPort != 0) {
1080 msg.msg_name = &aa.a;
1081 setPortAndAddress(header.destinationPort, header.destinationAddress,
1082 &aa, &msg.msg_namelen);
1085 if (msg.msg_namelen ==
sizeof(aa.a6)) {
1086 if (header.hopLimit != -1) {
1087 msg.msg_controllen += CMSG_SPACE(
sizeof(
int));
1088 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(
int));
1089 cmsgptr->cmsg_level = IPPROTO_IPV6;
1090 cmsgptr->cmsg_type = IPV6_HOPLIMIT;
1091 memcpy(CMSG_DATA(cmsgptr), &header.hopLimit,
sizeof(
int));
1092 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(
int)));
1094 if (header.ifindex != 0 || !header.senderAddress.isNull()) {
1095 struct in6_pktinfo *data =
reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
1096 memset(data, 0,
sizeof(*data));
1097 msg.msg_controllen += CMSG_SPACE(
sizeof(*data));
1098 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(*data));
1099 cmsgptr->cmsg_level = IPPROTO_IPV6;
1100 cmsgptr->cmsg_type = IPV6_PKTINFO;
1101 data->ipi6_ifindex = header.ifindex;
1103 QIPv6Address tmp = header.senderAddress.toIPv6Address();
1104 memcpy(&data->ipi6_addr, &tmp,
sizeof(tmp));
1105 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1108 if (header.hopLimit != -1) {
1109 msg.msg_controllen += CMSG_SPACE(
sizeof(
int));
1110 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(
int));
1111 cmsgptr->cmsg_level = IPPROTO_IP;
1112 cmsgptr->cmsg_type = IP_TTL;
1113 memcpy(CMSG_DATA(cmsgptr), &header.hopLimit,
sizeof(
int));
1114 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(
int)));
1117#if defined(IP_PKTINFO
) || defined(IP_SENDSRCADDR)
1118 if (header.ifindex != 0 || !header.senderAddress.isNull()) {
1120 struct in_pktinfo *data =
reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr));
1121 memset(data, 0,
sizeof(*data));
1122 cmsgptr->cmsg_type = IP_PKTINFO;
1123 data->ipi_ifindex = header.ifindex;
1124 data->ipi_addr.s_addr = htonl(header.senderAddress.toIPv4Address());
1125# elif defined(IP_SENDSRCADDR)
1126 struct in_addr *data =
reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr));
1127 cmsgptr->cmsg_type = IP_SENDSRCADDR;
1128 data->s_addr = htonl(header.senderAddress.toIPv4Address());
1130 cmsgptr->cmsg_level = IPPROTO_IP;
1131 msg.msg_controllen += CMSG_SPACE(
sizeof(*data));
1132 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(*data));
1133 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1139 if (header.streamNumber != -1) {
1140 struct sctp_sndrcvinfo *data =
reinterpret_cast<sctp_sndrcvinfo *>(CMSG_DATA(cmsgptr));
1141 memset(data, 0,
sizeof(*data));
1142 msg.msg_controllen += CMSG_SPACE(
sizeof(sctp_sndrcvinfo));
1143 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(sctp_sndrcvinfo));
1144 cmsgptr->cmsg_level = IPPROTO_SCTP;
1145 cmsgptr->cmsg_type = SCTP_SNDRCV;
1146 data->sinfo_stream = uint16_t(header.streamNumber);
1147 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1151 if (msg.msg_controllen == 0)
1152 msg.msg_control =
nullptr;
1153 ssize_t sentBytes = qt_safe_sendmsg(socketDescriptor, &msg, 0);
1155 if (sentBytes < 0) {
1157#if defined(EWOULDBLOCK
) && EWOULDBLOCK
!= EAGAIN
1164 setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
1167 setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString);
1170 setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
1174#if defined (QNATIVESOCKETENGINE_DEBUG)
1175 qDebug(
"QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data,
1176 QtDebugUtils::toPrintable(data, len, 16).constData(), len,
1177 header.destinationAddress.toString().toLatin1().constData(),
1178 header.destinationPort, (qint64) sentBytes);
1181 return qint64(sentBytes);
1187 localAddress.clear();
1189 peerAddress.clear();
1190 inboundStreamCount = outboundStreamCount = 0;
1192 if (socketDescriptor == -1)
1196 QT_SOCKLEN_T sockAddrSize =
sizeof(sa);
1199 memset(&sa, 0,
sizeof(sa));
1200 if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
1201 qt_socket_getPortAndAddress(&sa, &localPort, &localAddress);
1204 switch (sa.a.sa_family) {
1206 socketProtocol = QAbstractSocket::IPv4Protocol;
1209 socketProtocol = QAbstractSocket::IPv6Protocol;
1212 socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
1216 }
else if (errno == EBADF) {
1217 setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidSocketErrorString);
1227 socklen_t optlen =
sizeof(ipv6only);
1228 if (socketProtocol == QAbstractSocket::IPv6Protocol
1229 && (localAddress == QHostAddress::AnyIPv4 || localAddress == QHostAddress::AnyIPv6)
1230 && !getsockopt(socketDescriptor, IPPROTO_IPV6,
IPV6_V6ONLY, (
char*)&ipv6only, &optlen )) {
1231 if (optlen !=
sizeof(ipv6only))
1232 qWarning(
"unexpected size of IPV6_V6ONLY socket option");
1234 socketProtocol = QAbstractSocket::AnyIPProtocol;
1235 localAddress = QHostAddress::Any;
1241 bool connected = ::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0;
1243 qt_socket_getPortAndAddress(&sa, &peerPort, &peerAddress);
1244 inboundStreamCount = outboundStreamCount = 1;
1249 QT_SOCKOPTLEN_T valueSize =
sizeof(
int);
1250 if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, &value, &valueSize) == 0) {
1251 if (value == SOCK_STREAM) {
1252 socketType = QAbstractSocket::TcpSocket;
1254 if (option(QNativeSocketEngine::MaxStreamsSocketOption) != -1) {
1255 socketType = QAbstractSocket::SctpSocket;
1257 sctp_status sctpStatus;
1258 QT_SOCKOPTLEN_T sctpStatusSize =
sizeof(sctpStatus);
1259 sctp_event_subscribe sctpEvents;
1261 memset(&sctpEvents, 0,
sizeof(sctpEvents));
1262 sctpEvents.sctp_data_io_event = 1;
1263 if (::getsockopt(socketDescriptor, SOL_SCTP, SCTP_STATUS, &sctpStatus,
1264 &sctpStatusSize) == 0 &&
1265 ::setsockopt(socketDescriptor, SOL_SCTP, SCTP_EVENTS, &sctpEvents,
1266 sizeof(sctpEvents)) == 0) {
1267 inboundStreamCount =
int(sctpStatus.sstat_instrms);
1268 outboundStreamCount =
int(sctpStatus.sstat_outstrms);
1270 setError(QAbstractSocket::UnsupportedSocketOperationError,
1271 InvalidSocketErrorString);
1277 }
else if (value == SOCK_DGRAM) {
1278 socketType = QAbstractSocket::UdpSocket;
1279#ifdef SOCK_SEQPACKET
1280 }
else if (value == SOCK_SEQPACKET) {
1288 socketType = QAbstractSocket::TcpSocket;
1291 socketType = QAbstractSocket::UnknownSocketType;
1294#if defined (QNATIVESOCKETENGINE_DEBUG)
1295 QString socketProtocolStr = QStringLiteral(
"UnknownProtocol");
1296 if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = QStringLiteral(
"IPv4Protocol");
1297 else if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) socketProtocolStr = QStringLiteral(
"IPv6Protocol");
1299 QString socketTypeStr = QStringLiteral(
"UnknownSocketType");
1300 if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = QStringLiteral(
"TcpSocket");
1301 else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = QStringLiteral(
"UdpSocket");
1302 else if (socketType == QAbstractSocket::SctpSocket) socketTypeStr = QStringLiteral(
"SctpSocket");
1304 qDebug(
"QNativeSocketEnginePrivate::fetchConnectionParameters() local == %s:%i,"
1305 " peer == %s:%i, socket == %s - %s, inboundStreamCount == %i, outboundStreamCount == %i",
1306 localAddress.toString().toLatin1().constData(), localPort,
1307 peerAddress.toString().toLatin1().constData(), peerPort,socketTypeStr.toLatin1().constData(),
1308 socketProtocolStr.toLatin1().constData(), inboundStreamCount, outboundStreamCount);