xrpld
Loading...
Searching...
No Matches
OverlayImpl.h
1#pragma once
2
3#include <xrpld/app/main/Application.h>
4#include <xrpld/core/Config.h>
5#include <xrpld/overlay/Message.h>
6#include <xrpld/overlay/Overlay.h>
7#include <xrpld/overlay/Peer.h>
8#include <xrpld/overlay/Slot.h>
9#include <xrpld/overlay/detail/Handshake.h>
10#include <xrpld/overlay/detail/TrafficCount.h>
11#include <xrpld/overlay/detail/TxMetrics.h>
12#include <xrpld/peerfinder/detail/StoreSqdb.h>
13#include <xrpld/rpc/ServerHandler.h>
14
15#include <xrpl/basics/Resolver.h>
16#include <xrpl/basics/UnorderedContainers.h>
17#include <xrpl/basics/UptimeClock.h>
18#include <xrpl/basics/base_uint.h>
19#include <xrpl/beast/insight/Collector.h>
20#include <xrpl/beast/insight/Gauge.h>
21#include <xrpl/beast/insight/Hook.h>
22#include <xrpl/beast/net/IPEndpoint.h>
23#include <xrpl/beast/utility/Journal.h>
24#include <xrpl/beast/utility/PropertyStream.h>
25#include <xrpl/beast/utility/instrumentation.h>
26#include <xrpl/json/json_value.h>
27#include <xrpl/peerfinder/PeerfinderManager.h>
28#include <xrpl/peerfinder/Slot.h>
29#include <xrpl/resource/ResourceManager.h>
30#include <xrpl/server/Handoff.h>
31#include <xrpl/server/Writer.h>
32
33#include <boost/algorithm/string/predicate.hpp>
34#include <boost/asio/basic_waitable_timer.hpp>
35#include <boost/asio/ip/tcp.hpp>
36#include <boost/asio/ssl/context.hpp>
37#include <boost/asio/strand.hpp>
38#include <boost/container/flat_map.hpp>
39
40#include <xrpl.pb.h>
41
42#include <atomic>
43#include <chrono>
44#include <condition_variable>
45#include <cstddef>
46#include <cstdint>
47#include <functional>
48#include <memory>
49#include <mutex>
50#include <optional>
51#include <set>
52#include <string>
53#include <unordered_map>
54#include <utility>
55#include <vector>
56
57namespace xrpl {
58
59// The largest counts an operator can configure must still imply a message size
60// within the overall protocol message limit. The same check for the defaults
61// lives in Message.h.
62static_assert(
65
66class PeerImp;
67class BasicConfig;
68
70{
71public:
72 class Child
73 {
74 protected:
76
77 explicit Child(OverlayImpl& overlay);
78
79 public:
80 virtual ~Child();
81 virtual void
82 stop() = 0;
83 };
84
85private:
87 using socket_type = boost::asio::ip::tcp::socket;
88 using address_type = boost::asio::ip::address;
89 using endpoint_type = boost::asio::ip::tcp::endpoint;
90 using error_code = boost::system::error_code;
91
93 {
94 boost::asio::basic_waitable_timer<clock_type> timer;
95 bool stopping{false};
96
97 explicit Timer(OverlayImpl& overlay);
98
99 void
100 stop() override;
101
102 void
103 asyncWait();
104
105 void
107 };
108
110 boost::asio::io_context& ioContext_;
112 boost::asio::strand<boost::asio::io_context::executor_type> strand_;
113 mutable std::recursive_mutex mutex_; // VFALCO use std::mutex
116 boost::container::flat_map<Child*, std::weak_ptr<Child>> list_;
132
134
135 // Transaction reduce-relay metrics
137
138 // A message with the list of manifests we send to peers
140 // Used to track whether we need to update the cached list of manifests
142 // Protects the message and the sequence list of manifests
144
145 //--------------------------------------------------------------------------
146
147public:
149 Application& app,
150 Setup setup,
151 ServerHandler& serverHandler,
153 Resolver& resolver,
154 boost::asio::io_context& ioContext,
155 BasicConfig const& config,
156 beast::insight::Collector::ptr const& collector);
157
158 OverlayImpl(OverlayImpl const&) = delete;
160 operator=(OverlayImpl const&) = delete;
161
162 void
163 start() override;
164
165 void
166 stop() override;
167
170 {
171 return *peerFinder_;
172 }
173
176 {
177 return resourceManager_;
178 }
179
180 Setup const&
181 setup() const
182 {
183 return setup_;
184 }
185
186 Handoff
187 onHandoff(
189 http_request_type&& request,
190 endpoint_type remoteEndpoint) override;
191
192 void
193 connect(beast::ip::Endpoint const& remoteEndpoint) override;
194
195 int
196 limit() override;
197
199 size() const override;
200
202 json() override;
203
205 getActivePeers() const override;
206
219 std::set<Peer::id_t> const& toSkip,
220 std::size_t& active,
221 std::size_t& disabled,
222 std::size_t& enabledInSkip) const;
223
224 void
226
228 findPeerByShortID(Peer::id_t const& id) const override;
229
231 findPeerByPublicKey(PublicKey const& pubKey) override;
232
233 void
234 broadcast(protocol::TMProposeSet const& m) override;
235
236 void
237 broadcast(protocol::TMValidation const& m) override;
238
240 relay(protocol::TMProposeSet const& m, uint256 const& uid, PublicKey const& validator) override;
241
243 relay(protocol::TMValidation const& m, uint256 const& uid, PublicKey const& validator) override;
244
245 void
246 relay(
247 uint256 const&,
249 std::set<Peer::id_t> const& skip) override;
250
253
254 //--------------------------------------------------------------------------
255 //
256 // OverlayImpl
257 //
258
259 void
261
262 void
264
271 void
273
274 // Called when an active peer is destroyed.
275 void
277
278 // UnaryFunc will be called as
279 // void(std::shared_ptr<PeerImp>&&)
280 //
281 template <class UnaryFunc>
282 void
283 forEach(UnaryFunc&& f) const
284 {
286 {
287 std::scoped_lock const lock(mutex_);
288
289 // Iterate over a copy of the peer list because peer
290 // destruction can invalidate iterators.
291 wp.reserve(ids_.size());
292
293 for (auto& x : ids_)
294 wp.push_back(x.second);
295 }
296
297 for (auto& w : wp)
298 {
299 if (auto p = w.lock())
300 f(std::move(p));
301 }
302 }
303
304 // Called when TMManifests is received from a peer
305 void
308 std::shared_ptr<PeerImp> const& from);
309
310 static bool
311 isPeerUpgrade(http_request_type const& request);
312
313 template <class Body>
314 static bool
315 isPeerUpgrade(boost::beast::http::response<Body> const& response)
316 {
317 if (!isUpgrade(response))
318 return false;
319 return response.result() == boost::beast::http::status::switching_protocols;
320 }
321
322 template <class Fields>
323 static bool
324 isUpgrade(boost::beast::http::header<true, Fields> const& req)
325 {
326 if (req.version() < 11)
327 return false;
328 if (req.method() != boost::beast::http::verb::get)
329 return false;
330 if (!boost::beast::http::token_list{req["Connection"]}.exists("upgrade"))
331 return false;
332 return true;
333 }
334
335 template <class Fields>
336 static bool
337 isUpgrade(boost::beast::http::header<false, Fields> const& req)
338 {
339 if (req.version() < 11)
340 return false;
341 if (!boost::beast::http::token_list{req["Connection"]}.exists("upgrade"))
342 return false;
343 return true;
344 }
345
346 static std::string
348
349 void
351
352 void
354
355 void
357 {
359 }
360
362 getJqTransOverflow() const override
363 {
364 return jqTransOverflow_;
365 }
366
367 void
369 {
371 }
372
374 getPeerDisconnect() const override
375 {
376 return peerDisconnects_;
377 }
378
379 void
384
387 {
389 }
390
392 networkID() const override
393 {
394 return setup_.networkID;
395 }
396
407 void
409 uint256 const& key,
410 PublicKey const& validator,
411 std::set<Peer::id_t>&& peers,
412 protocol::MessageType type);
413
417 void
419 uint256 const& key,
420 PublicKey const& validator,
421 Peer::id_t peer,
422 protocol::MessageType type);
423
430 void
432
434 txMetrics() const override
435 {
436 return txMetrics_.json();
437 }
438
442 template <typename... Args>
443 void
444 addTxMetrics(Args... args)
445 {
446 if (!strand_.running_in_this_thread())
447 return post(strand_, [this, args...] { addTxMetrics(args...); });
448
449 txMetrics_.addMetrics(args...);
450 }
451
452private:
453 void
454 squelch(PublicKey const& validator, Peer::id_t const id, std::uint32_t squelchDuration)
455 const override;
456
457 void
458 unsquelch(PublicKey const& validator, Peer::id_t id) const override;
459
463 http_request_type const& request,
464 address_type remoteAddress);
465
469 http_request_type const& request,
470 address_type remoteAddress,
471 std::string const& msg);
472
479 bool
480 processCrawl(http_request_type const& req, Handoff& handoff);
481
490 bool
491 processValidatorList(http_request_type const& req, Handoff& handoff);
492
499 bool
500 processHealth(http_request_type const& req, Handoff& handoff);
501
507 bool
508 processRequest(http_request_type const& req, Handoff& handoff);
509
516 getOverlayInfo() const;
517
525
533
540 getUnlInfo();
541
542 //--------------------------------------------------------------------------
543
544 //
545 // PropertyStream
546 //
547
548 void
549 onWrite(beast::PropertyStream::Map& stream) override;
550
551 //--------------------------------------------------------------------------
552
553 void
554 remove(Child& child);
555
556 void
557 stopChildren();
558
559 void
560 autoConnect();
561
562 void
564
568 void
569 sendTxQueue() const;
570
575 void
577
578private:
580 {
582 : name(name)
583 , bytesIn(collector->makeGauge(name, "Bytes_In"))
584 , bytesOut(collector->makeGauge(name, "Bytes_Out"))
585 , messagesIn(collector->makeGauge(name, "Messages_In"))
586 , messagesOut(collector->makeGauge(name, "Messages_Out"))
587 {
588 }
594 };
595
596 struct Stats
597 {
598 template <class Handler>
600 Handler const& handler,
601 beast::insight::Collector::ptr const& collector,
603 : peerDisconnects(collector->makeGauge("Overlay", "Peer_Disconnects"))
605 , hook(collector->makeHook(handler))
606 {
607 }
608
612 };
613
616
617private:
618 void
620 {
621 auto counts = traffic_.getCounts();
622 std::scoped_lock const lock(statsMutex_);
623 XRPL_ASSERT(
624 counts.size() == stats_.trafficGauges.size(),
625 "xrpl::OverlayImpl::collect_metrics : counts size do match");
626
627 for (auto const& [key, value] : counts)
628 {
629 auto it = stats_.trafficGauges.find(key);
630 if (it == stats_.trafficGauges.end())
631 continue;
632
633 auto& gauge = it->second;
634
635 XRPL_ASSERT(
636 gauge.name == value.name,
637 "xrpl::OverlayImpl::collect_metrics : gauge and counter "
638 "match");
639
640 gauge.bytesIn = value.bytesIn;
641 gauge.bytesOut = value.bytesOut;
642 gauge.messagesIn = value.messagesIn;
643 gauge.messagesOut = value.messagesOut;
644 }
645
646 stats_.peerDisconnects = getPeerDisconnect();
647 }
648};
649
650} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
std::shared_ptr< Collector > ptr
Definition Collector.h:29
A metric for measuring an integral value.
Definition Gauge.h:21
A reference to a handler for performing polled collection.
Definition Hook.h:14
A version-independent IP address and port combination.
Definition IPEndpoint.h:24
Represents a JSON value.
Definition json_value.h:117
Holds unparsed configuration information.
static constexpr std::size_t kMaxManifestCount
Child(OverlayImpl &overlay)
virtual void stop()=0
void deletePeer(Peer::id_t id)
Called when the peer is deleted.
std::weak_ptr< Timer > timer_
boost::asio::io_context & ioContext_
resource::Manager & resourceManager()
bool processRequest(http_request_type const &req, Handoff &handoff)
Handles non-peer protocol requests.
json::Value getOverlayInfo() const
Returns information about peers on the overlay network.
boost::asio::ip::address address_type
Definition OverlayImpl.h:88
static bool isPeerUpgrade(http_request_type const &request)
Resolver & resolver_
void addActive(std::shared_ptr< PeerImp > const &peer)
boost::system::error_code error_code
Definition OverlayImpl.h:90
std::mutex statsMutex_
bool processCrawl(http_request_type const &req, Handoff &handoff)
Handles crawl requests.
void broadcast(protocol::TMProposeSet const &m) override
Broadcast a proposal.
OverlayImpl(OverlayImpl const &)=delete
void addTxMetrics(Args... args)
Add tx reduce-relay metrics.
bool processHealth(http_request_type const &req, Handoff &handoff)
Handles health requests.
void incPeerDisconnectCharges() override
void activate(std::shared_ptr< PeerImp > const &peer)
Called when a peer has connected successfully This is called after the peer handshake has been comple...
std::atomic< uint64_t > peerDisconnectsCharges_
boost::asio::ip::tcp::socket socket_type
Definition OverlayImpl.h:87
std::optional< boost::asio::executor_work_guard< boost::asio::io_context::executor_type > > work_
void connect(beast::ip::Endpoint const &remoteEndpoint) override
Establish a peer connection to the specified endpoint.
peer_finder::Manager & peerFinder()
static bool isUpgrade(boost::beast::http::header< false, Fields > const &req)
void remove(std::shared_ptr< peer_finder::Slot > const &slot)
json::Value txMetrics() const override
Returns tx reduce-relay metrics.
std::set< Peer::id_t > relay(protocol::TMProposeSet const &m, uint256 const &uid, PublicKey const &validator) override
Relay a proposal.
void stop() override
OverlayImpl & operator=(OverlayImpl const &)=delete
std::size_t size() const override
The number of active peers on the network Active peers are only those peers that have completed the h...
static bool isUpgrade(boost::beast::http::header< true, Fields > const &req)
std::chrono::steady_clock clock_type
Definition OverlayImpl.h:86
ServerHandler & serverHandler_
void onManifests(std::shared_ptr< protocol::TMManifests > const &m, std::shared_ptr< PeerImp > const &from)
std::uint64_t getPeerDisconnectCharges() const override
static std::shared_ptr< Writer > makeErrorResponse(std::shared_ptr< peer_finder::Slot > const &slot, http_request_type const &request, address_type remoteAddress, std::string const &msg)
std::shared_ptr< Writer > makeRedirectResponse(std::shared_ptr< peer_finder::Slot > const &slot, http_request_type const &request, address_type remoteAddress)
Handoff onHandoff(std::unique_ptr< stream_type > &&bundle, http_request_type &&request, endpoint_type remoteEndpoint) override
Conditionally accept an incoming HTTP request.
peer_finder::StoreSqdb store_
reduce_relay::Slots< UptimeClock > slots_
hash_map< Peer::id_t, std::weak_ptr< PeerImp > > ids_
void deleteIdlePeers()
Check if peers stopped relaying messages and if slots stopped receiving messages from the validator.
OverlayImpl(Application &app, Setup setup, ServerHandler &serverHandler, resource::Manager &resourceManager, Resolver &resolver, boost::asio::io_context &ioContext, BasicConfig const &config, beast::insight::Collector::ptr const &collector)
void squelch(PublicKey const &validator, Peer::id_t const id, std::uint32_t squelchDuration) const override
Squelch handler.
void reportInboundTraffic(TrafficCount::Category cat, int bytes)
std::shared_ptr< Message > manifestMessage_
void sendTxQueue() const
Send once a second transactions' hashes aggregated by peers.
std::uint64_t getPeerDisconnect() const override
std::optional< std::uint32_t > manifestListSeq_
std::unique_ptr< peer_finder::Manager > peerFinder_
void onWrite(beast::PropertyStream::Map &stream) override
Subclass override.
resource::Manager & resourceManager_
Application & app_
std::atomic< Peer::id_t > nextId_
json::Value getServerCounts()
Returns information about the local server's performance counters.
std::recursive_mutex mutex_
void incPeerDisconnect() override
Increment and retrieve counters for total peer disconnects, and disconnects we initiate for excessive...
beast::Journal const journal_
json::Value json() override
Return diagnostics on the status of all peers.
boost::asio::ip::tcp::endpoint endpoint_type
Definition OverlayImpl.h:89
void forEach(UnaryFunc &&f) const
void onPeerDeactivate(Peer::id_t id)
std::mutex manifestLock_
boost::asio::strand< boost::asio::io_context::executor_type > strand_
static std::string makePrefix(std::uint32_t id)
Setup const & setup() const
std::atomic< uint64_t > peerDisconnects_
metrics::TxMetrics txMetrics_
boost::container::flat_map< Child *, std::weak_ptr< Child > > list_
int limit() override
Returns the maximum number of peers we are configured to allow.
std::condition_variable_any cond_
json::Value getUnlInfo()
Returns information about the local server's UNL.
std::shared_ptr< Message > getManifestsMessage()
std::shared_ptr< Peer > findPeerByPublicKey(PublicKey const &pubKey) override
Returns the peer with the matching public key, or null.
TrafficCount traffic_
std::atomic< uint64_t > jqTransOverflow_
hash_map< std::shared_ptr< peer_finder::Slot >, std::weak_ptr< PeerImp > > peers_
std::optional< std::uint32_t > networkID() const override
Returns the ID of the network this server is configured for, if any.
bool processValidatorList(http_request_type const &req, Handoff &handoff)
Handles validator list requests.
void checkTracking(std::uint32_t) override
Calls the checkTracking function on each peer.
json::Value getServerInfo()
Returns information about the local server.
void updateSlotAndSquelch(uint256 const &key, PublicKey const &validator, std::set< Peer::id_t > &&peers, protocol::MessageType type)
Updates message count for validator/peer.
void reportOutboundTraffic(TrafficCount::Category cat, int bytes)
std::uint64_t getJqTransOverflow() const override
static bool isPeerUpgrade(boost::beast::http::response< Body > const &response)
std::shared_ptr< Peer > findPeerByShortID(Peer::id_t const &id) const override
Returns the peer with the matching short id, or null.
void start() override
PeerSequence getActivePeers() const override
Returns a sequence representing the current list of peers.
void unsquelch(PublicKey const &validator, Peer::id_t id) const override
Unsquelch handler.
void incJqTransOverflow() override
Increment and retrieve counter for transaction job queue overflows.
std::vector< std::shared_ptr< Peer > > PeerSequence
Definition Overlay.h:66
std::uint32_t id_t
Uniquely identifies a peer.
A public key.
Definition PublicKey.h:53
TrafficCount is used to count ingress and egress wire bytes and number of messages.
Maintains a set of IP addresses used for getting into the network.
Database persistence for PeerFinder using SQLite.
Definition StoreSqdb.h:23
Slots is a container for validator's Slot and handles Slot update when a message is received from a v...
Tracks load and resource consumption.
STL namespace.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
constexpr std::size_t kMaximumMessageSize
Definition Message.h:22
constexpr std::size_t maximumManifestsMessageSize(std::size_t const trustedCount, std::size_t const untrustedCount)
Upper bound on the wire size of a TMManifests message.
Definition Message.h:48
std::unordered_map< Key, Value, Hash, Pred, Allocator > hash_map
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
Definition Handoff.h:12
BaseUInt< 256 > uint256
Definition base_uint.h:580
T push_back(T... args)
T reserve(T... args)
Used to indicate the result of a server connection handoff.
Definition Handoff.h:20
beast::insight::Gauge peerDisconnects
std::unordered_map< TrafficCount::Category, TrafficGauges > trafficGauges
beast::insight::Hook hook
Stats(Handler const &handler, beast::insight::Collector::ptr const &collector, std::unordered_map< TrafficCount::Category, TrafficGauges > &&trafficGauges)
void onTimer(error_code ec)
boost::asio::basic_waitable_timer< clock_type > timer
Definition OverlayImpl.h:94
Timer(OverlayImpl &overlay)
beast::insight::Gauge messagesOut
beast::insight::Gauge bytesOut
TrafficGauges(std::string const &name, beast::insight::Collector::ptr const &collector)
beast::insight::Gauge messagesIn
beast::insight::Gauge bytesIn
Run transaction reduce-relay feature related metrics.
Definition TxMetrics.h:78