QAbstractSocketEngine: introduce QIpPacketHeader for datagrams
authorThiago Macieira <thiago.macieira@intel.com>
Tue, 10 Mar 2015 22:01:21 +0000 (15:01 -0700)
committerThiago Macieira <thiago.macieira@intel.com>
Sat, 22 Aug 2015 22:26:23 +0000 (22:26 +0000)
This commit changes the readDatagram() and writeDatagram() virtual
functions to take a QIpPacketHeader as meta data, instead of a
QHostAddress/quint16 pair. As previously, the header is an "out"
parameter for readDatagram() and an "in" parameter for writeDatagram().

The header pointer in readDatagram() is allowed to be null if the
PacketHeaderOptions indicates WantNone. Otherwise, it must not be null.
The extra options parameter is introduced because we may not always want
all the metadata upon reception. For sending, we know what to include or
not based on what's set in the incoming header parameter.

QIpPacketHeader splits sender and destination because we'll be able to
return both on datagram reception.

Change-Id: Iee8cbc07c4434ce9b560ffff13ca4213255008c7
Reviewed-by: Richard J. Moore <rich@kde.org>
14 files changed:
src/network/socket/qabstractsocketengine_p.h
src/network/socket/qhttpsocketengine.cpp
src/network/socket/qhttpsocketengine_p.h
src/network/socket/qnativesocketengine.cpp
src/network/socket/qnativesocketengine_p.h
src/network/socket/qnativesocketengine_unix.cpp
src/network/socket/qnativesocketengine_win.cpp
src/network/socket/qnativesocketengine_winrt.cpp
src/network/socket/qnativesocketengine_winrt_p.h
src/network/socket/qsocks5socketengine.cpp
src/network/socket/qsocks5socketengine_p.h
src/network/socket/qudpsocket.cpp
tests/auto/network/socket/platformsocketengine/tst_platformsocketengine.cpp
tests/auto/network/socket/qsocks5socketengine/tst_qsocks5socketengine.cpp

index f2a314967847d0f16cb81277f7192a856524bc8e..c485e80f5d53c91e1ac7a3ca2e117a8bfaffc224 100644 (file)
@@ -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
index 23347ce08b4b490246a4d9996a791d0c5f2e6efd..1a90abd22c5851b21e6b6db4cc4e1c2260d4d209 100644 (file)
@@ -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;
 }
index 4d90487679ef3fe179fec5669acbb7122c9d678c..41c63fe11e4c5bb53ea426322d4ce1a21d91bf3e 100644 (file)
@@ -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
index 22151b8e56743364a37d3c89f26233d8a517b1e8..901dab5473e6f7fc32012a52b2ee7f55b669078d 100644 (file)
     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 <qabstracteventdispatcher.h>
@@ -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);
 }
 
 /*!
index 653309302c9fc20c3fd0b161df86655ba32ad7f8..fb36ce620438790294498c231f6028d46fd7bcb1 100644 (file)
@@ -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;
index 5c4e4e885b86b6074ccc4768a387f1e06963d19f..0e040962964159f87c89a30648fb3d9d9ca5b8d5 100644 (file)
@@ -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) {
index 8c3f68f04f050212c3b9bd1b770863d25e33d1aa..ed376eed951860d8dede1b88126f064ad4206d20 100644 (file)
@@ -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)
index 2d04946601dc9344b291724e836aedbb4289ba05..4a92ca5a95afdabc1df55515f82aeafdb3135839 100644 (file)
@@ -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<IDataReader> reader;
     hr = args->GetDataReader(&reader);
index eb032bc977a5728e860b819ff234f6a8dcdc52d2..4286ff6373336a4c8684d4ffb8180c4017c41ef5 100644 (file)
@@ -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;
 
index a6eafd2601b8634fbe3ffc2f7ecf8af903badb06..26543883cc133963c9bb1190e6d02c80b374871f 100644 (file)
@@ -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<int>(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);
index c97b0e89ce0991a5948cbd7221953635b4e63445..de20e0ef0e2a384a5078a4f08faf3a8a4d573f2b 100644 (file)
@@ -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
index 87686f94e1c89b953b5897b71fd31c5072c06b57..f4e7d20b0399e1ba23a46e2b49a22ca2c1072b5b 100644 (file)
@@ -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();
index 44081d474f59bac90805df4f1db19c2a680328be..7669aff66a3583eb7d957efada8dbac014673a89 100644 (file)
@@ -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);
 }
 
index 66fd74017eb87048d52c456bc3c5bf86289dc990..8da656aab7562f0c10736748325d816cfa1b7589 100644 (file)
@@ -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()