summaryrefslogtreecommitdiffstats
path: root/src/network/kernel
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2017-08-10 20:34:31 -0700
committerThiago Macieira <thiago.macieira@intel.com>2017-09-25 05:38:24 +0000
commit8656ee950b4f57eae605180fd8328441b3e670b9 (patch)
tree53c533a39977fc53e0a0dd16a2e7be558e344621 /src/network/kernel
parent758982bd74f8eecfc8eac2010de6eabbf60b7d53 (diff)
Refactor QNetworkAddress not to keep a full QHostAddress
QHostAddressPrivate is one QString and 24 bytes, allocated on the heap, which is WAY too heavy for something that fits into 8 bits. So instead of storing the expanded netmask inside QNetworkAddressEntryPrivate, we store the simple prefix length and calculate the mask only if asked. Change-Id: Ie05c6480d8a44fda817ffffd14d9ad4707aa8a92 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/network/kernel')
-rw-r--r--src/network/kernel/qhostaddress.cpp79
-rw-r--r--src/network/kernel/qhostaddress_p.h27
-rw-r--r--src/network/kernel/qnetworkinterface.cpp4
-rw-r--r--src/network/kernel/qnetworkinterface_p.h2
4 files changed, 52 insertions, 60 deletions
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index ca64e3b95f..ee4c1e1943 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -206,18 +206,8 @@ void QHostAddressPrivate::clear()
}
-bool QNetmaskAddress::setAddress(const QString &address)
+bool QNetmask::setAddress(const QHostAddress &address)
{
- d.detach();
- length = -1;
- QHostAddress other;
- return other.setAddress(address) && setAddress(other);
-}
-
-bool QNetmaskAddress::setAddress(const QHostAddress &address)
-{
- d.detach();
-
static const quint8 zeroes[16] = { 0 };
union {
quint32 v4;
@@ -229,16 +219,13 @@ bool QNetmaskAddress::setAddress(const QHostAddress &address)
quint8 *end;
length = -1;
- QHostAddress::operator=(address);
-
- if (d->protocol == QAbstractSocket::IPv4Protocol) {
- ip.v4 = qToBigEndian(d->a);
+ if (address.protocol() == QAbstractSocket::IPv4Protocol) {
+ ip.v4 = qToBigEndian(address.toIPv4Address());
end = ptr + 4;
- } else if (d->protocol == QAbstractSocket::IPv6Protocol) {
- memcpy(ip.v6, d->a6.c, 16);
+ } else if (address.protocol() == QAbstractSocket::IPv6Protocol) {
+ memcpy(ip.v6, address.toIPv6Address().c, 16);
end = ptr + 16;
} else {
- d->clear();
return false;
}
@@ -250,7 +237,6 @@ bool QNetmaskAddress::setAddress(const QHostAddress &address)
continue;
default:
- d->clear();
return false; // invalid IP-style netmask
case 254:
@@ -281,10 +267,8 @@ bool QNetmaskAddress::setAddress(const QHostAddress &address)
}
// confirm that the rest is only zeroes
- if (ptr < end && memcmp(ptr + 1, zeroes, end - ptr - 1) != 0) {
- d->clear();
+ if (ptr < end && memcmp(ptr + 1, zeroes, end - ptr - 1) != 0)
return false;
- }
length = netmask;
return true;
@@ -304,35 +288,25 @@ static void clearBits(quint8 *where, int start, int end)
memset(where + (start + 7) / 8, 0, end / 8 - (start + 7) / 8);
}
-int QNetmaskAddress::prefixLength() const
+QHostAddress QNetmask::address(QAbstractSocket::NetworkLayerProtocol protocol) const
{
- return length;
-}
-
-void QNetmaskAddress::setPrefixLength(QAbstractSocket::NetworkLayerProtocol proto, int newLength)
-{
- d.detach();
- length = newLength;
- if (length < 0 || length > (proto == QAbstractSocket::IPv4Protocol ? 32 :
- proto == QAbstractSocket::IPv6Protocol ? 128 : -1)) {
- // invalid information, reject
- d->protocol = QAbstractSocket::UnknownNetworkLayerProtocol;
- length = -1;
- return;
- }
-
- d->protocol = proto;
- if (d->protocol == QAbstractSocket::IPv4Protocol) {
- if (length == 0) {
- d->a = 0;
- } else if (length == 32) {
- d->a = quint32(0xffffffff);
- } else {
- d->a = quint32(0xffffffff) >> (32 - length) << (32 - length);
- }
+ if (length == 255 || protocol == QAbstractSocket::AnyIPProtocol ||
+ protocol == QAbstractSocket::UnknownNetworkLayerProtocol) {
+ return QHostAddress();
+ } else if (protocol == QAbstractSocket::IPv4Protocol) {
+ quint32 a;
+ if (length == 0)
+ a = 0;
+ else if (length == 32)
+ a = quint32(0xffffffff);
+ else
+ a = quint32(0xffffffff) >> (32 - length) << (32 - length);
+ return QHostAddress(a);
} else {
- memset(d->a6.c, 0xFF, sizeof(d->a6));
- clearBits(d->a6.c, length, 128);
+ Q_IPV6ADDR a6;
+ memset(a6.c, 0xFF, sizeof(a6));
+ clearBits(a6.c, length, 128);
+ return QHostAddress(a6);
}
}
@@ -1104,8 +1078,11 @@ QPair<QHostAddress, int> QHostAddress::parseSubnet(const QString &subnet)
// is the netmask given in IP-form or in bit-count form?
if (!isIpv6 && subnet.indexOf(QLatin1Char('.'), slash + 1) != -1) {
// IP-style, convert it to bit-count form
- QNetmaskAddress parser;
- if (!parser.setAddress(subnet.mid(slash + 1)))
+ QHostAddress mask;
+ QNetmask parser;
+ if (!mask.setAddress(subnet.mid(slash + 1)))
+ return invalid;
+ if (!parser.setAddress(mask))
return invalid;
netmask = parser.prefixLength();
} else {
diff --git a/src/network/kernel/qhostaddress_p.h b/src/network/kernel/qhostaddress_p.h
index 55c3e5afde..5106760ed9 100644
--- a/src/network/kernel/qhostaddress_p.h
+++ b/src/network/kernel/qhostaddress_p.h
@@ -57,17 +57,32 @@
QT_BEGIN_NAMESPACE
-class QNetmaskAddress: public QHostAddress
+class QNetmask
{
- int length;
+ // stores 0-32 for IPv4, 0-128 for IPv6, or 255 for invalid
+ quint8 length;
public:
- QNetmaskAddress() : QHostAddress(), length(-1) { }
+ Q_DECL_CONSTEXPR QNetmask() : length(255) {}
- bool setAddress(const QString &address);
bool setAddress(const QHostAddress &address);
+ QHostAddress address(QAbstractSocket::NetworkLayerProtocol protocol) const;
- int prefixLength() const;
- void setPrefixLength(QAbstractSocket::NetworkLayerProtocol proto, int len);
+ int prefixLength() const { return length == 255 ? -1 : length; }
+ void setPrefixLength(QAbstractSocket::NetworkLayerProtocol proto, int len)
+ {
+ int maxlen = -1;
+ if (proto == QAbstractSocket::IPv4Protocol)
+ maxlen = 32;
+ else if (proto == QAbstractSocket::IPv6Protocol)
+ maxlen = 128;
+ if (len > maxlen || len < 0)
+ length = 255U;
+ else
+ length = unsigned(len);
+ }
+
+ friend bool operator==(QNetmask n1, QNetmask n2)
+ { return n1.length == n2.length; }
};
QT_END_NAMESPACE
diff --git a/src/network/kernel/qnetworkinterface.cpp b/src/network/kernel/qnetworkinterface.cpp
index c5d1adbef0..2c28ae9ed9 100644
--- a/src/network/kernel/qnetworkinterface.cpp
+++ b/src/network/kernel/qnetworkinterface.cpp
@@ -257,7 +257,7 @@ void QNetworkAddressEntry::setIp(const QHostAddress &newIp)
*/
QHostAddress QNetworkAddressEntry::netmask() const
{
- return d->netmask;
+ return d->netmask.address(d->address.protocol());
}
/*!
@@ -270,7 +270,7 @@ QHostAddress QNetworkAddressEntry::netmask() const
void QNetworkAddressEntry::setNetmask(const QHostAddress &newNetmask)
{
if (newNetmask.protocol() != ip().protocol()) {
- d->netmask = QNetmaskAddress();
+ d->netmask = QNetmask();
return;
}
diff --git a/src/network/kernel/qnetworkinterface_p.h b/src/network/kernel/qnetworkinterface_p.h
index ec25fdf37e..51901eeda8 100644
--- a/src/network/kernel/qnetworkinterface_p.h
+++ b/src/network/kernel/qnetworkinterface_p.h
@@ -68,8 +68,8 @@ class QNetworkAddressEntryPrivate
{
public:
QHostAddress address;
- QNetmaskAddress netmask;
QHostAddress broadcast;
+ QNetmask netmask;
};
class QNetworkInterfacePrivate: public QSharedData