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>
47 XRPL_ASSERT(
m_pending.
load() == 0,
"xrpl::AsyncObject::~AsyncObject : nothing pending");
70 m_owner->asyncHandlersComplete();
90 (
static_cast<Derived*
>(
this))->asyncHandlersComplete();
106 boost::asio::strand<boost::asio::io_context::executor_type>
m_strand;
122 template <
class StringSequence>
146 XRPL_ASSERT(
m_work.empty(),
"xrpl::ResolverAsioImpl::~ResolverAsioImpl : no pending work");
147 XRPL_ASSERT(
m_stopped,
"xrpl::ResolverAsioImpl::~ResolverAsioImpl : stopped");
169 XRPL_ASSERT(
m_stopped ==
true,
"xrpl::ResolverAsioImpl::start : stopped");
170 XRPL_ASSERT(
m_stop_called ==
false,
"xrpl::ResolverAsioImpl::start : not stopping");
187 boost::asio::dispatch(
189 boost::asio::bind_executor(
211 XRPL_ASSERT(
m_stop_called ==
false,
"xrpl::ResolverAsioImpl::resolve : not stopping");
212 XRPL_ASSERT(!names.
empty(),
"xrpl::ResolverAsioImpl::resolve : names non-empty");
216 boost::asio::dispatch(
218 boost::asio::bind_executor(
227 XRPL_ASSERT(
m_stop_called ==
true,
"xrpl::ResolverAsioImpl::do_stop : stopping");
241 boost::system::error_code
const& ec,
243 boost::asio::ip::tcp::resolver::results_type results,
246 if (ec == boost::asio::error::operation_aborted)
250 auto iter = results.
begin();
256 while (iter != results.end())
263 handler(name, addresses);
278 return make_pair(result->address().to_string(),
std::to_string(result->port()));
286 auto const find_whitespace =
294 if (host_first >= port_last)
298 auto const find_port_separator = [](
char const c) ->
bool {
308 auto host_last =
std::find_if(host_first, port_last, find_port_separator);
310 auto port_first =
std::find_if_not(host_last, port_last, find_port_separator);
328 m_work.front().names.pop_back();
330 if (
m_work.front().names.empty())
333 auto const [host, port] =
parseName(name);
341 boost::asio::bind_executor(
354 std::placeholders::_1,
356 std::placeholders::_2,
357 CompletionCounter(
this)));
363 XRPL_ASSERT(!names.
empty(),
"xrpl::ResolverAsioImpl::do_resolve : names non-empty");
367 m_work.emplace_back(names, handler);
370 <<
" jobs outstanding.";
376 boost::asio::bind_executor(
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 & operator=(CompletionCounter const &)=delete
CompletionCounter(Derived *owner)
CompletionCounter(CompletionCounter const &other)
Mix-in to track when all pending I/O is complete.
std::atomic< int > m_pending
std::atomic< bool > m_stop_called
void do_stop(CompletionCounter)
boost::asio::io_context & m_io_context
boost::asio::ip::tcp::resolver m_resolver
ResolverAsioImpl(boost::asio::io_context &io_context, beast::Journal journal)
bool m_asyncHandlersCompleted
void resolve(std::vector< std::string > const &names, HandlerType const &handler) override
void start() override
Issue a synchronous start request.
void do_finish(std::string name, boost::system::error_code const &ec, HandlerType handler, boost::asio::ip::tcp::resolver::results_type results, CompletionCounter)
std::deque< Work > m_work
void stop() override
Issue a synchronous stop request.
~ResolverAsioImpl() override
std::condition_variable m_cv
std::atomic< bool > m_stopped
boost::asio::strand< boost::asio::io_context::executor_type > m_strand
void do_resolve(std::vector< std::string > const &names, HandlerType const &handler, CompletionCounter)
HostAndPort parseName(std::string const &str)
std::pair< std::string, std::string > HostAndPort
void stop_async() override
Issue an asynchronous stop request.
void asyncHandlersComplete()
void do_work(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_)