diff --git a/charybdis/console.cc b/charybdis/console.cc index 1b2a772a9..a8fb03855 100644 --- a/charybdis/console.cc +++ b/charybdis/console.cc @@ -385,6 +385,21 @@ try std::cout << future.get() << std::endl; break; } + + case hash("ptr"): + { + net::ipport in[1] + { + net::hostport { host, port }, + }; + + std::string out[1]; + net::resolve{in, out}; + for(const auto &ptr : out) + std::cout << ptr << std::endl; + + break; + } } break; diff --git a/include/ircd/net/asio.h b/include/ircd/net/asio.h index c66e83f3d..0acf80983 100644 --- a/include/ircd/net/asio.h +++ b/include/ircd/net/asio.h @@ -44,6 +44,9 @@ namespace ircd::net std::string host(const ip::tcp::endpoint &); std::string string(const ip::address &); std::string string(const ip::tcp::endpoint &); + + ipport make_ipport(const boost::asio::ip::tcp::endpoint &); + ip::tcp::endpoint make_endpoint(const ipport &); } namespace ircd diff --git a/include/ircd/net/remote.h b/include/ircd/net/remote.h index 996e58d71..38a123dc1 100644 --- a/include/ircd/net/remote.h +++ b/include/ircd/net/remote.h @@ -105,12 +105,17 @@ struct ircd::net::resolve { using callback_one = std::function; using callback_many = std::function)>; + using callback_reverse = std::function; resolve(const hostport &, callback_one); resolve(const hostport &, callback_many); + resolve(const ipport &, callback_reverse); + resolve(const hostport &, ctx::future &); resolve(const hostport &, ctx::future> &); + resolve(const vector_view &in, const vector_view &out); + resolve(const vector_view &in, const vector_view &out); }; /// This lightweight structure holds an IP address and port in native byte @@ -134,10 +139,7 @@ struct ircd::net::ipport operator bool() const; bool operator!() const { return !static_cast(*this); } - // DNS lookup! May yield ircd::ctx! - ipport(const hostport &); - - // Trivial constructors + ipport(const hostport &); // DNS lookup! May yield ircd::ctx! ipport(const uint32_t &ip, const uint16_t &port); ipport(const uint128_t &ip, const uint16_t &port); ipport(const boost::asio::ip::address &, const uint16_t &port); diff --git a/ircd/net.cc b/ircd/net.cc index 12a15eadc..16d5edee4 100644 --- a/ircd/net.cc +++ b/ircd/net.cc @@ -29,8 +29,6 @@ namespace ircd::net { ip::tcp::resolver *resolver; - - ipport make_ipport(const boost::asio::ip::tcp::endpoint &); } struct ircd::log::log @@ -72,18 +70,7 @@ std::shared_ptr ircd::net::connect(const net::remote &remote, const milliseconds &timeout) { - const asio::ip::tcp::endpoint ep - { - is_v6(remote)? asio::ip::tcp::endpoint - { - asio::ip::address_v6 { std::get(remote) }, port(remote) - } - : asio::ip::tcp::endpoint - { - asio::ip::address_v4 { host4(remote) }, port(remote) - }, - }; - + const auto ep{make_endpoint(remote)}; return connect(ep, timeout); } @@ -1605,6 +1592,22 @@ ircd::net::make_ipport(const boost::asio::ip::tcp::endpoint &ep) }; } +boost::asio::ip::tcp::endpoint +ircd::net::make_endpoint(const ipport &ipport) +{ + return + { + is_v6(ipport)? ip::tcp::endpoint + { + asio::ip::address_v6 { std::get(ipport) }, port(ipport) + } + : ip::tcp::endpoint + { + asio::ip::address_v4 { host4(ipport) }, port(ipport) + }, + }; +} + ircd::net::ipport::ipport(const hostport &hp) { ctx::future future; @@ -1635,7 +1638,54 @@ namespace ircd::net { // Internal resolve base (requires boost syms) using resolve_callback = std::function; - void async_resolve(const hostport &, ip::tcp::resolver::flags, resolve_callback); + void _resolve(const hostport &, ip::tcp::resolver::flags, resolve_callback); + void _resolve(const ipport &, resolve_callback); +} + +ircd::net::resolve::resolve(const vector_view &in, + const vector_view &out) +{ + assert(in.size() == out.size()); + + size_t a{0}, b{0}; + ctx::ctx &c{ctx::cur()}; + const size_t count{std::min(in.size(), out.size())}; + for(; a < count; ++a) resolve + { + in[a], [&b, &c, &count, &ret(out[a])] + (std::exception_ptr eptr, std::string hostname) noexcept + { + ret = std::move(hostname); + if(++b >= count) + notify(c); + } + }; + + while(b < count) + ctx::wait(); +} + +ircd::net::resolve::resolve(const vector_view &in, + const vector_view &out) +{ + assert(in.size() == out.size()); + + size_t a{0}, b{0}; + ctx::ctx &c{ctx::cur()}; + const size_t count{std::min(in.size(), out.size())}; + for(; a < count; ++a) resolve + { + in[a], [&b, &c, &count, &ret(out[a])] + (std::exception_ptr eptr, const ipport &ip) noexcept + { + ret = ip; + if(++b >= count) + notify(c); + } + }; + + while(b < count) + ctx::wait(); } ircd::net::resolve::resolve(const hostport &hostport, @@ -1670,6 +1720,24 @@ ircd::net::resolve::resolve(const hostport &hostport, }); } +ircd::net::resolve::resolve(const ipport &ipport, + callback_reverse callback) +{ + _resolve(ipport, [callback(std::move(callback))] + (std::exception_ptr eptr, ip::tcp::resolver::results_type results) + { + if(eptr) + return callback(std::move(eptr), {}); + + if(results.empty()) + return callback({}, {}); + + assert(results.size() <= 1); + const auto &result(*begin(results)); + callback({}, result.host_name()); + }); +} + ircd::net::resolve::resolve(const hostport &hostport, callback_one callback) { @@ -1686,37 +1754,11 @@ ircd::net::resolve::resolve(const hostport &hostport, }); } -ircd::net::resolve::resolve(const vector_view &in, - const vector_view &out) -{ - assert(in.size() == out.size()); - const size_t count - { - std::min(in.size(), out.size()) - }; - - size_t a{0}, b{0}; - ctx::ctx &c{ctx::cur()}; - for(; a < count; ++a) resolve - { - in[a], [&b, &c, &count, &ret(out[a])] - (std::exception_ptr eptr, const ipport &ip) noexcept - { - ret = ip; - if(++b >= count) - notify(c); - } - }; - - while(b < count) - ctx::wait(); -} - ircd::net::resolve::resolve(const hostport &hostport, callback_many callback) { static const ip::tcp::resolver::flags flags{}; - async_resolve(hostport, flags, [callback(std::move(callback))] + _resolve(hostport, flags, [callback(std::move(callback))] (std::exception_ptr eptr, ip::tcp::resolver::results_type results) { if(eptr) @@ -1738,10 +1780,11 @@ ircd::net::resolve::resolve(const hostport &hostport, }); } +/// Internal A/AAAA record resolver function void -ircd::net::async_resolve(const hostport &hostport, - ip::tcp::resolver::flags flags, - resolve_callback callback) +ircd::net::_resolve(const hostport &hostport, + ip::tcp::resolver::flags flags, + resolve_callback callback) { // Trivial host string const string_view &host @@ -1770,7 +1813,32 @@ ircd::net::async_resolve(const hostport &hostport, { if(ec) { - callback(std::make_exception_ptr(boost::system::system_error{ec}), {}); + callback(std::make_exception_ptr(boost::system::system_error{ec}), std::move(results)); + } + else try + { + callback({}, std::move(results)); + } + catch(...) + { + callback(std::make_exception_ptr(std::current_exception()), {}); + } + }); +} + +/// Internal PTR record resolver function +void +ircd::net::_resolve(const ipport &ipport, + resolve_callback callback) +{ + assert(bool(ircd::net::resolver)); + resolver->async_resolve(make_endpoint(ipport), [callback(std::move(callback))] + (const error_code &ec, ip::tcp::resolver::results_type results) + noexcept + { + if(ec) + { + callback(std::make_exception_ptr(boost::system::system_error{ec}), std::move(results)); } else try {