uvcc
libuv C++ bindings
request-dns.hpp
1 
2 #ifndef UVCC_REQUEST_DNS__HPP
3 #define UVCC_REQUEST_DNS__HPP
4 
5 #include "uvcc/utility.hpp"
6 #include "uvcc/request-base.hpp"
7 #include "uvcc/loop.hpp"
8 
9 #include <uv.h>
10 
11 #include <functional> // function
12 #include <type_traits> // enable_if_t
13 
14 
15 namespace uv
16 {
17 
18 
19 /*! \ingroup doxy_group__request
20  \brief Getaddrinfo request type.
21  \sa libuv API documentation: [DNS utility functions](http://docs.libuv.org/en/v1.x/dns.html#dns-utility-functions). */
22 class getaddrinfo : public request
23 {
24  //! \cond
25  friend class request::instance< getaddrinfo >;
26  //! \endcond
27 
28 public: /*types*/
29  using uv_t = ::uv_getaddrinfo_t;
30  using on_request_t = std::function< void(getaddrinfo _request) >;
31  /*!< \brief The function type of the callback called with the `getaddrinfo` request result once complete.
32  \sa libuv API documentation: [`uv_getaddrinfo_cb`](http://docs.libuv.org/en/v1.x/dns.html#c.uv_getaddrinfo_cb). */
33 
34 protected: /*types*/
35  //! \cond internals
36  //! \addtogroup doxy_group__internals
37  //! \{
38  struct properties : request::properties
39  {
40  uv_t *uv_req = nullptr;
41  ~properties() { if (uv_req) ::uv_freeaddrinfo(uv_req->addrinfo); }
42  };
43  //! \}
44  //! \endcond
45 
46 private: /*types*/
47  using instance = request::instance< getaddrinfo >;
48 
49 protected: /*constructors*/
50  //! \cond
51  explicit getaddrinfo(uv_t *_uv_req) : request(reinterpret_cast< request::uv_t* >(_uv_req)) {}
52  //! \endcond
53 
54 public: /*constructors*/
55  ~getaddrinfo() = default;
56  getaddrinfo()
57  {
58  uv_req = instance::create();
59  static_cast< uv_t* >(uv_req)->type = UV_GETADDRINFO;
60  static_cast< uv_t* >(uv_req)->addrinfo = nullptr; // ensure for desired initial value
61  instance::from(uv_req)->properties().uv_req = static_cast< uv_t* >(uv_req);
62  }
63 
64  getaddrinfo(const getaddrinfo&) = default;
65  getaddrinfo& operator =(const getaddrinfo&) = default;
66 
67  getaddrinfo(getaddrinfo&&) noexcept = default;
68  getaddrinfo& operator =(getaddrinfo&&) noexcept = default;
69 
70 private: /*functions*/
71  template< typename = void > static void getaddrinfo_cb(::uv_getaddrinfo_t*, int, ::addrinfo*);
72 
73  int run_(uv::loop &_loop, const char *_hostname, const char *_service, const ::addrinfo *_hints)
74  {
75  ::uv_freeaddrinfo(static_cast< uv_t* >(uv_req)->addrinfo); // assuming that *uv_req or this particular field has initially been nulled
76 
77  auto instance_ptr = instance::from(uv_req);
78 
79  if (!instance_ptr->request_cb_storage.value())
80  {
81  return uv_status(::uv_getaddrinfo(
82  static_cast< uv::loop::uv_t* >(_loop), static_cast< uv_t* >(uv_req),
83  nullptr,
84  _hostname, _service, _hints
85  ));
86  }
87  else
88  {
89  instance_ptr->ref();
90 
91  uv_status(0);
92  auto uv_ret = ::uv_getaddrinfo(
93  static_cast< uv::loop::uv_t* >(_loop), static_cast< uv_t* >(uv_req),
94  getaddrinfo_cb,
95  _hostname, _service, _hints
96  );
97  if (uv_ret < 0)
98  {
99  uv_status(uv_ret);
100  instance_ptr->unref();
101  }
102 
103  return uv_ret;
104  }
105  }
106 
107 public: /*interface*/
108  on_request_t& on_request() const noexcept { return instance::from(uv_req)->request_cb_storage.value(); }
109 
110  /*! \brief The libuv loop that started this `getaddrinfo` request and where completion will be reported.
111  \details It is guaranteed that it will be a valid instance at least within the request callback. */
112  uv::loop loop() const noexcept { return uv::loop(static_cast< uv_t* >(uv_req)->loop); }
113 
114  /*! \brief The pointer to a `struct addrinfo` containing the request result. */
115  const ::addrinfo* addrinfo() const noexcept { return static_cast< uv_t* >(uv_req)->addrinfo; }
116 
117  /*! \brief Run the request.
118  \details For supplying `_hints` argument the appropriate helper function for \ref doxy_group__netstruct can be utilized.
119  \sa libuv API documentation: [`uv_getaddrinfo()`](http://docs.libuv.org/en/v1.x/dns.html#c.uv_getaddrinfo).
120  \note If the request callback is empty (has not been set), the request runs _synchronously_
121  (and `_loop` parameter is ignored). */
122  int run(uv::loop &_loop, const char *_hostname, const char *_service, const ::addrinfo &_hints)
123  {
124  return run_(_loop, _hostname, _service, &_hints);
125  }
126  /*! \brief Idem with empty `_hints`. */
127  int run(uv::loop &_loop, const char *_hostname, const char *_service)
128  {
129  return run_(_loop, _hostname, _service, nullptr);
130  }
131 
132 public: /*conversion operators*/
133  explicit operator const uv_t*() const noexcept { return static_cast< const uv_t* >(uv_req); }
134  explicit operator uv_t*() noexcept { return static_cast< uv_t* >(uv_req); }
135 };
136 
137 template< typename >
138 void getaddrinfo::getaddrinfo_cb(::uv_getaddrinfo_t *_uv_req, int _status, ::addrinfo *_result)
139 {
140  auto instance_ptr = instance::from(_uv_req);
141  instance_ptr->uv_error = _status;
142 
143  ref_guard< instance > unref_req(*instance_ptr, adopt_ref);
144 
145  auto &getaddrinfo_cb = instance_ptr->request_cb_storage.value();
146  if (getaddrinfo_cb) getaddrinfo_cb(getaddrinfo(_uv_req));
147 }
148 
149 
150 
151 /*! \ingroup doxy_group__request
152  \brief Getnameinfo request type.
153  \sa libuv API documentation: [DNS utility functions](http://docs.libuv.org/en/v1.x/dns.html#dns-utility-functions). */
154 class getnameinfo : public request
155 {
156  //! \cond
157  friend class request::instance< getnameinfo >;
158  //! \endcond
159 
160 public: /*types*/
161  using uv_t = ::uv_getnameinfo_t;
162  using on_request_t = std::function< void(getnameinfo _request) >;
163  /*!< \brief The function type of the callback called with the `getnameinfo` request result once complete.
164  \sa libuv API documentation: [`uv_getnameinfo_cb`](http://docs.libuv.org/en/v1.x/dns.html#c.uv_getnameinfo_cb). */
165 
166 private: /*types*/
167  using instance = request::instance< getnameinfo >;
168 
169 protected: /*constructors*/
170  //! \cond
171  explicit getnameinfo(uv_t *_uv_req) : request(reinterpret_cast< request::uv_t* >(_uv_req)) {}
172  //! \endcond
173 
174 public: /*constructors*/
175  ~getnameinfo() = default;
176  getnameinfo()
177  {
178  uv_req = instance::create();
179  static_cast< uv_t* >(uv_req)->type = UV_GETNAMEINFO;
180  }
181 
182  getnameinfo(const getnameinfo&) = default;
183  getnameinfo& operator =(const getnameinfo&) = default;
184 
185  getnameinfo(getnameinfo&&) noexcept = default;
186  getnameinfo& operator =(getnameinfo&&) noexcept = default;
187 
188 private: /*functions*/
189  template< typename = void > static void getnameinfo_cb(::uv_getnameinfo_t*, int, const char*, const char*);
190 
191 public: /*interface*/
192  on_request_t& on_request() const noexcept { return instance::from(uv_req)->request_cb_storage.value(); }
193 
194  /*! \brief The libuv loop that started this `getnameinfo` request and where completion will be reported.
195  \details It is guaranteed that it will be a valid instance at least within the request callback. */
196  uv::loop loop() const noexcept { return uv::loop(static_cast< uv_t* >(uv_req)->loop); }
197 
198  /*! \brief The char array containing the resulting host. It’s null terminated. */
199  const char (& host() const noexcept)[NI_MAXHOST] { return static_cast< uv_t* >(uv_req)->host; }
200  /*! \brief The char array containing the resulting service. It’s null terminated. */
201  const char (& service() const noexcept)[NI_MAXSERV] { return static_cast< uv_t* >(uv_req)->service; }
202 
203  /*! \brief Run the request.
204  \sa libuv API documentation: [`uv_getnameinfo()`](http://docs.libuv.org/en/v1.x/dns.html#c.uv_getnameinfo).
205  \note If the request callback is empty (has not been set), the request runs _synchronously_.
206 
207  Available `_NI_FLAGS` are:
208  - NI_DGRAM
209  - NI_NAMEREQD
210  - NI_NOFQDN
211  - NI_NUMERICHOST
212  - NI_NUMERICSERV
213  .
214  \sa Linux: [`getnameinfo()`](http://man7.org/linux/man-pages/man3/getnameinfo.3.html).\n
215  Windows: [`getnameinfo()`](https://msdn.microsoft.com/en-us/library/ms738532(v=vs.85).aspx). */
216  template< typename _T_, typename = std::enable_if_t< is_one_of< _T_, ::sockaddr, ::sockaddr_in, ::sockaddr_in6, ::sockaddr_storage >::value > >
217  int run(uv::loop &_loop, const _T_ &_sa, int _NI_FLAGS = 0)
218  {
219  auto instance_ptr = instance::from(uv_req);
220 
221  if (!instance_ptr->request_cb_storage.value())
222  {
223  return uv_status(::uv_getnameinfo(
224  static_cast< uv::loop::uv_t* >(_loop), static_cast< uv_t* >(uv_req),
225  nullptr,
226  reinterpret_cast< const ::sockaddr* >(&_sa), _NI_FLAGS
227  ));
228  }
229  else
230  {
231  instance_ptr->ref();
232 
233  uv_status(0);
234  auto uv_ret = ::uv_getnameinfo(
235  static_cast< uv::loop::uv_t* >(_loop), static_cast< uv_t* >(uv_req),
236  getnameinfo_cb,
237  reinterpret_cast< const ::sockaddr* >(&_sa), _NI_FLAGS
238  );
239  if (uv_ret < 0)
240  {
241  uv_status(uv_ret);
242  instance_ptr->unref();
243  }
244 
245  return uv_ret;
246  }
247  }
248 
249 public: /*conversion operators*/
250  explicit operator const uv_t*() const noexcept { return static_cast< const uv_t* >(uv_req); }
251  explicit operator uv_t*() noexcept { return static_cast< uv_t* >(uv_req); }
252 };
253 
254 template< typename >
255 void getnameinfo::getnameinfo_cb(::uv_getnameinfo_t *_uv_req, int _status, const char* _hostname, const char* _service)
256 {
257  auto instance_ptr = instance::from(_uv_req);
258  instance_ptr->uv_error = _status;
259 
260  ref_guard< instance > unref_req(*instance_ptr, adopt_ref);
261 
262  auto &getnameinfo_cb = instance_ptr->request_cb_storage.value();
263  if (getnameinfo_cb) getnameinfo_cb(getnameinfo(_uv_req));
264 }
265 
266 
267 
268 }
269 
270 
271 #endif
Namespace for all uvcc definitions.
Definition: buffer.hpp:17
const char(& service() const noexcept)[NI_MAXSERV]
The char array containing the resulting service. It’s null terminated.
The base class for the libuv requests.
Getaddrinfo request type.
Definition: request-dns.hpp:22
const char(& host() const noexcept)[NI_MAXHOST]
The char array containing the resulting host. It’s null terminated.
int run(uv::loop &_loop, const char *_hostname, const char *_service)
Idem with empty _hints.
int run(uv::loop &_loop, const char *_hostname, const char *_service, const ::addrinfo &_hints)
Run the request.
The I/O event loop class.
Definition: loop.hpp:33
A scoped reference counting guard.
Definition: utility.hpp:280
int run(uv::loop &_loop, const _T_ &_sa, int _NI_FLAGS=0)
Run the request.
Getnameinfo request type.