rippled
InboundHandoff.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012-2021 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/overlay/Cluster.h>
21 #include <ripple/overlay/impl/InboundHandoff.h>
22 #include <ripple/overlay/impl/PeerImp.h>
23 
24 #include <boost/beast/core/ostream.hpp>
25 
26 namespace ripple {
27 
29  Application& app,
30  id_t id,
32  http_request_type&& request,
33  PublicKey const& publicKey,
35  Resource::Consumer consumer,
36  std::unique_ptr<stream_type>&& stream_ptr,
37  OverlayImpl& overlay)
38  : OverlayImpl::Child(overlay)
39  , app_(app)
40  , id_(id)
41  , sink_(
42  app_.journal("Peer"),
43  [id]() {
45  ss << "[" << std::setfill('0') << std::setw(3) << id << "] ";
46  return ss.str();
47  }())
48  , journal_(sink_)
49  , stream_ptr_(std::move(stream_ptr))
50  , strand_(stream_ptr_->next_layer().socket().get_executor())
51  , remote_address_(slot->remote_endpoint())
52  , protocol_(protocol)
53  , publicKey_(publicKey)
54  , usage_(consumer)
55  , slot_(slot)
56  , request_(std::move(request))
57 {
58 }
59 
60 void
62 {
63  if (!strand_.running_in_this_thread())
64  return post(
66  sendResponse();
67 }
68 
69 void
71 {
72  if (!strand_.running_in_this_thread())
73  return post(
75  if (stream_ptr_->next_layer().socket().is_open())
76  {
77  JLOG(journal_.debug()) << "Stop";
78  }
79  close();
80 }
81 
82 void
84 {
85  auto const sharedValue = makeSharedValue(*stream_ptr_, journal_);
86  // This shouldn't fail since we already computed
87  // the shared value successfully in OverlayImpl
88  if (!sharedValue)
89  return fail("makeSharedValue: Unexpected failure");
90 
91  JLOG(journal_.info()) << "Protocol: " << to_string(protocol_);
92  JLOG(journal_.info()) << "Public Key: "
94 
95  auto write_buffer = std::make_shared<boost::beast::multi_buffer>();
96 
97  boost::beast::ostream(*write_buffer) << makeResponse(
99  request_,
100  overlay_.setup().public_ip,
102  *sharedValue,
103  overlay_.setup().networkID,
104  protocol_,
105  app_);
106 
107  // Write the whole buffer and only start protocol when that's done.
108  boost::asio::async_write(
109  *stream_ptr_,
110  write_buffer->data(),
111  boost::asio::transfer_all(),
112  bind_executor(
113  strand_,
114  [this, write_buffer, self = shared_from_this()](
115  error_code ec, std::size_t bytes_transferred) {
116  if (!stream_ptr_->next_layer().socket().is_open())
117  return;
118  if (ec == boost::asio::error::operation_aborted)
119  return;
120  if (ec)
121  return fail("onWriteResponse", ec);
122  if (write_buffer->size() == bytes_transferred)
123  return createPeer();
124  return fail("Failed to write header");
125  }));
126 }
127 
128 void
130 {
131  if (socket().is_open())
132  {
133  JLOG(journal_.warn())
134  << name << " from " << toBase58(TokenType::NodePublic, publicKey_)
135  << " at " << remote_address_.to_string() << ": " << ec.message();
136  }
137  close();
138 }
139 
140 void
142 {
144  {
145  auto const n = app_.cluster().member(publicKey_);
146  JLOG(journal_.warn())
147  << (n ? remote_address_.to_string() : *n) << " failed: " << reason;
148  }
149  close();
150 }
151 
152 void
154 {
155  if (socket().is_open())
156  {
157  socket().close();
158  JLOG(journal_.debug()) << "Closed";
159  }
160 }
161 
162 void
164 {
165  auto peer = std::make_shared<PeerImp>(
166  app_,
167  id_,
168  slot_,
169  std::move(request_),
170  publicKey_,
171  protocol_,
172  usage_,
173  std::move(stream_ptr_),
174  overlay_);
175 
176  overlay_.add_active(peer);
177 }
178 
181 {
182  return stream_ptr_->next_layer().socket();
183 }
184 
185 } // namespace ripple
ripple::Application
Definition: Application.h:116
ripple::InboundHandoff::slot_
const std::shared_ptr< PeerFinder::Slot > slot_
Definition: InboundHandoff.h:50
ripple::Application::cluster
virtual Cluster & cluster()=0
std::bind
T bind(T... args)
std::string
STL class.
std::shared_ptr
STL class.
ripple::OverlayImpl::Child::overlay_
OverlayImpl & overlay_
Definition: OverlayImpl.h:64
beast::IP::Endpoint::to_string
std::string to_string() const
Returns a string representing the endpoint.
Definition: IPEndpoint.cpp:57
std::pair
ripple::InboundHandoff::close
void close()
Close connection.
Definition: InboundHandoff.cpp:153
ripple::InboundHandoff::createPeer
void createPeer()
Instantiate and run the overlay peer.
Definition: InboundHandoff.cpp:163
ripple::InboundHandoff::usage_
Resource::Consumer usage_
Definition: InboundHandoff.h:49
ripple::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:104
beast::IP::Endpoint::address
Address const & address() const
Returns the address portion of this endpoint.
Definition: IPEndpoint.h:76
std::stringstream
STL class.
beast::Journal::warn
Stream warn() const
Definition: Journal.h:326
ripple::InboundHandoff::strand_
boost::asio::strand< boost::asio::executor > strand_
Definition: InboundHandoff.h:45
ripple::InboundHandoff::app_
Application & app_
Definition: InboundHandoff.h:40
ripple::makeSharedValue
std::optional< uint256 > makeSharedValue(stream_type &ssl, beast::Journal journal)
Computes a shared value based on the SSL connection state.
Definition: Handshake.cpp:147
ripple::Cluster::member
std::optional< std::string > member(PublicKey const &node) const
Determines whether a node belongs in the cluster.
Definition: Cluster.cpp:39
ripple::InboundHandoff::stream_ptr_
std::unique_ptr< stream_type > stream_ptr_
Definition: InboundHandoff.h:44
std::setfill
T setfill(T... args)
ripple::OverlayImpl::setup
Setup const & setup() const
Definition: OverlayImpl.h:176
ripple::PeerFinder::Config::peerPrivate
bool peerPrivate
true if we want our IP address kept private.
Definition: PeerfinderManager.h:61
ripple::InboundHandoff::InboundHandoff
InboundHandoff(Application &app, id_t id, std::shared_ptr< PeerFinder::Slot > const &slot, http_request_type &&request, PublicKey const &publicKey, ProtocolVersion protocol, Resource::Consumer consumer, std::unique_ptr< stream_type > &&stream_ptr, OverlayImpl &overlay)
Definition: InboundHandoff.cpp:28
ripple::OverlayImpl::peerFinder
PeerFinder::Manager & peerFinder()
Definition: OverlayImpl.h:164
std::enable_shared_from_this< InboundHandoff >::shared_from_this
T shared_from_this(T... args)
ripple::PublicKey
A public key.
Definition: PublicKey.h:61
ripple::InboundHandoff::stop
void stop() override
Stop the child.
Definition: InboundHandoff.cpp:70
beast::Journal::active
bool active(Severity level) const
Returns true if any message would be logged at this severity level.
Definition: Journal.h:300
ripple::InboundHandoff::sendResponse
void sendResponse()
Send upgrade response to the client.
Definition: InboundHandoff.cpp:83
ripple::InboundHandoff::protocol_
ProtocolVersion protocol_
Definition: InboundHandoff.h:47
beast::Journal::info
Stream info() const
Definition: Journal.h:320
ripple::InboundHandoff::request_
http_request_type request_
Definition: InboundHandoff.h:51
std::uint32_t
ripple::InboundHandoff::fail
void fail(std::string const &name, error_code const &ec)
Log and close.
Definition: InboundHandoff.cpp:129
ripple::InboundHandoff::socket_type
boost::asio::ip::tcp::socket socket_type
Definition: InboundHandoff.h:36
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
protocol
Definition: ValidatorList.h:38
ripple::InboundHandoff::journal_
const beast::Journal journal_
Definition: InboundHandoff.h:43
ripple::PeerFinder::Manager::config
virtual Config config()=0
Returns the configuration for the manager.
beast::severities::kWarning
@ kWarning
Definition: Journal.h:37
ripple::Resource::Consumer
An endpoint that consumes resources.
Definition: Consumer.h:34
ripple::InboundHandoff::error_code
boost::system::error_code error_code
Definition: InboundHandoff.h:35
ripple::InboundHandoff::remote_address_
const beast::IP::Endpoint remote_address_
Definition: InboundHandoff.h:46
ripple::TokenType::NodePublic
@ NodePublic
std::stringstream::str
T str(T... args)
beast::Journal::debug
Stream debug() const
Definition: Journal.h:314
std::size_t
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::InboundHandoff::run
void run()
Start the handshake.
Definition: InboundHandoff.cpp:61
std::setw
T setw(T... args)
ripple::OverlayImpl
Definition: OverlayImpl.h:58
ripple::InboundHandoff::socket
socket_type & socket() const
Get underlying socket.
Definition: InboundHandoff.cpp:180
ripple::makeResponse
http_response_type makeResponse(bool crawlPublic, http_request_type const &req, beast::IP::Address public_ip, beast::IP::Address remote_ip, uint256 const &sharedValue, std::optional< std::uint32_t > networkID, ProtocolVersion protocol, Application &app)
Make http response.
Definition: Handshake.cpp:394
ripple::http_request_type
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
Definition: Handshake.h:47
std::unique_ptr< stream_type >
ripple::OverlayImpl::add_active
void add_active(std::shared_ptr< PeerImp > const &peer)
Definition: OverlayImpl.cpp:421
ripple::InboundHandoff::id_
const id_t id_
Definition: InboundHandoff.h:41
ripple::InboundHandoff::publicKey_
const PublicKey publicKey_
Definition: InboundHandoff.h:48