From b86547dc1ef407ca3838444533bc7145e32a0d90 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 9 Jul 2014 13:02:37 +0200 Subject: Implement async DNS resolution using c-ares fix #2533 --- src/network/tcp_socket_handler.hpp | 47 +++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) (limited to 'src/network/tcp_socket_handler.hpp') diff --git a/src/network/tcp_socket_handler.hpp b/src/network/tcp_socket_handler.hpp index 6d4bbe4..7f10cff 100644 --- a/src/network/tcp_socket_handler.hpp +++ b/src/network/tcp_socket_handler.hpp @@ -17,6 +17,10 @@ #include "config.h" +#ifdef CARES_FOUND +# include +#endif + #ifdef BOTAN_FOUND # include # include @@ -44,7 +48,7 @@ public: class TCPSocketHandler: public SocketHandler { protected: - ~TCPSocketHandler() {} + ~TCPSocketHandler(); public: explicit TCPSocketHandler(std::shared_ptr poller); @@ -54,16 +58,16 @@ public: * start_tls() when the connection succeeds. */ void connect(const std::string& address, const std::string& port, const bool tls); - void connect(); + void connect() override final; /** * Reads raw data from the socket. And pass it to parse_in_buffer() * If we are using TLS on this connection, we call tls_recv() */ - void on_recv(); + void on_recv() override final; /** * Write as much data from out_buf as possible, in the socket. */ - void on_send(); + void on_send() override final; /** * Add the given data to out_buf and tell our poller that we want to be * notified when a send event is ready. @@ -107,9 +111,19 @@ public: * The size argument is the size of the last chunk of data that was added to the buffer. */ virtual void parse_in_buffer(const size_t size) = 0; - bool is_connected() const; + bool is_connected() const override final; bool is_connecting() const; +#ifdef CARES_FOUND + void on_hostname4_resolved(int status, struct hostent* hostent); + void on_hostname6_resolved(int status, struct hostent* hostent); + + void free_cares_addrinfo(); + + void fill_ares_addrinfo4(const struct hostent* hostent); + void fill_ares_addrinfo6(const struct hostent* hostent); +#endif + private: /** * Initialize the socket with the parameters contained in the given @@ -185,7 +199,7 @@ private: */ std::list out_buf; /** - * Keep the details of the addrinfo the triggered a EINPROGRESS error when + * Keep the details of the addrinfo that triggered a EINPROGRESS error when * connect()ing to it, to reuse it directly when connect() is called * again. */ @@ -225,6 +239,27 @@ protected: bool connected; bool connecting; +#ifdef CARES_FOUND + /** + * Whether or not the DNS resolution was successfully done + */ + bool resolved; + bool resolved4; + bool resolved6; + /** + * When using c-ares to resolve the host asynchronously, we need the + * c-ares callback to fill a structure (a struct addrinfo, for + * compatibility with getaddrinfo and the rest of the code that works when + * c-ares is not used) with all returned values (for example an IPv6 and + * an IPv4). The next call of connect() will then try all these values + * (exactly like we do with the result of getaddrinfo) and save the one + * that worked (or returned EINPROGRESS) in the other struct addrinfo (see + * the members addrinfo, ai_addrlen, and ai_addr). + */ + struct addrinfo* cares_addrinfo; + std::string cares_error; +#endif // CARES_FOUND + private: TCPSocketHandler(const TCPSocketHandler&) = delete; TCPSocketHandler(TCPSocketHandler&&) = delete; -- cgit v1.2.3