diff options
-rw-r--r-- | src/network/socket/qnativesocketengine_unix.cpp | 3 | ||||
-rw-r--r-- | src/network/socket/qnativesocketengine_win.cpp | 3 | ||||
-rw-r--r-- | src/network/socket/qudpsocket.cpp | 4 | ||||
-rw-r--r-- | tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp | 79 |
4 files changed, 86 insertions, 3 deletions
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index b7c149c18d..295d3961a8 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -854,7 +854,8 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l struct sockaddr_in6 sockAddrIPv6; if (host.protocol() == QAbstractSocket::IPv6Protocol - || socketProtocol == QAbstractSocket::IPv6Protocol) { + || socketProtocol == QAbstractSocket::IPv6Protocol + || socketProtocol == QAbstractSocket::AnyIPProtocol) { memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6)); sockAddrIPv6.sin6_family = AF_INET6; sockAddrIPv6.sin6_port = htons(port); diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 93a470c77f..4bf2a6c6e3 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -202,7 +202,8 @@ void QNativeSocketEnginePrivate::setPortAndAddress(sockaddr_in * sockAddrIPv4, q if (address.protocol() == QAbstractSocket::IPv6Protocol || address.protocol() == QAbstractSocket::AnyIPProtocol - || socketProtocol == QAbstractSocket::IPv6Protocol) { + || socketProtocol == QAbstractSocket::IPv6Protocol + || socketProtocol == QAbstractSocket::AnyIPProtocol) { memset(sockAddrIPv6, 0, sizeof(qt_sockaddr_in6)); sockAddrIPv6->sin6_family = AF_INET6; sockAddrIPv6->sin6_scope_id = address.scopeId().toInt(); diff --git a/src/network/socket/qudpsocket.cpp b/src/network/socket/qudpsocket.cpp index a31b16e97d..ec751c289e 100644 --- a/src/network/socket/qudpsocket.cpp +++ b/src/network/socket/qudpsocket.cpp @@ -332,8 +332,10 @@ qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddre qDebug("QUdpSocket::writeDatagram(%p, %llu, \"%s\", %i)", data, size, address.toString().toLatin1().constData(), port); #endif - if (!d->ensureInitialized(address)) + if (!d->doEnsureInitialized(QHostAddress::Any, 0, address)) return -1; + if (state() == UnconnectedState) + bind(); qint64 sent = d->socketEngine->writeDatagram(data, size, address, port); d->cachedSocketDescriptor = d->socketEngine->socketDescriptor(); diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index 3dabe6741a..c53450eec6 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -92,6 +92,8 @@ private slots: void ipv6Loop_data(); void ipv6Loop(); void dualStack(); + void dualStackAutoBinding(); + void dualStackNoIPv4onV6only(); void readLine(); void pendingDatagramSize(); void writeDatagram(); @@ -490,6 +492,83 @@ void tst_QUdpSocket::dualStack() } +void tst_QUdpSocket::dualStackAutoBinding() +{ + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + QSKIP("test server SOCKS proxy doesn't support IPv6"); + QUdpSocket v4Sock; + QVERIFY(v4Sock.bind(QHostAddress(QHostAddress::AnyIPv4), 0)); + + QUdpSocket v6Sock; + QVERIFY(v6Sock.bind(QHostAddress(QHostAddress::AnyIPv6), 0)); + + QByteArray dualData("dual"); + QHostAddress from; + quint16 port; + QByteArray buffer; + int size; + + { + //test an autobound socket can send to both v4 and v6 addresses (v4 first) + QUdpSocket dualSock; + + QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHost), v4Sock.localPort()), dualData.length()); + QVERIFY(v4Sock.waitForReadyRead(5000)); + buffer.reserve(100); + size = v4Sock.readDatagram(buffer.data(), 100, &from, &port); + QCOMPARE((int)size, dualData.length()); + buffer.resize(size); + QCOMPARE(buffer, dualData); + + QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHostIPv6), v6Sock.localPort()), dualData.length()); + QVERIFY(v6Sock.waitForReadyRead(5000)); + buffer.reserve(100); + size = v6Sock.readDatagram(buffer.data(), 100, &from, &port); + QCOMPARE((int)size, dualData.length()); + buffer.resize(size); + QCOMPARE(buffer, dualData); + } + + { + //test an autobound socket can send to both v4 and v6 addresses (v6 first) + QUdpSocket dualSock; + + QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHostIPv6), v6Sock.localPort()), dualData.length()); + QVERIFY(v6Sock.waitForReadyRead(5000)); + buffer.reserve(100); + size = v6Sock.readDatagram(buffer.data(), 100, &from, &port); + QCOMPARE((int)size, dualData.length()); + buffer.resize(size); + QCOMPARE(buffer, dualData); + + QCOMPARE((int)dualSock.writeDatagram(dualData.constData(), dualData.length(), QHostAddress(QHostAddress::LocalHost), v4Sock.localPort()), dualData.length()); + QVERIFY(v4Sock.waitForReadyRead(5000)); + buffer.reserve(100); + size = v4Sock.readDatagram(buffer.data(), 100, &from, &port); + QCOMPARE((int)size, dualData.length()); + buffer.resize(size); + QCOMPARE(buffer, dualData); + } +} + +void tst_QUdpSocket::dualStackNoIPv4onV6only() +{ + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + QSKIP("test server SOCKS proxy doesn't support IPv6"); + QUdpSocket v4Sock; + QVERIFY(v4Sock.bind(QHostAddress(QHostAddress::AnyIPv4), 0)); + QByteArray v4Data("v4"); + + QUdpSocket v6Sock; + QVERIFY(v6Sock.bind(QHostAddress(QHostAddress::AnyIPv6), 0)); + + //test v4 -> v6 (should not be received as this is a v6 only socket) + QCOMPARE((int)v4Sock.writeDatagram(v4Data.constData(), v4Data.length(), QHostAddress(QHostAddress::LocalHost), v6Sock.localPort()), v4Data.length()); + QVERIFY(!v6Sock.waitForReadyRead(1000)); +} + void tst_QUdpSocket::empty_readyReadSlot() { QTestEventLoop::instance().exitLoop(); |