summaryrefslogtreecommitdiffstats
path: root/src/network/socket/qnativesocketengine_unix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/socket/qnativesocketengine_unix.cpp')
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp86
1 files changed, 50 insertions, 36 deletions
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 0e04096296..37651dcbc3 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -847,19 +847,29 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const
qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, QIpPacketHeader *header,
QAbstractSocketEngine::PacketHeaderOptions options)
{
+ struct msghdr msg;
+ struct iovec vec;
qt_sockaddr aa;
+ char c;
+ memset(&msg, 0, sizeof(msg));
memset(&aa, 0, sizeof(aa));
- QT_SOCKLEN_T sz;
- sz = sizeof(aa);
- ssize_t recvFromResult = 0;
+ // 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);
+ }
+
+ ssize_t recvResult = 0;
do {
- char c;
- recvFromResult = ::recvfrom(socketDescriptor, maxSize ? data : &c, maxSize ? maxSize : 1,
- 0, &aa.a, &sz);
- } while (recvFromResult == -1 && errno == EINTR);
+ recvResult = ::recvmsg(socketDescriptor, &msg, 0);
+ } while (recvResult == -1 && errno == EINTR);
- if (recvFromResult == -1) {
+ if (recvResult == -1) {
setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
if (header)
header->clear();
@@ -870,46 +880,50 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS
#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,
+ data, qt_prettyDebug(data, qMin(recvResult, ssize_t(16)), recvResult).data(), maxSize,
address ? address->toString().toLatin1().constData() : "(nil)",
- port ? *port : 0, (qint64) recvFromResult);
+ port ? *port : 0, (qint64) recvResult);
#endif
- return qint64(maxSize ? recvFromResult : recvFromResult == -1 ? -1 : 0);
+ return qint64(maxSize ? recvResult : recvResult == -1 ? -1 : 0);
}
qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, const QIpPacketHeader &header)
{
- struct sockaddr_in sockAddrIPv4;
- struct sockaddr *sockAddrPtr = 0;
- QT_SOCKLEN_T sockAddrSize = 0;
+ struct msghdr msg;
+ struct iovec vec;
+ qt_sockaddr aa;
- struct sockaddr_in6 sockAddrIPv6;
- const QHostAddress &host = header.destinationAddress;
- quint16 port = header.destinationPort;
- if (host.protocol() == QAbstractSocket::IPv6Protocol
+ 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;
+
+ if (header.destinationAddress.protocol() == QAbstractSocket::IPv6Protocol
|| socketProtocol == QAbstractSocket::IPv6Protocol
|| socketProtocol == QAbstractSocket::AnyIPProtocol) {
- memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
- sockAddrIPv6.sin6_family = AF_INET6;
- sockAddrIPv6.sin6_port = htons(port);
- sockAddrIPv6.sin6_scope_id = makeScopeId(host);
-
- Q_IPV6ADDR tmp = host.toIPv6Address();
- memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
- sockAddrSize = sizeof(sockAddrIPv6);
- sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
- } else 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;
+ aa.a6.sin6_family = AF_INET6;
+ aa.a6.sin6_port = htons(header.destinationPort);
+ aa.a6.sin6_scope_id = makeScopeId(header.destinationAddress);
+
+ Q_IPV6ADDR tmp = header.destinationAddress.toIPv6Address();
+ memcpy(&aa.a6.sin6_addr, &tmp, sizeof(tmp));
+ msg.msg_namelen = sizeof(aa.a6);
+ } else if (header.destinationAddress.protocol() == QAbstractSocket::IPv4Protocol) {
+ aa.a4.sin_family = AF_INET;
+ aa.a4.sin_port = htons(header.destinationPort);
+ aa.a4.sin_addr.s_addr = htonl(header.destinationAddress.toIPv4Address());
+ msg.msg_namelen = sizeof(aa.a4);
+ } else {
+ // Don't know what IP type this is, let's hope it sends
+ msg.msg_name = 0;
+ msg.msg_namelen = 0;
}
- ssize_t sentBytes = qt_safe_sendto(socketDescriptor, data, len,
- 0, sockAddrPtr, sockAddrSize);
+ ssize_t sentBytes = qt_safe_sendmsg(socketDescriptor, &msg, 0);
if (sentBytes < 0) {
switch (errno) {