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
(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::ServerFailureError:
case QDnsLookup::ServerRefusedError:
case QDnsLookup::TimeoutError:
break; // no warning for these
case QDnsLookup::ResolverError:

View File

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

View File

@ -65,6 +65,12 @@ public:
setError(QDnsLookup::ResolverError, qt_error_string(code));
}
void makeTimeoutError()
{
Q_ASSERT(allAreEmpty());
setError(QDnsLookup::TimeoutError, QDnsLookup::tr("Request timed out"));
}
void makeDnsRcodeError(quint8 rcode)
{
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());
if (responseLength < 0) {
// network error of some sort
reply->makeResolverSystemError();
if (errno == ETIMEDOUT)
reply->makeTimeoutError();
else
reply->makeResolverSystemError();
}
return responseLength;
};

View File

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

View File

@ -328,7 +328,8 @@ void tst_QDnsLookup::lookup()
};
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.
// This happens for queries of type ANY through Dnsmasq, for example.
qWarning("Server refused or was unable to answer query; %s", extraErrorMsg().constData());