QHostAddress compat bits

the scope parsing and output (from QHostAddress::toString()) is totally not
according to the RFC mentioned in the QHostAddress documentation tho

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2024-03-30 01:42:14 +02:00
parent e2ac5c5b3d
commit 84905cd974
3 changed files with 38 additions and 26 deletions

View file

@ -34,6 +34,8 @@
QT_BEGIN_NAMESPACE
static const char addrscopeseparator = '%';
QHostAddressPrivate::QHostAddressPrivate()
: protocol(QAbstractSocket::UnknownNetworkLayerProtocol)
{
@ -214,21 +216,33 @@ void QHostAddress::clear()
*/
bool QHostAddress::setAddress(const QByteArray &address)
{
// compat
QByteArray scope;
QByteArray fixedaddress(address.trimmed());
if (fixedaddress.contains(':')) {
const int indexofpercent = fixedaddress.indexOf(addrscopeseparator);
if (indexofpercent >= 0) {
scope = fixedaddress.mid(indexofpercent + 1, fixedaddress.size() - indexofpercent - 1);
fixedaddress = fixedaddress.mid(0, indexofpercent);
}
}
int result = 0;
#ifndef QT_NO_IPV6
struct in6_addr inaddripv6;
result = inet_pton(AF_INET6, address.constData(), &inaddripv6);
result = inet_pton(AF_INET6, fixedaddress.constData(), &inaddripv6);
if (result == 1) {
d->protocol = QAbstractSocket::IPv6Protocol;
d->ipString = address;
d->ipString = fixedaddress;
d->scopeId = scope;
return true;
}
#endif
struct in_addr inaddripv4;
result = inet_pton(AF_INET, address.constData(), &inaddripv4);
result = inet_pton(AF_INET, fixedaddress.constData(), &inaddripv4);
if (result == 1) {
d->protocol = QAbstractSocket::IPv4Protocol;
d->ipString = address;
d->ipString = fixedaddress;
d->scopeId.clear();
return true;
}
return false;
@ -281,6 +295,9 @@ QAbstractSocket::NetworkLayerProtocol QHostAddress::protocol() const
*/
QByteArray QHostAddress::toString() const
{
if (d->protocol == QAbstractSocket::IPv6Protocol && !d->scopeId.isEmpty()) {
return d->ipString + addrscopeseparator + d->scopeId;
}
return d->ipString;
}
@ -398,13 +415,9 @@ QDataStream &operator<<(QDataStream &out, const QHostAddress &address)
case QAbstractSocket::UnknownNetworkLayerProtocol: {
break;
}
case QAbstractSocket::IPv4Protocol: {
out << address.toString();
break;
}
case QAbstractSocket::IPv4Protocol:
case QAbstractSocket::IPv6Protocol: {
out << address.toString();
out << address.scopeId();
break;
}
}
@ -431,16 +444,12 @@ QDataStream &operator>>(QDataStream &in, QHostAddress &address)
QByteArray ipv4;
in >> ipv4;
address.setAddress(ipv4);
address.setScopeId(QByteArray());
break;
}
case QAbstractSocket::IPv6Protocol: {
QByteArray ipv6;
QByteArray scope;
in >> ipv6;
in >> scope;
address.setAddress(ipv6);
address.setScopeId(scope);
break;
}
default: {

View file

@ -134,13 +134,15 @@ QList<QNetworkInterfacePrivate *> QNetworkInterfacePrivate::scan()
QNetworkAddressEntry entry;
entry.d->address = addressFromSockaddr(ifiter->ifa_addr);
if (entry.ip().isNull())
if (entry.ip().isNull()) {
// could not parse the address
continue;
}
entry.d->netmask = addressFromSockaddr(ifiter->ifa_netmask);
if (iface->flags & QNetworkInterface::CanBroadcast)
if (iface->flags & QNetworkInterface::CanBroadcast) {
entry.d->broadcast = addressFromSockaddr(ifiter->ifa_broadaddr);
}
iface->addressEntries << entry;

View file

@ -49,10 +49,10 @@ public slots:
void init();
void cleanup();
private slots:
void constructor_QString_data();
void constructor_QString();
void setAddress_QString_data();
void setAddress_QString();
void constructor_QByteArray_data();
void constructor_QByteArray();
void setAddress_QByteArray_data();
void setAddress_QByteArray();
void specialAddresses_data();
void specialAddresses();
void compare_data();
@ -96,15 +96,16 @@ void tst_QHostAddress::cleanup()
// No cleanup is required.
}
void tst_QHostAddress::constructor_QString_data()
void tst_QHostAddress::constructor_QByteArray_data()
{
setAddress_QString_data();
setAddress_QByteArray_data();
}
void tst_QHostAddress::constructor_QString()
void tst_QHostAddress::constructor_QByteArray()
{
QFETCH(QByteArray, address);
QFETCH(bool, ok);
QFETCH(QByteArray, resAddr);
QFETCH(int, protocol);
QHostAddress hostAddr(address);
@ -116,7 +117,7 @@ void tst_QHostAddress::constructor_QString()
}
if (ok)
QTEST(hostAddr.toString(), "resAddr");
QTEST(hostAddr.toString(), resAddr);
if ( protocol == 4 ) {
QVERIFY( hostAddr.protocol() == QAbstractSocket::IPv4Protocol || hostAddr.protocol() == QAbstractSocket::UnknownNetworkLayerProtocol );
@ -130,14 +131,14 @@ void tst_QHostAddress::constructor_QString()
}
}
void tst_QHostAddress::setAddress_QString_data()
void tst_QHostAddress::setAddress_QByteArray_data()
{
QTest::addColumn<QByteArray>("address");
QTest::addColumn<bool>("ok");
QTest::addColumn<QByteArray>("resAddr");
QTest::addColumn<int>("protocol"); // 4: IPv4, 6: IPv6, other: undefined
//next we fill it with data
// next fill it with data
QTest::newRow("ip4_00") << QByteArray("127.0.0.1") << (bool)true << QByteArray("127.0.0.1") << 4;
QTest::newRow("ip4_01") << QByteArray("255.3.2.1") << (bool)true << QByteArray("255.3.2.1") << 4;
QTest::newRow("ip4_03") << QByteArray(" 255.3.2.1") << (bool)true << QByteArray("255.3.2.1") << 4;
@ -202,7 +203,7 @@ void tst_QHostAddress::setAddress_QString_data()
}
void tst_QHostAddress::setAddress_QString()
void tst_QHostAddress::setAddress_QByteArray()
{
QFETCH(QByteArray, address);
QFETCH(bool, ok);