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;
173 case QNativeSocketEngine::KeepAliveIdleOption:
181 case QNativeSocketEngine::KeepAliveIntervalOption:
187 case QNativeSocketEngine::KeepAliveCountOption:
202 QAbstractSocket::NetworkLayerProtocol &socketProtocol)
205 int protocol = (socketType == QAbstractSocket::SctpSocket) ? IPPROTO_SCTP : 0;
207 if (socketType == QAbstractSocket::SctpSocket) {
208 setError(QAbstractSocket::UnsupportedSocketOperationError,
209 ProtocolUnsupportedErrorString);
210#if defined (QNATIVESOCKETENGINE_DEBUG)
211 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d): unsupported protocol",
212 socketType, socketProtocol);
218 int domain = (socketProtocol == QAbstractSocket::IPv6Protocol
219 || socketProtocol == QAbstractSocket::AnyIPProtocol) ?
AF_INET6 : AF_INET;
220 int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
222 int socket = qt_safe_socket(domain, type, protocol, O_NONBLOCK);
223 if (socket < 0 && socketProtocol == QAbstractSocket::AnyIPProtocol && (errno == EAFNOSUPPORT || errno == ENOTSUP )) {
225 socket = qt_safe_socket(domain, type, protocol, O_NONBLOCK);
226 socketProtocol = QAbstractSocket::IPv4Protocol;
232 case EPROTONOSUPPORT:
235 setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
241 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
244 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
250#if defined (QNATIVESOCKETENGINE_DEBUG)
251 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d) == false (%s)",
252 socketType, socketProtocol,
261 const int ipv6only = 0;
262 [[maybe_unused]]
const int ret = ::setsockopt(socket, IPPROTO_IPV6,
IPV6_V6ONLY,
263 &ipv6only,
sizeof(ipv6only));
264#if defined (QNATIVESOCKETENGINE_DEBUG)
266 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d): "
267 "failed to set IPV6_V6ONLY to %d.",
268 socketType, socketProtocol, ipv6only);
273#if defined (QNATIVESOCKETENGINE_DEBUG)
274 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d) == true",
275 socketType, socketProtocol);
278 socketDescriptor = socket;
279 this->socketProtocol = socketProtocol;
280 this->socketType = socketType;
289 Q_Q(
const QNativeSocketEngine);
295 case QNativeSocketEngine::BindExclusively:
296 case QNativeSocketEngine::NonBlockingSocketOption:
297 case QNativeSocketEngine::BroadcastSocketOption:
299 case QNativeSocketEngine::MaxStreamsSocketOption: {
301 sctp_initmsg sctpInitMsg;
302 QT_SOCKOPTLEN_T sctpInitMsgSize =
sizeof(sctpInitMsg);
303 if (::getsockopt(socketDescriptor, SOL_SCTP, SCTP_INITMSG, &sctpInitMsg,
304 &sctpInitMsgSize) == 0)
305 return int(qMin(sctpInitMsg.sinit_num_ostreams, sctpInitMsg.sinit_max_instreams));
310 case QNativeSocketEngine::PathMtuInformation:
311#if defined(IPV6_PATHMTU
) && !defined(IPV6_MTU
)
314 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
316 QT_SOCKOPTLEN_T len =
sizeof(mtuinfo);
317 if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_PATHMTU, &mtuinfo, &len) == 0)
318 return int(mtuinfo.ip6m_mtu);
330 QT_SOCKOPTLEN_T len =
sizeof(v);
332 convertToLevelAndOption(opt, socketProtocol, level, n);
333 if (n != -1 && ::getsockopt(socketDescriptor, level, n, (
char *) &v, &len) != -1)
334 return len == 1 ? qFromUnaligned<quint8>(&v) : v;
345#ifdef QNATIVESOCKETENGINE_DEBUG
346# define perrorDebug(msg) perror("QNativeSocketEnginePrivate::setOption(): " msg)
348# define perrorDebug(msg) (void)0
350 Q_Q(QNativeSocketEngine);
356 case QNativeSocketEngine::NonBlockingSocketOption: {
358#if !defined(Q_OS_VXWORKS)
359 int flags = ::fcntl(socketDescriptor, F_GETFL, 0);
364 if (::fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) {
369 if (qt_safe_ioctl(socketDescriptor, FIONBIO, &v) < 0) {
370 perrorDebug(
"ioctl(FIONBIO, 1) failed");
376 case QNativeSocketEngine::BindExclusively:
379 case QNativeSocketEngine::ReceivePacketInformation:
380 if (socketProtocol == QAbstractSocket::IPv4Protocol) {
381#if !defined(IP_PKTINFO
) && defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
384 r += ::setsockopt(socketDescriptor, IPPROTO_IP, IP_RECVDSTADDR, &v,
sizeof(v));
385 r += ::setsockopt(socketDescriptor, IPPROTO_IP, IP_RECVIF, &v,
sizeof(v));
391 case QNativeSocketEngine::MaxStreamsSocketOption: {
393 sctp_initmsg sctpInitMsg;
394 QT_SOCKOPTLEN_T sctpInitMsgSize =
sizeof(sctpInitMsg);
395 if (::getsockopt(socketDescriptor, SOL_SCTP, SCTP_INITMSG, &sctpInitMsg,
396 &sctpInitMsgSize) == 0) {
397 sctpInitMsg.sinit_num_ostreams = sctpInitMsg.sinit_max_instreams = uint16_t(v);
398 return ::setsockopt(socketDescriptor, SOL_SCTP, SCTP_INITMSG, &sctpInitMsg,
399 sctpInitMsgSize) == 0;
404 case QNativeSocketEngine::BindInterfaceIndex: {
405#if defined(SO_BINDTOIFINDEX
)
406 return ::setsockopt(socketDescriptor, SOL_SOCKET, SO_BINDTOIFINDEX,
408#elif defined(IPV6_BOUND_IF) && defined(IP_BOUND_IF)
410 if (socketProtocol == QAbstractSocket::IPv6Protocol
411 || socketProtocol == QAbstractSocket::AnyIPProtocol) {
412 return ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_BOUND_IF, &v,
sizeof(v)) == 0;
414 return ::setsockopt(socketDescriptor, IPPROTO_IP, IP_BOUND_IF, &v,
sizeof(v)) == 0;
416#elif defined(SO_BINDTODEVICE) && QT_CONFIG(networkinterface)
418 const QByteArray name = QNetworkInterfaceManager::interfaceNameFromIndex(v).toLatin1();
419 return ::setsockopt(socketDescriptor, SOL_SOCKET, SO_BINDTODEVICE,
420 name.data(), socklen_t(name.size())) == 0;
430 convertToLevelAndOption(opt, socketProtocol, level, n);
431#if defined(SO_REUSEPORT
) && !defined(Q_OS_LINUX)
432 if (opt == QNativeSocketEngine::AddressReusable) {
436 if (socketType == QAbstractSocket::UdpSocket)
443 return ::setsockopt(socketDescriptor, level, n, (
char *) &v,
sizeof(v)) == 0;
449#ifdef QNATIVESOCKETENGINE_DEBUG
450 qDebug() <<
"QNativeSocketEnginePrivate::nativeConnect() " << socketDescriptor;
454 QT_SOCKLEN_T sockAddrSize;
455 setPortAndAddress(port, addr, &aa, &sockAddrSize);
457 int connectResult = qt_safe_connect(socketDescriptor, &aa.a, sockAddrSize);
458#if defined (QNATIVESOCKETENGINE_DEBUG)
461 if (connectResult == -1) {
464 socketState = QAbstractSocket::ConnectedState;
469 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
470 socketState = QAbstractSocket::UnconnectedState;
473 setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
476 setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
477 socketState = QAbstractSocket::UnconnectedState;
480 setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString);
481 socketState = QAbstractSocket::UnconnectedState;
484 setError(QAbstractSocket::NetworkError, AddressInuseErrorString);
488 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
489 socketState = QAbstractSocket::ConnectingState;
492 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
496 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
497 socketState = QAbstractSocket::UnconnectedState;
503 socketState = QAbstractSocket::UnconnectedState;
509 if (socketState != QAbstractSocket::ConnectedState) {
510#if defined (QNATIVESOCKETENGINE_DEBUG)
511 qDebug(
"QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
512 addr.toString().toLatin1().constData(), port,
513 socketState == QAbstractSocket::ConnectingState
514 ?
"Connection in progress" : strerror(ecopy));
520#if defined (QNATIVESOCKETENGINE_DEBUG)
521 qDebug(
"QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true",
522 addr.toString().toLatin1().constData(), port);
525 socketState = QAbstractSocket::ConnectedState;
532 QT_SOCKLEN_T sockAddrSize;
533 setPortAndAddress(port, address, &aa, &sockAddrSize);
538 if (address.protocol() == QAbstractSocket::IPv6Protocol)
541 ::setsockopt(socketDescriptor, IPPROTO_IPV6,
IPV6_V6ONLY, (
char*)&ipv6only,
sizeof(ipv6only) );
545 int bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
546 if (bindResult < 0 && errno == EAFNOSUPPORT && address.protocol() == QAbstractSocket::AnyIPProtocol) {
548 aa.a4.sin_family = AF_INET;
549 aa.a4.sin_port = htons(port);
550 aa.a4.sin_addr.s_addr = htonl(address.toIPv4Address());
551 sockAddrSize =
sizeof(aa.a4);
552 bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
555 if (bindResult < 0) {
556#if defined (QNATIVESOCKETENGINE_DEBUG)
561 setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
564 setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString);
567 setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString);
570 setError(QAbstractSocket::SocketAddressNotAvailableError, AddressNotAvailableErrorString);
576#if defined (QNATIVESOCKETENGINE_DEBUG)
577 qDebug(
"QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
578 address.toString().toLatin1().constData(), port, strerror(ecopy));
584#if defined (QNATIVESOCKETENGINE_DEBUG)
585 qDebug(
"QNativeSocketEnginePrivate::nativeBind(%s, %i) == true",
586 address.toString().toLatin1().constData(), port);
588 socketState = QAbstractSocket::BoundState;
624 int acceptedDescriptor = qt_safe_accept(socketDescriptor,
nullptr,
nullptr);
625 if (acceptedDescriptor == -1) {
629 setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidSocketErrorString);
632 setError(QAbstractSocket::NetworkError, RemoteHostClosedErrorString);
636 setError(QAbstractSocket::SocketResourceError, NotSocketErrorString);
638 case EPROTONOSUPPORT:
639#if !defined(Q_OS_OPENBSD)
644 setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
650 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
654 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
656#if EAGAIN
!= EWOULDBLOCK
660 setError(QAbstractSocket::TemporaryError, TemporaryErrorString);
663 setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString);
668 return qintptr(acceptedDescriptor);
676 const QHostAddress &groupAddress,
677 const QNetworkInterface &interface)
687 if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) {
688 level = IPPROTO_IPV6;
691 sockArgSize =
sizeof(mreq6);
692 memset(&mreq6, 0,
sizeof(mreq6));
693 Q_IPV6ADDR ip6 = groupAddress.toIPv6Address();
694 memcpy(&mreq6.ipv6mr_multiaddr, &ip6,
sizeof(ip6));
695 mreq6.ipv6mr_interface = interface.index();
696 }
else if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
700 sockArgSize =
sizeof(mreq4);
701 memset(&mreq4, 0,
sizeof(mreq4));
702 mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address());
704 if (interface.isValid()) {
705 const QList<QNetworkAddressEntry> addressEntries = interface.addressEntries();
707 for (
const QNetworkAddressEntry &entry : addressEntries) {
708 const QHostAddress ip = entry.ip();
709 if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
710 mreq4.imr_interface.s_addr = htonl(ip.toIPv4Address());
716 d->setError(QAbstractSocket::NetworkError,
721 mreq4.imr_interface.s_addr = INADDR_ANY;
725 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
730 int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize);
734 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
738 d->setError(QAbstractSocket::SocketAddressNotAvailableError,
742 d->setError(QAbstractSocket::UnknownSocketError,
773 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
775 QT_SOCKOPTLEN_T sizeofv =
sizeof(v);
776 if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, &sizeofv) == -1)
777 return QNetworkInterface();
778 return QNetworkInterface::interfaceFromIndex(v);
781#if defined(Q_OS_SOLARIS)
782 struct in_addr v = { 0, 0, 0, 0};
784 struct in_addr v = { 0 };
786 QT_SOCKOPTLEN_T sizeofv =
sizeof(v);
787 if (::getsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, &sizeofv) == -1)
788 return QNetworkInterface();
789 if (v.s_addr != 0 && sizeofv >= QT_SOCKOPTLEN_T(
sizeof(v))) {
790 QHostAddress ipv4(ntohl(v.s_addr));
791 QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
792 for (
int i = 0; i < ifaces.size(); ++i) {
793 const QNetworkInterface &iface = ifaces.at(i);
794 QList<QNetworkAddressEntry> entries = iface.addressEntries();
795 for (
int j = 0; j < entries.size(); ++j) {
796 const QNetworkAddressEntry &entry = entries.at(j);
797 if (entry.ip() == ipv4)
802 return QNetworkInterface();
807 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
808 uint v = iface.index();
809 return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v,
sizeof(v)) != -1);
813 if (iface.isValid()) {
814 QList<QNetworkAddressEntry> entries = iface.addressEntries();
815 for (
int i = 0; i < entries.size(); ++i) {
816 const QNetworkAddressEntry &entry = entries.at(i);
817 const QHostAddress &ip = entry.ip();
818 if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
819 v.s_addr = htonl(ip.toIPv4Address());
820 int r = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v,
sizeof(v));
828 v.s_addr = INADDR_ANY;
829 return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v,
sizeof(v)) != -1);
877 ssize_t recvResult = -1;
881 QT_EINTR_LOOP(recvResult, ::recv(socketDescriptor, &c, 1, MSG_PEEK | MSG_TRUNC));
882#elif defined(SO_NREAD)
885 socklen_t valuelen =
sizeof(value);
886 recvResult = getsockopt(socketDescriptor, SOL_SOCKET, SO_NREAD, &value, &valuelen);
887 if (recvResult != -1)
889#elif defined(Q_OS_VXWORKS)
892 int ioctlResult = ::ioctl(socketDescriptor, FIONREAD, &available);
893 if (ioctlResult != -1)
894 recvResult = available;
900 char udpMessagePeekBuffer[1500];
904 memset(&msg, 0,
sizeof(msg));
907 vec.iov_base = udpMessagePeekBuffer;
908 vec.iov_len =
sizeof(udpMessagePeekBuffer);
914 recvResult = ::recvmsg(socketDescriptor, &msg, MSG_PEEK);
915 if (recvResult == -1 && errno == EINTR)
919 if ((msg.msg_flags & MSG_TRUNC) == 0)
923 msg.msg_iovlen *= 16;
924 if (msg.msg_iov != &vec)
925 delete[] msg.msg_iov;
926 msg.msg_iov =
new struct iovec[msg.msg_iovlen];
927 std::fill_n(msg.msg_iov, msg.msg_iovlen, vec);
930 if (msg.msg_iov != &vec)
931 delete[] msg.msg_iov;
934#if defined (QNATIVESOCKETENGINE_DEBUG)
935 qDebug(
"QNativeSocketEnginePrivate::nativePendingDatagramSize() == %zd", recvResult);
938 return qint64(recvResult);
942 QAbstractSocketEngine::PacketHeaderOptions options)
945 quintptr cbuf[(CMSG_SPACE(
sizeof(
struct in6_pktinfo)) + CMSG_SPACE(
sizeof(
int))
946#if !defined(IP_PKTINFO
) && defined(IP_RECVIF) && defined(AF_LINK)
947 + CMSG_SPACE(
sizeof(sockaddr_dl))
950 + CMSG_SPACE(
sizeof(
struct sctp_sndrcvinfo))
952 +
sizeof(quintptr) - 1) /
sizeof(quintptr)];
958 memset(&msg, 0,
sizeof(msg));
959 memset(&aa, 0,
sizeof(aa));
962 vec.iov_base = maxSize ? data : &c;
963 vec.iov_len = maxSize ? maxSize : 1;
966 if (options & QAbstractSocketEngine::WantDatagramSender) {
968 msg.msg_namelen =
sizeof(aa);
970 if (options & (QAbstractSocketEngine::WantDatagramHopLimit | QAbstractSocketEngine::WantDatagramDestination
971 | QAbstractSocketEngine::WantStreamNumber)) {
972 msg.msg_control = cbuf;
973 msg.msg_controllen =
sizeof(cbuf);
976 ssize_t recvResult = 0;
978 recvResult = ::recvmsg(socketDescriptor, &msg, 0);
979 }
while (recvResult == -1 && errno == EINTR);
981 if (recvResult == -1) {
983#if defined(EWOULDBLOCK
) && EWOULDBLOCK
!= EAGAIN
991 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
994 setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
998 }
else if (options != QAbstractSocketEngine::WantNone) {
1000 qt_socket_getPortAndAddress(&aa, &header->senderPort, &header->senderAddress);
1001 header->destinationPort = localPort;
1002 header->endOfRecord = (msg.msg_flags & MSG_EOR) != 0;
1005 struct cmsghdr *cmsgptr;
1007 QT_WARNING_DISABLE_CLANG(
"-Wsign-compare")
1008 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr !=
nullptr;
1009 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
1011 if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO
1012 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in6_pktinfo))) {
1013 in6_pktinfo *info =
reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
1015 header->destinationAddress.setAddress(
reinterpret_cast<quint8 *>(&info->ipi6_addr));
1016 header->ifindex = info->ipi6_ifindex;
1017 if (header->ifindex)
1018 header->destinationAddress.setScopeId(QString::number(info->ipi6_ifindex));
1022 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO
1023 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in_pktinfo))) {
1024 in_pktinfo *info =
reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr));
1026 header->destinationAddress.setAddress(ntohl(info->ipi_addr.s_addr));
1027 header->ifindex = info->ipi_ifindex;
1030# ifdef IP_RECVDSTADDR
1031 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVDSTADDR
1032 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in_addr))) {
1033 in_addr *addr =
reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr));
1035 header->destinationAddress.setAddress(ntohl(addr->s_addr));
1038# if defined(IP_RECVIF) && defined(AF_LINK)
1039 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVIF
1040 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(sockaddr_dl))) {
1041 sockaddr_dl *sdl =
reinterpret_cast<sockaddr_dl *>(CMSG_DATA(cmsgptr));
1042 header->ifindex = sdl->sdl_index;
1047 if (cmsgptr->cmsg_len == CMSG_LEN(
sizeof(
int))
1048 && ((cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT)
1049 || (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TTL))) {
1050 static_assert(
sizeof(header->hopLimit) ==
sizeof(
int));
1051 memcpy(&header->hopLimit, CMSG_DATA(cmsgptr),
sizeof(header->hopLimit));
1055 if (cmsgptr->cmsg_level == IPPROTO_SCTP && cmsgptr->cmsg_type == SCTP_SNDRCV
1056 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(sctp_sndrcvinfo))) {
1057 sctp_sndrcvinfo *rcvInfo =
reinterpret_cast<sctp_sndrcvinfo *>(CMSG_DATA(cmsgptr));
1059 header->streamNumber =
int(rcvInfo->sinfo_stream);
1065#if defined (QNATIVESOCKETENGINE_DEBUG)
1066 qDebug(
"QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli",
1067 data, QtDebugUtils::toPrintable(data, recvResult, 16).constData(), maxSize,
1068 (recvResult != -1 && options != QAbstractSocketEngine::WantNone)
1069 ? header->senderAddress.toString().toLatin1().constData() :
"(unknown)",
1070 (recvResult != -1 && options != QAbstractSocketEngine::WantNone)
1071 ? header->senderPort : 0, (qint64) recvResult);
1074 return qint64((maxSize || recvResult < 0) ? recvResult : Q_INT64_C(0));
1080 quintptr cbuf[(CMSG_SPACE(
sizeof(
struct in6_pktinfo)) + CMSG_SPACE(
sizeof(
int))
1082 + CMSG_SPACE(
sizeof(
struct sctp_sndrcvinfo))
1084 +
sizeof(quintptr) - 1) /
sizeof(quintptr)];
1086 struct cmsghdr *cmsgptr =
reinterpret_cast<
struct cmsghdr *>(cbuf);
1091 memset(&msg, 0,
sizeof(msg));
1092 memset(&aa, 0,
sizeof(aa));
1093 vec.iov_base =
const_cast<
char *>(data);
1097 msg.msg_control = &cbuf;
1099 if (header.destinationPort != 0) {
1100 msg.msg_name = &aa.a;
1101 setPortAndAddress(header.destinationPort, header.destinationAddress,
1102 &aa, &msg.msg_namelen);
1105 if (msg.msg_namelen ==
sizeof(aa.a6)) {
1106 if (header.hopLimit != -1) {
1107 msg.msg_controllen += CMSG_SPACE(
sizeof(
int));
1108 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(
int));
1109 cmsgptr->cmsg_level = IPPROTO_IPV6;
1110 cmsgptr->cmsg_type = IPV6_HOPLIMIT;
1111 memcpy(CMSG_DATA(cmsgptr), &header.hopLimit,
sizeof(
int));
1112 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(
int)));
1114 if (header.ifindex != 0 || !header.senderAddress.isNull()) {
1115 struct in6_pktinfo *data =
reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
1116 memset(data, 0,
sizeof(*data));
1117 msg.msg_controllen += CMSG_SPACE(
sizeof(*data));
1118 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(*data));
1119 cmsgptr->cmsg_level = IPPROTO_IPV6;
1120 cmsgptr->cmsg_type = IPV6_PKTINFO;
1121 data->ipi6_ifindex = header.ifindex;
1123 QIPv6Address tmp = header.senderAddress.toIPv6Address();
1124 memcpy(&data->ipi6_addr, &tmp,
sizeof(tmp));
1125 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1128 if (header.hopLimit != -1) {
1129 msg.msg_controllen += CMSG_SPACE(
sizeof(
int));
1130 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(
int));
1131 cmsgptr->cmsg_level = IPPROTO_IP;
1132 cmsgptr->cmsg_type = IP_TTL;
1133 memcpy(CMSG_DATA(cmsgptr), &header.hopLimit,
sizeof(
int));
1134 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(
int)));
1137#if defined(IP_PKTINFO
) || defined(IP_SENDSRCADDR)
1138 if (header.ifindex != 0 || !header.senderAddress.isNull()) {
1140 struct in_pktinfo *data =
reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr));
1141 memset(data, 0,
sizeof(*data));
1142 cmsgptr->cmsg_type = IP_PKTINFO;
1143 data->ipi_ifindex = header.ifindex;
1144 data->ipi_addr.s_addr = htonl(header.senderAddress.toIPv4Address());
1145# elif defined(IP_SENDSRCADDR)
1146 struct in_addr *data =
reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr));
1147 cmsgptr->cmsg_type = IP_SENDSRCADDR;
1148 data->s_addr = htonl(header.senderAddress.toIPv4Address());
1150 cmsgptr->cmsg_level = IPPROTO_IP;
1151 msg.msg_controllen += CMSG_SPACE(
sizeof(*data));
1152 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(*data));
1153 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1159 if (header.streamNumber != -1) {
1160 struct sctp_sndrcvinfo *data =
reinterpret_cast<sctp_sndrcvinfo *>(CMSG_DATA(cmsgptr));
1161 memset(data, 0,
sizeof(*data));
1162 msg.msg_controllen += CMSG_SPACE(
sizeof(sctp_sndrcvinfo));
1163 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(sctp_sndrcvinfo));
1164 cmsgptr->cmsg_level = IPPROTO_SCTP;
1165 cmsgptr->cmsg_type = SCTP_SNDRCV;
1166 data->sinfo_stream = uint16_t(header.streamNumber);
1167 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1171 if (msg.msg_controllen == 0)
1172 msg.msg_control =
nullptr;
1173 ssize_t sentBytes = qt_safe_sendmsg(socketDescriptor, &msg, 0);
1175 if (sentBytes < 0) {
1177#if defined(EWOULDBLOCK
) && EWOULDBLOCK
!= EAGAIN
1186 setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
1189 setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString);
1192 setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
1196#if defined (QNATIVESOCKETENGINE_DEBUG)
1197 qDebug(
"QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data,
1198 QtDebugUtils::toPrintable(data, len, 16).constData(), len,
1199 header.destinationAddress.toString().toLatin1().constData(),
1200 header.destinationPort, (qint64) sentBytes);
1203 return qint64(sentBytes);
1209 localAddress.clear();
1211 peerAddress.clear();
1212 inboundStreamCount = outboundStreamCount = 0;
1214 if (socketDescriptor == -1)
1218 QT_SOCKLEN_T sockAddrSize =
sizeof(sa);
1221 memset(&sa, 0,
sizeof(sa));
1222 if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
1223 qt_socket_getPortAndAddress(&sa, &localPort, &localAddress);
1226 switch (sa.a.sa_family) {
1228 socketProtocol = QAbstractSocket::IPv4Protocol;
1231 socketProtocol = QAbstractSocket::IPv6Protocol;
1234 socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
1238 }
else if (errno == EBADF) {
1239 setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidSocketErrorString);
1249 socklen_t optlen =
sizeof(ipv6only);
1250 if (socketProtocol == QAbstractSocket::IPv6Protocol
1251 && (localAddress == QHostAddress::AnyIPv4 || localAddress == QHostAddress::AnyIPv6)
1252 && !getsockopt(socketDescriptor, IPPROTO_IPV6,
IPV6_V6ONLY, (
char*)&ipv6only, &optlen )) {
1253 if (optlen !=
sizeof(ipv6only))
1254 qWarning(
"unexpected size of IPV6_V6ONLY socket option");
1256 socketProtocol = QAbstractSocket::AnyIPProtocol;
1257 localAddress = QHostAddress::Any;
1263 bool connected = ::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0;
1265 qt_socket_getPortAndAddress(&sa, &peerPort, &peerAddress);
1266 inboundStreamCount = outboundStreamCount = 1;
1271 QT_SOCKOPTLEN_T valueSize =
sizeof(
int);
1272 if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, &value, &valueSize) == 0) {
1273 if (value == SOCK_STREAM) {
1274 socketType = QAbstractSocket::TcpSocket;
1276 if (option(QNativeSocketEngine::MaxStreamsSocketOption) != -1) {
1277 socketType = QAbstractSocket::SctpSocket;
1279 sctp_status sctpStatus;
1280 QT_SOCKOPTLEN_T sctpStatusSize =
sizeof(sctpStatus);
1281 sctp_event_subscribe sctpEvents;
1283 memset(&sctpEvents, 0,
sizeof(sctpEvents));
1284 sctpEvents.sctp_data_io_event = 1;
1285 if (::getsockopt(socketDescriptor, SOL_SCTP, SCTP_STATUS, &sctpStatus,
1286 &sctpStatusSize) == 0 &&
1287 ::setsockopt(socketDescriptor, SOL_SCTP, SCTP_EVENTS, &sctpEvents,
1288 sizeof(sctpEvents)) == 0) {
1289 inboundStreamCount =
int(sctpStatus.sstat_instrms);
1290 outboundStreamCount =
int(sctpStatus.sstat_outstrms);
1292 setError(QAbstractSocket::UnsupportedSocketOperationError,
1293 InvalidSocketErrorString);
1299 }
else if (value == SOCK_DGRAM) {
1300 socketType = QAbstractSocket::UdpSocket;
1301#ifdef SOCK_SEQPACKET
1302 }
else if (value == SOCK_SEQPACKET) {
1310 socketType = QAbstractSocket::TcpSocket;
1313 socketType = QAbstractSocket::UnknownSocketType;
1316#if defined (QNATIVESOCKETENGINE_DEBUG)
1317 QString socketProtocolStr = QStringLiteral(
"UnknownProtocol");
1318 if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = QStringLiteral(
"IPv4Protocol");
1319 else if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) socketProtocolStr = QStringLiteral(
"IPv6Protocol");
1321 QString socketTypeStr = QStringLiteral(
"UnknownSocketType");
1322 if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = QStringLiteral(
"TcpSocket");
1323 else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = QStringLiteral(
"UdpSocket");
1324 else if (socketType == QAbstractSocket::SctpSocket) socketTypeStr = QStringLiteral(
"SctpSocket");
1326 qDebug(
"QNativeSocketEnginePrivate::fetchConnectionParameters() local == %s:%i,"
1327 " peer == %s:%i, socket == %s - %s, inboundStreamCount == %i, outboundStreamCount == %i",
1328 localAddress.toString().toLatin1().constData(), localPort,
1329 peerAddress.toString().toLatin1().constData(), peerPort,socketTypeStr.toLatin1().constData(),
1330 socketProtocolStr.toLatin1().constData(), inboundStreamCount, outboundStreamCount);