Fix QTcpServer::serverAddress() for dual stack sockets
When listening on QHostAddress::Any, serverAddress() should return QHostAddress::Any too, assuming that setting the socket options was successful. Task-number: QTBUG-22899 Change-Id: I50a9ff1b4ad0c1c1905e2952c595d7068df2627d Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
0fc713b436
commit
1a52819c70
@ -922,6 +922,21 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
|
|||||||
return false;
|
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
|
// Determine the remote address
|
||||||
if (!::getpeername(socketDescriptor, &sa.a, &sockAddrSize))
|
if (!::getpeername(socketDescriptor, &sa.a, &sockAddrSize))
|
||||||
qt_socket_getPortAndAddress(&sa, &peerPort, &peerAddress);
|
qt_socket_getPortAndAddress(&sa, &peerPort, &peerAddress);
|
||||||
|
@ -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));
|
memset(&sa, 0, sizeof(sa));
|
||||||
if (::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
|
if (::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
|
||||||
qt_socket_getPortAndAddress(socketDescriptor, &sa, &peerPort, &peerAddress);
|
qt_socket_getPortAndAddress(socketDescriptor, &sa, &peerPort, &peerAddress);
|
||||||
|
@ -116,6 +116,8 @@ private slots:
|
|||||||
|
|
||||||
void qtbug14268_peek();
|
void qtbug14268_peek();
|
||||||
|
|
||||||
|
void serverAddress_data();
|
||||||
|
void serverAddress();
|
||||||
private:
|
private:
|
||||||
#ifndef QT_NO_BEARERMANAGEMENT
|
#ifndef QT_NO_BEARERMANAGEMENT
|
||||||
QNetworkSession *networkSession;
|
QNetworkSession *networkSession;
|
||||||
@ -789,5 +791,39 @@ void tst_QTcpServer::qtbug14268_peek()
|
|||||||
QVERIFY(helper.lastDataPeeked == QByteArray("6162630a6465660a6768690a"));
|
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)
|
QTEST_MAIN(tst_QTcpServer)
|
||||||
#include "tst_qtcpserver.moc"
|
#include "tst_qtcpserver.moc"
|
||||||
|
@ -1542,7 +1542,9 @@ void tst_QTcpSocket::dontCloseOnTimeout()
|
|||||||
QVERIFY(server.listen());
|
QVERIFY(server.listen());
|
||||||
|
|
||||||
QHostAddress serverAddress = QHostAddress::LocalHost;
|
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();
|
serverAddress = server.serverAddress();
|
||||||
|
|
||||||
QTcpSocket *socket = newSocket();
|
QTcpSocket *socket = newSocket();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user