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 if (socketState == QAbstractSocket::ConnectingState) {
458 socklen_t len =
sizeof(socketError);
459 if (getsockopt(
int(socketDescriptor), SOL_SOCKET, SO_ERROR, &socketError, &len) != 0) {
465 int connectResult = -1;
466 if (socketError == 0) {
468 QT_SOCKLEN_T sockAddrSize;
469 setPortAndAddress(port, addr, &aa, &sockAddrSize);
471 connectResult = qt_safe_connect(socketDescriptor, &aa.a, sockAddrSize);
474 if (connectResult == -1) {
475 switch (socketError) {
477 socketState = QAbstractSocket::ConnectedState;
482 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
483 socketState = QAbstractSocket::UnconnectedState;
486 setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
489 setError(QAbstractSocket::NetworkError, HostUnreachableErrorString);
490 socketState = QAbstractSocket::UnconnectedState;
493 setError(QAbstractSocket::NetworkError, NetworkUnreachableErrorString);
494 socketState = QAbstractSocket::UnconnectedState;
497 setError(QAbstractSocket::NetworkError, AddressInuseErrorString);
501 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
502 socketState = QAbstractSocket::ConnectingState;
505 setError(QAbstractSocket::UnfinishedSocketOperationError, InvalidSocketErrorString);
509 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
510 socketState = QAbstractSocket::UnconnectedState;
516 socketState = QAbstractSocket::UnconnectedState;
522 if (socketState != QAbstractSocket::ConnectedState) {
523#if defined (QNATIVESOCKETENGINE_DEBUG)
524 qDebug(
"QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
525 addr.toString().toLatin1().constData(), port,
526 socketState == QAbstractSocket::ConnectingState
527 ?
"Connection in progress" : strerror(socketError));
533#if defined (QNATIVESOCKETENGINE_DEBUG)
534 qDebug(
"QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true",
535 addr.toString().toLatin1().constData(), port);
538 socketState = QAbstractSocket::ConnectedState;
545 QT_SOCKLEN_T sockAddrSize;
546 setPortAndAddress(port, address, &aa, &sockAddrSize);
551 if (address.protocol() == QAbstractSocket::IPv6Protocol)
554 ::setsockopt(socketDescriptor, IPPROTO_IPV6,
IPV6_V6ONLY, (
char*)&ipv6only,
sizeof(ipv6only) );
558 int bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
559 if (bindResult < 0 && errno == EAFNOSUPPORT && address.protocol() == QAbstractSocket::AnyIPProtocol) {
561 aa.a4.sin_family = AF_INET;
562 aa.a4.sin_port = htons(port);
563 aa.a4.sin_addr.s_addr = htonl(address.toIPv4Address());
564 sockAddrSize =
sizeof(aa.a4);
565 bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
568 if (bindResult < 0) {
569#if defined (QNATIVESOCKETENGINE_DEBUG)
574 setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
577 setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString);
580 setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString);
583 setError(QAbstractSocket::SocketAddressNotAvailableError, AddressNotAvailableErrorString);
589#if defined (QNATIVESOCKETENGINE_DEBUG)
590 qDebug(
"QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
591 address.toString().toLatin1().constData(), port, strerror(ecopy));
597#if defined (QNATIVESOCKETENGINE_DEBUG)
598 qDebug(
"QNativeSocketEnginePrivate::nativeBind(%s, %i) == true",
599 address.toString().toLatin1().constData(), port);
601 socketState = QAbstractSocket::BoundState;
637 int acceptedDescriptor = qt_safe_accept(socketDescriptor,
nullptr,
nullptr);
638 if (acceptedDescriptor == -1) {
642 setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidSocketErrorString);
645 setError(QAbstractSocket::NetworkError, RemoteHostClosedErrorString);
649 setError(QAbstractSocket::SocketResourceError, NotSocketErrorString);
651 case EPROTONOSUPPORT:
652#if !defined(Q_OS_OPENBSD)
657 setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
663 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
667 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
669#if EAGAIN
!= EWOULDBLOCK
673 setError(QAbstractSocket::TemporaryError, TemporaryErrorString);
676 setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString);
681 return qintptr(acceptedDescriptor);
689 const QHostAddress &groupAddress,
690 const QNetworkInterface &interface)
700 if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) {
701 level = IPPROTO_IPV6;
704 sockArgSize =
sizeof(mreq6);
705 memset(&mreq6, 0,
sizeof(mreq6));
706 Q_IPV6ADDR ip6 = groupAddress.toIPv6Address();
707 memcpy(&mreq6.ipv6mr_multiaddr, &ip6,
sizeof(ip6));
708 mreq6.ipv6mr_interface = interface.index();
709 }
else if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
713 sockArgSize =
sizeof(mreq4);
714 memset(&mreq4, 0,
sizeof(mreq4));
715 mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address());
717 if (interface.isValid()) {
718 const QList<QNetworkAddressEntry> addressEntries = interface.addressEntries();
720 for (
const QNetworkAddressEntry &entry : addressEntries) {
721 const QHostAddress ip = entry.ip();
722 if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
723 mreq4.imr_interface.s_addr = htonl(ip.toIPv4Address());
729 d->setError(QAbstractSocket::NetworkError,
734 mreq4.imr_interface.s_addr = INADDR_ANY;
738 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
743 int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize);
747 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
751 d->setError(QAbstractSocket::SocketAddressNotAvailableError,
755 d->setError(QAbstractSocket::UnknownSocketError,
786 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
788 QT_SOCKOPTLEN_T sizeofv =
sizeof(v);
789 if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, &sizeofv) == -1)
790 return QNetworkInterface();
791 return QNetworkInterface::interfaceFromIndex(v);
794#if defined(Q_OS_SOLARIS)
795 struct in_addr v = { 0, 0, 0, 0};
797 struct in_addr v = { 0 };
799 QT_SOCKOPTLEN_T sizeofv =
sizeof(v);
800 if (::getsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, &sizeofv) == -1)
801 return QNetworkInterface();
802 if (v.s_addr != 0 && sizeofv >= QT_SOCKOPTLEN_T(
sizeof(v))) {
803 QHostAddress ipv4(ntohl(v.s_addr));
804 QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
805 for (
int i = 0; i < ifaces.size(); ++i) {
806 const QNetworkInterface &iface = ifaces.at(i);
807 QList<QNetworkAddressEntry> entries = iface.addressEntries();
808 for (
int j = 0; j < entries.size(); ++j) {
809 const QNetworkAddressEntry &entry = entries.at(j);
810 if (entry.ip() == ipv4)
815 return QNetworkInterface();
820 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
821 uint v = iface.index();
822 return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v,
sizeof(v)) != -1);
826 if (iface.isValid()) {
827 QList<QNetworkAddressEntry> entries = iface.addressEntries();
828 for (
int i = 0; i < entries.size(); ++i) {
829 const QNetworkAddressEntry &entry = entries.at(i);
830 const QHostAddress &ip = entry.ip();
831 if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
832 v.s_addr = htonl(ip.toIPv4Address());
833 int r = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v,
sizeof(v));
841 v.s_addr = INADDR_ANY;
842 return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v,
sizeof(v)) != -1);
890 ssize_t recvResult = -1;
894 QT_EINTR_LOOP(recvResult, ::recv(socketDescriptor, &c, 1, MSG_PEEK | MSG_TRUNC));
895#elif defined(SO_NREAD)
898 socklen_t valuelen =
sizeof(value);
899 recvResult = getsockopt(socketDescriptor, SOL_SOCKET, SO_NREAD, &value, &valuelen);
900 if (recvResult != -1)
902#elif defined(Q_OS_VXWORKS)
905 int ioctlResult = ::ioctl(socketDescriptor, FIONREAD, &available);
906 if (ioctlResult != -1)
907 recvResult = available;
913 char udpMessagePeekBuffer[1500];
917 memset(&msg, 0,
sizeof(msg));
920 vec.iov_base = udpMessagePeekBuffer;
921 vec.iov_len =
sizeof(udpMessagePeekBuffer);
927 recvResult = ::recvmsg(socketDescriptor, &msg, MSG_PEEK);
928 if (recvResult == -1 && errno == EINTR)
932 if ((msg.msg_flags & MSG_TRUNC) == 0)
936 msg.msg_iovlen *= 16;
937 if (msg.msg_iov != &vec)
938 delete[] msg.msg_iov;
939 msg.msg_iov =
new struct iovec[msg.msg_iovlen];
940 std::fill_n(msg.msg_iov, msg.msg_iovlen, vec);
943 if (msg.msg_iov != &vec)
944 delete[] msg.msg_iov;
947#if defined (QNATIVESOCKETENGINE_DEBUG)
948 qDebug(
"QNativeSocketEnginePrivate::nativePendingDatagramSize() == %zd", recvResult);
951 return qint64(recvResult);
955 QAbstractSocketEngine::PacketHeaderOptions options)
958 quintptr cbuf[(CMSG_SPACE(
sizeof(
struct in6_pktinfo)) + CMSG_SPACE(
sizeof(
int))
959#if !defined(IP_PKTINFO
) && defined(IP_RECVIF) && defined(AF_LINK)
960 + CMSG_SPACE(
sizeof(sockaddr_dl))
963 + CMSG_SPACE(
sizeof(
struct sctp_sndrcvinfo))
965 +
sizeof(quintptr) - 1) /
sizeof(quintptr)];
971 memset(&msg, 0,
sizeof(msg));
972 memset(&aa, 0,
sizeof(aa));
975 vec.iov_base = maxSize ? data : &c;
976 vec.iov_len = maxSize ? maxSize : 1;
979 if (options & QAbstractSocketEngine::WantDatagramSender) {
981 msg.msg_namelen =
sizeof(aa);
983 if (options & (QAbstractSocketEngine::WantDatagramHopLimit | QAbstractSocketEngine::WantDatagramDestination
984 | QAbstractSocketEngine::WantStreamNumber)) {
985 msg.msg_control = cbuf;
986 msg.msg_controllen =
sizeof(cbuf);
989 ssize_t recvResult = 0;
991 recvResult = ::recvmsg(socketDescriptor, &msg, 0);
992 }
while (recvResult == -1 && errno == EINTR);
994 if (recvResult == -1) {
996#if defined(EWOULDBLOCK
) && EWOULDBLOCK
!= EAGAIN
1004 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
1007 setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
1011 }
else if (options != QAbstractSocketEngine::WantNone) {
1013 qt_socket_getPortAndAddress(&aa, &header->senderPort, &header->senderAddress);
1014 header->destinationPort = localPort;
1015 header->endOfRecord = (msg.msg_flags & MSG_EOR) != 0;
1018 struct cmsghdr *cmsgptr;
1020 QT_WARNING_DISABLE_CLANG(
"-Wsign-compare")
1021 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr !=
nullptr;
1022 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
1024 if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO
1025 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in6_pktinfo))) {
1026 in6_pktinfo *info =
reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
1028 header->destinationAddress.setAddress(
reinterpret_cast<quint8 *>(&info->ipi6_addr));
1029 header->ifindex = info->ipi6_ifindex;
1030 if (header->ifindex)
1031 header->destinationAddress.setScopeId(QString::number(info->ipi6_ifindex));
1035 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO
1036 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in_pktinfo))) {
1037 in_pktinfo *info =
reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr));
1039 header->destinationAddress.setAddress(ntohl(info->ipi_addr.s_addr));
1040 header->ifindex = info->ipi_ifindex;
1043# ifdef IP_RECVDSTADDR
1044 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVDSTADDR
1045 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in_addr))) {
1046 in_addr *addr =
reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr));
1048 header->destinationAddress.setAddress(ntohl(addr->s_addr));
1051# if defined(IP_RECVIF) && defined(AF_LINK)
1052 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVIF
1053 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(sockaddr_dl))) {
1054 sockaddr_dl *sdl =
reinterpret_cast<sockaddr_dl *>(CMSG_DATA(cmsgptr));
1055 header->ifindex = sdl->sdl_index;
1060 if (cmsgptr->cmsg_len == CMSG_LEN(
sizeof(
int))
1061 && ((cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT)
1062 || (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TTL))) {
1063 static_assert(
sizeof(header->hopLimit) ==
sizeof(
int));
1064 memcpy(&header->hopLimit, CMSG_DATA(cmsgptr),
sizeof(header->hopLimit));
1068 if (cmsgptr->cmsg_level == IPPROTO_SCTP && cmsgptr->cmsg_type == SCTP_SNDRCV
1069 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(sctp_sndrcvinfo))) {
1070 sctp_sndrcvinfo *rcvInfo =
reinterpret_cast<sctp_sndrcvinfo *>(CMSG_DATA(cmsgptr));
1072 header->streamNumber =
int(rcvInfo->sinfo_stream);
1078#if defined (QNATIVESOCKETENGINE_DEBUG)
1079 qDebug(
"QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli",
1080 data, QtDebugUtils::toPrintable(data, recvResult, 16).constData(), maxSize,
1081 (recvResult != -1 && options != QAbstractSocketEngine::WantNone)
1082 ? header->senderAddress.toString().toLatin1().constData() :
"(unknown)",
1083 (recvResult != -1 && options != QAbstractSocketEngine::WantNone)
1084 ? header->senderPort : 0, (qint64) recvResult);
1087 return qint64((maxSize || recvResult < 0) ? recvResult : Q_INT64_C(0));
1093 quintptr cbuf[(CMSG_SPACE(
sizeof(
struct in6_pktinfo)) + CMSG_SPACE(
sizeof(
int))
1095 + CMSG_SPACE(
sizeof(
struct sctp_sndrcvinfo))
1097 +
sizeof(quintptr) - 1) /
sizeof(quintptr)];
1099 struct cmsghdr *cmsgptr =
reinterpret_cast<
struct cmsghdr *>(cbuf);
1104 memset(&msg, 0,
sizeof(msg));
1105 memset(&aa, 0,
sizeof(aa));
1106 vec.iov_base =
const_cast<
char *>(data);
1110 msg.msg_control = &cbuf;
1112 if (header.destinationPort != 0) {
1113 msg.msg_name = &aa.a;
1114 setPortAndAddress(header.destinationPort, header.destinationAddress,
1115 &aa, &msg.msg_namelen);
1118 if (msg.msg_namelen ==
sizeof(aa.a6)) {
1119 if (header.hopLimit != -1) {
1120 msg.msg_controllen += CMSG_SPACE(
sizeof(
int));
1121 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(
int));
1122 cmsgptr->cmsg_level = IPPROTO_IPV6;
1123 cmsgptr->cmsg_type = IPV6_HOPLIMIT;
1124 memcpy(CMSG_DATA(cmsgptr), &header.hopLimit,
sizeof(
int));
1125 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(
int)));
1127 if (header.ifindex != 0 || !header.senderAddress.isNull()) {
1128 struct in6_pktinfo *data =
reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
1129 memset(data, 0,
sizeof(*data));
1130 msg.msg_controllen += CMSG_SPACE(
sizeof(*data));
1131 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(*data));
1132 cmsgptr->cmsg_level = IPPROTO_IPV6;
1133 cmsgptr->cmsg_type = IPV6_PKTINFO;
1134 data->ipi6_ifindex = header.ifindex;
1136 QIPv6Address tmp = header.senderAddress.toIPv6Address();
1137 memcpy(&data->ipi6_addr, &tmp,
sizeof(tmp));
1138 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1141 if (header.hopLimit != -1) {
1142 msg.msg_controllen += CMSG_SPACE(
sizeof(
int));
1143 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(
int));
1144 cmsgptr->cmsg_level = IPPROTO_IP;
1145 cmsgptr->cmsg_type = IP_TTL;
1146 memcpy(CMSG_DATA(cmsgptr), &header.hopLimit,
sizeof(
int));
1147 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(
int)));
1150#if defined(IP_PKTINFO
) || defined(IP_SENDSRCADDR)
1151 if (header.ifindex != 0 || !header.senderAddress.isNull()) {
1153 struct in_pktinfo *data =
reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr));
1154 memset(data, 0,
sizeof(*data));
1155 cmsgptr->cmsg_type = IP_PKTINFO;
1156 data->ipi_ifindex = header.ifindex;
1157 data->ipi_addr.s_addr = htonl(header.senderAddress.toIPv4Address());
1158# elif defined(IP_SENDSRCADDR)
1159 struct in_addr *data =
reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr));
1160 cmsgptr->cmsg_type = IP_SENDSRCADDR;
1161 data->s_addr = htonl(header.senderAddress.toIPv4Address());
1163 cmsgptr->cmsg_level = IPPROTO_IP;
1164 msg.msg_controllen += CMSG_SPACE(
sizeof(*data));
1165 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(*data));
1166 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1172 if (header.streamNumber != -1) {
1173 struct sctp_sndrcvinfo *data =
reinterpret_cast<sctp_sndrcvinfo *>(CMSG_DATA(cmsgptr));
1174 memset(data, 0,
sizeof(*data));
1175 msg.msg_controllen += CMSG_SPACE(
sizeof(sctp_sndrcvinfo));
1176 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(sctp_sndrcvinfo));
1177 cmsgptr->cmsg_level = IPPROTO_SCTP;
1178 cmsgptr->cmsg_type = SCTP_SNDRCV;
1179 data->sinfo_stream = uint16_t(header.streamNumber);
1180 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1184 if (msg.msg_controllen == 0)
1185 msg.msg_control =
nullptr;
1186 ssize_t sentBytes = qt_safe_sendmsg(socketDescriptor, &msg, 0);
1188 if (sentBytes < 0) {
1190#if defined(EWOULDBLOCK
) && EWOULDBLOCK
!= EAGAIN
1199 setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
1202 setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString);
1205 setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
1209#if defined (QNATIVESOCKETENGINE_DEBUG)
1210 qDebug(
"QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data,
1211 QtDebugUtils::toPrintable(data, len, 16).constData(), len,
1212 header.destinationAddress.toString().toLatin1().constData(),
1213 header.destinationPort, (qint64) sentBytes);
1216 return qint64(sentBytes);
1222 localAddress.clear();
1224 peerAddress.clear();
1225 inboundStreamCount = outboundStreamCount = 0;
1227 if (socketDescriptor == -1)
1231 QT_SOCKLEN_T sockAddrSize =
sizeof(sa);
1234 memset(&sa, 0,
sizeof(sa));
1235 if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
1236 qt_socket_getPortAndAddress(&sa, &localPort, &localAddress);
1239 switch (sa.a.sa_family) {
1241 socketProtocol = QAbstractSocket::IPv4Protocol;
1244 socketProtocol = QAbstractSocket::IPv6Protocol;
1247 socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
1251 }
else if (errno == EBADF) {
1252 setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidSocketErrorString);
1262 socklen_t optlen =
sizeof(ipv6only);
1263 if (socketProtocol == QAbstractSocket::IPv6Protocol
1264 && (localAddress == QHostAddress::AnyIPv4 || localAddress == QHostAddress::AnyIPv6)
1265 && !getsockopt(socketDescriptor, IPPROTO_IPV6,
IPV6_V6ONLY, (
char*)&ipv6only, &optlen )) {
1266 if (optlen !=
sizeof(ipv6only))
1267 qWarning(
"unexpected size of IPV6_V6ONLY socket option");
1269 socketProtocol = QAbstractSocket::AnyIPProtocol;
1270 localAddress = QHostAddress::Any;
1276 bool connected = ::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0;
1278 qt_socket_getPortAndAddress(&sa, &peerPort, &peerAddress);
1279 inboundStreamCount = outboundStreamCount = 1;
1284 QT_SOCKOPTLEN_T valueSize =
sizeof(
int);
1285 if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, &value, &valueSize) == 0) {
1286 if (value == SOCK_STREAM) {
1287 socketType = QAbstractSocket::TcpSocket;
1289 if (option(QNativeSocketEngine::MaxStreamsSocketOption) != -1) {
1290 socketType = QAbstractSocket::SctpSocket;
1292 sctp_status sctpStatus;
1293 QT_SOCKOPTLEN_T sctpStatusSize =
sizeof(sctpStatus);
1294 sctp_event_subscribe sctpEvents;
1296 memset(&sctpEvents, 0,
sizeof(sctpEvents));
1297 sctpEvents.sctp_data_io_event = 1;
1298 if (::getsockopt(socketDescriptor, SOL_SCTP, SCTP_STATUS, &sctpStatus,
1299 &sctpStatusSize) == 0 &&
1300 ::setsockopt(socketDescriptor, SOL_SCTP, SCTP_EVENTS, &sctpEvents,
1301 sizeof(sctpEvents)) == 0) {
1302 inboundStreamCount =
int(sctpStatus.sstat_instrms);
1303 outboundStreamCount =
int(sctpStatus.sstat_outstrms);
1305 setError(QAbstractSocket::UnsupportedSocketOperationError,
1306 InvalidSocketErrorString);
1312 }
else if (value == SOCK_DGRAM) {
1313 socketType = QAbstractSocket::UdpSocket;
1314#ifdef SOCK_SEQPACKET
1315 }
else if (value == SOCK_SEQPACKET) {
1323 socketType = QAbstractSocket::TcpSocket;
1326 socketType = QAbstractSocket::UnknownSocketType;
1329#if defined (QNATIVESOCKETENGINE_DEBUG)
1330 QString socketProtocolStr = QStringLiteral(
"UnknownProtocol");
1331 if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = QStringLiteral(
"IPv4Protocol");
1332 else if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) socketProtocolStr = QStringLiteral(
"IPv6Protocol");
1334 QString socketTypeStr = QStringLiteral(
"UnknownSocketType");
1335 if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = QStringLiteral(
"TcpSocket");
1336 else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = QStringLiteral(
"UdpSocket");
1337 else if (socketType == QAbstractSocket::SctpSocket) socketTypeStr = QStringLiteral(
"SctpSocket");
1339 qDebug(
"QNativeSocketEnginePrivate::fetchConnectionParameters() local == %s:%i,"
1340 " peer == %s:%i, socket == %s - %s, inboundStreamCount == %i, outboundStreamCount == %i",
1341 localAddress.toString().toLatin1().constData(), localPort,
1342 peerAddress.toString().toLatin1().constData(), peerPort,socketTypeStr.toLatin1().constData(),
1343 socketProtocolStr.toLatin1().constData(), inboundStreamCount, outboundStreamCount);