1#include <xrpld/overlay/detail/ConnectAttempt.h>
3#include <xrpld/app/main/Application.h>
4#include <xrpld/overlay/Cluster.h>
5#include <xrpld/overlay/Peer.h>
6#include <xrpld/overlay/detail/Handshake.h>
7#include <xrpld/overlay/detail/OverlayImpl.h>
8#include <xrpld/overlay/detail/PeerImp.h>
9#include <xrpld/overlay/detail/ProtocolVersion.h>
10#include <xrpld/peerfinder/PeerfinderManager.h>
11#include <xrpld/peerfinder/Slot.h>
13#include <xrpl/basics/Log.h>
14#include <xrpl/beast/net/IPAddressConversion.h>
15#include <xrpl/beast/utility/Journal.h>
16#include <xrpl/beast/utility/instrumentation.h>
17#include <xrpl/json/json_reader.h>
18#include <xrpl/json/json_value.h>
19#include <xrpl/protocol/PublicKey.h>
20#include <xrpl/protocol/tokens.h>
21#include <xrpl/resource/Consumer.h>
23#include <boost/asio/bind_executor.hpp>
24#include <boost/asio/buffer.hpp>
25#include <boost/asio/error.hpp>
26#include <boost/asio/io_context.hpp>
27#include <boost/asio/ip/tcp.hpp>
28#include <boost/asio/post.hpp>
29#include <boost/asio/ssl/stream_base.hpp>
30#include <boost/asio/ssl/verify_mode.hpp>
31#include <boost/asio/strand.hpp>
32#include <boost/beast/http/impl/read.hpp>
33#include <boost/beast/http/impl/write.hpp>
34#include <boost/beast/http/status.hpp>
35#include <boost/system/system_error.hpp>
50 boost::asio::io_context& ioContext,
81 JLOG(
journal_.trace()) <<
"~ConnectAttempt";
87 if (!
strand_.running_in_this_thread())
104 stream_.next_layer().async_connect(
106 boost::asio::bind_executor(
117 strand_.running_in_this_thread(),
"xrpl::ConnectAttempt::close : strand in this thread");
126 catch (boost::system::system_error
const&)
144 JLOG(
journal_.debug()) << name <<
": " << ec.message();
155 catch (boost::system::system_error
const& e)
157 JLOG(
journal_.error()) <<
"setTimer: " << e.code();
162 boost::asio::bind_executor(
174 catch (boost::system::system_error
const&)
189 if (ec == boost::asio::error::operation_aborted)
193 JLOG(
journal_.error()) <<
"onTimer: " << ec.message();
207 if (ec == boost::asio::error::operation_aborted)
210 fail(
"onConnect", ec);
221 fail(
"onConnect", ec);
227 stream_.set_verify_mode(boost::asio::ssl::verify_none);
229 boost::asio::ssl::stream_base::client,
230 boost::asio::bind_executor(
244 if (ec == boost::asio::error::operation_aborted)
247 fail(
"onHandshake", ec);
251 auto const localEndpoint =
socket_.local_endpoint(ec);
254 fail(
"onHandshake", ec);
258 if (!
overlay_.peerFinder().onConnected(
261 fail(
"Duplicate connection");
273 !
overlay_.peerFinder().config().peerPrivate,
274 app_.config().compression,
275 app_.config().ledgerReplay,
276 app_.config().txReduceRelayEnable,
277 app_.config().vpReduceRelayBaseSquelchEnable);
288 boost::beast::http::async_write(
291 boost::asio::bind_executor(
306 if (ec == boost::asio::error::operation_aborted)
313 boost::beast::http::async_read(
317 boost::asio::bind_executor(
332 if (ec == boost::asio::error::operation_aborted)
335 if (ec == boost::asio::error::eof)
340 boost::asio::bind_executor(
364 if (ec != boost::asio::error::eof)
366 fail(
"onShutdown", ec);
377 if (
response_.result() == boost::beast::http::status::service_unavailable)
383 for (
auto const buffer :
response_.body().data())
385 s.
append(
static_cast<char const*
>(buffer.data()), boost::asio::buffer_size(buffer));
390 if (
json.isObject() &&
json.isMember(
"peer-ips"))
397 for (
auto const& v : ips)
415 JLOG(
journal_.info()) <<
"Unable to upgrade to peer protocol: " <<
response_.result()
429 negotiatedProtocol = pvs[0];
431 if (!negotiatedProtocol)
433 fail(
"processResponse: Unable to negotiate protocol version");
455 usage_.setPublicKey(publicKey);
461 auto const member =
app_.getCluster().member(publicKey);
464 JLOG(
journal_.info()) <<
"Cluster name: " << *member;
468 overlay_.peerFinder().activate(
slot_, publicKey,
static_cast<bool>(member));
469 if (result != PeerFinder::Result::Success)
A generic endpoint for log messages.
Unserialize a JSON document into a Value.
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
UInt size() const
Number of values in array or object.
boost::system::error_code error_code
boost::beast::ssl_stream< middle_type > stream_type
void fail(std::string const &reason)
boost::asio::basic_waitable_timer< std::chrono::steady_clock > timer_
boost::beast::multi_buffer readBuf_
boost::asio::strand< boost::asio::io_context::executor_type > strand_
static boost::asio::ip::tcp::endpoint parseEndpoint(std::string const &s, boost::system::error_code &ec)
std::shared_ptr< boost::asio::ssl::context > shared_context
~ConnectAttempt() override
void onRead(error_code ec)
endpoint_type remoteEndpoint_
void onConnect(error_code ec)
ConnectAttempt(Application &app, boost::asio::io_context &ioContext, endpoint_type remoteEndpoint, Resource::Consumer usage, shared_context const &context, Peer::id_t id, std::shared_ptr< PeerFinder::Slot > const &slot, beast::Journal journal, OverlayImpl &overlay)
void onShutdown(error_code ec)
std::shared_ptr< PeerFinder::Slot > slot_
boost::asio::ip::tcp::socket socket_type
std::unique_ptr< stream_type > streamPtr_
boost::asio::ip::tcp::endpoint endpoint_type
void onHandshake(error_code ec)
Resource::Consumer usage_
beast::Journal const journal_
void onWrite(error_code ec)
void onTimer(error_code ec)
Child(OverlayImpl &overlay)
static bool isPeerUpgrade(http_request_type const &request)
std::uint32_t id_t
Uniquely identifies a peer.
An endpoint that consumes resources.
JSON (JavaScript Object Notation).
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::vector< ProtocolVersion > parseProtocolVersions(boost::beast::string_view const &value)
Parse a set of protocol versions.
PublicKey verifyHandshake(boost::beast::http::fields const &headers, xrpl::uint256 const &sharedValue, std::optional< std::uint32_t > networkID, beast::IP::Address publicIp, beast::IP::Address remote, Application &app)
Validate header fields necessary for upgrading the link to the peer protocol.
bool isProtocolSupported(ProtocolVersion const &v)
Determine whether we support a specific protocol version.
std::optional< uint256 > makeSharedValue(stream_type &ssl, beast::Journal journal)
Computes a shared value based on the SSL connection state.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
std::string to_string(BaseUInt< Bits, Tag > const &a)
auto makeRequest(bool crawlPublic, bool comprEnabled, bool ledgerReplayEnabled, bool txReduceRelayEnabled, bool vpReduceRelayEnabled) -> request_type
Make outbound http request.
void buildHandshake(boost::beast::http::fields &h, xrpl::uint256 const &sharedValue, std::optional< std::uint32_t > networkID, beast::IP::Address publicIp, beast::IP::Address remoteIp, Application &app)
Insert fields headers necessary for upgrading the link to the peer protocol.
T shared_from_this(T... args)
static IP::Endpoint fromAsio(boost::asio::ip::address const &address)