1 #pragma once
2 
3 
4 #include <utility>
5 #include <memory>
6 #include <string>
7 #include <uv.h>
8 #include "request.hpp"
9 #include "util.hpp"
10 #include "loop.hpp"
11 
12 
13 namespace uvw {
14 
15 
16 /**
17  * @brief AddrInfoEvent event.
18  *
19  * It will be emitted by GetAddrInfoReq according with its functionalities.
20  */
21 struct AddrInfoEvent {
22     using Deleter = void(*)(addrinfo *);
23 
AddrInfoEventuvw::AddrInfoEvent24     AddrInfoEvent(std::unique_ptr<addrinfo, Deleter> addr)
25         : data{std::move(addr)}
26     {}
27 
28     /**
29      * @brief An initialized instance of `addrinfo`.
30      *
31      * See [getaddrinfo](http://linux.die.net/man/3/getaddrinfo) for further
32      * details.
33      */
34     std::unique_ptr<addrinfo, Deleter> data;
35 };
36 
37 
38 /**
39  * @brief NameInfoEvent event.
40  *
41  * It will be emitted by GetNameInfoReq according with its functionalities.
42  */
43 struct NameInfoEvent {
NameInfoEventuvw::NameInfoEvent44     NameInfoEvent(const char *host, const char *serv)
45         : hostname{host}, service{serv}
46     {}
47 
48     /**
49      * @brief A valid hostname.
50      *
51      * See [getnameinfo](http://linux.die.net/man/3/getnameinfo) for further
52      * details.
53      */
54     const char * hostname;
55 
56     /**
57      * @brief A valid service name.
58      *
59      * See [getnameinfo](http://linux.die.net/man/3/getnameinfo) for further
60      * details.
61      */
62     const char * service;
63 };
64 
65 
66 /**
67  * @brief The GetAddrInfoReq request.
68  *
69  * Wrapper for [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).<br/>
70  * It offers either asynchronous and synchronous access methods.
71  *
72  * To create a `GetAddrInfoReq` through a `Loop`, no arguments are required.
73  */
74 class GetAddrInfoReq final: public Request<GetAddrInfoReq, uv_getaddrinfo_t> {
addrInfoCallback(uv_getaddrinfo_t * req,int status,addrinfo * res)75     static void addrInfoCallback(uv_getaddrinfo_t *req, int status, addrinfo *res) {
76         auto ptr = reserve(req);
77 
78         if(status) {
79             ptr->publish(ErrorEvent{status});
80         } else {
81             auto data = std::unique_ptr<addrinfo, void(*)(addrinfo *)>{
82                 res, [](addrinfo *addr){ uv_freeaddrinfo(addr); }};
83 
84             ptr->publish(AddrInfoEvent{std::move(data)});
85         }
86     }
87 
nodeAddrInfo(const char * node,const char * service,addrinfo * hints=nullptr)88     void nodeAddrInfo(const char *node, const char *service, addrinfo *hints = nullptr) {
89         invoke(&uv_getaddrinfo, parent(), get(), &addrInfoCallback, node, service, hints);
90     }
91 
nodeAddrInfoSync(const char * node,const char * service,addrinfo * hints=nullptr)92     auto nodeAddrInfoSync(const char *node, const char *service, addrinfo *hints = nullptr) {
93         auto req = get();
94         auto err = uv_getaddrinfo(parent(), req, nullptr, node, service, hints);
95         auto data = std::unique_ptr<addrinfo, void(*)(addrinfo *)>{req->addrinfo, [](addrinfo *addr){ uv_freeaddrinfo(addr); }};
96         return std::make_pair(!err, std::move(data));
97     }
98 
99 public:
100     using Deleter = void(*)(addrinfo *);
101 
102     using Request::Request;
103 
104     /**
105      * @brief Async [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
106      * @param node Either a numerical network address or a network hostname.
107      * @param hints Optional `addrinfo` data structure with additional address
108      * type constraints.
109      */
nodeAddrInfo(std::string node,addrinfo * hints=nullptr)110     void nodeAddrInfo(std::string node, addrinfo *hints = nullptr) {
111         nodeAddrInfo(node.data(), nullptr, hints);
112     }
113 
114     /**
115      * @brief Sync [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
116      *
117      * @param node Either a numerical network address or a network hostname.
118      * @param hints Optional `addrinfo` data structure with additional address
119      * type constraints.
120      *
121      * @return A `std::pair` composed as it follows:
122      * * A boolean value that is true in case of success, false otherwise.
123      * * A `std::unique_ptr<addrinfo, Deleter>` containing the data requested.
124      */
125     std::pair<bool, std::unique_ptr<addrinfo, Deleter>>
nodeAddrInfoSync(std::string node,addrinfo * hints=nullptr)126     nodeAddrInfoSync(std::string node, addrinfo *hints = nullptr) {
127         return nodeAddrInfoSync(node.data(), nullptr, hints);
128     }
129 
130     /**
131      * @brief Async [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
132      * @param service Either a service name or a port number as a string.
133      * @param hints Optional `addrinfo` data structure with additional address
134      * type constraints.
135      */
serviceAddrInfo(std::string service,addrinfo * hints=nullptr)136     void serviceAddrInfo(std::string service, addrinfo *hints = nullptr) {
137         nodeAddrInfo(nullptr, service.data(), hints);
138     }
139 
140     /**
141      * @brief Sync [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
142      *
143      * @param service Either a service name or a port number as a string.
144      * @param hints Optional `addrinfo` data structure with additional address
145      * type constraints.
146      *
147      * @return A `std::pair` composed as it follows:
148      * * A boolean value that is true in case of success, false otherwise.
149      * * A `std::unique_ptr<addrinfo, Deleter>` containing the data requested.
150      */
151     std::pair<bool, std::unique_ptr<addrinfo, Deleter>>
serviceAddrInfoSync(std::string service,addrinfo * hints=nullptr)152     serviceAddrInfoSync(std::string service, addrinfo *hints = nullptr) {
153         return nodeAddrInfoSync(nullptr, service.data(), hints);
154     }
155 
156     /**
157      * @brief Async [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
158      * @param node Either a numerical network address or a network hostname.
159      * @param service Either a service name or a port number as a string.
160      * @param hints Optional `addrinfo` data structure with additional address
161      * type constraints.
162      */
addrInfo(std::string node,std::string service,addrinfo * hints=nullptr)163     void addrInfo(std::string node, std::string service, addrinfo *hints = nullptr) {
164         nodeAddrInfo(node.data(), service.data(), hints);
165     }
166 
167     /**
168      * @brief Sync [getaddrinfo](http://linux.die.net/man/3/getaddrinfo).
169      *
170      * @param node Either a numerical network address or a network hostname.
171      * @param service Either a service name or a port number as a string.
172      * @param hints Optional `addrinfo` data structure with additional address
173      * type constraints.
174      *
175      * @return A `std::pair` composed as it follows:
176      * * A boolean value that is true in case of success, false otherwise.
177      * * A `std::unique_ptr<addrinfo, Deleter>` containing the data requested.
178      */
179     std::pair<bool, std::unique_ptr<addrinfo, Deleter>>
addrInfoSync(std::string node,std::string service,addrinfo * hints=nullptr)180     addrInfoSync(std::string node, std::string service, addrinfo *hints = nullptr) {
181         return nodeAddrInfoSync(node.data(), service.data(), hints);
182     }
183 };
184 
185 
186 /**
187  * @brief The GetNameInfoReq request.
188  *
189  * Wrapper for [getnameinfo](http://linux.die.net/man/3/getnameinfo).<br/>
190  * It offers either asynchronous and synchronous access methods.
191  *
192  * To create a `GetNameInfoReq` through a `Loop`, no arguments are required.
193  */
194 class GetNameInfoReq final: public Request<GetNameInfoReq, uv_getnameinfo_t> {
nameInfoCallback(uv_getnameinfo_t * req,int status,const char * hostname,const char * service)195     static void nameInfoCallback(uv_getnameinfo_t *req, int status, const char *hostname, const char *service) {
196         auto ptr = reserve(req);
197         if(status) { ptr->publish(ErrorEvent{status}); }
198         else { ptr->publish(NameInfoEvent{hostname, service}); }
199     }
200 
201 public:
202     using Request::Request;
203 
204     /**
205      * @brief Async [getnameinfo](http://linux.die.net/man/3/getnameinfo).
206      * @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
207      * @param flags Optional flags that modify the behavior of `getnameinfo`.
208      */
nameInfo(const sockaddr & addr,int flags=0)209     void nameInfo(const sockaddr &addr, int flags = 0) {
210         invoke(&uv_getnameinfo, parent(), get(), &nameInfoCallback, &addr, flags);
211     }
212 
213     /**
214      * @brief Async [getnameinfo](http://linux.die.net/man/3/getnameinfo).
215      * @param ip A valid IP address.
216      * @param port A valid port number.
217      * @param flags Optional flags that modify the behavior of `getnameinfo`.
218      */
219     template<typename I = IPv4>
nameInfo(std::string ip,unsigned int port,int flags=0)220     void nameInfo(std::string ip, unsigned int port, int flags = 0) {
221         typename details::IpTraits<I>::Type addr;
222         details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
223         nameInfo(reinterpret_cast<const sockaddr &>(addr), flags);
224     }
225 
226     /**
227      * @brief Async [getnameinfo](http://linux.die.net/man/3/getnameinfo).
228      * @param addr A valid instance of Addr.
229      * @param flags Optional flags that modify the behavior of `getnameinfo`.
230      */
231     template<typename I = IPv4>
nameInfo(Addr addr,int flags=0)232     void nameInfo(Addr addr, int flags = 0) {
233         nameInfo<I>(std::move(addr.ip), addr.port, flags);
234     }
235 
236     /**
237      * @brief Sync [getnameinfo](http://linux.die.net/man/3/getnameinfo).
238      *
239      * @param addr Initialized `sockaddr_in` or `sockaddr_in6` data structure.
240      * @param flags Optional flags that modify the behavior of `getnameinfo`.
241      *
242      * @return A `std::pair` composed as it follows:
243      * * A boolean value that is true in case of success, false otherwise.
244      * * A `std::pair` composed as it follows:
245      *   * A `const char *` containing a valid hostname.
246      *   * A `const char *` containing a valid service name.
247      */
248     std::pair<bool, std::pair<const char *, const char *>>
nameInfoSync(const sockaddr & addr,int flags=0)249     nameInfoSync(const sockaddr &addr, int flags = 0) {
250         auto req = get();
251         auto err = uv_getnameinfo(parent(), req, nullptr, &addr, flags);
252         return std::make_pair(!err, std::make_pair(req->host, req->service));
253     }
254 
255     /**
256      * @brief Sync [getnameinfo](http://linux.die.net/man/3/getnameinfo).
257      *
258      * @param ip A valid IP address.
259      * @param port A valid port number.
260      * @param flags Optional flags that modify the behavior of `getnameinfo`.
261      *
262      * @return A `std::pair` composed as it follows:
263      * * A boolean value that is true in case of success, false otherwise.
264      * * A `std::pair` composed as it follows:
265      *   * A `const char *` containing a valid hostname.
266      *   * A `const char *` containing a valid service name.
267      */
268     template<typename I = IPv4>
269     std::pair<bool, std::pair<const char *, const char *>>
nameInfoSync(std::string ip,unsigned int port,int flags=0)270     nameInfoSync(std::string ip, unsigned int port, int flags = 0) {
271         typename details::IpTraits<I>::Type addr;
272         details::IpTraits<I>::addrFunc(ip.data(), port, &addr);
273         return nameInfoSync(reinterpret_cast<const sockaddr &>(addr), flags);
274     }
275 
276     /**
277      * @brief Sync [getnameinfo](http://linux.die.net/man/3/getnameinfo).
278      *
279      * @param addr A valid instance of Addr.
280      * @param flags Optional flags that modify the behavior of `getnameinfo`.
281      *
282      * @return A `std::pair` composed as it follows:
283      * * A boolean value that is true in case of success, false otherwise.
284      * * A `std::pair` composed as it follows:
285      *   * A `const char *` containing a valid hostname.
286      *   * A `const char *` containing a valid service name.
287      */
288     template<typename I = IPv4>
289     std::pair<bool, std::pair<const char *, const char *>>
nameInfoSync(Addr addr,int flags=0)290     nameInfoSync(Addr addr, int flags = 0) {
291         return nameInfoSync<I>(std::move(addr.ip), addr.port, flags);
292     }
293 };
294 
295 
296 }
297