From aa340e1c5e4e28397ef212aa210633e9dcb81f98 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 15 Oct 2015 04:32:02 +0200 Subject: Separate the DNS resolution logic from the TCP communication logic fix #3137 --- louloulibs/network/tcp_socket_handler.cpp | 202 +++--------------------------- 1 file changed, 20 insertions(+), 182 deletions(-) (limited to 'louloulibs/network/tcp_socket_handler.cpp') diff --git a/louloulibs/network/tcp_socket_handler.cpp b/louloulibs/network/tcp_socket_handler.cpp index 9424a1a..72abdcc 100644 --- a/louloulibs/network/tcp_socket_handler.cpp +++ b/louloulibs/network/tcp_socket_handler.cpp @@ -11,13 +11,9 @@ #include #include #include -#include #include #include -#include -#include - #ifdef BOTAN_FOUND # include # include @@ -43,24 +39,9 @@ TCPSocketHandler::TCPSocketHandler(std::shared_ptr poller): use_tls(false), connected(false), connecting(false), -#ifdef CARES_FOUND - resolving(false), - resolved(false), - resolved4(false), - resolved6(false), - cares_addrinfo(nullptr), - cares_error(), -#endif hostname_resolution_failed(false) {} -TCPSocketHandler::~TCPSocketHandler() -{ -#ifdef CARES_FOUND - this->free_cares_addrinfo(); -#endif -} - void TCPSocketHandler::init_socket(const struct addrinfo* rp) { if ((this->socket = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) == -1) @@ -91,17 +72,24 @@ void TCPSocketHandler::connect(const std::string& address, const std::string& po { // Get the addrinfo from getaddrinfo (or ares_gethostbyname), only if // this is the first call of this function. -#ifdef CARES_FOUND - if (!this->resolved) + if (!this->resolver.is_resolved()) { log_info("Trying to connect to " << address << ":" << port); // Start the asynchronous process of resolving the hostname. Once // the addresses have been found and `resolved` has been set to true // (but connecting will still be false), TCPSocketHandler::connect() // needs to be called, again. - this->resolving = true; - DNSHandler::instance.gethostbyname(address, this, AF_INET6); - DNSHandler::instance.gethostbyname(address, this, AF_INET); + this->resolver.resolve(address, port, + [this](const struct addrinfo*) + { + log_debug("Resolution success, calling connect() again"); + this->connect(); + }, + [this](const char*) + { + log_debug("Resolution failed, calling connect() again"); + this->connect(); + }); return; } else @@ -109,39 +97,16 @@ void TCPSocketHandler::connect(const std::string& address, const std::string& po // The c-ares resolved the hostname and the available addresses // where saved in the cares_addrinfo linked list. Now, just use // this list to try to connect. - addr_res = this->cares_addrinfo; + addr_res = this->resolver.get_result().get(); if (!addr_res) { this->hostname_resolution_failed = true; - const auto msg = this->cares_error; + const auto msg = this->resolver.get_error_message(); this->close(); this->on_connection_failed(msg); return ; } } -#else - log_info("Trying to connect to " << address << ":" << port); - struct addrinfo hints; - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_flags = 0; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - - const int res = ::getaddrinfo(address.c_str(), port.c_str(), &hints, &addr_res); - - if (res != 0) - { - log_warning("getaddrinfo failed: "s + gai_strerror(res)); - this->hostname_resolution_failed = true; - this->close(); - this->on_connection_failed(gai_strerror(res)); - return ; - } - // Make sure the alloced structure is always freed at the end of the - // function - sg.add_callback([&addr_res](){ freeaddrinfo(addr_res); }); -#endif } else { // This function is called again, use the saved addrinfo structure, @@ -335,30 +300,18 @@ void TCPSocketHandler::close() } this->connected = false; this->connecting = false; -#ifdef CARES_FOUND - this->resolving = false; - this->resolved = false; - this->resolved4 = false; - this->resolved6 = false; - this->free_cares_addrinfo(); - this->cares_error.clear(); -#endif this->in_buf.clear(); this->out_buf.clear(); this->port.clear(); + this->resolver.clear(); } void TCPSocketHandler::display_resolved_ip(struct addrinfo* rp) const { - char buf[INET6_ADDRSTRLEN]; if (rp->ai_family == AF_INET) - log_debug("Connecting to IP address " << ::inet_ntop(rp->ai_family, - &reinterpret_cast(rp->ai_addr)->sin_addr, - buf, sizeof(buf))); + log_debug("Trying IPv4 address " << addr_to_string(rp)); else if (rp->ai_family == AF_INET6) - log_debug("Connecting to IPv6 address " << ::inet_ntop(rp->ai_family, - &reinterpret_cast(rp->ai_addr)->sin6_addr, - buf, sizeof(buf))); + log_debug("Trying IPv6 address " << addr_to_string(rp)); } void TCPSocketHandler::send_data(std::string&& data) @@ -399,11 +352,7 @@ bool TCPSocketHandler::is_connected() const bool TCPSocketHandler::is_connecting() const { -#ifdef CARES_FOUND - return this->connecting || this->resolving; -#else - return this->connecting; -#endif + return this->connecting || this->resolver.is_resolving(); } void* TCPSocketHandler::get_receive_buffer(const size_t) const @@ -506,122 +455,11 @@ void TCPSocketHandler::on_tls_activated() } void Permissive_Credentials_Manager::verify_certificate_chain(const std::string& type, - const std::string& purported_hostname, - const std::vector&) + const std::string& purported_hostname, + const std::vector&) { // TODO: Offer the admin to disallow connection on untrusted // certificates log_debug("Checking remote certificate (" << type << ") for hostname " << purported_hostname); } #endif // BOTAN_FOUND - -#ifdef CARES_FOUND - -void TCPSocketHandler::on_hostname4_resolved(int status, struct hostent* hostent) -{ - this->resolved4 = true; - if (status == ARES_SUCCESS) - this->fill_ares_addrinfo4(hostent); - else - this->cares_error = ::ares_strerror(status); - - if (this->resolved4 && this->resolved6) - { - this->resolved = true; - this->resolving = false; - this->connect(); - } -} - -void TCPSocketHandler::on_hostname6_resolved(int status, struct hostent* hostent) -{ - this->resolved6 = true; - if (status == ARES_SUCCESS) - this->fill_ares_addrinfo6(hostent); - else - this->cares_error = ::ares_strerror(status); - - if (this->resolved4 && this->resolved6) - { - this->resolved = true; - this->resolving = false; - this->connect(); - } -} - -void TCPSocketHandler::fill_ares_addrinfo4(const struct hostent* hostent) -{ - struct addrinfo* prev = this->cares_addrinfo; - struct in_addr** address = reinterpret_cast(hostent->h_addr_list); - - while (*address) - { - // Create a new addrinfo list element, and fill it - struct addrinfo* current = new struct addrinfo; - current->ai_flags = 0; - current->ai_family = hostent->h_addrtype; - current->ai_socktype = SOCK_STREAM; - current->ai_protocol = 0; - current->ai_addrlen = sizeof(struct sockaddr_in); - - struct sockaddr_in* addr = new struct sockaddr_in; - addr->sin_family = hostent->h_addrtype; - addr->sin_port = htons(strtoul(this->port.data(), nullptr, 10)); - addr->sin_addr.s_addr = (*address)->s_addr; - - current->ai_addr = reinterpret_cast(addr); - current->ai_next = nullptr; - current->ai_canonname = nullptr; - - current->ai_next = prev; - this->cares_addrinfo = current; - prev = current; - ++address; - } -} - -void TCPSocketHandler::fill_ares_addrinfo6(const struct hostent* hostent) -{ - struct addrinfo* prev = this->cares_addrinfo; - struct in6_addr** address = reinterpret_cast(hostent->h_addr_list); - - while (*address) - { - // Create a new addrinfo list element, and fill it - struct addrinfo* current = new struct addrinfo; - current->ai_flags = 0; - current->ai_family = hostent->h_addrtype; - current->ai_socktype = SOCK_STREAM; - current->ai_protocol = 0; - current->ai_addrlen = sizeof(struct sockaddr_in6); - - struct sockaddr_in6* addr = new struct sockaddr_in6; - addr->sin6_family = hostent->h_addrtype; - addr->sin6_port = htons(strtoul(this->port.data(), nullptr, 10)); - ::memcpy(addr->sin6_addr.s6_addr, (*address)->s6_addr, 16); - addr->sin6_flowinfo = 0; - addr->sin6_scope_id = 0; - - current->ai_addr = reinterpret_cast(addr); - current->ai_next = nullptr; - current->ai_canonname = nullptr; - - current->ai_next = prev; - this->cares_addrinfo = current; - prev = current; - ++address; - } -} - -void TCPSocketHandler::free_cares_addrinfo() -{ - while (this->cares_addrinfo) - { - delete this->cares_addrinfo->ai_addr; - auto next = this->cares_addrinfo->ai_next; - delete this->cares_addrinfo; - this->cares_addrinfo = next; - } -} - -#endif // CARES_FOUND -- cgit v1.2.3