1 #pragma once
2 
3 #include "biboumi.h"
4 
5 #include <functional>
6 #include <vector>
7 #include <memory>
8 #include <string>
9 
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netdb.h>
13 #ifdef UDNS_FOUND
14 # include <udns.h>
15 #endif
16 
17 class AddrinfoDeleter
18 {
19  public:
operator ()(struct addrinfo * addr)20   void operator()(struct addrinfo* addr)
21   {
22     freeaddrinfo(addr);
23   }
24 };
25 
26 
27 class Resolver
28 {
29 public:
30 
31   using ErrorCallbackType = std::function<void(const char*)>;
32   using SuccessCallbackType = std::function<void(const struct addrinfo*)>;
33 
34   Resolver();
35   ~Resolver() = default;
36   Resolver(const Resolver&) = delete;
37   Resolver(Resolver&&) = delete;
38   Resolver& operator=(const Resolver&) = delete;
39   Resolver& operator=(Resolver&&) = delete;
40 
is_resolving() const41   bool is_resolving() const
42   {
43 #ifdef UDNS_FOUND
44     return this->resolving;
45 #else
46     return false;
47 #endif
48   }
49 
is_resolved() const50   bool is_resolved() const
51   {
52     return this->resolved;
53   }
54 
get_result() const55   const auto& get_result() const
56   {
57     return this->addr;
58   }
get_error_message() const59   std::string get_error_message() const
60   {
61     return this->error_msg;
62   }
63 
clear()64   void clear()
65   {
66 #ifdef UDNS_FOUND
67     this->resolved6 = false;
68     this->resolved4 = false;
69     this->resolving = false;
70     this->port.clear();
71 #endif
72     this->resolved = false;
73     this->addr.reset();
74     this->error_msg.clear();
75   }
76 
77   void resolve(const std::string& hostname, const std::string& port,
78                SuccessCallbackType success_cb, ErrorCallbackType error_cb);
79 
80 private:
81   void start_resolving(const std::string& hostname, const std::string& port);
82   std::vector<std::string> look_in_etc_hosts(const std::string& hostname);
83   /**
84    * Call getaddrinfo() on the given hostname or IP, and append the result
85    * to our internal addrinfo list. Return getaddrinfo()’s return value.
86    */
87   int call_getaddrinfo(const char* name, const char* port, int flags);
88 
89 #ifdef UDNS_FOUND
90   void on_hostname4_resolved(dns_rr_a4 *result);
91   void on_hostname6_resolved(dns_rr_a6 *result);
92   /**
93    * Called after one record (4 or 6) has been resolved.
94    */
95   void after_resolved();
96 
97   void start_timer();
98 
99   void on_resolved();
100 
101   bool resolved4;
102   bool resolved6;
103 
104   bool resolving;
105 
106   std::string port;
107 
108 #endif
109  /**
110   * Tells if we finished the resolution process. It doesn't indicate if it
111   * was successful (it is true even if the result is an error).
112   */
113   bool resolved;
114   std::string error_msg;
115 
116   std::unique_ptr<struct addrinfo, AddrinfoDeleter> addr;
117 
118   ErrorCallbackType error_cb;
119   SuccessCallbackType success_cb;
120 };
121 
122 std::string addr_to_string(const struct addrinfo* rp);
123