From 4130f1679d909e90d691d47d07cd0e0d4fbe64e1 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 9 Jul 2015 13:54:24 +0200 Subject: Check for timeouts on the DNS resolution using c-ares ref #3083 --- louloulibs/network/dns_handler.cpp | 30 ++++++++++++++++++++++++++++-- louloulibs/network/dns_handler.hpp | 4 ++-- 2 files changed, 30 insertions(+), 4 deletions(-) (limited to 'louloulibs/network') diff --git a/louloulibs/network/dns_handler.cpp b/louloulibs/network/dns_handler.cpp index ec53683..324784b 100644 --- a/louloulibs/network/dns_handler.cpp +++ b/louloulibs/network/dns_handler.cpp @@ -6,6 +6,8 @@ #include #include +#include + #include #include @@ -30,7 +32,13 @@ DNSHandler::DNSHandler() int ares_error; if ((ares_error = ::ares_library_init(ARES_LIB_INIT_ALL)) != 0) throw std::runtime_error("Failed to initialize c-ares lib: "s + ares_strerror(ares_error)); - if ((ares_error = ::ares_init(&this->channel)) != ARES_SUCCESS) + struct ares_options options = {}; + // The default timeout values are way too high + options.timeout = 1000; + options.tries = 3; + if ((ares_error = ::ares_init_options(&this->channel, + &options, + ARES_OPT_TIMEOUTMS|ARES_OPT_TRIES)) != ARES_SUCCESS) throw std::runtime_error("Failed to initialize c-ares channel: "s + ares_strerror(ares_error)); } @@ -99,7 +107,8 @@ void DNSHandler::watch_dns_sockets(std::shared_ptr& poller) { // If not found, create it because we need to watch it if (it == this->socket_handlers.end()) { - this->socket_handlers.emplace_front(std::make_unique(poller, i)); + this->socket_handlers.emplace(this->socket_handlers.begin(), + std::make_unique(poller, i)); it = this->socket_handlers.begin(); } poller->add_socket_handler(it->get()); @@ -107,6 +116,23 @@ void DNSHandler::watch_dns_sockets(std::shared_ptr& poller) poller->watch_send_events(it->get()); } } + // Cancel previous timer, if any. + TimedEventsManager::instance().cancel("DNS timeout"); + struct timeval tv; + struct timeval* tvp; + tvp = ::ares_timeout(this->channel, NULL, &tv); + if (tvp) + { + auto future_time = std::chrono::steady_clock::now() + std::chrono::seconds(tvp->tv_sec) + \ + std::chrono::microseconds(tvp->tv_usec); + TimedEventsManager::instance().add_event(TimedEvent(std::move(future_time), + [this]() + { + for (auto& dns_socket_handler: this->socket_handlers) + dns_socket_handler->on_recv(); + }, + "DNS timeout")); + } } #endif /* CARES_FOUND */ diff --git a/louloulibs/network/dns_handler.hpp b/louloulibs/network/dns_handler.hpp index a515f52..ec35374 100644 --- a/louloulibs/network/dns_handler.hpp +++ b/louloulibs/network/dns_handler.hpp @@ -11,7 +11,7 @@ class DNSSocketHandler; # include # include # include -# include +# include void on_hostname4_resolved(void* arg, int status, int, struct hostent* hostent); void on_hostname6_resolved(void* arg, int status, int, struct hostent* hostent); @@ -49,7 +49,7 @@ private: * call to ares_fds. DNSSocketHandlers are added to it or removed from it * in the watch_dns_sockets() method */ - std::list> socket_handlers; + std::vector> socket_handlers; ares_channel channel; DNSHandler(const DNSHandler&) = delete; -- cgit v1.2.3