Add a QHostAddress::toIPv4Address overload taking a bool *ok
This allows one to check whether the conversion is successful without checking for the return result, as the value of 0 represents the valid IPv4 address 0.0.0.0. Change-Id: I637fe55583f2255c85b0d955e5886b61494e0c7c Reviewed-by: Richard J. Moore <rich@kde.org>
This commit is contained in:
parent
ab8d36d6f3
commit
775d04f97e
@ -633,8 +633,32 @@ void QHostAddress::setAddress(const struct sockaddr *sockaddr)
|
|||||||
\sa toString()
|
\sa toString()
|
||||||
*/
|
*/
|
||||||
quint32 QHostAddress::toIPv4Address() const
|
quint32 QHostAddress::toIPv4Address() const
|
||||||
|
{
|
||||||
|
return toIPv4Address(Q_NULLPTR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the IPv4 address as a number.
|
||||||
|
|
||||||
|
For example, if the address is 127.0.0.1, the returned value is
|
||||||
|
2130706433 (i.e. 0x7f000001).
|
||||||
|
|
||||||
|
This value is valid if the protocol() is
|
||||||
|
\l{QAbstractSocket::}{IPv4Protocol},
|
||||||
|
or if the protocol is
|
||||||
|
\l{QAbstractSocket::}{IPv6Protocol},
|
||||||
|
and the IPv6 address is an IPv4 mapped address. (RFC4291). In those
|
||||||
|
cases, \a ok will be set to true. Otherwise, it will be set to false.
|
||||||
|
|
||||||
|
\sa toString()
|
||||||
|
*/
|
||||||
|
quint32 QHostAddress::toIPv4Address(bool *ok) const
|
||||||
{
|
{
|
||||||
QT_ENSURE_PARSED(this);
|
QT_ENSURE_PARSED(this);
|
||||||
|
quint32 dummy;
|
||||||
|
if (ok)
|
||||||
|
*ok = d->protocol == QAbstractSocket::IPv4Protocol || d->protocol == QAbstractSocket::AnyIPProtocol
|
||||||
|
|| (d->protocol == QAbstractSocket::IPv6Protocol && convertToIpv4(dummy, d->a6));
|
||||||
return d->a;
|
return d->a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,8 @@ public:
|
|||||||
bool setAddress(const QString &address);
|
bool setAddress(const QString &address);
|
||||||
|
|
||||||
QAbstractSocket::NetworkLayerProtocol protocol() const;
|
QAbstractSocket::NetworkLayerProtocol protocol() const;
|
||||||
quint32 toIPv4Address() const;
|
quint32 toIPv4Address() const; // ### Qt6: merge with next overload
|
||||||
|
quint32 toIPv4Address(bool *ok) const;
|
||||||
Q_IPV6ADDR toIPv6Address() const;
|
Q_IPV6ADDR toIPv6Address() const;
|
||||||
|
|
||||||
QString toString() const;
|
QString toString() const;
|
||||||
|
@ -83,6 +83,8 @@ private slots:
|
|||||||
void isInSubnet();
|
void isInSubnet();
|
||||||
void isLoopback_data();
|
void isLoopback_data();
|
||||||
void isLoopback();
|
void isLoopback();
|
||||||
|
void convertv4v6_data();
|
||||||
|
void convertv4v6();
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -662,5 +664,51 @@ void tst_QHostAddress::isLoopback()
|
|||||||
QCOMPARE(address.isLoopback(), result);
|
QCOMPARE(address.isLoopback(), result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QHostAddress::convertv4v6_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QHostAddress>("source");
|
||||||
|
QTest::addColumn<int>("protocol");
|
||||||
|
QTest::addColumn<QHostAddress>("result");
|
||||||
|
|
||||||
|
QTest::newRow("any-to-v4") << QHostAddress(QHostAddress::Any) << 4 << QHostAddress(QHostAddress::AnyIPv4);
|
||||||
|
QTest::newRow("any-to-v6") << QHostAddress(QHostAddress::Any) << 6 << QHostAddress(QHostAddress::AnyIPv6);
|
||||||
|
QTest::newRow("anyv4-to-v6") << QHostAddress(QHostAddress::AnyIPv4) << 6 << QHostAddress(QHostAddress::AnyIPv6);
|
||||||
|
QTest::newRow("anyv6-to-v4") << QHostAddress(QHostAddress::AnyIPv6) << 4 << QHostAddress(QHostAddress::AnyIPv4);
|
||||||
|
|
||||||
|
QTest::newRow("v4mapped-to-v4") << QHostAddress("::ffff:192.0.2.1") << 4 << QHostAddress("192.0.2.1");
|
||||||
|
QTest::newRow("v4-to-v4mapped") << QHostAddress("192.0.2.1") << 6 << QHostAddress("::ffff:192.0.2.1");
|
||||||
|
|
||||||
|
// we won't convert 127.0.0.1 to ::1 or vice-versa:
|
||||||
|
// you can connect to a v4 server socket with ::ffff:127.0.0.1, but not with ::1
|
||||||
|
QTest::newRow("localhost-to-v4mapped") << QHostAddress(QHostAddress::LocalHost) << 6 << QHostAddress("::ffff:127.0.0.1");
|
||||||
|
QTest::newRow("v4mapped-to-localhost") << QHostAddress("::ffff:127.0.0.1") << 4 << QHostAddress(QHostAddress::LocalHost);
|
||||||
|
|
||||||
|
// in turn, that means localhost6 doesn't convert to v4
|
||||||
|
QTest::newRow("localhost6-to-v4") << QHostAddress(QHostAddress::LocalHostIPv6) << 4 << QHostAddress();
|
||||||
|
|
||||||
|
// some other v6 addresses that won't convert to v4
|
||||||
|
QTest::newRow("v4compat-to-v4") << QHostAddress("::192.0.2.1") << 4 << QHostAddress();
|
||||||
|
QTest::newRow("localhostv4compat-to-v4") << QHostAddress("::127.0.0.1") << 4 << QHostAddress();
|
||||||
|
QTest::newRow("v6global-to-v4") << QHostAddress("2001:db8::1") << 4 << QHostAddress();
|
||||||
|
QTest::newRow("v6multicast-to-v4") << QHostAddress("ff02::1") << 4 << QHostAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QHostAddress::convertv4v6()
|
||||||
|
{
|
||||||
|
QFETCH(QHostAddress, source);
|
||||||
|
QFETCH(int, protocol);
|
||||||
|
QFETCH(QHostAddress, result);
|
||||||
|
|
||||||
|
if (protocol == 4) {
|
||||||
|
bool ok;
|
||||||
|
quint32 v4 = source.toIPv4Address(&ok);
|
||||||
|
QCOMPARE(ok, result.protocol() == QAbstractSocket::IPv4Protocol);
|
||||||
|
if (ok)
|
||||||
|
QCOMPARE(QHostAddress(v4), result);
|
||||||
|
} else if (protocol == 6) {
|
||||||
|
QCOMPARE(QHostAddress(source.toIPv6Address()), result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QHostAddress)
|
QTEST_MAIN(tst_QHostAddress)
|
||||||
#include "tst_qhostaddress.moc"
|
#include "tst_qhostaddress.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user