Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 54 additions & 44 deletions pdns/dnsdistdist/dnsdist-async.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,60 +94,70 @@ void AsynchronousHolder::mainThread(std::shared_ptr<Data> data)
std::vector<int> readyFDs;

while (true) {
bool shouldWait = true;
int timeout = -1;
dnsdist::configuration::refreshLocalRuntimeConfiguration();

{
auto content = data->d_content.lock();
if (data->d_done) {
return;
}
try {
bool shouldWait = true;
int timeout = -1;
dnsdist::configuration::refreshLocalRuntimeConfiguration();

if (!content->empty()) {
gettimeofday(&now, nullptr);
struct timeval next = getNextTTD(*content);
if (next <= now) {
pickupExpired(*content, now, expiredEvents);
shouldWait = false;
{
auto content = data->d_content.lock();
if (data->d_done) {
return;
}
else {
auto remainingUsec = uSec(next - now);
timeout = static_cast<int>(std::round(static_cast<double>(remainingUsec) / 1000.0));
if (timeout == 0 && remainingUsec > 0) {
/* if we have less than 1 ms, let's wait at least 1 ms */
timeout = 1;

if (!content->empty()) {
gettimeofday(&now, nullptr);
struct timeval next = getNextTTD(*content);
if (next <= now) {
pickupExpired(*content, now, expiredEvents);
shouldWait = false;
}
else {
auto remainingUsec = uSec(next - now);
timeout = static_cast<int>(std::round(static_cast<double>(remainingUsec) / 1000.0));
if (timeout == 0 && remainingUsec > 0) {
/* if we have less than 1 ms, let's wait at least 1 ms */
timeout = 1;
}
}
}
}
}

if (shouldWait) {
auto timedOut = wait(*data, *mplexer, readyFDs, timeout);
if (timedOut) {
auto content = data->d_content.lock();
gettimeofday(&now, nullptr);
pickupExpired(*content, now, expiredEvents);
if (shouldWait) {
auto timedOut = wait(*data, *mplexer, readyFDs, timeout);
if (timedOut) {
auto content = data->d_content.lock();
gettimeofday(&now, nullptr);
pickupExpired(*content, now, expiredEvents);
}
}
}

while (!expiredEvents.empty()) {
auto [queryID, query] = std::move(expiredEvents.front());
expiredEvents.pop_front();
if (!data->d_failOpen) {
VERBOSESLOG(infolog("Asynchronous query %d has expired at %d.%d, notifying the sender", queryID, now.tv_sec, now.tv_usec),
dnsdist::logging::getTopLogger("async-thread")->info(Logr::Info, "Asynchronous query has expired, notifying the sender", "dns.question.id", Logging::Loggable(queryID)));
auto sender = query->getTCPQuerySender();
if (sender) {
TCPResponse tresponse(std::move(query->query));
sender->notifyIOError(now, std::move(tresponse));
while (!expiredEvents.empty()) {
auto [queryID, query] = std::move(expiredEvents.front());
expiredEvents.pop_front();
if (!data->d_failOpen) {
VERBOSESLOG(infolog("Asynchronous query %d has expired at %d.%d, notifying the sender", queryID, now.tv_sec, now.tv_usec),
dnsdist::logging::getTopLogger("async-thread")->info(Logr::Info, "Asynchronous query has expired, notifying the sender", "dns.question.id", Logging::Loggable(queryID)));
auto sender = query->getTCPQuerySender();
if (sender) {
TCPResponse tresponse(std::move(query->query));
sender->notifyIOError(now, std::move(tresponse));
}
}
else {
VERBOSESLOG(infolog("Asynchronous query %d has expired at %d.%d, resuming", queryID, now.tv_sec, now.tv_usec),
dnsdist::logging::getTopLogger("async-thread")->info(Logr::Info, "Asynchronous query has expired, resuming", "dns.question.id", Logging::Loggable(queryID)));
resumeQuery(std::move(query));
}
}
else {
VERBOSESLOG(infolog("Asynchronous query %d has expired at %d.%d, resuming", queryID, now.tv_sec, now.tv_usec),
dnsdist::logging::getTopLogger("async-thread")->info(Logr::Info, "Asynchronous query has expired, resuming", "dns.question.id", Logging::Loggable(queryID)));
resumeQuery(std::move(query));
}
}
catch (const std::exception& exp) {
VERBOSESLOG(infolog("Got exception in the main asynchronous handler thread: %s", exp.what()),
dnsdist::logging::getTopLogger("async-thread")->error(Logr::Info, exp.what(), "Got exception in the main asynchronous handler thread"));
}
catch (...) {
VERBOSESLOG(infolog("Got exception in the main asynchronous handler thread"),
dnsdist::logging::getTopLogger("async-thread")->info(Logr::Info, "Got exception in the main asynchronous handler thread"));
}
}
}
Expand Down
19 changes: 15 additions & 4 deletions pdns/dnsdistdist/dnsdist-nghttp2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,9 @@ void DoHConnectionToBackend::queueQuery(std::shared_ptr<TCPQuerySender>& sender,

PendingRequest pending;
pending.d_query = std::move(query);
pending.d_sender = std::move(sender);
/* don't move the sender, we don't own it at this point and the caller might need it,
especially if we throw below */
pending.d_sender = sender;

uint32_t tentativeStreamId = nghttp2_session_get_next_stream_id(d_session.get());
if (tentativeStreamId == static_cast<uint32_t>(1 << 31)) {
Expand Down Expand Up @@ -714,7 +716,8 @@ int DoHConnectionToBackend::on_data_chunk_recv_callback(nghttp2_session* session
int DoHConnectionToBackend::on_stream_close_callback(nghttp2_session* session, StreamID stream_id, uint32_t error_code, void* user_data)
{
(void)session;
DoHConnectionToBackend* conn = reinterpret_cast<DoHConnectionToBackend*>(user_data);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): nghttp2 API
auto* conn = reinterpret_cast<DoHConnectionToBackend*>(user_data);

if (error_code == 0) {
return 0;
Expand All @@ -738,8 +741,16 @@ int DoHConnectionToBackend::on_stream_close_callback(nghttp2_session* session, S

if (request.d_query.d_downstreamFailures < conn->d_ds->d_config.d_retries) {
++request.d_query.d_downstreamFailures;
auto downstream = t_downstreamDoHConnectionsManager.getConnectionToDownstream(conn->d_mplexer, conn->d_ds, now, std::string(conn->d_proxyProtocolPayload));
downstream->queueQuery(request.d_sender, std::move(request.d_query));
try {
auto downstream = t_downstreamDoHConnectionsManager.getConnectionToDownstream(conn->d_mplexer, conn->d_ds, now, std::string(conn->d_proxyProtocolPayload));
downstream->queueQuery(request.d_sender, std::move(request.d_query));
}
catch (const std::exception& exp) {
++conn->d_ds->tcpDiedSendingQuery;
VERBOSESLOG(infolog("Failed to retry DoH query after stream close: %s", exp.what()),
conn->getLogger()->error(Logr::Info, exp.what(), "Failed to retry DoH query after stream close"));
conn->handleResponseError(std::move(request), now);
}
}
else {
conn->handleResponseError(std::move(request), now);
Expand Down
16 changes: 13 additions & 3 deletions pdns/tcpiohandler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,13 @@ class OpenSSLTLSIOCtx: public TLSCtx, public std::enable_shared_from_this<OpenSS
return 0;
}

conn->addNewTicket(session);
try {
conn->addNewTicket(session);
}
// NOLINTNEXTLINE(bugprone-empty-catch)
catch (...) {
}

return 1;
}

Expand Down Expand Up @@ -1299,7 +1305,8 @@ class GnuTLSConnection: public TLSConnection
return 0;
}

GnuTLSConnection* conn = reinterpret_cast<GnuTLSConnection*>(gnutls_session_get_ptr(session));
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): GnuTLS API
auto* conn = reinterpret_cast<GnuTLSConnection*>(gnutls_session_get_ptr(session));
if (conn == nullptr) {
return 0;
}
Expand All @@ -1308,7 +1315,10 @@ class GnuTLSConnection: public TLSConnection
auto ret = gnutls_session_get_data2(session, &sess);
/* GnuTLS returns a 'fake' ticket of 4 bytes set to zero when there is no ticket available */
if (ret != GNUTLS_E_SUCCESS || sess.size <= 4) {
throw std::runtime_error("Error getting GnuTLSSession: " + std::string(gnutls_strerror(ret)));
if (sess.data != nullptr) {
gnutls_free(sess.data);
}
return 0;
}
conn->d_tlsSessions.push_back(std::make_unique<GnuTLSSession>(sess));
return 0;
Expand Down
Loading