QDnsLookup/Unix: cache previously decoded domain names
Change-Id: I5f7f427ded124479baa6fffd175f3ce37f0e49aa Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
59a2a32276
commit
114d00f043
@ -52,6 +52,17 @@ static constexpr qsizetype QueryBufferSize =
|
|||||||
HFIXEDSZ + QFIXEDSZ + MAXCDNAME + 1 + sizeof(Edns0Record);
|
HFIXEDSZ + QFIXEDSZ + MAXCDNAME + 1 + sizeof(Edns0Record);
|
||||||
using QueryBuffer = std::array<unsigned char, (QueryBufferSize + 15) / 16 * 16>;
|
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)
|
#if QT_CONFIG(res_setservers)
|
||||||
// https://www.ibm.com/docs/en/i/7.3?topic=ssw_ibm_i_73/apis/ressetservers.html
|
// 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
|
// 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();
|
unsigned char *response = buffer.data();
|
||||||
int status;
|
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];
|
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)
|
if (status >= 0)
|
||||||
return decodeLabel(QLatin1StringView(host));
|
return cache.emplaceBack(decodeLabel(QLatin1StringView(host)), offset).name;
|
||||||
|
|
||||||
// failed
|
// failed
|
||||||
reply->makeInvalidReplyError(QDnsLookup::tr("Could not expand domain name"));
|
reply->makeInvalidReplyError(QDnsLookup::tr("Could not expand domain name"));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user