20#include <xrpl/basics/Log.h>
21#include <xrpl/basics/Resolver.h>
22#include <xrpl/basics/ResolverAsio.h>
23#include <xrpl/beast/net/IPAddressConversion.h>
24#include <xrpl/beast/net/IPEndpoint.h>
25#include <xrpl/beast/utility/Journal.h>
26#include <xrpl/beast/utility/instrumentation.h>
28#include <boost/asio/error.hpp>
29#include <boost/asio/io_service.hpp>
30#include <boost/asio/ip/tcp.hpp>
31#include <boost/system/detail/error_code.hpp>
53template <
class Derived>
67 "ripple::AsyncObject::~AsyncObject : nothing pending");
91 m_owner->asyncHandlersComplete();
111 (
static_cast<Derived*
>(
this))->asyncHandlersComplete();
144 template <
class StringSequence>
158 boost::asio::io_service& io_service,
174 "ripple::ResolverAsioImpl::~ResolverAsioImpl : no pending work");
176 m_stopped,
"ripple::ResolverAsioImpl::~ResolverAsioImpl : stopped");
199 m_stopped ==
true,
"ripple::ResolverAsioImpl::start : stopped");
202 "ripple::ResolverAsioImpl::start : not stopping");
244 "ripple::ResolverAsioImpl::resolve : not stopping");
247 "ripple::ResolverAsioImpl::resolve : names non-empty");
256 CompletionCounter(
this))));
266 "ripple::ResolverAsioImpl::do_stop : stopping");
280 boost::system::error_code
const& ec,
282 boost::asio::ip::tcp::resolver::iterator iter,
285 if (ec == boost::asio::error::operation_aborted)
294 while (iter != boost::asio::ip::tcp::resolver::iterator())
302 handler(name, addresses);
326 &std::isspace<std::string::value_type>,
327 std::placeholders::_1,
337 if (host_first >= port_last)
341 auto const find_port_separator = [](
char const c) ->
bool {
342 if (std::isspace(
static_cast<unsigned char>(c)))
352 std::find_if(host_first, port_last, find_port_separator);
375 m_work.front().names.pop_back();
377 if (
m_work.front().names.empty())
380 auto const [host, port] =
parseName(name);
392 boost::asio::ip::tcp::resolver::query query(host, port);
400 std::placeholders::_1,
402 std::placeholders::_2,
403 CompletionCounter(
this)));
414 "ripple::ResolverAsioImpl::do_resolve : names non-empty");
418 m_work.emplace_back(names, handler);
421 <<
"Queued new job with " << names.
size() <<
" tasks. "
422 <<
m_work.size() <<
" jobs outstanding.";
429 CompletionCounter(
this))));
440 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_)