1 /** 2 * net/resolver.h 3 * (c) 2005-2008 Murat Deligonul 4 */ 5 6 #ifndef __NET_RESOLVER_H 7 #define __NET_RESOLVER_H 8 9 #include <vector> 10 #include <queue> 11 #include <sys/types.h> 12 #include <netdb.h> 13 #include <arpa/inet.h> 14 #include <netinet/in.h> 15 #include <pthread.h> 16 #include "debug.h" 17 18 namespace net { 19 20 class resolver_callback; 21 22 class resolver { 23 public: 24 /** 25 * Operational constants 26 */ 27 static const size_t MAX_HOSTLEN = NI_MAXHOST; 28 29 const unsigned int MAX_THREADS; 30 const unsigned int MAX_LOOKUPS_PER_THREAD; 31 32 33 public: 34 enum { 35 OPT_NORMAL_LOOKUP = 0, 36 OPT_REVERSE_LOOKUP = 1, 37 }; 38 39 enum { 40 SUCCESS = 0, 41 ILLEGAL_REQUEST = -1, 42 }; 43 44 45 public: 46 struct request { 47 int id; /* request id */ 48 int family; /* family of address */ 49 int options; /* other options */ 50 51 union { 52 int iresult; /* return value from resolution functions */ 53 unsigned short port; 54 }; 55 56 addrinfo * ai; /* raw result data */ 57 const resolver_callback * callback; /* callback object pointer */ 58 char name[MAX_HOSTLEN]; 59 ~requestrequest60 ~request() { 61 if (ai != NULL) { 62 freeaddrinfo(ai); 63 } 64 } 65 }; 66 typedef struct request result; 67 68 private: 69 struct resolver_thread { 70 pthread_t thread; 71 resolver *self; 72 }; 73 74 static const struct resolver_thread default_rt; 75 76 private: 77 std::queue<request *> request_queue; 78 std::vector<int> cancelled_requests; 79 80 /* synchronization elements */ 81 pthread_mutex_t queue_mutex; 82 pthread_mutex_t threads_mutex; 83 pthread_cond_t queue_cv; 84 85 int fifo[2]; 86 int current_id; 87 unsigned active_threads; 88 resolver_thread first_thread; 89 90 91 static void * resolver_thread_fn(void *); 92 93 public: 94 resolver(unsigned int, unsigned int); 95 ~resolver(); 96 97 /* asnyc. dns resolution methods */ 98 static request * create_request(int, const char *, unsigned short, 99 int, const resolver_callback *); 100 int async_lookup(request *); 101 int cancel_async_lookup(int); 102 async_lookup(int family,const char * hostname,unsigned short port,int options,const resolver_callback * callback)103 int async_lookup(int family, 104 const char * hostname, unsigned short port, 105 int options, const resolver_callback * callback) 106 { 107 struct request * req = create_request(family, hostname, port, options, callback); 108 return async_lookup(req); 109 } 110 111 int process_results(); 112 113 /* async. lookup result analysis */ 114 static char * result_to_string(const request *, char *, size_t); result_error(const request * req)115 static const char * result_error(const request * req) { 116 return gai_strerror(req->iresult); 117 } 118 119 public: 120 /* Low level resolution functions */ 121 static int resolve_address(int, int, const char *, unsigned short, struct addrinfo **); 122 static int lookup(const char *, char * , size_t); 123 static int reverse_lookup(const char *, char * , size_t); 124 static int test_bind(const char *, unsigned short); 125 static int raw_to_ip(const struct sockaddr *, size_t, char *, size_t, unsigned short * = NULL); 126 static int ip_to_raw(const char *, unsigned short, struct sockaddr *, size_t); 127 static bool is_ip_address(int, const char *); 128 129 private: fifo_reader_fd()130 int fifo_reader_fd() const { 131 return fifo[0]; 132 } fifo_writer_fd()133 int fifo_writer_fd() const { 134 return fifo[1]; 135 } 136 137 int process_request(request *); 138 int write_result(const request *); 139 request * read_result(); 140 int process_result(request *); 141 142 friend class radaptor; 143 144 private: 145 // non-copyable 146 resolver(const resolver&); 147 resolver& operator=(const resolver&); 148 }; 149 150 /** 151 * Interface for resolver callback 152 */ 153 class resolver_callback { 154 public: 155 virtual int async_lookup_finished(const resolver::result *) const = 0; 156 virtual int async_lookup_failed(const resolver::result *) const = 0; ~resolver_callback()157 virtual ~resolver_callback() {} 158 }; 159 160 /** 161 * Class template to wrap class member functions into a resolver callback; 162 * avoids having to use inheritance. 163 */ 164 165 template<class T, 166 int (T::*finished_fn)(const resolver::result *), 167 int (T::*failed_fn)(const resolver::result *)> 168 class resolver_callback_wrapper : public resolver_callback { 169 private: 170 T * const instance; 171 172 public: resolver_callback_wrapper(T * t)173 resolver_callback_wrapper(T * t) : instance(t) { } async_lookup_finished(const resolver::result * r)174 virtual int async_lookup_finished(const resolver::result * r) const { 175 return (instance->*finished_fn)(r); 176 } 177 async_lookup_failed(const resolver::result * r)178 virtual int async_lookup_failed(const resolver::result * r) const { 179 return (instance->*failed_fn)(r); 180 } 181 }; 182 183 } /* namespace net */ 184 #endif /* __NET_RESOLVER_H */ 185