/*! \reimp */ qint64 QProcess::writeData(const char *data, qint64 len) { Q_D(QProcess); if (d->writeChannelClosing) { #if defined QPROCESS_DEBUG qDebug("QProcess::writeData(%p \"%s\", %lld) == 0 (write channel closing)", data, qt_prettyDebug(data, len, 16).constData(), len); #endif return 0; } if (len == 1) { d->writeBuffer.putChar(*data); if (d->writeSocketNotifier) d->writeSocketNotifier->setEnabled(true); #if defined QPROCESS_DEBUG qDebug("QProcess::writeData(%p \"%s\", %lld) == 1 (written to buffer)", data, qt_prettyDebug(data, len, 16).constData(), len); #endif return 1; } char *dest = d->writeBuffer.reserve(len); memcpy(dest, data, len); if (d->writeSocketNotifier) d->writeSocketNotifier->setEnabled(true); #if defined QPROCESS_DEBUG qDebug("QProcess::writeData(%p \"%s\", %lld) == %lld (written to buffer)", data, qt_prettyDebug(data, len, 16).constData(), len, len); #endif return len; }
qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) { Q_Q(QNativeSocketEngine); ssize_t writtenBytes; writtenBytes = qt_safe_write_nosignal(socketDescriptor, data, len); if (writtenBytes < 0) { switch (errno) { case EPIPE: case ECONNRESET: writtenBytes = -1; setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString); q->close(); break; case EAGAIN: writtenBytes = 0; break; case EMSGSIZE: setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); break; default: break; } } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %llu) == %i", data, qt_prettyDebug(data, qMin((int) len, 16), (int) len).data(), len, (int) writtenBytes); #endif return qint64(writtenBytes); }
qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, QHostAddress *address, quint16 *port) { #if !defined(QT_NO_IPV6) struct sockaddr_storage aa; #else struct sockaddr_in aa; #endif memset(&aa, 0, sizeof(aa)); QT_SOCKLEN_T sz; sz = sizeof(aa); ssize_t recvFromResult = 0; do { char c; recvFromResult = ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1, 0, (struct sockaddr *)&aa, &sz); } while (recvFromResult == -1 && errno == EINTR); if (recvFromResult == -1) { setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); } else if (port || address) { qt_socket_getPortAndAddress((struct sockaddr *) &aa, port, address); } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli", data, qt_prettyDebug(data, qMin(recvFromResult, ssize_t(16)), recvFromResult).data(), maxSize, address ? address->toString().toLatin1().constData() : "(nil)", port ? *port : 0, (qint64) recvFromResult); #endif return qint64(maxSize ? recvFromResult : recvFromResult == -1 ? -1 : 0); }
qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, const QHostAddress &host, quint16 port) { struct sockaddr_in sockAddrIPv4; struct sockaddr *sockAddrPtr = 0; QT_SOCKLEN_T sockAddrSize = 0; #if !defined(QT_NO_IPV6) struct sockaddr_in6 sockAddrIPv6; if (host.protocol() == QAbstractSocket::IPv6Protocol) { memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6)); sockAddrIPv6.sin6_family = AF_INET6; sockAddrIPv6.sin6_port = htons(port); Q_IPV6ADDR tmp = host.toIPv6Address(); memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp)); QString scopeid = host.scopeId(); bool ok; sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok); #ifndef QT_NO_IPV6IFNAME if (!ok) sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1()); #endif sockAddrSize = sizeof(sockAddrIPv6); sockAddrPtr = (struct sockaddr *)&sockAddrIPv6; } else #endif if (host.protocol() == QAbstractSocket::IPv4Protocol) { memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4)); sockAddrIPv4.sin_family = AF_INET; sockAddrIPv4.sin_port = htons(port); sockAddrIPv4.sin_addr.s_addr = htonl(host.toIPv4Address()); sockAddrSize = sizeof(sockAddrIPv4); sockAddrPtr = (struct sockaddr *)&sockAddrIPv4; } // ignore the SIGPIPE signal qt_ignore_sigpipe(); ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len, 0, sockAddrPtr, sockAddrSize); if (sentBytes < 0) { switch (errno) { case EMSGSIZE: setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); break; default: setError(QAbstractSocket::NetworkError, SendDatagramErrorString); } } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data, qt_prettyDebug(data, qMin<int>(len, 16), len).data(), len, host.toString().toLatin1().constData(), port, (qint64) sentBytes); #endif return qint64(sentBytes); }
qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) { Q_Q(QNativeSocketEngine); qint64 ret = 0; qint64 bytesToSend = len; for (;;) { WSABUF buf; buf.buf = (char*)data + ret; buf.len = bytesToSend; DWORD flags = 0; DWORD bytesWritten = 0; int socketRet = ::WSASend(socketDescriptor, &buf, 1, &bytesWritten, flags, 0,0); ret += qint64(bytesWritten); int err; if (socketRet != SOCKET_ERROR) { if (ret == len) break; else continue; } else if ((err = WSAGetLastError()) == WSAEWOULDBLOCK) { break; } else if (err == WSAENOBUFS) { // this function used to not send more than 49152 per call to WSASendTo // to avoid getting a WSAENOBUFS. However this is a performance regression // and we think it only appears with old windows versions. We now handle the // WSAENOBUFS and hope it never appears anyway. // just go on, the next loop run we will try a smaller number } else { WS_ERROR_DEBUG(err); switch (err) { case WSAECONNRESET: case WSAECONNABORTED: ret = -1; setError(QAbstractSocket::NetworkError, WriteErrorString); q->close(); break; default: break; } break; } // for next send: bytesToSend = qMin<qint64>(49152, len - ret); } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %li) == %li", data, qt_prettyDebug(data, qMin((int)ret, 16), (int)ret).data(), (int)len, (int)ret); #endif return ret; }
qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength, QHostAddress *address, quint16 *port) { qint64 ret = 0; #if !defined(QT_NO_IPV6) qt_sockaddr_storage aa; #else struct sockaddr_in aa; #endif memset(&aa, 0, sizeof(aa)); QT_SOCKLEN_T sz; sz = sizeof(aa); WSABUF buf; buf.buf = data; buf.len = maxLength; #if !defined(Q_OS_WINCE) buf.buf = data; buf.len = maxLength; #else char tmpChar; buf.buf = data ? data : &tmpChar; buf.len = maxLength; #endif DWORD flags = 0; DWORD bytesRead = 0; int wsaRet = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, (struct sockaddr *) &aa, &sz,0,0); if (wsaRet == SOCKET_ERROR) { int err = WSAGetLastError(); if (err == WSAEMSGSIZE) { // it is ok the buffer was to small if bytesRead is larger than // maxLength (win 9x) then assume bytes read is really maxLenth ret = qint64(bytesRead) > maxLength ? maxLength : qint64(bytesRead); } else { WS_ERROR_DEBUG(err); setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); ret = -1; } } else { ret = qint64(bytesRead); } qt_socket_getPortAndAddress(socketDescriptor, (struct sockaddr *) &aa, port, address); #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %li, %s, %i) == %li", data, qt_prettyDebug(data, qMin<qint64>(ret, 16), ret).data(), maxLength, address ? address->toString().toLatin1().constData() : "(nil)", port ? *port : 0, ret); #endif return ret; }
qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) { Q_Q(QNativeSocketEngine); if (!q->isValid()) { qWarning("QNativeSocketEngine::unbufferedRead: Invalid socket"); return -1; } ssize_t r = 0; do { #ifdef Q_OS_SYMBIAN r = ::read(socketDescriptor, data, maxSize); #else r = qt_safe_read(socketDescriptor, data, maxSize); #endif } while (r == -1 && errno == EINTR); if (r < 0) { r = -1; switch (errno) { #if EWOULDBLOCK-0 && EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif case EAGAIN: // No data was available for reading r = -2; break; case EBADF: case EINVAL: case EIO: setError(QAbstractSocket::NetworkError, ReadErrorString); break; #ifdef Q_OS_SYMBIAN case EPIPE: #endif case ECONNRESET: #if defined(Q_OS_VXWORKS) case ESHUTDOWN: #endif r = 0; break; default: break; } } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %llu) == %i", data, qt_prettyDebug(data, qMin(r, ssize_t(16)), r).data(), maxSize, r); #endif return qint64(r); }
/*! \reimp */ qint64 QProcess::readData(char *data, qint64 maxlen) { Q_D(QProcess); QRingBuffer *readBuffer = (d->processChannel == QProcess::StandardError) ? &d->errorReadBuffer : &d->outputReadBuffer; if (maxlen == 1) { int c = readBuffer->getChar(); if (c == -1) { #if defined QPROCESS_DEBUG qDebug("QProcess::readData(%p \"%s\", %d) == -1", data, qt_prettyDebug(data, maxlen, 1).constData(), 1); #endif return -1; } *data = (char) c; #if defined QPROCESS_DEBUG qDebug("QProcess::readData(%p \"%s\", %d) == 1", data, qt_prettyDebug(data, maxlen, 1).constData(), 1); #endif return 1; } qint64 bytesToRead = qint64(qMin(readBuffer->size(), (int)maxlen)); qint64 readSoFar = 0; while (readSoFar < bytesToRead) { char *ptr = readBuffer->readPointer(); int bytesToReadFromThisBlock = qMin<qint64>(bytesToRead - readSoFar, readBuffer->nextDataBlockSize()); memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock); readSoFar += bytesToReadFromThisBlock; readBuffer->free(bytesToReadFromThisBlock); } #if defined QPROCESS_DEBUG qDebug("QProcess::readData(%p \"%s\", %lld) == %lld", data, qt_prettyDebug(data, readSoFar, 16).constData(), maxlen, readSoFar); #endif return readSoFar; }
qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, const QHostAddress &address, quint16 port) { qint64 ret = -1; struct sockaddr_in sockAddrIPv4; qt_sockaddr_in6 sockAddrIPv6; struct sockaddr *sockAddrPtr; QT_SOCKLEN_T sockAddrSize; qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize); if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based && len > qint64(qt_socket_getMaxMsgSize(socketDescriptor))) { // WSAEMSGSIZE is not reliable enough (win 9x) so we check max size our self. setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); } else { WSABUF buf; #if !defined(Q_OS_WINCE) buf.buf = len ? (char*)data : 0; #else char tmp; buf.buf = len ? (char*)data : &tmp; #endif buf.len = len; DWORD flags = 0; DWORD bytesSent = 0; if (::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, sockAddrPtr, sockAddrSize, 0,0) == SOCKET_ERROR) { int err = WSAGetLastError(); WS_ERROR_DEBUG(err); switch (err) { case WSAEMSGSIZE: setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); break; default: setError(QAbstractSocket::NetworkError, SendDatagramErrorString); break; } ret = -1; } else { ret = qint64(bytesSent); } } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeSendDatagram(%p \"%s\", %li, \"%s\", %i) == %li", data, qt_prettyDebug(data, qMin<qint64>(len, 16), len).data(), 0, address.toString().toLatin1().constData(), port, ret); #endif return ret; }
qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxLength) { qint64 ret = -1; WSABUF buf; buf.buf = data; buf.len = maxLength; DWORD flags = 0; DWORD bytesRead = 0; #if defined(Q_OS_WINCE) WSASetLastError(0); #endif if (::WSARecv(socketDescriptor, &buf, 1, &bytesRead, &flags, 0,0) == SOCKET_ERROR) { int err = WSAGetLastError(); WS_ERROR_DEBUG(err); switch (err) { case WSAEWOULDBLOCK: ret = -2; break; case WSAEBADF: case WSAEINVAL: //error string is now set in read(), not here in nativeRead() break; case WSAECONNRESET: case WSAECONNABORTED: // for tcp sockets this will be handled in QNativeSocketEngine::read ret = 0; break; default: break; } } else { if (WSAGetLastError() == WSAEWOULDBLOCK) ret = -2; else ret = qint64(bytesRead); } #if defined (QNATIVESOCKETENGINE_DEBUG) if (ret != -2) { qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %l) == %li", data, qt_prettyDebug(data, qMin((int)bytesRead, 16), (int)bytesRead).data(), (int)maxLength, (int)ret); } else { qDebug("QNativeSocketEnginePrivate::nativeRead(%p, %l) == -2 (WOULD BLOCK)", data, int(maxLength)); } #endif return ret; }
qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) { Q_Q(QNativeSocketEngine); qint64 ret = 0; // don't send more than 49152 per call to WSASendTo to avoid getting a WSAENOBUFS for (;;) { qint64 bytesToSend = qMin<qint64>(49152, len - ret); WSABUF buf; buf.buf = (char*)data + ret; buf.len = bytesToSend; DWORD flags = 0; DWORD bytesWritten = 0; int socketRet = ::WSASend(socketDescriptor, &buf, 1, &bytesWritten, flags, 0,0); ret += qint64(bytesWritten); if (socketRet != SOCKET_ERROR) { if (ret == len) break; else continue; } else if (WSAGetLastError() == WSAEWOULDBLOCK) { break; } else { int err = WSAGetLastError(); WS_ERROR_DEBUG(err); switch (err) { case WSAECONNRESET: case WSAECONNABORTED: ret = -1; setError(QAbstractSocket::NetworkError, WriteErrorString); q->close(); break; default: break; } break; } } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %li) == %li", data, qt_prettyDebug(data, qMin((int)ret, 16), (int)ret).data(), (int)len, (int)ret); #endif return ret; }
qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) { Q_Q(QNativeSocketEngine); // ignore the SIGPIPE signal qt_ignore_sigpipe(); // loop while ::write() returns -1 and errno == EINTR, in case // of an interrupting signal. ssize_t writtenBytes; do { #ifdef Q_OS_SYMBIAN writtenBytes = ::write(socketDescriptor, data, len); #else writtenBytes = qt_safe_write(socketDescriptor, data, len); #endif // writtenBytes = QT_WRITE(socketDescriptor, data, len); ### TODO S60: Should this line be removed or the one above it? } while (writtenBytes < 0 && errno == EINTR); if (writtenBytes < 0) { switch (errno) { case EPIPE: case ECONNRESET: writtenBytes = -1; setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString); q->close(); break; case EAGAIN: writtenBytes = 0; break; case EMSGSIZE: setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); break; default: break; } } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %llu) == %i", data, qt_prettyDebug(data, qMin((int) len, 16), (int) len).data(), len, (int) writtenBytes); #endif return qint64(writtenBytes); }
qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) { Q_Q(QNativeSocketEngine); if (!q->isValid()) { qWarning("QNativeSocketEngine::nativeRead: Invalid socket"); return -1; } ssize_t r = 0; r = qt_safe_read(socketDescriptor, data, maxSize); if (r < 0) { r = -1; switch (errno) { #if EWOULDBLOCK-0 && EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif case EAGAIN: // No data was available for reading r = -2; break; case EBADF: case EINVAL: case EIO: //error string is now set in read(), not here in nativeRead() break; case ECONNRESET: #if defined(Q_OS_VXWORKS) case ESHUTDOWN: #endif r = 0; break; default: break; } } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %llu) == %i", data, qt_prettyDebug(data, qMin(r, ssize_t(16)), r).data(), maxSize, r); #endif return qint64(r); }
qint64 QNativeSocketEnginePrivate::nativeWrite(const char *data, qint64 len) { Q_Q(QNativeSocketEngine); // ignore the SIGPIPE signal qt_ignore_sigpipe(); ssize_t writtenBytes; #ifdef Q_OS_SYMBIAN // Symbian does not support signals natively and Open C returns EINTR when moving to offline writtenBytes = ::write(socketDescriptor, data, len); #else writtenBytes = qt_safe_write(socketDescriptor, data, len); #endif if (writtenBytes < 0) { switch (errno) { case EPIPE: case ECONNRESET: writtenBytes = -1; setError(QAbstractSocket::RemoteHostClosedError, RemoteHostClosedErrorString); q->close(); break; case EAGAIN: writtenBytes = 0; break; case EMSGSIZE: setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); break; default: break; } } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeWrite(%p \"%s\", %llu) == %i", data, qt_prettyDebug(data, qMin((int) len, 16), (int) len).data(), len, (int) writtenBytes); #endif return qint64(writtenBytes); }
qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) { Q_Q(QNativeSocketEngine); if (!q->isValid()) { qWarning("QNativeSocketEngine::unbufferedRead: Invalid socket"); return -1; } ssize_t r = 0; do { r = ::read(socketDescriptor, data, maxSize); } while (r == -1 && errno == EINTR); if (r < 0) { switch (errno) { case EAGAIN: // No data was available for reading return 0; case EBADF: case EINVAL: case EIO: setError(QAbstractSocket::NetworkError, ReadErrorString); break; default: break; } r = -1; } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeRead(%p \"%s\", %llu) == %i", data, qt_prettyDebug(data, qMin(r, 16), r).data(), maxSize, r); #endif return qint64(r); }
qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, QIpPacketHeader *header, QAbstractSocketEngine::PacketHeaderOptions options) { // we use quintptr to force the alignment quintptr cbuf[(CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)) #if !defined(IP_PKTINFO) && defined(IP_RECVIF) && defined(Q_OS_BSD4) + CMSG_SPACE(sizeof(sockaddr_dl)) #endif + sizeof(quintptr) - 1) / sizeof(quintptr)]; struct msghdr msg; struct iovec vec; qt_sockaddr aa; char c; memset(&msg, 0, sizeof(msg)); memset(&aa, 0, sizeof(aa)); // we need to receive at least one byte, even if our user isn't interested in it vec.iov_base = maxSize ? data : &c; vec.iov_len = maxSize ? maxSize : 1; msg.msg_iov = &vec; msg.msg_iovlen = 1; if (options & QAbstractSocketEngine::WantDatagramSender) { msg.msg_name = &aa; msg.msg_namelen = sizeof(aa); } if (options & (QAbstractSocketEngine::WantDatagramHopLimit | QAbstractSocketEngine::WantDatagramDestination)) { msg.msg_control = cbuf; msg.msg_controllen = sizeof(cbuf); } ssize_t recvResult = 0; do { recvResult = ::recvmsg(socketDescriptor, &msg, 0); } while (recvResult == -1 && errno == EINTR); if (recvResult == -1) { setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); if (header) header->clear(); } else if (options != QAbstractSocketEngine::WantNone) { Q_ASSERT(header); qt_socket_getPortAndAddress(&aa, &header->senderPort, &header->senderAddress); header->destinationPort = localPort; // parse the ancillary data struct cmsghdr *cmsgptr; for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(in6_pktinfo))) { in6_pktinfo *info = reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr)); header->destinationAddress.setAddress(reinterpret_cast<quint8 *>(&info->ipi6_addr)); header->ifindex = info->ipi6_ifindex; if (header->ifindex) header->destinationAddress.setScopeId(QString::number(info->ipi6_ifindex)); } #ifdef IP_PKTINFO if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(in_pktinfo))) { in_pktinfo *info = reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr)); header->destinationAddress.setAddress(ntohl(info->ipi_addr.s_addr)); header->ifindex = info->ipi_ifindex; } #else # ifdef IP_RECVDSTADDR if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVDSTADDR && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(in_addr))) { in_addr *addr = reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr)); header->destinationAddress.setAddress(ntohl(addr->s_addr)); } # endif # if defined(IP_RECVIF) && defined(Q_OS_BSD4) if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVIF && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(sockaddr_dl))) { sockaddr_dl *sdl = reinterpret_cast<sockaddr_dl *>(CMSG_DATA(cmsgptr)); header->ifindex = LLINDEX(sdl); } # endif #endif if (cmsgptr->cmsg_len == CMSG_LEN(sizeof(int)) && ((cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT) || (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TTL))) { header->hopLimit = *reinterpret_cast<int *>(CMSG_DATA(cmsgptr)); } } } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli", data, qt_prettyDebug(data, qMin(recvResult, ssize_t(16)), recvResult).data(), maxSize, (recvResult != -1 && options != QAbstractSocketEngine::WantNone) ? header->senderAddress.toString().toLatin1().constData() : "(unknown)", (recvResult != -1 && options != QAbstractSocketEngine::WantNone) ? header->senderPort : 0, (qint64) recvResult); #endif return qint64(maxSize ? recvResult : recvResult == -1 ? -1 : 0); }
qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, const QIpPacketHeader &header) { // we use quintptr to force the alignment quintptr cbuf[(CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)) + sizeof(quintptr) - 1) / sizeof(quintptr)]; struct cmsghdr *cmsgptr = reinterpret_cast<struct cmsghdr *>(cbuf); struct msghdr msg; struct iovec vec; qt_sockaddr aa; memset(&msg, 0, sizeof(msg)); memset(&aa, 0, sizeof(aa)); vec.iov_base = const_cast<char *>(data); vec.iov_len = len; msg.msg_iov = &vec; msg.msg_iovlen = 1; msg.msg_name = &aa.a; msg.msg_control = &cbuf; setPortAndAddress(header.destinationPort, header.destinationAddress, &aa, &msg.msg_namelen); if (msg.msg_namelen == sizeof(aa.a6)) { if (header.hopLimit != -1) { msg.msg_controllen += CMSG_SPACE(sizeof(int)); cmsgptr->cmsg_len = CMSG_LEN(sizeof(int)); cmsgptr->cmsg_level = IPPROTO_IPV6; cmsgptr->cmsg_type = IPV6_HOPLIMIT; memcpy(CMSG_DATA(cmsgptr), &header.hopLimit, sizeof(int)); cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(int))); } if (header.ifindex != 0 || !header.senderAddress.isNull()) { struct in6_pktinfo *data = reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr)); memset(data, 0, sizeof(*data)); msg.msg_controllen += CMSG_SPACE(sizeof(*data)); cmsgptr->cmsg_len = CMSG_LEN(sizeof(*data)); cmsgptr->cmsg_level = IPPROTO_IPV6; cmsgptr->cmsg_type = IPV6_PKTINFO; data->ipi6_ifindex = header.ifindex; QIPv6Address tmp = header.senderAddress.toIPv6Address(); memcpy(&data->ipi6_addr, &tmp, sizeof(tmp)); cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(*data))); } } else { if (header.hopLimit != -1) { msg.msg_controllen += CMSG_SPACE(sizeof(int)); cmsgptr->cmsg_len = CMSG_LEN(sizeof(int)); cmsgptr->cmsg_level = IPPROTO_IP; cmsgptr->cmsg_type = IP_TTL; memcpy(CMSG_DATA(cmsgptr), &header.hopLimit, sizeof(int)); cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(int))); } #if defined(IP_PKTINFO) || defined(IP_SENDSRCADDR) if (header.ifindex != 0 || !header.senderAddress.isNull()) { # ifdef IP_PKTINFO struct in_pktinfo *data = reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr)); memset(data, 0, sizeof(*data)); cmsgptr->cmsg_type = IP_PKTINFO; data->ipi_ifindex = header.ifindex; data->ipi_addr.s_addr = htonl(header.senderAddress.toIPv4Address()); # elif defined(IP_SENDSRCADDR) struct in_addr *data = reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr)); cmsgptr->cmsg_type = IP_SENDSRCADDR; data->s_addr = htonl(header.senderAddress.toIPv4Address()); # endif cmsgptr->cmsg_level = IPPROTO_IP; msg.msg_controllen += CMSG_SPACE(sizeof(*data)); cmsgptr->cmsg_len = CMSG_LEN(sizeof(*data)); cmsgptr = reinterpret_cast<cmsghdr *>(reinterpret_cast<char *>(cmsgptr) + CMSG_SPACE(sizeof(*data))); } #endif } if (msg.msg_controllen == 0) msg.msg_control = 0; ssize_t sentBytes = qt_safe_sendmsg(socketDescriptor, &msg, 0); if (sentBytes < 0) { switch (errno) { case EMSGSIZE: setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); break; default: setError(QAbstractSocket::NetworkError, SendDatagramErrorString); } } #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEngine::sendDatagram(%p \"%s\", %lli, \"%s\", %i) == %lli", data, qt_prettyDebug(data, qMin<int>(len, 16), len).data(), len, header.destinationAddress.toString().toLatin1().constData(), header.destinationPort, (qint64) sentBytes); #endif return qint64(sentBytes); }