1#include <xrpl/basics/Log.h>
2#include <xrpl/basics/Resolver.h>
3#include <xrpl/basics/ResolverAsio.h>
4#include <xrpl/beast/net/IPAddressConversion.h>
5#include <xrpl/beast/net/IPEndpoint.h>
6#include <xrpl/beast/utility/Journal.h>
7#include <xrpl/beast/utility/instrumentation.h>
9#include <boost/asio/bind_executor.hpp>
10#include <boost/asio/error.hpp>
11#include <boost/asio/io_context.hpp>
12#include <boost/asio/ip/tcp.hpp>
13#include <boost/system/detail/error_code.hpp>
35template <
class Derived>
49 "ripple::AsyncObject::~AsyncObject : nothing pending");
73 m_owner->asyncHandlersComplete();
93 (
static_cast<Derived*
>(
this))->asyncHandlersComplete();
110 boost::asio::strand<boost::asio::io_context::executor_type>
m_strand;
126 template <
class StringSequence>
140 boost::asio::io_context& io_context,
156 "ripple::ResolverAsioImpl::~ResolverAsioImpl : no pending work");
158 m_stopped,
"ripple::ResolverAsioImpl::~ResolverAsioImpl : stopped");
181 m_stopped ==
true,
"ripple::ResolverAsioImpl::start : stopped");
184 "ripple::ResolverAsioImpl::start : not stopping");
201 boost::asio::dispatch(
203 boost::asio::bind_executor(
208 CompletionCounter(
this))));
232 "ripple::ResolverAsioImpl::resolve : not stopping");
235 "ripple::ResolverAsioImpl::resolve : names non-empty");
239 boost::asio::dispatch(
241 boost::asio::bind_executor(
248 CompletionCounter(
this))));
258 "ripple::ResolverAsioImpl::do_stop : stopping");
272 boost::system::error_code
const& ec,
274 boost::asio::ip::tcp::resolver::results_type results,
277 if (ec == boost::asio::error::operation_aborted)
281 auto iter = results.
begin();
287 while (iter != results.end())
295 handler(name, addresses);
299 boost::asio::bind_executor(
304 CompletionCounter(
this))));
326 std::placeholders::_1,
336 if (host_first >= port_last)
340 auto const find_port_separator = [](
char const c) ->
bool {
351 std::find_if(host_first, port_last, find_port_separator);
374 m_work.front().names.pop_back();
376 if (
m_work.front().names.empty())
379 auto const [host, port] =
parseName(name);
387 boost::asio::bind_executor(
392 CompletionCounter(
this))));
404 std::placeholders::_1,
406 std::placeholders::_2,
407 CompletionCounter(
this)));
418 "ripple::ResolverAsioImpl::do_resolve : names non-empty");
422 m_work.emplace_back(names, handler);
425 <<
"Queued new job with " << names.
size() <<
" tasks. "
426 <<
m_work.size() <<
" jobs outstanding.";
432 boost::asio::bind_executor(
437 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_)