diff options
4 files changed, 70 insertions, 1 deletions
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index ae7e239309..09aed255d6 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -922,6 +922,21 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() return false; } +#if defined (IPV6_V6ONLY) + // determine if local address is dual mode + int ipv6only = 0; + socklen_t optlen = sizeof(ipv6only); + if (localAddress == QHostAddress::AnyIPv6 + && !getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, &optlen )) { + if (optlen != sizeof(ipv6only)) + qWarning("unexpected size of IPV6_V6ONLY socket option"); + if (!ipv6only) { + socketProtocol = QAbstractSocket::AnyIPProtocol; + localAddress = QHostAddress::Any; + } + } +#endif + // Determine the remote address if (!::getpeername(socketDescriptor, &sa.a, &sockAddrSize)) qt_socket_getPortAndAddress(&sa, &peerPort, &peerAddress); diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 4be930bb20..247de01072 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -554,6 +554,22 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() } } +#if defined (IPV6_V6ONLY) + // determine if local address is dual mode + DWORD ipv6only = 0; + int optlen = sizeof(ipv6only); + if (localAddress == QHostAddress::AnyIPv6 + && QSysInfo::windowsVersion() >= QSysInfo::WV_6_0 + && !getsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, &optlen )) { + if (optlen != sizeof(ipv6only)) + qWarning("unexpected size of IPV6_V6ONLY socket option"); + if (!ipv6only) { + socketProtocol = QAbstractSocket::AnyIPProtocol; + localAddress = QHostAddress::Any; + } + } +#endif + memset(&sa, 0, sizeof(sa)); if (::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0) { qt_socket_getPortAndAddress(socketDescriptor, &sa, &peerPort, &peerAddress); diff --git a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp index 0cdd3a7120..769544e17e 100644 --- a/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp +++ b/tests/auto/network/socket/qtcpserver/tst_qtcpserver.cpp @@ -116,6 +116,8 @@ private slots: void qtbug14268_peek(); + void serverAddress_data(); + void serverAddress(); private: #ifndef QT_NO_BEARERMANAGEMENT QNetworkSession *networkSession; @@ -789,5 +791,39 @@ void tst_QTcpServer::qtbug14268_peek() QVERIFY(helper.lastDataPeeked == QByteArray("6162630a6465660a6768690a")); } +void tst_QTcpServer::serverAddress_data() +{ + QTest::addColumn<QHostAddress>("listenAddress"); + QTest::addColumn<QHostAddress>("serverAddress"); +#ifdef Q_OS_WIN + if (QSysInfo::windowsVersion() < QSysInfo::WV_6_0) + QTest::newRow("Any") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::AnyIPv4); //windows XP doesn't support dual stack sockets + else +#endif + QTest::newRow("Any") << QHostAddress(QHostAddress::Any) << QHostAddress(QHostAddress::Any); + QTest::newRow("AnyIPv4") << QHostAddress(QHostAddress::AnyIPv4) << QHostAddress(QHostAddress::AnyIPv4); + QTest::newRow("AnyIPv6") << QHostAddress(QHostAddress::AnyIPv6) << QHostAddress(QHostAddress::AnyIPv6); + foreach (const QHostAddress& addr, QNetworkInterface::allAddresses()) { + if (addr.isInSubnet(QHostAddress::parseSubnet("fe80::/10")) + || addr.isInSubnet(QHostAddress::parseSubnet("169.254/16"))) + continue; //cannot bind on link local addresses + QTest::newRow(qPrintable(addr.toString())) << addr << addr; + } +} + +void tst_QTcpServer::serverAddress() +{ + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + QFETCH(QHostAddress, listenAddress); + QFETCH(QHostAddress, serverAddress); + QTcpServer server; + if (!server.listen(listenAddress)) + QSKIP(qPrintable(server.errorString())); + QCOMPARE(server.serverAddress(), serverAddress); +} + QTEST_MAIN(tst_QTcpServer) #include "tst_qtcpserver.moc" diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index 9c87ac04a0..00a9ed2d40 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -1542,7 +1542,9 @@ void tst_QTcpSocket::dontCloseOnTimeout() QVERIFY(server.listen()); QHostAddress serverAddress = QHostAddress::LocalHost; - if (!(server.serverAddress() == QHostAddress::AnyIPv4) && !(server.serverAddress() == QHostAddress::AnyIPv6)) + if (!(server.serverAddress() == QHostAddress::AnyIPv4) + && !(server.serverAddress() == QHostAddress::AnyIPv6) + && !(server.serverAddress() == QHostAddress::Any)) serverAddress = server.serverAddress(); QTcpSocket *socket = newSocket(); |