diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2017-11-28 16:49:00 -0800 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2017-12-29 00:10:54 +0000 |
commit | 198c59dbce63e97ef0fa8f75236ee8b2887997c2 (patch) | |
tree | d39cf80c4c4a74ed9d9e3ea229ae4ad293fc4e3c /tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp | |
parent | 656804b9645a83430dcd0929c49b4065d43d7990 (diff) |
tst_QUdpSocket: always use an interface when binding to IPv6
Binding without an interface and expecting the OS to select something is
not supported in all OSes. On FreeBSD, I keep getting EADDRNOTAVAIL. So
modify our test to only join, leave and send to multicast groups with an
interface selection.
With this, all tests either pass or are skipped for me on Linux,
FreeBSD, and macOS. On Windows, this revealed an inconsistency in
behavior, which this commit adds a workaround for.
Change-Id: Ifb5969bf206e4cd7b14efffd14fb6815456494d2
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Diffstat (limited to 'tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp')
-rw-r--r-- | tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index 69d549d738..5fdf014fc6 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -122,6 +122,7 @@ private: #ifdef SHOULD_CHECK_SYSCALL_SUPPORT bool ipv6SetsockoptionMissing(int level, int optname); #endif + QNetworkInterface interfaceForGroup(const QHostAddress &multicastGroup); bool m_skipUnsupportedIPv6Tests; QList<QHostAddress> allAddresses; @@ -167,6 +168,33 @@ bool tst_QUdpSocket::shouldSkipIpv6TestsForBrokenSetsockopt() return false; } +QNetworkInterface tst_QUdpSocket::interfaceForGroup(const QHostAddress &multicastGroup) +{ + if (multicastGroup.protocol() == QAbstractSocket::IPv4Protocol) + return QNetworkInterface(); + + static QNetworkInterface ipv6if = [=]() { + // find any link local address in the allAddress list + for (const QHostAddress &addr: qAsConst(allAddresses)) { + if (addr.isLoopback()) + continue; + + QString scope = addr.scopeId(); + if (!scope.isEmpty()) { + QNetworkInterface iface = QNetworkInterface::interfaceFromName(scope); + qDebug() << "Will bind IPv6 sockets to" << iface; + return iface; + } + } + + qWarning("interfaceForGroup(%s) could not find any link-local IPv6 address! " + "Make sure this test is behind a check of QtNetworkSettings::hasIPv6().", + qUtf8Printable(multicastGroup.toString())); + return QNetworkInterface(); + }(); + return ipv6if; +} + static QHostAddress makeNonAny(const QHostAddress &address, QHostAddress::SpecialAddress preferForAny = QHostAddress::LocalHost) { if (address == QHostAddress::Any) @@ -1299,7 +1327,7 @@ void tst_QUdpSocket::multicastLeaveAfterClose() bindAddress = QHostAddress::AnyIPv6; QVERIFY2(udpSocket.bind(bindAddress, 0), qPrintable(udpSocket.errorString())); - QVERIFY2(udpSocket.joinMulticastGroup(groupAddress), + QVERIFY2(udpSocket.joinMulticastGroup(groupAddress, interfaceForGroup(groupAddress)), qPrintable(udpSocket.errorString())); udpSocket.close(); QTest::ignoreMessage(QtWarningMsg, "QUdpSocket::leaveMulticastGroup() called on a QUdpSocket when not in QUdpSocket::BoundState"); @@ -1413,7 +1441,7 @@ void tst_QUdpSocket::multicast() "QAbstractSocket: cannot bind to QHostAddress::Any (or an IPv6 address) and join an IPv4 multicast group;" " bind to QHostAddress::AnyIPv4 instead if you want to do this"); } - QVERIFY2(receiver.joinMulticastGroup(groupAddress) == joinResult, + QVERIFY2(receiver.joinMulticastGroup(groupAddress, interfaceForGroup(groupAddress)) == joinResult, qPrintable(receiver.errorString())); if (!joinResult) return; @@ -1427,7 +1455,9 @@ void tst_QUdpSocket::multicast() QUdpSocket sender; sender.bind(); foreach (const QByteArray &datagram, datagrams) { - QCOMPARE(int(sender.writeDatagram(datagram, groupAddress, receiver.localPort())), + QNetworkDatagram dgram(datagram, groupAddress, receiver.localPort()); + dgram.setInterfaceIndex(interfaceForGroup(groupAddress).index()); + QCOMPARE(int(sender.writeDatagram(dgram)), int(datagram.size())); } @@ -1452,7 +1482,8 @@ void tst_QUdpSocket::multicast() } QCOMPARE(receivedDatagrams, datagrams); - QVERIFY2(receiver.leaveMulticastGroup(groupAddress), qPrintable(receiver.errorString())); + QVERIFY2(receiver.leaveMulticastGroup(groupAddress, interfaceForGroup(groupAddress)), + qPrintable(receiver.errorString())); } void tst_QUdpSocket::echo_data() |