libutil++  1.9.3
 All Classes Functions Variables
DNSCallback.h
1 /*
2 ** libutil++
3 ** $Id: DNSCallback.h 1653 2016-02-28 19:54:59Z sella $
4 ** Copyright (c) 2011-2016 Digital Genesis, LLC. All Rights Reserved.
5 ** Released under the LGPL Version 2.1 License.
6 ** http://www.digitalgenesis.com
7 */
8 
9 #ifndef __libutilxx__sella__net__DNSCallback_H__
10 #define __libutilxx__sella__net__DNSCallback_H__
11 
12 #include "../../common.h"
13 #include "DNSException.h"
14 #include "DNS.h"
15 #include "IPAddress.h"
16 #include "../util/String.h"
17 
18 #include <sys/socket.h>
19 #include <stdint.h>
20 #include <udns.h>
21 
22 #include <map>
23 #include <string>
24 #include <memory>
25 #include <vector>
26 #include <algorithm>
27 
28 namespace sella {
29  namespace net {
30  class DNSCallback;
31  class StoreDNSCallback;
32  class SharedStoreDNSCallback;
33  }
34 }
35 
37  friend class DNS;
38 
39  public:
40  typedef std::shared_ptr<DNSCallback> shared;
41  typedef DNSCallback *ptr;
42  enum Error : int { None = DNS_E_NOERROR, Temporary = DNS_E_TEMPFAIL, Protocol = DNS_E_PROTOCOL, NXDomain = DNS_E_NXDOMAIN, NoData = DNS_E_NODATA, NoMemory = DNS_E_NOMEM, BadQuery = DNS_E_BADQUERY };
43 
44  static const std::vector<IPAddress> none;
45  static const std::vector<std::string> empty;
46 
47  public:
48  DNSCallback() : protocol(0), flags(0) { };
49 
50  virtual void success(const std::string &qname, const std::string &cname, int ttl, const std::vector<std::string> &response = empty) throw () = 0;
51  virtual void failure(const std::string &qname, Error error) throw () = 0;
52 
53  const std::string& getQname(void) const throw () {
54  return qname;
55  }
56 
57  int getRecord(void) const throw () {
58  return record;
59  }
60 
61  int getProtocol(void) const throw () {
62  return protocol;
63  }
64 
65  int getFlags(void) const throw () {
66  return flags;
67  }
68 
69  virtual void clear(void) throw () {
70  qname.clear();
71  record = -1;
72  protocol = -1;
73  flags = 0;
74  }
75 
76  static const char* getErrorDetail(Error error) {
77  return ::dns_strerror((int) error);
78  }
79 
80  static const char* getErrorName(Error error) {
81  switch (error) {
82  case None:
83  return "None";
84  case Temporary:
85  return "Temporary";
86  case Protocol:
87  return "Protocol";
88  case NXDomain:
89  return "NXDomain";
90  case NoData:
91  return "NoData";
92  case NoMemory:
93  return "NoMemory";
94  case BadQuery:
95  return "BadQuery";
96  }
97 
98  return "Unknown";
99  }
100 
101  protected:
102  std::string qname;
103  int record;
104  int protocol;
105  int flags;
106 };
107 
109  public:
110  StoreDNSCallback() : ttl(-1), error(None) { }
111 
112  virtual void success(const std::string &qname, const std::string &cname, int ttl, const std::vector<std::string> &responses = empty) throw () { /* Supports multiple calls for the same qname. */
113  if (this->cname.empty()) {
114  this->cname = cname;
115  }
116 
117  if (this->ttl < 0) {
118  this->ttl = ttl;
119  }
120 
121  this->responses.insert(this->responses.end(), responses.begin(), responses.end()); /* Handle DNS::AnyProtocol properly */
122  std::sort(this->responses.begin(), this->responses.end());
123  this->responses.erase(std::unique(this->responses.begin(), this->responses.end()), this->responses.end());
124 
125  this->error = None;
126  }
127 
128  virtual void failure(const std::string &qname, Error error) throw () {
129  clear();
130 
131  this->error = error;
132  }
133 
134  const std::string& getCname(void) const throw () {
135  return cname;
136  }
137 
138  int getTTL(void) const throw () {
139  return ttl;
140  }
141 
142  const std::vector<std::string>& getResponses(void) const throw () {
143  return responses;
144  }
145 
146  Error getError(void) const throw () {
147  return error;
148  }
149 
150  const char* getErrorName(void) const throw () {
151  return DNSCallback::getErrorName(error);
152  }
153 
154  virtual void clear(void) throw () {
155  DNSCallback::clear();
156  cname.clear();
157  ttl = -1;
158  responses.clear();
159  error = None;
160  }
161 
162  protected:
163  std::string cname;
164  int ttl;
165  std::vector<std::string> responses;
166  Error error;
167 };
168 
170  public:
171  struct result_t {
172  std::string cname;
173  int ttl;
174  std::vector<std::string> responses;
175  int record;
176  int protocol;
177  Error error;
178  };
179 
180  public:
181  SharedStoreDNSCallback(std::map<std::string, result_t> &results) : DNSCallback(), results(results) { }
182 
183  virtual void success(const std::string &qname, const std::string &cname, int ttl, const std::vector<std::string> &responses = empty) throw () {
184  std::string query = qname;
185  std::string alias = cname;
186 
187  try {
188  query = IPAddress(DNS::convertArpa(qname)).str();
189  alias = qname;
190  } catch (...) { }
191 
192  if (!this->results.count(query)) {
193  this->results[query] = { alias, ttl, responses, record, protocol, None };
194  } else { /* Supports multiple calls for the same query. */
195  result_t &result = this->results[query];
196 
197  if (ttl > result.ttl) {
198  result.ttl = ttl;
199  }
200 
201  result.responses.insert(result.responses.end(), responses.begin(), responses.end());
202  std::sort(result.responses.begin(), result.responses.end());
203  result.responses.erase(std::unique(result.responses.begin(), result.responses.end()), result.responses.end());
204  result.error = None;
205  }
206  }
207 
208  virtual void failure(const std::string &qname, Error error) throw () {
209  std::string query = qname;
210  std::string alias;
211 
212  try {
213  query = IPAddress(DNS::convertArpa(qname)).str();
214  alias = qname;
215  } catch (...) { }
216 
217  this->results[query] = { alias, -1, empty, record, protocol, error };
218  }
219 
220  const std::map<std::string, result_t>& getResults(void) const throw () {
221  return results;
222  }
223 
224  virtual void clear(void) throw () {
225  DNSCallback::clear();
226  results.erase(qname);
227  }
228 
229  protected:
230  std::map<std::string, result_t> &results;
231 };
232 
233 #endif
234 
235 /*
236 ** vim: noet ts=3 sw=3
237 */