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/bind_executor.hpp>
29#include <boost/asio/error.hpp>
30#include <boost/asio/io_context.hpp>
31#include <boost/asio/ip/tcp.hpp>
32#include <boost/system/detail/error_code.hpp>
54template <
class Derived>
68 "ripple::AsyncObject::~AsyncObject : nothing pending");
92 m_owner->asyncHandlersComplete();
112 (
static_cast<Derived*
>(
this))->asyncHandlersComplete();
129 boost::asio::strand<boost::asio::io_context::executor_type>
m_strand;
145 template <
class StringSequence>
159 boost::asio::io_context& io_context,
175 "ripple::ResolverAsioImpl::~ResolverAsioImpl : no pending work");
177 m_stopped,
"ripple::ResolverAsioImpl::~ResolverAsioImpl : stopped");
200 m_stopped ==
true,
"ripple::ResolverAsioImpl::start : stopped");
203 "ripple::ResolverAsioImpl::start : not stopping");
220 boost::asio::dispatch(
222 boost::asio::bind_executor(
227 CompletionCounter(
this))));
251 "ripple::ResolverAsioImpl::resolve : not stopping");
254 "ripple::ResolverAsioImpl::resolve : names non-empty");
258 boost::asio::dispatch(
260 boost::asio::bind_executor(
267 CompletionCounter(
this))));
277 "ripple::ResolverAsioImpl::do_stop : stopping");
291 boost::system::error_code
const& ec,
293 boost::asio::ip::tcp::resolver::results_type results,
296 if (ec == boost::asio::error::operation_aborted)
300 auto iter = results.
begin();
306 while (iter != results.end())
314 handler(name, addresses);
318 boost::asio::bind_executor(
323 CompletionCounter(
this))));
345 std::placeholders::_1,
355 if (host_first >= port_last)
359 auto const find_port_separator = [](
char const c) ->
bool {
370 std::find_if(host_first, port_last, find_port_separator);
393 m_work.front().names.pop_back();
395 if (
m_work.front().names.empty())
398 auto const [host, port] =
parseName(name);
406 boost::asio::bind_executor(
411 CompletionCounter(
this))));
423 std::placeholders::_1,
425 std::placeholders::_2,
426 CompletionCounter(
this)));
437 "ripple::ResolverAsioImpl::do_resolve : names non-empty");
441 m_work.emplace_back(names, handler);
444 <<
"Queued new job with " << names.
size() <<
" tasks. "
445 <<
m_work.size() <<
" jobs outstanding.";
451 boost::asio::bind_executor(
456 CompletionCounter(
this))));
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
std::atomic< bool > m_stopped
boost::asio::strand< boost::asio::io_context::executor_type > m_strand
void do_work(CompletionCounter)
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
ResolverAsioImpl(boost::asio::io_context &io_context, beast::Journal journal)
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.
HostAndPort parseName(std::string const &str)
boost::asio::io_context & m_io_context
void do_finish(std::string name, boost::system::error_code const &ec, HandlerType handler, boost::asio::ip::tcp::resolver::results_type results, CompletionCounter)
void do_resolve(std::vector< std::string > const &names, HandlerType const &handler, CompletionCounter)
static std::unique_ptr< ResolverAsio > New(boost::asio::io_context &, 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_)