summaryrefslogtreecommitdiffstats
path: root/src/network/kernel
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2023-05-14 23:22:13 -0700
committerThiago Macieira <thiago.macieira@intel.com>2023-06-03 19:28:15 -0700
commit114d00f0430c8a5ef6905931ffaa340bcb54cde6 (patch)
tree138b7b130bafdd03dcef06e42068f43ae9d3bd7c /src/network/kernel
parent59a2a32276247349a44fc1f8d9e4dc632a990ce3 (diff)
QDnsLookup/Unix: cache previously decoded domain names
Change-Id: I5f7f427ded124479baa6fffd175f3ce37f0e49aa Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/network/kernel')
-rw-r--r--src/network/kernel/qdnslookup_unix.cpp32
1 files changed, 29 insertions, 3 deletions
diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp
index a7984f936c..57ac430ea1 100644
--- a/src/network/kernel/qdnslookup_unix.cpp
+++ b/src/network/kernel/qdnslookup_unix.cpp
@@ -52,6 +52,17 @@ static constexpr qsizetype QueryBufferSize =
HFIXEDSZ + QFIXEDSZ + MAXCDNAME + 1 + sizeof(Edns0Record);
using QueryBuffer = std::array<unsigned char, (QueryBufferSize + 15) / 16 * 16>;
+namespace {
+struct QDnsCachedName
+{
+ QString name;
+ int code = 0;
+ QDnsCachedName(const QString &name, int code) : name(name), code(code) {}
+};
+}
+Q_DECLARE_TYPEINFO(QDnsCachedName, Q_RELOCATABLE_TYPE);
+using Cache = QList<QDnsCachedName>; // QHash or QMap are overkill
+
#if QT_CONFIG(res_setservers)
// https://www.ibm.com/docs/en/i/7.3?topic=ssw_ibm_i_73/apis/ressetservers.html
// https://docs.oracle.com/cd/E86824_01/html/E54774/res-setservers-3resolv.html
@@ -223,11 +234,26 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
unsigned char *response = buffer.data();
int status;
- auto expandHost = [&](qptrdiff offset) {
+ auto expandHost = [&, cache = Cache{}](qptrdiff offset) mutable {
+ if (uchar n = response[offset]; n & NS_CMPRSFLGS) {
+ // compressed name, see if we already have it cached
+ if (offset + 1 < responseLength) {
+ int id = ((n & ~NS_CMPRSFLGS) << 8) | response[offset + 1];
+ auto it = std::find_if(cache.constBegin(), cache.constEnd(),
+ [id](const QDnsCachedName &n) { return n.code == id; });
+ if (it != cache.constEnd()) {
+ status = 2;
+ return it->name;
+ }
+ }
+ }
+
+ // uncached, expand it
char host[MAXCDNAME + 1];
- status = dn_expand(response, response + responseLength, response + offset, host, sizeof(host));
+ status = dn_expand(response, response + responseLength, response + offset,
+ host, sizeof(host));
if (status >= 0)
- return decodeLabel(QLatin1StringView(host));
+ return cache.emplaceBack(decodeLabel(QLatin1StringView(host)), offset).name;
// failed
reply->makeInvalidReplyError(QDnsLookup::tr("Could not expand domain name"));