50 switch (socketError) {
52 d->socketState = QAbstractSocket::ConnectedState;
58 d->socketState = QAbstractSocket::UnconnectedState;
65 d->socketState = QAbstractSocket::UnconnectedState;
69 d->socketState = QAbstractSocket::UnconnectedState;
77 d->socketState = QAbstractSocket::ConnectingState;
85 d->socketState = QAbstractSocket::UnconnectedState;
91 d->socketState = QAbstractSocket::UnconnectedState;
131 QAbstractSocket::NetworkLayerProtocol socketProtocol,
int &level,
int &n)
137 case QNativeSocketEngine::NonBlockingSocketOption:
138 case QNativeSocketEngine::BindExclusively:
139 case QNativeSocketEngine::MaxStreamsSocketOption:
142 case QNativeSocketEngine::BindInterfaceIndex:
145 case QNativeSocketEngine::BroadcastSocketOption:
148 case QNativeSocketEngine::ReceiveBufferSocketOption:
151 case QNativeSocketEngine::SendBufferSocketOption:
154 case QNativeSocketEngine::AddressReusable:
157 case QNativeSocketEngine::ReceiveOutOfBandData:
160 case QNativeSocketEngine::LowDelayOption:
164 case QNativeSocketEngine::KeepAliveOption:
167 case QNativeSocketEngine::MulticastTtlOption:
168 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
169 level = IPPROTO_IPV6;
170 n = IPV6_MULTICAST_HOPS;
174 n = IP_MULTICAST_TTL;
177 case QNativeSocketEngine::MulticastLoopbackOption:
178 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
179 level = IPPROTO_IPV6;
180 n = IPV6_MULTICAST_LOOP;
184 n = IP_MULTICAST_LOOP;
187 case QNativeSocketEngine::TypeOfServiceOption:
188 if (socketProtocol == QAbstractSocket::IPv4Protocol) {
193 case QNativeSocketEngine::ReceivePacketInformation:
194 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
195 level = IPPROTO_IPV6;
196 n = IPV6_RECVPKTINFO;
197 }
else if (socketProtocol == QAbstractSocket::IPv4Protocol) {
204 case QNativeSocketEngine::ReceiveHopLimit:
205 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
206 level = IPPROTO_IPV6;
207 n = IPV6_RECVHOPLIMIT;
208 }
else if (socketProtocol == QAbstractSocket::IPv4Protocol) {
216 case QNativeSocketEngine::PathMtuInformation:
217 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
219 level = IPPROTO_IPV6;
229 case QNativeSocketEngine::KeepAliveIdleOption:
237 case QNativeSocketEngine::KeepAliveIntervalOption:
243 case QNativeSocketEngine::KeepAliveCountOption:
258 QAbstractSocket::NetworkLayerProtocol &socketProtocol)
261 int protocol = (socketType == QAbstractSocket::SctpSocket) ? IPPROTO_SCTP : 0;
263 if (socketType == QAbstractSocket::SctpSocket) {
264 setError(QAbstractSocket::UnsupportedSocketOperationError,
265 ProtocolUnsupportedErrorString);
266#if defined (QNATIVESOCKETENGINE_DEBUG)
267 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d): unsupported protocol",
268 socketType, socketProtocol);
274 int domain = (socketProtocol == QAbstractSocket::IPv6Protocol
275 || socketProtocol == QAbstractSocket::AnyIPProtocol) ?
AF_INET6 : AF_INET;
276 int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM;
278 int socket = qt_safe_socket(domain, type, protocol, O_NONBLOCK);
279 if (socket < 0 && socketProtocol == QAbstractSocket::AnyIPProtocol && (errno == EAFNOSUPPORT || errno == ENOTSUP )) {
281 socket = qt_safe_socket(domain, type, protocol, O_NONBLOCK);
282 socketProtocol = QAbstractSocket::IPv4Protocol;
288 case EPROTONOSUPPORT:
291 setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
297 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
300 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
306#if defined (QNATIVESOCKETENGINE_DEBUG)
307 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d) == false (%s)",
308 socketType, socketProtocol,
317 const int ipv6only = 0;
318 [[maybe_unused]]
const int ret = ::setsockopt(socket, IPPROTO_IPV6,
IPV6_V6ONLY,
319 &ipv6only,
sizeof(ipv6only));
320#if defined (QNATIVESOCKETENGINE_DEBUG)
322 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d): "
323 "failed to set IPV6_V6ONLY to %d.",
324 socketType, socketProtocol, ipv6only);
329#if defined (QNATIVESOCKETENGINE_DEBUG)
330 qDebug(
"QNativeSocketEnginePrivate::createNewSocket(%d, %d) == true",
331 socketType, socketProtocol);
334 socketDescriptor = socket;
335 this->socketProtocol = socketProtocol;
336 this->socketType = socketType;
345 Q_Q(
const QNativeSocketEngine);
351 case QNativeSocketEngine::BindExclusively:
352 case QNativeSocketEngine::NonBlockingSocketOption:
353 case QNativeSocketEngine::BroadcastSocketOption:
355 case QNativeSocketEngine::MaxStreamsSocketOption: {
357 sctp_initmsg sctpInitMsg;
358 QT_SOCKOPTLEN_T sctpInitMsgSize =
sizeof(sctpInitMsg);
359 if (::getsockopt(socketDescriptor, SOL_SCTP, SCTP_INITMSG, &sctpInitMsg,
360 &sctpInitMsgSize) == 0)
361 return int(qMin(sctpInitMsg.sinit_num_ostreams, sctpInitMsg.sinit_max_instreams));
366 case QNativeSocketEngine::PathMtuInformation:
367#if defined(IPV6_PATHMTU
) && !defined(IPV6_MTU
)
370 if (socketProtocol == QAbstractSocket::IPv6Protocol) {
372 QT_SOCKOPTLEN_T len =
sizeof(mtuinfo);
373 if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_PATHMTU, &mtuinfo, &len) == 0)
374 return int(mtuinfo.ip6m_mtu);
386 QT_SOCKOPTLEN_T len =
sizeof(v);
388 convertToLevelAndOption(opt, socketProtocol, level, n);
389 if (n != -1 && ::getsockopt(socketDescriptor, level, n, (
char *) &v, &len) != -1)
390 return len == 1 ? qFromUnaligned<quint8>(&v) : v;
401#ifdef QNATIVESOCKETENGINE_DEBUG
402# define perrorDebug(msg) perror("QNativeSocketEnginePrivate::setOption(): " msg)
404# define perrorDebug(msg) (void)0
406 Q_Q(QNativeSocketEngine);
412 case QNativeSocketEngine::NonBlockingSocketOption: {
414#if !defined(Q_OS_VXWORKS)
415 int flags = ::fcntl(socketDescriptor, F_GETFL, 0);
420 if (::fcntl(socketDescriptor, F_SETFL, flags | O_NONBLOCK) == -1) {
425 if (qt_safe_ioctl(socketDescriptor, FIONBIO, &v) < 0) {
426 perrorDebug(
"ioctl(FIONBIO, 1) failed");
432 case QNativeSocketEngine::BindExclusively:
435 case QNativeSocketEngine::ReceivePacketInformation:
436 if (socketProtocol == QAbstractSocket::IPv4Protocol) {
437#if !defined(IP_PKTINFO
) && defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
440 r += ::setsockopt(socketDescriptor, IPPROTO_IP, IP_RECVDSTADDR, &v,
sizeof(v));
441 r += ::setsockopt(socketDescriptor, IPPROTO_IP, IP_RECVIF, &v,
sizeof(v));
447 case QNativeSocketEngine::MaxStreamsSocketOption: {
449 sctp_initmsg sctpInitMsg;
450 QT_SOCKOPTLEN_T sctpInitMsgSize =
sizeof(sctpInitMsg);
451 if (::getsockopt(socketDescriptor, SOL_SCTP, SCTP_INITMSG, &sctpInitMsg,
452 &sctpInitMsgSize) == 0) {
453 sctpInitMsg.sinit_num_ostreams = sctpInitMsg.sinit_max_instreams = uint16_t(v);
454 return ::setsockopt(socketDescriptor, SOL_SCTP, SCTP_INITMSG, &sctpInitMsg,
455 sctpInitMsgSize) == 0;
460 case QNativeSocketEngine::BindInterfaceIndex: {
461#if defined(SO_BINDTOIFINDEX
)
462 return ::setsockopt(socketDescriptor, SOL_SOCKET, SO_BINDTOIFINDEX,
464#elif defined(IPV6_BOUND_IF) && defined(IP_BOUND_IF)
466 if (socketProtocol == QAbstractSocket::IPv6Protocol
467 || socketProtocol == QAbstractSocket::AnyIPProtocol) {
468 return ::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_BOUND_IF, &v,
sizeof(v)) == 0;
470 return ::setsockopt(socketDescriptor, IPPROTO_IP, IP_BOUND_IF, &v,
sizeof(v)) == 0;
472#elif defined(SO_BINDTODEVICE) && QT_CONFIG(networkinterface)
474 const QByteArray name = QNetworkInterfaceManager::interfaceNameFromIndex(v).toLatin1();
475 return ::setsockopt(socketDescriptor, SOL_SOCKET, SO_BINDTODEVICE,
476 name.data(), socklen_t(name.size())) == 0;
486 convertToLevelAndOption(opt, socketProtocol, level, n);
487#if defined(SO_REUSEPORT
) && !defined(Q_OS_LINUX)
488 if (opt == QNativeSocketEngine::AddressReusable) {
492 if (socketType == QAbstractSocket::UdpSocket)
499 return ::setsockopt(socketDescriptor, level, n, (
char *) &v,
sizeof(v)) == 0;
505#ifdef QNATIVESOCKETENGINE_DEBUG
506 qDebug() <<
"QNativeSocketEnginePrivate::nativeConnect() " << socketDescriptor;
511 QT_SOCKLEN_T sockAddrSize;
512 setPortAndAddress(port, addr, &aa, &sockAddrSize);
514 const int connectResult = qt_safe_connect(socketDescriptor, &aa.a, sockAddrSize);
515 const int socketError = errno;
516 if (connectResult == -1) {
519 if (socketState != QAbstractSocket::ConnectedState) {
520#if defined (QNATIVESOCKETENGINE_DEBUG)
521 qDebug(
"QNativeSocketEnginePrivate::nativeConnect(%s, %i) == false (%s)",
522 addr.toString().toLatin1().constData(), port,
523 socketState == QAbstractSocket::ConnectingState
524 ?
"Connection in progress" : strerror(socketError));
530#if defined (QNATIVESOCKETENGINE_DEBUG)
531 qDebug(
"QNativeSocketEnginePrivate::nativeConnect(%s, %i) == true",
532 addr.toString().toLatin1().constData(), port);
535 socketState = QAbstractSocket::ConnectedState;
561 QT_SOCKLEN_T sockAddrSize;
562 setPortAndAddress(port, address, &aa, &sockAddrSize);
567 if (address.protocol() == QAbstractSocket::IPv6Protocol)
570 ::setsockopt(socketDescriptor, IPPROTO_IPV6,
IPV6_V6ONLY, (
char*)&ipv6only,
sizeof(ipv6only) );
574 int bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
575 if (bindResult < 0 && errno == EAFNOSUPPORT && address.protocol() == QAbstractSocket::AnyIPProtocol) {
577 aa.a4.sin_family = AF_INET;
578 aa.a4.sin_port = htons(port);
579 aa.a4.sin_addr.s_addr = htonl(address.toIPv4Address());
580 sockAddrSize =
sizeof(aa.a4);
581 bindResult = QT_SOCKET_BIND(socketDescriptor, &aa.a, sockAddrSize);
584 if (bindResult < 0) {
585#if defined (QNATIVESOCKETENGINE_DEBUG)
590 setError(QAbstractSocket::AddressInUseError, AddressInuseErrorString);
593 setError(QAbstractSocket::SocketAccessError, AddressProtectedErrorString);
596 setError(QAbstractSocket::UnsupportedSocketOperationError, OperationUnsupportedErrorString);
599 setError(QAbstractSocket::SocketAddressNotAvailableError, AddressNotAvailableErrorString);
605#if defined (QNATIVESOCKETENGINE_DEBUG)
606 qDebug(
"QNativeSocketEnginePrivate::nativeBind(%s, %i) == false (%s)",
607 address.toString().toLatin1().constData(), port, strerror(ecopy));
613#if defined (QNATIVESOCKETENGINE_DEBUG)
614 qDebug(
"QNativeSocketEnginePrivate::nativeBind(%s, %i) == true",
615 address.toString().toLatin1().constData(), port);
617 socketState = QAbstractSocket::BoundState;
653 int acceptedDescriptor = qt_safe_accept(socketDescriptor,
nullptr,
nullptr);
654 if (acceptedDescriptor == -1) {
658 setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidSocketErrorString);
661 setError(QAbstractSocket::NetworkError, RemoteHostClosedErrorString);
665 setError(QAbstractSocket::SocketResourceError, NotSocketErrorString);
667 case EPROTONOSUPPORT:
668#if !defined(Q_OS_OPENBSD)
673 setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
679 setError(QAbstractSocket::SocketResourceError, ResourceErrorString);
683 setError(QAbstractSocket::SocketAccessError, AccessErrorString);
685#if EAGAIN
!= EWOULDBLOCK
689 setError(QAbstractSocket::TemporaryError, TemporaryErrorString);
692 setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString);
697 return qintptr(acceptedDescriptor);
705 const QHostAddress &groupAddress,
706 const QNetworkInterface &interface)
716 if (groupAddress.protocol() == QAbstractSocket::IPv6Protocol) {
717 level = IPPROTO_IPV6;
720 sockArgSize =
sizeof(mreq6);
721 memset(&mreq6, 0,
sizeof(mreq6));
722 Q_IPV6ADDR ip6 = groupAddress.toIPv6Address();
723 memcpy(&mreq6.ipv6mr_multiaddr, &ip6,
sizeof(ip6));
724 mreq6.ipv6mr_interface = interface.index();
725 }
else if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
729 sockArgSize =
sizeof(mreq4);
730 memset(&mreq4, 0,
sizeof(mreq4));
731 mreq4.imr_multiaddr.s_addr = htonl(groupAddress.toIPv4Address());
733 if (interface.isValid()) {
734 const QList<QNetworkAddressEntry> addressEntries = interface.addressEntries();
736 for (
const QNetworkAddressEntry &entry : addressEntries) {
737 const QHostAddress ip = entry.ip();
738 if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
739 mreq4.imr_interface.s_addr = htonl(ip.toIPv4Address());
745 d->setError(QAbstractSocket::NetworkError,
750 mreq4.imr_interface.s_addr = INADDR_ANY;
754 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
759 int res = setsockopt(d->socketDescriptor, level, sockOpt, sockArg, sockArgSize);
763 d->setError(QAbstractSocket::UnsupportedSocketOperationError,
767 d->setError(QAbstractSocket::SocketAddressNotAvailableError,
771 d->setError(QAbstractSocket::UnknownSocketError,
802 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
804 QT_SOCKOPTLEN_T sizeofv =
sizeof(v);
805 if (::getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, &sizeofv) == -1)
806 return QNetworkInterface();
807 return QNetworkInterface::interfaceFromIndex(v);
810#if defined(Q_OS_SOLARIS)
811 struct in_addr v = { 0, 0, 0, 0};
813 struct in_addr v = { 0 };
815 QT_SOCKOPTLEN_T sizeofv =
sizeof(v);
816 if (::getsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v, &sizeofv) == -1)
817 return QNetworkInterface();
818 if (v.s_addr != 0 && sizeofv >= QT_SOCKOPTLEN_T(
sizeof(v))) {
819 QHostAddress ipv4(ntohl(v.s_addr));
820 QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
821 for (
int i = 0; i < ifaces.size(); ++i) {
822 const QNetworkInterface &iface = ifaces.at(i);
823 QList<QNetworkAddressEntry> entries = iface.addressEntries();
824 for (
int j = 0; j < entries.size(); ++j) {
825 const QNetworkAddressEntry &entry = entries.at(j);
826 if (entry.ip() == ipv4)
831 return QNetworkInterface();
836 if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) {
837 uint v = iface.index();
838 return (::setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_MULTICAST_IF, &v,
sizeof(v)) != -1);
842 if (iface.isValid()) {
843 QList<QNetworkAddressEntry> entries = iface.addressEntries();
844 for (
int i = 0; i < entries.size(); ++i) {
845 const QNetworkAddressEntry &entry = entries.at(i);
846 const QHostAddress &ip = entry.ip();
847 if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
848 v.s_addr = htonl(ip.toIPv4Address());
849 int r = ::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v,
sizeof(v));
857 v.s_addr = INADDR_ANY;
858 return (::setsockopt(socketDescriptor, IPPROTO_IP, IP_MULTICAST_IF, &v,
sizeof(v)) != -1);
906 ssize_t recvResult = -1;
910 QT_EINTR_LOOP(recvResult, ::recv(socketDescriptor, &c, 1, MSG_PEEK | MSG_TRUNC));
911#elif defined(SO_NREAD)
914 socklen_t valuelen =
sizeof(value);
915 recvResult = getsockopt(socketDescriptor, SOL_SOCKET, SO_NREAD, &value, &valuelen);
916 if (recvResult != -1)
918#elif defined(Q_OS_VXWORKS)
921 int ioctlResult = ::ioctl(socketDescriptor, FIONREAD, &available);
922 if (ioctlResult != -1)
923 recvResult = available;
929 char udpMessagePeekBuffer[1500];
933 memset(&msg, 0,
sizeof(msg));
936 vec.iov_base = udpMessagePeekBuffer;
937 vec.iov_len =
sizeof(udpMessagePeekBuffer);
943 recvResult = ::recvmsg(socketDescriptor, &msg, MSG_PEEK);
944 if (recvResult == -1 && errno == EINTR)
948 if ((msg.msg_flags & MSG_TRUNC) == 0)
952 msg.msg_iovlen *= 16;
953 if (msg.msg_iov != &vec)
954 delete[] msg.msg_iov;
955 msg.msg_iov =
new struct iovec[msg.msg_iovlen];
956 std::fill_n(msg.msg_iov, msg.msg_iovlen, vec);
959 if (msg.msg_iov != &vec)
960 delete[] msg.msg_iov;
963#if defined (QNATIVESOCKETENGINE_DEBUG)
964 qDebug(
"QNativeSocketEnginePrivate::nativePendingDatagramSize() == %zd", recvResult);
967 return qint64(recvResult);
971 QAbstractSocketEngine::PacketHeaderOptions options)
974 quintptr cbuf[(CMSG_SPACE(
sizeof(
struct in6_pktinfo)) + CMSG_SPACE(
sizeof(
int))
975#if !defined(IP_PKTINFO
) && defined(IP_RECVIF) && defined(AF_LINK)
976 + CMSG_SPACE(
sizeof(sockaddr_dl))
979 + CMSG_SPACE(
sizeof(
struct sctp_sndrcvinfo))
981 +
sizeof(quintptr) - 1) /
sizeof(quintptr)];
987 memset(&msg, 0,
sizeof(msg));
988 memset(&aa, 0,
sizeof(aa));
991 vec.iov_base = maxSize ? data : &c;
992 vec.iov_len = maxSize ? maxSize : 1;
995 if (options & QAbstractSocketEngine::WantDatagramSender) {
997 msg.msg_namelen =
sizeof(aa);
999 if (options & (QAbstractSocketEngine::WantDatagramHopLimit | QAbstractSocketEngine::WantDatagramDestination
1000 | QAbstractSocketEngine::WantStreamNumber)) {
1001 msg.msg_control = cbuf;
1002 msg.msg_controllen =
sizeof(cbuf);
1005 ssize_t recvResult = 0;
1007 recvResult = ::recvmsg(socketDescriptor, &msg, 0);
1008 }
while (recvResult == -1 && errno == EINTR);
1010 if (recvResult == -1) {
1012#if defined(EWOULDBLOCK
) && EWOULDBLOCK
!= EAGAIN
1020 setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
1023 setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
1027 }
else if (options != QAbstractSocketEngine::WantNone) {
1029 qt_socket_getPortAndAddress(&aa, &header->senderPort, &header->senderAddress);
1030 header->destinationPort = localPort;
1031 header->endOfRecord = (msg.msg_flags & MSG_EOR) != 0;
1034 struct cmsghdr *cmsgptr;
1036 QT_WARNING_DISABLE_CLANG(
"-Wsign-compare")
1037 for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr !=
nullptr;
1038 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
1040 if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO
1041 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in6_pktinfo))) {
1042 in6_pktinfo *info =
reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
1044 header->destinationAddress.setAddress(
reinterpret_cast<quint8 *>(&info->ipi6_addr));
1045 header->ifindex = info->ipi6_ifindex;
1046 if (header->ifindex)
1047 header->destinationAddress.setScopeId(QString::number(info->ipi6_ifindex));
1051 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO
1052 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in_pktinfo))) {
1053 in_pktinfo *info =
reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr));
1055 header->destinationAddress.setAddress(ntohl(info->ipi_addr.s_addr));
1056 header->ifindex = info->ipi_ifindex;
1059# ifdef IP_RECVDSTADDR
1060 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVDSTADDR
1061 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(in_addr))) {
1062 in_addr *addr =
reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr));
1064 header->destinationAddress.setAddress(ntohl(addr->s_addr));
1067# if defined(IP_RECVIF) && defined(AF_LINK)
1068 if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVIF
1069 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(sockaddr_dl))) {
1070 sockaddr_dl *sdl =
reinterpret_cast<sockaddr_dl *>(CMSG_DATA(cmsgptr));
1071 header->ifindex = sdl->sdl_index;
1076 if (cmsgptr->cmsg_len == CMSG_LEN(
sizeof(
int))
1077 && ((cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT)
1078 || (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TTL))) {
1079 static_assert(
sizeof(header->hopLimit) ==
sizeof(
int));
1080 memcpy(&header->hopLimit, CMSG_DATA(cmsgptr),
sizeof(header->hopLimit));
1084 if (cmsgptr->cmsg_level == IPPROTO_SCTP && cmsgptr->cmsg_type == SCTP_SNDRCV
1085 && cmsgptr->cmsg_len >= CMSG_LEN(
sizeof(sctp_sndrcvinfo))) {
1086 sctp_sndrcvinfo *rcvInfo =
reinterpret_cast<sctp_sndrcvinfo *>(CMSG_DATA(cmsgptr));
1088 header->streamNumber =
int(rcvInfo->sinfo_stream);
1094#if defined (QNATIVESOCKETENGINE_DEBUG)
1095 qDebug(
"QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli",
1096 data, QtDebugUtils::toPrintable(data, recvResult, 16).constData(), maxSize,
1097 (recvResult != -1 && options != QAbstractSocketEngine::WantNone)
1098 ? header->senderAddress.toString().toLatin1().constData() :
"(unknown)",
1099 (recvResult != -1 && options != QAbstractSocketEngine::WantNone)
1100 ? header->senderPort : 0, (qint64) recvResult);
1103 return qint64((maxSize || recvResult < 0) ? recvResult : Q_INT64_C(0));
1109 quintptr cbuf[(CMSG_SPACE(
sizeof(
struct in6_pktinfo)) + CMSG_SPACE(
sizeof(
int))
1111 + CMSG_SPACE(
sizeof(
struct sctp_sndrcvinfo))
1113 +
sizeof(quintptr) - 1) /
sizeof(quintptr)];
1115 struct cmsghdr *cmsgptr =
reinterpret_cast<
struct cmsghdr *>(cbuf);
1120 memset(&msg, 0,
sizeof(msg));
1121 memset(&aa, 0,
sizeof(aa));
1122 vec.iov_base =
const_cast<
char *>(data);
1126 msg.msg_control = &cbuf;
1128 if (header.destinationPort != 0) {
1129 msg.msg_name = &aa.a;
1130 setPortAndAddress(header.destinationPort, header.destinationAddress,
1131 &aa, &msg.msg_namelen);
1134 if (msg.msg_namelen ==
sizeof(aa.a6)) {
1135 if (header.hopLimit != -1) {
1136 msg.msg_controllen += CMSG_SPACE(
sizeof(
int));
1137 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(
int));
1138 cmsgptr->cmsg_level = IPPROTO_IPV6;
1139 cmsgptr->cmsg_type = IPV6_HOPLIMIT;
1140 memcpy(CMSG_DATA(cmsgptr), &header.hopLimit,
sizeof(
int));
1141 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(
int)));
1143 if (header.ifindex != 0 || !header.senderAddress.isNull()) {
1144 struct in6_pktinfo *data =
reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
1145 memset(data, 0,
sizeof(*data));
1146 msg.msg_controllen += CMSG_SPACE(
sizeof(*data));
1147 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(*data));
1148 cmsgptr->cmsg_level = IPPROTO_IPV6;
1149 cmsgptr->cmsg_type = IPV6_PKTINFO;
1150 data->ipi6_ifindex = header.ifindex;
1152 QIPv6Address tmp = header.senderAddress.toIPv6Address();
1153 memcpy(&data->ipi6_addr, &tmp,
sizeof(tmp));
1154 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1157 if (header.hopLimit != -1) {
1158 msg.msg_controllen += CMSG_SPACE(
sizeof(
int));
1159 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(
int));
1160 cmsgptr->cmsg_level = IPPROTO_IP;
1161 cmsgptr->cmsg_type = IP_TTL;
1162 memcpy(CMSG_DATA(cmsgptr), &header.hopLimit,
sizeof(
int));
1163 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(
int)));
1166#if defined(IP_PKTINFO
) || defined(IP_SENDSRCADDR)
1167 if (header.ifindex != 0 || !header.senderAddress.isNull()) {
1169 struct in_pktinfo *data =
reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr));
1170 memset(data, 0,
sizeof(*data));
1171 cmsgptr->cmsg_type = IP_PKTINFO;
1172 data->ipi_ifindex = header.ifindex;
1173 data->ipi_addr.s_addr = htonl(header.senderAddress.toIPv4Address());
1174# elif defined(IP_SENDSRCADDR)
1175 struct in_addr *data =
reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr));
1176 cmsgptr->cmsg_type = IP_SENDSRCADDR;
1177 data->s_addr = htonl(header.senderAddress.toIPv4Address());
1179 cmsgptr->cmsg_level = IPPROTO_IP;
1180 msg.msg_controllen += CMSG_SPACE(
sizeof(*data));
1181 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(*data));
1182 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1188 if (header.streamNumber != -1) {
1189 struct sctp_sndrcvinfo *data =
reinterpret_cast<sctp_sndrcvinfo *>(CMSG_DATA(cmsgptr));
1190 memset(data, 0,
sizeof(*data));
1191 msg.msg_controllen += CMSG_SPACE(
sizeof(sctp_sndrcvinfo));
1192 cmsgptr->cmsg_len = CMSG_LEN(
sizeof(sctp_sndrcvinfo));
1193 cmsgptr->cmsg_level = IPPROTO_SCTP;
1194 cmsgptr->cmsg_type = SCTP_SNDRCV;
1195 data->sinfo_stream = uint16_t(header.streamNumber);
1196 cmsgptr =
reinterpret_cast<cmsghdr *>(
reinterpret_cast<
char *>(cmsgptr) + CMSG_SPACE(
sizeof(*data)));
1200 if (msg.msg_controllen == 0)
1201 msg.msg_control =
nullptr;
1202 ssize_t sentBytes = qt_safe_sendmsg(socketDescriptor, &msg, 0);
1204 if (sentBytes < 0) {
1206#if defined(EWOULDBLOCK
) && EWOULDBLOCK
!= EAGAIN
1215 setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString);
1218 setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString);
1221 setError(QAbstractSocket::NetworkError, SendDatagramErrorString);
1225#if defined (QNATIVESOCKETENGINE_DEBUG)
1226 qDebug(
"QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data,
1227 QtDebugUtils::toPrintable(data, len, 16).constData(), len,
1228 header.destinationAddress.toString().toLatin1().constData(),
1229 header.destinationPort, (qint64) sentBytes);
1232 return qint64(sentBytes);
1238 localAddress.clear();
1240 peerAddress.clear();
1241 inboundStreamCount = outboundStreamCount = 0;
1243 if (socketDescriptor == -1)
1247 QT_SOCKLEN_T sockAddrSize =
sizeof(sa);
1250 memset(&sa, 0,
sizeof(sa));
1251 if (::getsockname(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
1252 qt_socket_getPortAndAddress(&sa, &localPort, &localAddress);
1255 switch (sa.a.sa_family) {
1257 socketProtocol = QAbstractSocket::IPv4Protocol;
1260 socketProtocol = QAbstractSocket::IPv6Protocol;
1263 socketProtocol = QAbstractSocket::UnknownNetworkLayerProtocol;
1267 }
else if (errno == EBADF) {
1268 setError(QAbstractSocket::UnsupportedSocketOperationError, InvalidSocketErrorString);
1278 socklen_t optlen =
sizeof(ipv6only);
1279 if (socketProtocol == QAbstractSocket::IPv6Protocol
1280 && (localAddress == QHostAddress::AnyIPv4 || localAddress == QHostAddress::AnyIPv6)
1281 && !getsockopt(socketDescriptor, IPPROTO_IPV6,
IPV6_V6ONLY, (
char*)&ipv6only, &optlen )) {
1282 if (optlen !=
sizeof(ipv6only))
1283 qWarning(
"unexpected size of IPV6_V6ONLY socket option");
1285 socketProtocol = QAbstractSocket::AnyIPProtocol;
1286 localAddress = QHostAddress::Any;
1292 bool connected = ::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0;
1294 qt_socket_getPortAndAddress(&sa, &peerPort, &peerAddress);
1295 inboundStreamCount = outboundStreamCount = 1;
1300 QT_SOCKOPTLEN_T valueSize =
sizeof(
int);
1301 if (::getsockopt(socketDescriptor, SOL_SOCKET, SO_TYPE, &value, &valueSize) == 0) {
1302 if (value == SOCK_STREAM) {
1303 socketType = QAbstractSocket::TcpSocket;
1305 if (option(QNativeSocketEngine::MaxStreamsSocketOption) != -1) {
1306 socketType = QAbstractSocket::SctpSocket;
1308 sctp_status sctpStatus;
1309 QT_SOCKOPTLEN_T sctpStatusSize =
sizeof(sctpStatus);
1310 sctp_event_subscribe sctpEvents;
1312 memset(&sctpEvents, 0,
sizeof(sctpEvents));
1313 sctpEvents.sctp_data_io_event = 1;
1314 if (::getsockopt(socketDescriptor, SOL_SCTP, SCTP_STATUS, &sctpStatus,
1315 &sctpStatusSize) == 0 &&
1316 ::setsockopt(socketDescriptor, SOL_SCTP, SCTP_EVENTS, &sctpEvents,
1317 sizeof(sctpEvents)) == 0) {
1318 inboundStreamCount =
int(sctpStatus.sstat_instrms);
1319 outboundStreamCount =
int(sctpStatus.sstat_outstrms);
1321 setError(QAbstractSocket::UnsupportedSocketOperationError,
1322 InvalidSocketErrorString);
1328 }
else if (value == SOCK_DGRAM) {
1329 socketType = QAbstractSocket::UdpSocket;
1330#ifdef SOCK_SEQPACKET
1331 }
else if (value == SOCK_SEQPACKET) {
1339 socketType = QAbstractSocket::TcpSocket;
1342 socketType = QAbstractSocket::UnknownSocketType;
1345#if defined (QNATIVESOCKETENGINE_DEBUG)
1346 QString socketProtocolStr = QStringLiteral(
"UnknownProtocol");
1347 if (socketProtocol == QAbstractSocket::IPv4Protocol) socketProtocolStr = QStringLiteral(
"IPv4Protocol");
1348 else if (socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) socketProtocolStr = QStringLiteral(
"IPv6Protocol");
1350 QString socketTypeStr = QStringLiteral(
"UnknownSocketType");
1351 if (socketType == QAbstractSocket::TcpSocket) socketTypeStr = QStringLiteral(
"TcpSocket");
1352 else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = QStringLiteral(
"UdpSocket");
1353 else if (socketType == QAbstractSocket::SctpSocket) socketTypeStr = QStringLiteral(
"SctpSocket");
1355 qDebug(
"QNativeSocketEnginePrivate::fetchConnectionParameters() local == %s:%i,"
1356 " peer == %s:%i, socket == %s - %s, inboundStreamCount == %i, outboundStreamCount == %i",
1357 localAddress.toString().toLatin1().constData(), localPort,
1358 peerAddress.toString().toLatin1().constData(), peerPort,socketTypeStr.toLatin1().constData(),
1359 socketProtocolStr.toLatin1().constData(), inboundStreamCount, outboundStreamCount);