diff --git a/dist/changes-5.0.0 b/dist/changes-5.0.0 index 92b4664708..b17353e88b 100644 --- a/dist/changes-5.0.0 +++ b/dist/changes-5.0.0 @@ -70,6 +70,8 @@ QtWidgets QtNetwork --------- +* QHostAddress::isLoopback() API added. Returns true if the address is + one of the IP loopback addresses. QtOpenGL -------- diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index d66d471206..cbd804c44b 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -1109,6 +1109,28 @@ QPair QHostAddress::parseSubnet(const QString &subnet) return qMakePair(QHostAddress(addr), netmask); } +/*! + \since 5.0 + + returns true if the address is the IPv6 loopback address, or any + of the IPv4 loopback addresses. +*/ +bool QHostAddress::isLoopback() const +{ + QT_ENSURE_PARSED(this); + if ((d->a & 0xFF000000) == 0x7F000000) + return true; // v4 range (including IPv6 wrapped IPv4 addresses) + if (d->protocol == QAbstractSocket::IPv6Protocol) { + if (d->a6.c[15] != 1) + return false; + for (int i = 0; i < 15; i++) + if (d->a6[i] != 0) + return false; + return true; + } + return false; +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const QHostAddress &address) { diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h index 3d364de6e6..83e8a7ce3c 100644 --- a/src/network/kernel/qhostaddress.h +++ b/src/network/kernel/qhostaddress.h @@ -120,6 +120,8 @@ public: bool isInSubnet(const QHostAddress &subnet, int netmask) const; bool isInSubnet(const QPair &subnet) const; + bool isLoopback() const; + static QPair parseSubnet(const QString &subnet); protected: diff --git a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp index b20e07be03..7e35830791 100644 --- a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp +++ b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp @@ -82,6 +82,8 @@ private slots: void parseSubnet(); void isInSubnet_data(); void isInSubnet(); + void isLoopback_data(); + void isLoopback(); }; QT_BEGIN_NAMESPACE @@ -607,5 +609,43 @@ void tst_QHostAddress::isInSubnet() QTEST(address.isInSubnet(prefix, prefixLength), "result"); } +void tst_QHostAddress::isLoopback_data() +{ + QTest::addColumn("address"); + QTest::addColumn("result"); + + QTest::newRow("ipv6_loop") << QHostAddress(QHostAddress::LocalHostIPv6) << true; + QTest::newRow("::1") << QHostAddress("::1") << true; + + QTest::newRow("ipv4_loop") << QHostAddress(QHostAddress::LocalHost) << true; + QTest::newRow("127.0.0.1") << QHostAddress("127.0.0.1") << true; + QTest::newRow("127.0.0.2") << QHostAddress("127.0.0.2") << true; + QTest::newRow("127.3.2.1") << QHostAddress("127.3.2.1") << true; + + QTest::newRow("default") << QHostAddress() << false; + QTest::newRow("1.2.3.4") << QHostAddress("1.2.3.4") << false; + QTest::newRow("10.0.0.4") << QHostAddress("10.0.0.4") << false; + QTest::newRow("192.168.3.4") << QHostAddress("192.168.3.4") << false; + + QTest::newRow("::") << QHostAddress("::") << false; + QTest::newRow("Any") << QHostAddress(QHostAddress::Any) << false; + QTest::newRow("AnyIPv4") << QHostAddress(QHostAddress::AnyIPv4) << false; + QTest::newRow("AnyIPv6") << QHostAddress(QHostAddress::AnyIPv6) << false; + QTest::newRow("Broadcast") << QHostAddress(QHostAddress::Broadcast) << false; + QTest::newRow("Null") << QHostAddress(QHostAddress::Null) << false; + + QTest::newRow("::ffff:127.0.0.1") << QHostAddress("::ffff:127.0.0.1") << true; + QTest::newRow("::ffff:127.0.0.2") << QHostAddress("::ffff:127.0.0.2") << true; + QTest::newRow("::ffff:127.3.2.1") << QHostAddress("::ffff:127.3.2.1") << true; +} + +void tst_QHostAddress::isLoopback() +{ + QFETCH(QHostAddress, address); + QFETCH(bool, result); + + QCOMPARE(address.isLoopback(), result); +} + QTEST_MAIN(tst_QHostAddress) #include "tst_qhostaddress.moc"