20#include <xrpl/basics/Log.h>
21#include <xrpl/basics/ResolverAsio.h>
22#include <xrpl/beast/net/IPAddressConversion.h>
23#include <xrpl/beast/net/IPEndpoint.h>
24#include <xrpl/beast/utility/instrumentation.h>
25#include <boost/asio.hpp>
39template <
class Derived>
53 "ripple::AsyncObject::~AsyncObject : nothing pending");
77 m_owner->asyncHandlersComplete();
97 (
static_cast<Derived*
>(
this))->asyncHandlersComplete();
130 template <
class StringSequence>
144 boost::asio::io_service& io_service,
160 "ripple::ResolverAsioImpl::~ResolverAsioImpl : no pending work");
162 m_stopped,
"ripple::ResolverAsioImpl::~ResolverAsioImpl : stopped");
185 m_stopped ==
true,
"ripple::ResolverAsioImpl::start : stopped");
188 "ripple::ResolverAsioImpl::start : not stopping");
230 "ripple::ResolverAsioImpl::resolve : not stopping");
233 "ripple::ResolverAsioImpl::resolve : names non-empty");
242 CompletionCounter(
this))));
252 "ripple::ResolverAsioImpl::do_stop : stopping");
266 boost::system::error_code
const& ec,
268 boost::asio::ip::tcp::resolver::iterator iter,
271 if (ec == boost::asio::error::operation_aborted)
280 while (iter != boost::asio::ip::tcp::resolver::iterator())
288 handler(name, addresses);
312 &std::isspace<std::string::value_type>,
313 std::placeholders::_1,
323 if (host_first >= port_last)
327 auto const find_port_separator = [](
char const c) ->
bool {
328 if (std::isspace(
static_cast<unsigned char>(c)))
338 std::find_if(host_first, port_last, find_port_separator);
361 m_work.front().names.pop_back();
363 if (
m_work.front().names.empty())
366 auto const [host, port] =
parseName(name);
378 boost::asio::ip::tcp::resolver::query query(host, port);
386 std::placeholders::_1,
388 std::placeholders::_2,
389 CompletionCounter(
this)));
400 "ripple::ResolverAsioImpl::do_resolve : names non-empty");
404 m_work.emplace_back(names, handler);
407 <<
"Queued new job with " << names.
size() <<
" tasks. "
408 <<
m_work.size() <<
" jobs outstanding.";
415 CompletionCounter(
this))));
426 return std::make_unique<ResolverAsioImpl>(io_service, journal);
T back_inserter(T... args)
static std::optional< Endpoint > from_string_checked(std::string const &s)
Create an Endpoint from a string.
A generic endpoint for log messages.
RAII container that maintains the count of pending I/O.
CompletionCounter(Derived *owner)
CompletionCounter(CompletionCounter const &other)
CompletionCounter & operator=(CompletionCounter const &)=delete
Mix-in to track when all pending I/O is complete.
std::atomic< int > m_pending
ResolverAsioImpl(boost::asio::io_service &io_service, beast::Journal journal)
std::atomic< bool > m_stopped
void do_work(CompletionCounter)
boost::asio::io_service & m_io_service
void resolve(std::vector< std::string > const &names, HandlerType const &handler) override
~ResolverAsioImpl() override
void stop() override
Issue a synchronous stop request.
void asyncHandlersComplete()
std::condition_variable m_cv
bool m_asyncHandlersCompleted
boost::asio::ip::tcp::resolver m_resolver
std::pair< std::string, std::string > HostAndPort
void do_stop(CompletionCounter)
std::deque< Work > m_work
void start() override
Issue a synchronous start request.
std::atomic< bool > m_stop_called
void stop_async() override
Issue an asynchronous stop request.
boost::asio::io_service::strand m_strand
void do_finish(std::string name, boost::system::error_code const &ec, HandlerType handler, boost::asio::ip::tcp::resolver::iterator iter, CompletionCounter)
HostAndPort parseName(std::string const &str)
void do_resolve(std::vector< std::string > const &names, HandlerType const &handler, CompletionCounter)
static std::unique_ptr< ResolverAsio > New(boost::asio::io_service &, beast::Journal)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
T reverse_copy(T... args)
static IP::Endpoint from_asio(boost::asio::ip::address const &address)
std::vector< std::string > names
Work(StringSequence const &names_, HandlerType const &handler_)