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