diff --git a/src/network/socket/qabstractsocketengine_p.h b/src/network/socket/qabstractsocketengine_p.h index f2a3149678..c485e80f5d 100644 --- a/src/network/socket/qabstractsocketengine_p.h +++ b/src/network/socket/qabstractsocketengine_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtNetwork module of the Qt Toolkit. @@ -58,6 +59,26 @@ class QNetworkInterface; #endif class QNetworkProxy; +class QIpPacketHeader +{ +public: + QIpPacketHeader(const QHostAddress &dstAddr = QHostAddress(), quint16 port = 0) + : destinationAddress(dstAddr), destinationPort(port) + {} + + void clear() + { + senderAddress.clear(); + destinationAddress.clear(); + } + + QHostAddress senderAddress; + QHostAddress destinationAddress; + + quint16 senderPort; + quint16 destinationPort; +}; + class QAbstractSocketEngineReceiver { public: virtual ~QAbstractSocketEngineReceiver(){} @@ -96,6 +117,14 @@ public: TypeOfServiceOption }; + enum PacketHeaderOption { + WantNone = 0, + WantDatagramSender, + + WantAll = 0xff + }; + Q_DECLARE_FLAGS(PacketHeaderOptions, PacketHeaderOption) + virtual bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol) = 0; virtual bool initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState) = 0; @@ -126,10 +155,9 @@ public: virtual bool setMulticastInterface(const QNetworkInterface &iface) = 0; #endif // QT_NO_NETWORKINTERFACE - virtual qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, - quint16 *port = 0) = 0; - virtual qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, - quint16 port) = 0; + virtual qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header = 0, + PacketHeaderOptions = WantNone) = 0; + virtual qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header) = 0; virtual bool hasPendingDatagrams() const = 0; virtual qint64 pendingDatagramSize() const = 0; #endif // QT_NO_UDPSOCKET @@ -225,6 +253,8 @@ private: friend class QAbstractSocketEngine; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractSocketEngine::PacketHeaderOptions) + QT_END_NAMESPACE #endif // QABSTRACTSOCKETENGINE_P_H diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index 23347ce08b..1a90abd22c 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -271,14 +271,12 @@ bool QHttpSocketEngine::setMulticastInterface(const QNetworkInterface &) } #endif // QT_NO_NETWORKINTERFACE -qint64 QHttpSocketEngine::readDatagram(char *, qint64, QHostAddress *, - quint16 *) +qint64 QHttpSocketEngine::readDatagram(char *, qint64, QIpPacketHeader *, PacketHeaderOptions) { return 0; } -qint64 QHttpSocketEngine::writeDatagram(const char *, qint64, const QHostAddress &, - quint16) +qint64 QHttpSocketEngine::writeDatagram(const char *, qint64, const QIpPacketHeader &) { return 0; } diff --git a/src/network/socket/qhttpsocketengine_p.h b/src/network/socket/qhttpsocketengine_p.h index 4d90487679..41c63fe11e 100644 --- a/src/network/socket/qhttpsocketengine_p.h +++ b/src/network/socket/qhttpsocketengine_p.h @@ -105,10 +105,9 @@ public: bool setMulticastInterface(const QNetworkInterface &iface) Q_DECL_OVERRIDE; #endif // QT_NO_NETWORKINTERFACE - qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, - quint16 *port = 0) Q_DECL_OVERRIDE; - qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, - quint16 port) Q_DECL_OVERRIDE; + qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *, + PacketHeaderOptions) Q_DECL_OVERRIDE; + qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) Q_DECL_OVERRIDE; bool hasPendingDatagrams() const Q_DECL_OVERRIDE; qint64 pendingDatagramSize() const Q_DECL_OVERRIDE; #endif // QT_NO_UDPSOCKET diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index 22151b8e56..901dab5473 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -88,6 +88,25 @@ errorString() can be called to determine the cause of the error. */ +/*! + \enum QAbstractSocketEngine::PacketHeaderOption + + Specifies which fields in the IP packet header are desired in the call to + readDatagram(). + + \value WantNone caller isn't interested in the packet metadata + \value WantDatagramSender caller wants the sender address and port number + \value WantDatagramDestination caller wants the packet's destination address and port number + (this option is useful to distinguish multicast packets from unicast) + \value WantDatagramHopLimit caller wants the packet's remaining hop limit or time to live + (this option is useful in IPv4 multicasting, where the TTL is used + to indicate the realm) + \value WantAll this is a catch-all value to indicate the caller is + interested in all the available information + + \sa readDatagram(), QUdpDatagram +*/ + #include "qnativesocketengine_p.h" #include @@ -759,9 +778,8 @@ qint64 QNativeSocketEngine::pendingDatagramSize() const /*! Reads up to \a maxSize bytes of a datagram from the socket, stores it in \a data and returns the number of bytes read. The - address and port of the sender are stored in \a address and \a - port. If either of these pointers is 0, the corresponding value is - discarded. + address, port, and other IP header fields are stored in \a header + according to the request in \a options. To avoid unnecessarily loss of data, call pendingDatagramSize() to determine the size of the pending message before reading it. If \a @@ -771,20 +789,23 @@ qint64 QNativeSocketEngine::pendingDatagramSize() const \sa hasPendingDatagrams() */ -qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxSize, QHostAddress *address, - quint16 *port) +qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxSize, QIpPacketHeader *header, + PacketHeaderOptions options) { Q_D(QNativeSocketEngine); Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::readDatagram(), -1); Q_CHECK_TYPE(QNativeSocketEngine::readDatagram(), QAbstractSocket::UdpSocket, -1); - return d->nativeReceiveDatagram(data, maxSize, address, port); + return d->nativeReceiveDatagram(data, maxSize, header, options); } /*! Writes a UDP datagram of size \a size bytes to the socket from - \a data to the address \a host on port \a port, and returns the - number of bytes written, or -1 if an error occurred. + \a data to the destination contained in \a header, and returns the + number of bytes written, or -1 if an error occurred. If \a header + contains other settings like hop limit or source address, this function + will try to pass them to the operating system too, but will not + indicate an error if it could not pass them. Only one datagram is sent, and if there is too much data to fit into a single datagram, the operation will fail and error() @@ -794,18 +815,19 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxSize, QHostAddres disadvised, as even if they are sent successfully, they are likely to be fragmented before arriving at their destination. - Experience has shown that it is in general safe to send datagrams - no larger than 512 bytes. + Experience has shown that it is in general safe to send IPv4 datagrams + no larger than 512 bytes or IPv6 datagrams no larger than 1280 (the + minimum MTU). \sa readDatagram() */ -qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 size, - const QHostAddress &host, quint16 port) +qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 size, const QIpPacketHeader &header) { Q_D(QNativeSocketEngine); Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::writeDatagram(), -1); Q_CHECK_TYPE(QNativeSocketEngine::writeDatagram(), QAbstractSocket::UdpSocket, -1); - return d->nativeSendDatagram(data, size, d->adjustAddressProtocol(host), port); + + return d->nativeSendDatagram(data, size, header); } /*! diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index 653309302c..fb36ce6204 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -133,10 +133,9 @@ public: qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE; qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE; - qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, - quint16 *port = 0) Q_DECL_OVERRIDE; - qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, - quint16 port) Q_DECL_OVERRIDE; + qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0, + PacketHeaderOptions = WantNone) Q_DECL_OVERRIDE; + qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) Q_DECL_OVERRIDE; bool hasPendingDatagrams() const Q_DECL_OVERRIDE; qint64 pendingDatagramSize() const Q_DECL_OVERRIDE; @@ -242,10 +241,9 @@ public: bool nativeHasPendingDatagrams() const; qint64 nativePendingDatagramSize() const; - qint64 nativeReceiveDatagram(char *data, qint64 maxLength, - QHostAddress *address, quint16 *port); - qint64 nativeSendDatagram(const char *data, qint64 length, - const QHostAddress &host, quint16 port); + qint64 nativeReceiveDatagram(char *data, qint64 maxLength, QIpPacketHeader *header, + QAbstractSocketEngine::PacketHeaderOptions options); + qint64 nativeSendDatagram(const char *data, qint64 length, const QIpPacketHeader &header); qint64 nativeRead(char *data, qint64 maxLength); qint64 nativeWrite(const char *data, qint64 length); int nativeSelect(int timeout, bool selectForRead) const; diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 5c4e4e885b..0e04096296 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -844,8 +844,8 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const return qint64(recvResult); } -qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, - QHostAddress *address, quint16 *port) +qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, QIpPacketHeader *header, + QAbstractSocketEngine::PacketHeaderOptions options) { qt_sockaddr aa; memset(&aa, 0, sizeof(aa)); @@ -861,8 +861,11 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS if (recvFromResult == -1) { setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); - } else if (port || address) { - qt_socket_getPortAndAddress(&aa, port, address); + if (header) + header->clear(); + } else if (options != QAbstractSocketEngine::WantNone) { + Q_ASSERT(header); + qt_socket_getPortAndAddress(&aa, &header->senderPort, &header->senderAddress); } #if defined (QNATIVESOCKETENGINE_DEBUG) @@ -875,14 +878,15 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS return qint64(maxSize ? recvFromResult : recvFromResult == -1 ? -1 : 0); } -qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, - const QHostAddress &host, quint16 port) +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 sockaddr_in6 sockAddrIPv6; + const QHostAddress &host = header.destinationAddress; + quint16 port = header.destinationPort; if (host.protocol() == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::IPv6Protocol || socketProtocol == QAbstractSocket::AnyIPProtocol) { diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 8c3f68f04f..ed376eed95 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -1197,8 +1197,8 @@ qint64 QNativeSocketEnginePrivate::nativePendingDatagramSize() const } -qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength, - QHostAddress *address, quint16 *port) +qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxLength, QIpPacketHeader *header, + QAbstractSocketEngine::PacketHeaderOptions options) { qint64 ret = 0; @@ -1232,12 +1232,15 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL WS_ERROR_DEBUG(err); setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); ret = -1; + if (header) + header->clear(); } } else { ret = qint64(bytesRead); + if (options & QNativeSocketEngine::WantDatagramSender) + qt_socket_getPortAndAddress(socketDescriptor, &aa, &header->senderPort, &header->senderAddress); } - qt_socket_getPortAndAddress(socketDescriptor, &aa, port, address); #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %li, %s, %i) == %li", @@ -1251,7 +1254,7 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 len, - const QHostAddress &address, quint16 port) + const QIpPacketHeader &header) { qint64 ret = -1; struct sockaddr_in sockAddrIPv4; @@ -1259,7 +1262,8 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l struct sockaddr *sockAddrPtr = 0; QT_SOCKLEN_T sockAddrSize = 0; - setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize); + setPortAndAddress(&sockAddrIPv4, &sockAddrIPv6, header.destinationPort, + header.destinationAddress, &sockAddrPtr, &sockAddrSize); WSABUF buf; #if !defined(Q_OS_WINCE) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 2d04946601..4a92ca5a95 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -538,18 +538,19 @@ qint64 QNativeSocketEngine::write(const char *data, qint64 len) return bytesWritten; } -qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress *addr, quint16 *port) +qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header, + PacketHeaderOptions options) { Q_D(QNativeSocketEngine); - if (d->socketType != QAbstractSocket::UdpSocket || d->pendingDatagrams.isEmpty()) + if (d->socketType != QAbstractSocket::UdpSocket || d->pendingDatagrams.isEmpty()) { + if (header) + header->clear(); return -1; + } WinRtDatagram datagram = d->pendingDatagrams.takeFirst(); - if (addr) - *addr = datagram.address; - - if (port) - *port = datagram.port; + if (header) + *header = datagram.header; QByteArray readOrigin; // Do not read the whole datagram. Put the rest of it back into the "queue" @@ -564,7 +565,7 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress return readOrigin.length(); } -qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QHostAddress &addr, quint16 port) +qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header) { Q_D(QNativeSocketEngine); if (d->socketType != QAbstractSocket::UdpSocket) @@ -1230,11 +1231,11 @@ HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, I remoteHost->get_CanonicalName(remoteHostString.GetAddressOf()); RETURN_OK_IF_FAILED("Could not obtain remote host's canonical name"); returnAddress.setAddress(qt_QStringFromHString(remoteHostString)); - datagram.address = returnAddress; + datagram.header.senderAddress = returnAddress; HString remotePort; hr = args->get_RemotePort(remotePort.GetAddressOf()); RETURN_OK_IF_FAILED("Could not obtain remote port"); - datagram.port = qt_QStringFromHString(remotePort).toInt(); + datagram.header.senderPort = qt_QStringFromHString(remotePort).toInt(); ComPtr reader; hr = args->GetDataReader(&reader); diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index eb032bc977..4286ff6373 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -58,8 +58,7 @@ class QNativeSocketEnginePrivate; struct WinRtDatagram { QByteArray data; - int port; - QHostAddress address; + QIpPacketHeader header; }; class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine @@ -97,10 +96,8 @@ public: qint64 read(char *data, qint64 maxlen); qint64 write(const char *data, qint64 len); - qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, - quint16 *port = 0); - qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, - quint16 port); + qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader *, PacketHeaderOptions); + qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header); bool hasPendingDatagrams() const; qint64 pendingDatagramSize() const; diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp index a6eafd2601..26543883cc 100644 --- a/src/network/socket/qsocks5socketengine.cpp +++ b/src/network/socket/qsocks5socketengine.cpp @@ -1383,7 +1383,7 @@ bool QSocks5SocketEngine::bind(const QHostAddress &addr, quint16 port) #endif dummy.setProxy(QNetworkProxy::NoProxy); if (!dummy.bind() - || writeDatagram(0,0, d->data->controlSocket->localAddress(), dummy.localPort()) != 0 + || writeDatagram(0,0, QIpPacketHeader(d->data->controlSocket->localAddress(), dummy.localPort())) != 0 || !dummy.waitForReadyRead(qt_subtract_from_timeout(msecs, stopWatch.elapsed())) || dummy.readDatagram(0,0, &d->localAddress, &d->localPort) != 0) { QSOCKS5_DEBUG << "udp actual address and port lookup failed"; @@ -1555,7 +1555,7 @@ qint64 QSocks5SocketEngine::write(const char *data, qint64 len) #ifndef QT_NO_UDPSOCKET } else if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode) { // send to connected address - return writeDatagram(data, len, d->peerAddress, d->peerPort); + return writeDatagram(data, len, QIpPacketHeader(d->peerAddress, d->peerPort)); #endif } //### set an error ??? @@ -1594,8 +1594,7 @@ bool QSocks5SocketEngine::setMulticastInterface(const QNetworkInterface &) } #endif // QT_NO_NETWORKINTERFACE -qint64 QSocks5SocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress *addr, - quint16 *port) +qint64 QSocks5SocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header, PacketHeaderOptions) { Q_D(QSocks5SocketEngine); @@ -1607,15 +1606,12 @@ qint64 QSocks5SocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress QSocks5RevivedDatagram datagram = d->udpData->pendingDatagrams.dequeue(); int copyLen = qMin(maxlen, datagram.data.size()); memcpy(data, datagram.data.constData(), copyLen); - if (addr) - *addr = datagram.address; - if (port) - *port = datagram.port; + header->senderAddress = datagram.address; + header->senderPort = datagram.port; return copyLen; } -qint64 QSocks5SocketEngine::writeDatagram(const char *data, qint64 len, const QHostAddress &address, - quint16 port) +qint64 QSocks5SocketEngine::writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header) { Q_D(QSocks5SocketEngine); @@ -1634,7 +1630,7 @@ qint64 QSocks5SocketEngine::writeDatagram(const char *data, qint64 len, const QH outBuf[0] = 0x00; outBuf[1] = 0x00; outBuf[2] = 0x00; - if (!qt_socks5_set_host_address_and_port(address, port, &outBuf)) { + if (!qt_socks5_set_host_address_and_port(header.destinationAddress, header.destinationPort, &outBuf)) { } outBuf += QByteArray(data, len); QSOCKS5_DEBUG << "sending" << dump(outBuf); diff --git a/src/network/socket/qsocks5socketengine_p.h b/src/network/socket/qsocks5socketengine_p.h index c97b0e89ce..de20e0ef0e 100644 --- a/src/network/socket/qsocks5socketengine_p.h +++ b/src/network/socket/qsocks5socketengine_p.h @@ -93,10 +93,9 @@ public: bool setMulticastInterface(const QNetworkInterface &iface) Q_DECL_OVERRIDE; #endif // QT_NO_NETWORKINTERFACE - qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *addr = 0, - quint16 *port = 0) Q_DECL_OVERRIDE; - qint64 writeDatagram(const char *data, qint64 len, const QHostAddress &addr, - quint16 port) Q_DECL_OVERRIDE; + qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0, + PacketHeaderOptions = WantNone) Q_DECL_OVERRIDE; + qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &) Q_DECL_OVERRIDE; bool hasPendingDatagrams() const Q_DECL_OVERRIDE; qint64 pendingDatagramSize() const Q_DECL_OVERRIDE; #endif // QT_NO_UDPSOCKET diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index 87686f94e1..f4e7d20b03 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -333,7 +333,7 @@ qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddre if (state() == UnconnectedState) bind(); - qint64 sent = d->socketEngine->writeDatagram(data, size, address, port); + qint64 sent = d->socketEngine->writeDatagram(data, size, QIpPacketHeader(address, port)); d->cachedSocketDescriptor = d->socketEngine->socketDescriptor(); if (sent >= 0) { @@ -379,7 +379,20 @@ qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *addres qDebug("QUdpSocket::readDatagram(%p, %llu, %p, %p)", data, maxSize, address, port); #endif QT_CHECK_BOUND("QUdpSocket::readDatagram()", -1); - qint64 readBytes = d->socketEngine->readDatagram(data, maxSize, address, port); + + qint64 readBytes; + if (address || port) { + QIpPacketHeader header; + readBytes = d->socketEngine->readDatagram(data, maxSize, &header, + QAbstractSocketEngine::WantDatagramSender); + if (address) + *address = header.senderAddress; + if (port) + *port = header.senderPort; + } else { + readBytes = d->socketEngine->readDatagram(data, maxSize); + } + d_func()->socketEngine->setReadNotificationEnabled(true); if (readBytes < 0) { d->socketError = d->socketEngine->error(); diff --git a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp index 44081d474f..7669aff66a 100644 --- a/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp +++ b/tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp @@ -243,13 +243,13 @@ void tst_PlatformSocketEngine::udpLoopbackTest() QVERIFY(available > 0); QByteArray answer; answer.resize(available); - QHostAddress senderAddress; - quint16 senderPort = 0; - QVERIFY(udpSocket.readDatagram(answer.data(), answer.size(), - &senderAddress, - &senderPort) == message1.size()); - QCOMPARE(senderAddress, QHostAddress("127.0.0.1")); - QVERIFY(senderPort != 0); + QIpPacketHeader header; + QCOMPARE(udpSocket.readDatagram(answer.data(), answer.size(), + &header, QAbstractSocketEngine::WantDatagramSender), + qint64(message1.size())); + QVERIFY(header.senderAddress == QHostAddress("127.0.0.1")); + QCOMPARE(header.senderAddress, QHostAddress("127.0.0.1")); + QVERIFY(header.senderPort != 0); } //--------------------------------------------------------------------------- @@ -291,13 +291,13 @@ void tst_PlatformSocketEngine::udpIPv6LoopbackTest() QVERIFY(available > 0); QByteArray answer; answer.resize(available); - QHostAddress senderAddress; - quint16 senderPort = 0; - QVERIFY(udpSocket.readDatagram(answer.data(), answer.size(), - &senderAddress, - &senderPort) == message1.size()); - QCOMPARE(senderAddress, QHostAddress("::1")); - QVERIFY(senderPort != 0); + QIpPacketHeader header; + QCOMPARE(udpSocket.readDatagram(answer.data(), answer.size(), + &header, QAbstractSocketEngine::WantDatagramSender), + qint64(message1.size())); + QVERIFY(header.senderAddress == QHostAddress("::1")); + QCOMPARE(header.senderAddress, QHostAddress("::1")); + QVERIFY(header.senderPort != 0); } } @@ -323,8 +323,7 @@ void tst_PlatformSocketEngine::broadcastTest() = "MOOT wtf is a MOOT? talk english not your sutpiD ENGLISH."; qint64 written = broadcastSocket.writeDatagram(trollMessage.data(), trollMessage.size(), - QHostAddress::Broadcast, - port); + QIpPacketHeader(QHostAddress::Broadcast, port)); QCOMPARE((int)written, trollMessage.size()); @@ -636,7 +635,7 @@ void tst_PlatformSocketEngine::invalidSend() QTest::ignoreMessage(QtWarningMsg, PLATFORMSOCKETENGINESTRING "::writeDatagram() was" " called by a socket other than QAbstractSocket::UdpSocket"); - QCOMPARE(socket.writeDatagram("hei", 3, QHostAddress::LocalHost, 143), + QCOMPARE(socket.writeDatagram("hei", 3, QIpPacketHeader(QHostAddress::LocalHost, 143)), (qlonglong) -1); } diff --git a/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp b/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp index 66fd74017e..8da656aab7 100644 --- a/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp +++ b/tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp @@ -591,13 +591,13 @@ void tst_QSocks5SocketEngine::udpTest() QVERIFY(available > 0); QByteArray answer; answer.resize(available); - QHostAddress senderAddress; - quint16 senderPort = 0; - QVERIFY(udpSocket.readDatagram(answer.data(), answer.size(), - &senderAddress, - &senderPort) == message1.size()); - QCOMPARE(senderAddress, udpSocket2.localAddress()); - QCOMPARE(senderPort, udpSocket2.localPort()); + QIpPacketHeader header; + QCOMPARE(udpSocket.readDatagram(answer.data(), answer.size(), + &header, QAbstractSocketEngine::WantDatagramSender), + qint64(message1.size())); + QVERIFY(header.senderAddress == udpSocket2.localAddress()); + QCOMPARE(header.senderAddress, udpSocket2.localAddress()); + QCOMPARE(header.senderPort, udpSocket2.localPort()); } void tst_QSocks5SocketEngine::tcpSocketBlockingTest()