QDnsLookup: add TimeoutError for timeouts

We were getting InvalidReplyError because it was simply unknown, which
is not very useful. Previously, the Unix code used res_nquery(), which
does not return timeouts as a condition. It returns -1 if a timeout did
happen, but the content in errno could be a left-over from a previous
timeout (see the "Not a typewriter"[1] problem).

With the rewrite to using res_nmkquery() and res_nsend() from the
previous commits, we can rely on errno being set properly by
res_nsend().

$ $objdir/tests/manual/qdnslookup/qdnslookup @0.0.0.1
; <<>> QDnsLookup 6.6.0 <<>> qdnslookup @0.0.0.1
;; status: TimeoutError (Request timed out)
;; QUESTION:
;qt-project.org                 IN A

;; Query time: 10008 ms
;; SERVER: 0.0.0.1#53

Tested on FreeBSD, Linux, macOS, and Windows.

[1] https://en.wikipedia.org/wiki/Not_a_typewriter

Change-Id: I3e3bfef633af4130a03afffd175e31958247f9b1
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Thiago Macieira 2023-05-16 09:40:32 -07:00
parent 5ecdce0c35
commit 432d67b43f
6 changed files with 20 additions and 3 deletions

View File

@ -187,6 +187,9 @@ static void qt_qdnsservicerecord_sort(QList<QDnsServiceRecord> &records)
\value NotFoundError the requested domain name does not exist \value NotFoundError the requested domain name does not exist
(NXDOMAIN). (NXDOMAIN).
\value TimeoutError the server was not reached or did not reply
in time (since 6.6).
*/ */
/*! /*!
@ -1079,6 +1082,7 @@ void QDnsLookupRunnable::run()
case QDnsLookup::NotFoundError: case QDnsLookup::NotFoundError:
case QDnsLookup::ServerFailureError: case QDnsLookup::ServerFailureError:
case QDnsLookup::ServerRefusedError: case QDnsLookup::ServerRefusedError:
case QDnsLookup::TimeoutError:
break; // no warning for these break; // no warning for these
case QDnsLookup::ResolverError: case QDnsLookup::ResolverError:

View File

@ -159,7 +159,8 @@ public:
InvalidReplyError, InvalidReplyError,
ServerFailureError, ServerFailureError,
ServerRefusedError, ServerRefusedError,
NotFoundError NotFoundError,
TimeoutError,
}; };
Q_ENUM(Error) Q_ENUM(Error)

View File

@ -65,6 +65,12 @@ public:
setError(QDnsLookup::ResolverError, qt_error_string(code)); setError(QDnsLookup::ResolverError, qt_error_string(code));
} }
void makeTimeoutError()
{
Q_ASSERT(allAreEmpty());
setError(QDnsLookup::TimeoutError, QDnsLookup::tr("Request timed out"));
}
void makeDnsRcodeError(quint8 rcode) void makeDnsRcodeError(quint8 rcode)
{ {
Q_ASSERT(allAreEmpty()); Q_ASSERT(allAreEmpty());

View File

@ -174,7 +174,10 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
int responseLength = res_nsend(&state, qbuffer.data(), queryLength, buffer.data(), buffer.size()); int responseLength = res_nsend(&state, qbuffer.data(), queryLength, buffer.data(), buffer.size());
if (responseLength < 0) { if (responseLength < 0) {
// network error of some sort // network error of some sort
reply->makeResolverSystemError(); if (errno == ETIMEDOUT)
reply->makeTimeoutError();
else
reply->makeResolverSystemError();
} }
return responseLength; return responseLength;
}; };

View File

@ -91,6 +91,8 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
const DNS_STATUS status = DnsQueryEx(&request, &results, nullptr); const DNS_STATUS status = DnsQueryEx(&request, &results, nullptr);
if (status >= DNS_ERROR_RCODE_FORMAT_ERROR && status <= DNS_ERROR_RCODE_LAST) if (status >= DNS_ERROR_RCODE_FORMAT_ERROR && status <= DNS_ERROR_RCODE_LAST)
return reply->makeDnsRcodeError(status - DNS_ERROR_RCODE_FORMAT_ERROR + 1); return reply->makeDnsRcodeError(status - DNS_ERROR_RCODE_FORMAT_ERROR + 1);
else if (status == ERROR_TIMEOUT)
return reply->makeTimeoutError();
else if (status != ERROR_SUCCESS) else if (status != ERROR_SUCCESS)
return reply->makeResolverSystemError(status); return reply->makeResolverSystemError(status);

View File

@ -328,7 +328,8 @@ void tst_QDnsLookup::lookup()
}; };
if (!dnsServersMustWork && (lookup.error() == QDnsLookup::ServerFailureError if (!dnsServersMustWork && (lookup.error() == QDnsLookup::ServerFailureError
|| lookup.error() == QDnsLookup::ServerRefusedError)) { || lookup.error() == QDnsLookup::ServerRefusedError
|| lookup.error() == QDnsLookup::TimeoutError)) {
// It's not a QDnsLookup problem if the server refuses to answer the query. // It's not a QDnsLookup problem if the server refuses to answer the query.
// This happens for queries of type ANY through Dnsmasq, for example. // This happens for queries of type ANY through Dnsmasq, for example.
qWarning("Server refused or was unable to answer query; %s", extraErrorMsg().constData()); qWarning("Server refused or was unable to answer query; %s", extraErrorMsg().constData());