rippled
Loading...
Searching...
No Matches
OverlayImpl.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 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 <xrpld/app/misc/HashRouter.h>
21#include <xrpld/app/misc/NetworkOPs.h>
22#include <xrpld/app/misc/ValidatorList.h>
23#include <xrpld/app/misc/ValidatorSite.h>
24#include <xrpld/app/rdb/RelationalDatabase.h>
25#include <xrpld/app/rdb/Wallet.h>
26#include <xrpld/overlay/Cluster.h>
27#include <xrpld/overlay/detail/ConnectAttempt.h>
28#include <xrpld/overlay/detail/PeerImp.h>
29#include <xrpld/overlay/detail/Tuning.h>
30#include <xrpld/overlay/predicates.h>
31#include <xrpld/peerfinder/make_Manager.h>
32#include <xrpld/rpc/handlers/GetCounts.h>
33#include <xrpld/rpc/json_body.h>
34
35#include <xrpl/basics/base64.h>
36#include <xrpl/basics/make_SSLContext.h>
37#include <xrpl/basics/random.h>
38#include <xrpl/beast/core/LexicalCast.h>
39#include <xrpl/protocol/STTx.h>
40#include <xrpl/server/SimpleWriter.h>
41
42#include <boost/algorithm/string/predicate.hpp>
43
44namespace ripple {
45
46namespace CrawlOptions {
47enum {
49 Overlay = (1 << 0),
50 ServerInfo = (1 << 1),
51 ServerCounts = (1 << 2),
52 Unl = (1 << 3)
53};
54}
55
56//------------------------------------------------------------------------------
57
58OverlayImpl::Child::Child(OverlayImpl& overlay) : overlay_(overlay)
59{
60}
61
63{
64 overlay_.remove(*this);
65}
66
67//------------------------------------------------------------------------------
68
70 : Child(overlay), timer_(overlay_.io_service_)
71{
72}
73
74void
76{
77 // This method is only ever called from the same strand that calls
78 // Timer::on_timer, ensuring they never execute concurrently.
79 stopping_ = true;
80 timer_.cancel();
81}
82
83void
85{
86 timer_.expires_after(std::chrono::seconds(1));
87 timer_.async_wait(overlay_.strand_.wrap(std::bind(
88 &Timer::on_timer, shared_from_this(), std::placeholders::_1)));
89}
90
91void
93{
94 if (ec || stopping_)
95 {
96 if (ec && ec != boost::asio::error::operation_aborted)
97 {
98 JLOG(overlay_.journal_.error()) << "on_timer: " << ec.message();
99 }
100 return;
101 }
102
103 overlay_.m_peerFinder->once_per_second();
104 overlay_.sendEndpoints();
105 overlay_.autoConnect();
106 if (overlay_.app_.config().TX_REDUCE_RELAY_ENABLE)
107 overlay_.sendTxQueue();
108
109 if ((++overlay_.timer_count_ % Tuning::checkIdlePeers) == 0)
110 overlay_.deleteIdlePeers();
111
112 async_wait();
113}
114
115//------------------------------------------------------------------------------
116
118 Application& app,
119 Setup const& setup,
120 ServerHandler& serverHandler,
122 Resolver& resolver,
123 boost::asio::io_service& io_service,
124 BasicConfig const& config,
125 beast::insight::Collector::ptr const& collector)
126 : app_(app)
127 , io_service_(io_service)
128 , work_(std::in_place, std::ref(io_service_))
130 , setup_(setup)
131 , journal_(app_.journal("Overlay"))
132 , serverHandler_(serverHandler)
134 , m_peerFinder(PeerFinder::make_Manager(
135 io_service,
136 stopwatch(),
137 app_.journal("PeerFinder"),
138 config,
139 collector))
140 , m_resolver(resolver)
141 , next_id_(1)
142 , timer_count_(0)
143 , slots_(app.logs(), *this)
144 , m_stats(
145 std::bind(&OverlayImpl::collect_metrics, this),
146 collector,
147 [counts = m_traffic.getCounts(), collector]() {
149 ret.reserve(counts.size());
150
151 for (size_t i = 0; i < counts.size(); ++i)
152 {
153 ret.push_back(TrafficGauges(counts[i].name, collector));
154 }
155
156 return ret;
157 }())
158{
160}
161
162Handoff
164 std::unique_ptr<stream_type>&& stream_ptr,
165 http_request_type&& request,
166 endpoint_type remote_endpoint)
167{
168 auto const id = next_id_++;
169 beast::WrappedSink sink(app_.logs()["Peer"], makePrefix(id));
170 beast::Journal journal(sink);
171
172 Handoff handoff;
173 if (processRequest(request, handoff))
174 return handoff;
175 if (!isPeerUpgrade(request))
176 return handoff;
177
178 handoff.moved = true;
179
180 JLOG(journal.debug()) << "Peer connection upgrade from " << remote_endpoint;
181
182 error_code ec;
183 auto const local_endpoint(
184 stream_ptr->next_layer().socket().local_endpoint(ec));
185 if (ec)
186 {
187 JLOG(journal.debug()) << remote_endpoint << " failed: " << ec.message();
188 return handoff;
189 }
190
193 if (consumer.disconnect(journal))
194 return handoff;
195
196 auto const slot = m_peerFinder->new_inbound_slot(
199
200 if (slot == nullptr)
201 {
202 // self-connect, close
203 handoff.moved = false;
204 return handoff;
205 }
206
207 // Validate HTTP request
208
209 {
210 auto const types = beast::rfc2616::split_commas(request["Connect-As"]);
211 if (std::find_if(types.begin(), types.end(), [](std::string const& s) {
212 return boost::iequals(s, "peer");
213 }) == types.end())
214 {
215 handoff.moved = false;
216 handoff.response =
217 makeRedirectResponse(slot, request, remote_endpoint.address());
218 handoff.keep_alive = beast::rfc2616::is_keep_alive(request);
219 return handoff;
220 }
221 }
222
223 auto const negotiatedVersion = negotiateProtocolVersion(request["Upgrade"]);
224 if (!negotiatedVersion)
225 {
226 m_peerFinder->on_closed(slot);
227 handoff.moved = false;
228 handoff.response = makeErrorResponse(
229 slot,
230 request,
231 remote_endpoint.address(),
232 "Unable to agree on a protocol version");
233 handoff.keep_alive = false;
234 return handoff;
235 }
236
237 auto const sharedValue = makeSharedValue(*stream_ptr, journal);
238 if (!sharedValue)
239 {
240 m_peerFinder->on_closed(slot);
241 handoff.moved = false;
242 handoff.response = makeErrorResponse(
243 slot,
244 request,
245 remote_endpoint.address(),
246 "Incorrect security cookie");
247 handoff.keep_alive = false;
248 return handoff;
249 }
250
251 try
252 {
253 auto publicKey = verifyHandshake(
254 request,
255 *sharedValue,
258 remote_endpoint.address(),
259 app_);
260
261 {
262 // The node gets a reserved slot if it is in our cluster
263 // or if it has a reservation.
264 bool const reserved =
265 static_cast<bool>(app_.cluster().member(publicKey)) ||
266 app_.peerReservations().contains(publicKey);
267 auto const result =
268 m_peerFinder->activate(slot, publicKey, reserved);
269 if (result != PeerFinder::Result::success)
270 {
271 m_peerFinder->on_closed(slot);
272 JLOG(journal.debug())
273 << "Peer " << remote_endpoint << " redirected, slots full";
274 handoff.moved = false;
276 slot, request, remote_endpoint.address());
277 handoff.keep_alive = false;
278 return handoff;
279 }
280 }
281
282 auto const peer = std::make_shared<PeerImp>(
283 app_,
284 id,
285 slot,
286 std::move(request),
287 publicKey,
288 *negotiatedVersion,
289 consumer,
290 std::move(stream_ptr),
291 *this);
292 {
293 // As we are not on the strand, run() must be called
294 // while holding the lock, otherwise new I/O can be
295 // queued after a call to stop().
296 std::lock_guard<decltype(mutex_)> lock(mutex_);
297 {
298 auto const result = m_peers.emplace(peer->slot(), peer);
299 XRPL_ASSERT(
300 result.second,
301 "ripple::OverlayImpl::onHandoff : peer is inserted");
302 (void)result.second;
303 }
304 list_.emplace(peer.get(), peer);
305
306 peer->run();
307 }
308 handoff.moved = true;
309 return handoff;
310 }
311 catch (std::exception const& e)
312 {
313 JLOG(journal.debug()) << "Peer " << remote_endpoint
314 << " fails handshake (" << e.what() << ")";
315
316 m_peerFinder->on_closed(slot);
317 handoff.moved = false;
318 handoff.response = makeErrorResponse(
319 slot, request, remote_endpoint.address(), e.what());
320 handoff.keep_alive = false;
321 return handoff;
322 }
323}
324
325//------------------------------------------------------------------------------
326
327bool
329{
330 if (!is_upgrade(request))
331 return false;
332 auto const versions = parseProtocolVersions(request["Upgrade"]);
333 return !versions.empty();
334}
335
338{
340 ss << "[" << std::setfill('0') << std::setw(3) << id << "] ";
341 return ss.str();
342}
343
347 http_request_type const& request,
348 address_type remote_address)
349{
350 boost::beast::http::response<json_body> msg;
351 msg.version(request.version());
352 msg.result(boost::beast::http::status::service_unavailable);
353 msg.insert("Server", BuildInfo::getFullVersionString());
354 {
356 ostr << remote_address;
357 msg.insert("Remote-Address", ostr.str());
358 }
359 msg.insert("Content-Type", "application/json");
360 msg.insert(boost::beast::http::field::connection, "close");
361 msg.body() = Json::objectValue;
362 {
363 Json::Value& ips = (msg.body()["peer-ips"] = Json::arrayValue);
364 for (auto const& _ : m_peerFinder->redirect(slot))
365 ips.append(_.address.to_string());
366 }
367 msg.prepare_payload();
368 return std::make_shared<SimpleWriter>(msg);
369}
370
374 http_request_type const& request,
375 address_type remote_address,
376 std::string text)
377{
378 boost::beast::http::response<boost::beast::http::empty_body> msg;
379 msg.version(request.version());
380 msg.result(boost::beast::http::status::bad_request);
381 msg.reason("Bad Request (" + text + ")");
382 msg.insert("Server", BuildInfo::getFullVersionString());
383 msg.insert("Remote-Address", remote_address.to_string());
384 msg.insert(boost::beast::http::field::connection, "close");
385 msg.prepare_payload();
386 return std::make_shared<SimpleWriter>(msg);
387}
388
389//------------------------------------------------------------------------------
390
391void
393{
394 XRPL_ASSERT(work_, "ripple::OverlayImpl::connect : work is set");
395
396 auto usage = resourceManager().newOutboundEndpoint(remote_endpoint);
397 if (usage.disconnect(journal_))
398 {
399 JLOG(journal_.info()) << "Over resource limit: " << remote_endpoint;
400 return;
401 }
402
403 auto const slot = peerFinder().new_outbound_slot(remote_endpoint);
404 if (slot == nullptr)
405 {
406 JLOG(journal_.debug()) << "Connect: No slot for " << remote_endpoint;
407 return;
408 }
409
410 auto const p = std::make_shared<ConnectAttempt>(
411 app_,
414 usage,
416 next_id_++,
417 slot,
418 app_.journal("Peer"),
419 *this);
420
422 list_.emplace(p.get(), p);
423 p->run();
424}
425
426//------------------------------------------------------------------------------
427
428// Adds a peer that is already handshaked and active
429void
431{
433
434 {
435 auto const result = m_peers.emplace(peer->slot(), peer);
436 XRPL_ASSERT(
437 result.second,
438 "ripple::OverlayImpl::add_active : peer is inserted");
439 (void)result.second;
440 }
441
442 {
443 auto const result = ids_.emplace(
444 std::piecewise_construct,
445 std::make_tuple(peer->id()),
446 std::make_tuple(peer));
447 XRPL_ASSERT(
448 result.second,
449 "ripple::OverlayImpl::add_active : peer ID is inserted");
450 (void)result.second;
451 }
452
453 list_.emplace(peer.get(), peer);
454
455 JLOG(journal_.debug()) << "activated " << peer->getRemoteAddress() << " ("
456 << peer->id() << ":"
457 << toBase58(
458 TokenType::NodePublic, peer->getNodePublic())
459 << ")";
460
461 // As we are not on the strand, run() must be called
462 // while holding the lock, otherwise new I/O can be
463 // queued after a call to stop().
464 peer->run();
465}
466
467void
469{
471 auto const iter = m_peers.find(slot);
472 XRPL_ASSERT(
473 iter != m_peers.end(), "ripple::OverlayImpl::remove : valid input");
474 m_peers.erase(iter);
475}
476
477void
479{
481 app_.config(),
482 serverHandler_.setup().overlay.port(),
483 app_.getValidationPublicKey().has_value(),
485
486 m_peerFinder->setConfig(config);
487 m_peerFinder->start();
488
489 // Populate our boot cache: if there are no entries in [ips] then we use
490 // the entries in [ips_fixed].
491 auto bootstrapIps =
493
494 // If nothing is specified, default to several well-known high-capacity
495 // servers to serve as bootstrap:
496 if (bootstrapIps.empty())
497 {
498 // Pool of servers operated by Ripple Labs Inc. - https://ripple.com
499 bootstrapIps.push_back("r.ripple.com 51235");
500
501 // Pool of servers operated by ISRDC - https://isrdc.in
502 bootstrapIps.push_back("sahyadri.isrdc.in 51235");
503
504 // Pool of servers operated by @Xrpkuwait - https://xrpkuwait.com
505 bootstrapIps.push_back("hubs.xrpkuwait.com 51235");
506 }
507
509 bootstrapIps,
510 [this](
511 std::string const& name,
512 std::vector<beast::IP::Endpoint> const& addresses) {
514 ips.reserve(addresses.size());
515 for (auto const& addr : addresses)
516 {
517 if (addr.port() == 0)
518 ips.push_back(to_string(addr.at_port(DEFAULT_PEER_PORT)));
519 else
520 ips.push_back(to_string(addr));
521 }
522
523 std::string const base("config: ");
524 if (!ips.empty())
525 m_peerFinder->addFallbackStrings(base + name, ips);
526 });
527
528 // Add the ips_fixed from the rippled.cfg file
530 {
533 [this](
534 std::string const& name,
535 std::vector<beast::IP::Endpoint> const& addresses) {
537 ips.reserve(addresses.size());
538
539 for (auto& addr : addresses)
540 {
541 if (addr.port() == 0)
542 ips.emplace_back(addr.address(), DEFAULT_PEER_PORT);
543 else
544 ips.emplace_back(addr);
545 }
546
547 if (!ips.empty())
548 m_peerFinder->addFixedPeer(name, ips);
549 });
550 }
551 auto const timer = std::make_shared<Timer>(*this);
553 list_.emplace(timer.get(), timer);
554 timer_ = timer;
555 timer->async_wait();
556}
557
558void
560{
562 {
563 std::unique_lock<decltype(mutex_)> lock(mutex_);
564 cond_.wait(lock, [this] { return list_.empty(); });
565 }
566 m_peerFinder->stop();
567}
568
569//------------------------------------------------------------------------------
570//
571// PropertyStream
572//
573//------------------------------------------------------------------------------
574
575void
577{
578 beast::PropertyStream::Set set("traffic", stream);
579 auto const stats = m_traffic.getCounts();
580 for (auto const& i : stats)
581 {
582 if (i)
583 {
585 item["category"] = i.name;
586 item["bytes_in"] = std::to_string(i.bytesIn.load());
587 item["messages_in"] = std::to_string(i.messagesIn.load());
588 item["bytes_out"] = std::to_string(i.bytesOut.load());
589 item["messages_out"] = std::to_string(i.messagesOut.load());
590 }
591 }
592}
593
594//------------------------------------------------------------------------------
600void
602{
603 // Now track this peer
604 {
606 auto const result(ids_.emplace(
607 std::piecewise_construct,
608 std::make_tuple(peer->id()),
609 std::make_tuple(peer)));
610 XRPL_ASSERT(
611 result.second,
612 "ripple::OverlayImpl::activate : peer ID is inserted");
613 (void)result.second;
614 }
615
616 JLOG(journal_.debug()) << "activated " << peer->getRemoteAddress() << " ("
617 << peer->id() << ":"
618 << toBase58(
619 TokenType::NodePublic, peer->getNodePublic())
620 << ")";
621
622 // We just accepted this peer so we have non-zero active peers
623 XRPL_ASSERT(size(), "ripple::OverlayImpl::activate : nonzero peers");
624}
625
626void
628{
630 ids_.erase(id);
631}
632
633void
636 std::shared_ptr<PeerImp> const& from)
637{
638 auto const n = m->list_size();
639 auto const& journal = from->pjournal();
640
641 protocol::TMManifests relay;
642
643 for (std::size_t i = 0; i < n; ++i)
644 {
645 auto& s = m->list().Get(i).stobject();
646
647 if (auto mo = deserializeManifest(s))
648 {
649 auto const serialized = mo->serialized;
650
651 auto const result =
652 app_.validatorManifests().applyManifest(std::move(*mo));
653
654 if (result == ManifestDisposition::accepted)
655 {
656 relay.add_list()->set_stobject(s);
657
658 // N.B.: this is important; the applyManifest call above moves
659 // the loaded Manifest out of the optional so we need to
660 // reload it here.
661 mo = deserializeManifest(serialized);
662 XRPL_ASSERT(
663 mo,
664 "ripple::OverlayImpl::onManifests : manifest "
665 "deserialization succeeded");
666
667 app_.getOPs().pubManifest(*mo);
668
669 if (app_.validators().listed(mo->masterKey))
670 {
671 auto db = app_.getWalletDB().checkoutDb();
672 addValidatorManifest(*db, serialized);
673 }
674 }
675 }
676 else
677 {
678 JLOG(journal.debug())
679 << "Malformed manifest #" << i + 1 << ": " << strHex(s);
680 continue;
681 }
682 }
683
684 if (!relay.list().empty())
685 for_each([m2 = std::make_shared<Message>(relay, protocol::mtMANIFESTS)](
686 std::shared_ptr<PeerImp>&& p) { p->send(m2); });
687}
688
689void
692 bool isInbound,
693 int number)
694{
695 m_traffic.addCount(cat, isInbound, number);
696}
697
704{
706 return ids_.size();
707}
708
709int
711{
712 return m_peerFinder->config().maxPeers;
713}
714
717{
718 using namespace std::chrono;
719 Json::Value jv;
720 auto& av = jv["active"] = Json::Value(Json::arrayValue);
721
723 auto& pv = av.append(Json::Value(Json::objectValue));
724 pv[jss::public_key] = base64_encode(
725 sp->getNodePublic().data(), sp->getNodePublic().size());
726 pv[jss::type] = sp->slot()->inbound() ? "in" : "out";
727 pv[jss::uptime] = static_cast<std::uint32_t>(
728 duration_cast<seconds>(sp->uptime()).count());
729 if (sp->crawl())
730 {
731 pv[jss::ip] = sp->getRemoteAddress().address().to_string();
732 if (sp->slot()->inbound())
733 {
734 if (auto port = sp->slot()->listening_port())
735 pv[jss::port] = *port;
736 }
737 else
738 {
739 pv[jss::port] = std::to_string(sp->getRemoteAddress().port());
740 }
741 }
742
743 {
744 auto version{sp->getVersion()};
745 if (!version.empty())
746 // Could move here if Json::value supported moving from strings
747 pv[jss::version] = std::string{version};
748 }
749
750 std::uint32_t minSeq, maxSeq;
751 sp->ledgerRange(minSeq, maxSeq);
752 if (minSeq != 0 || maxSeq != 0)
753 pv[jss::complete_ledgers] =
754 std::to_string(minSeq) + "-" + std::to_string(maxSeq);
755 });
756
757 return jv;
758}
759
762{
763 bool const humanReadable = false;
764 bool const admin = false;
765 bool const counters = false;
766
767 Json::Value server_info =
768 app_.getOPs().getServerInfo(humanReadable, admin, counters);
769
770 // Filter out some information
771 server_info.removeMember(jss::hostid);
772 server_info.removeMember(jss::load_factor_fee_escalation);
773 server_info.removeMember(jss::load_factor_fee_queue);
774 server_info.removeMember(jss::validation_quorum);
775
776 if (server_info.isMember(jss::validated_ledger))
777 {
778 Json::Value& validated_ledger = server_info[jss::validated_ledger];
779
780 validated_ledger.removeMember(jss::base_fee);
781 validated_ledger.removeMember(jss::reserve_base_xrp);
782 validated_ledger.removeMember(jss::reserve_inc_xrp);
783 }
784
785 return server_info;
786}
787
790{
791 return getCountsJson(app_, 10);
792}
793
796{
797 Json::Value validators = app_.validators().getJson();
798
799 if (validators.isMember(jss::publisher_lists))
800 {
801 Json::Value& publisher_lists = validators[jss::publisher_lists];
802
803 for (auto& publisher : publisher_lists)
804 {
805 publisher.removeMember(jss::list);
806 }
807 }
808
809 validators.removeMember(jss::signing_keys);
810 validators.removeMember(jss::trusted_validator_keys);
811 validators.removeMember(jss::validation_quorum);
812
813 Json::Value validatorSites = app_.validatorSites().getJson();
814
815 if (validatorSites.isMember(jss::validator_sites))
816 {
817 validators[jss::validator_sites] =
818 std::move(validatorSites[jss::validator_sites]);
819 }
820
821 return validators;
822}
823
824// Returns information on verified peers.
827{
829 for (auto const& peer : getActivePeers())
830 {
831 json.append(peer->json());
832 }
833 return json;
834}
835
836bool
838{
839 if (req.target() != "/crawl" ||
841 return false;
842
843 boost::beast::http::response<json_body> msg;
844 msg.version(req.version());
845 msg.result(boost::beast::http::status::ok);
846 msg.insert("Server", BuildInfo::getFullVersionString());
847 msg.insert("Content-Type", "application/json");
848 msg.insert("Connection", "close");
849 msg.body()["version"] = Json::Value(2u);
850
852 {
853 msg.body()["overlay"] = getOverlayInfo();
854 }
856 {
857 msg.body()["server"] = getServerInfo();
858 }
860 {
861 msg.body()["counts"] = getServerCounts();
862 }
864 {
865 msg.body()["unl"] = getUnlInfo();
866 }
867
868 msg.prepare_payload();
869 handoff.response = std::make_shared<SimpleWriter>(msg);
870 return true;
871}
872
873bool
875 http_request_type const& req,
876 Handoff& handoff)
877{
878 // If the target is in the form "/vl/<validator_list_public_key>",
879 // return the most recent validator list for that key.
880 constexpr std::string_view prefix("/vl/");
881
882 if (!req.target().starts_with(prefix.data()) || !setup_.vlEnabled)
883 return false;
884
885 std::uint32_t version = 1;
886
887 boost::beast::http::response<json_body> msg;
888 msg.version(req.version());
889 msg.insert("Server", BuildInfo::getFullVersionString());
890 msg.insert("Content-Type", "application/json");
891 msg.insert("Connection", "close");
892
893 auto fail = [&msg, &handoff](auto status) {
894 msg.result(status);
895 msg.insert("Content-Length", "0");
896
897 msg.body() = Json::nullValue;
898
899 msg.prepare_payload();
900 handoff.response = std::make_shared<SimpleWriter>(msg);
901 return true;
902 };
903
904 std::string_view key = req.target().substr(prefix.size());
905
906 if (auto slash = key.find('/'); slash != std::string_view::npos)
907 {
908 auto verString = key.substr(0, slash);
909 if (!boost::conversion::try_lexical_convert(verString, version))
910 return fail(boost::beast::http::status::bad_request);
911 key = key.substr(slash + 1);
912 }
913
914 if (key.empty())
915 return fail(boost::beast::http::status::bad_request);
916
917 // find the list
918 auto vl = app_.validators().getAvailable(key, version);
919
920 if (!vl)
921 {
922 // 404 not found
923 return fail(boost::beast::http::status::not_found);
924 }
925 else if (!*vl)
926 {
927 return fail(boost::beast::http::status::bad_request);
928 }
929 else
930 {
931 msg.result(boost::beast::http::status::ok);
932
933 msg.body() = *vl;
934
935 msg.prepare_payload();
936 handoff.response = std::make_shared<SimpleWriter>(msg);
937 return true;
938 }
939}
940
941bool
943{
944 if (req.target() != "/health")
945 return false;
946 boost::beast::http::response<json_body> msg;
947 msg.version(req.version());
948 msg.insert("Server", BuildInfo::getFullVersionString());
949 msg.insert("Content-Type", "application/json");
950 msg.insert("Connection", "close");
951
952 auto info = getServerInfo();
953
954 int last_validated_ledger_age = -1;
955 if (info.isMember(jss::validated_ledger))
956 last_validated_ledger_age =
957 info[jss::validated_ledger][jss::age].asInt();
958 bool amendment_blocked = false;
959 if (info.isMember(jss::amendment_blocked))
960 amendment_blocked = true;
961 int number_peers = info[jss::peers].asInt();
962 std::string server_state = info[jss::server_state].asString();
963 auto load_factor = info[jss::load_factor_server].asDouble() /
964 info[jss::load_base].asDouble();
965
966 enum { healthy, warning, critical };
967 int health = healthy;
968 auto set_health = [&health](int state) {
969 if (health < state)
970 health = state;
971 };
972
973 msg.body()[jss::info] = Json::objectValue;
974 if (last_validated_ledger_age >= 7 || last_validated_ledger_age < 0)
975 {
976 msg.body()[jss::info][jss::validated_ledger] =
977 last_validated_ledger_age;
978 if (last_validated_ledger_age < 20)
979 set_health(warning);
980 else
981 set_health(critical);
982 }
983
984 if (amendment_blocked)
985 {
986 msg.body()[jss::info][jss::amendment_blocked] = true;
987 set_health(critical);
988 }
989
990 if (number_peers <= 7)
991 {
992 msg.body()[jss::info][jss::peers] = number_peers;
993 if (number_peers != 0)
994 set_health(warning);
995 else
996 set_health(critical);
997 }
998
999 if (!(server_state == "full" || server_state == "validating" ||
1000 server_state == "proposing"))
1001 {
1002 msg.body()[jss::info][jss::server_state] = server_state;
1003 if (server_state == "syncing" || server_state == "tracking" ||
1004 server_state == "connected")
1005 {
1006 set_health(warning);
1007 }
1008 else
1009 set_health(critical);
1010 }
1011
1012 if (load_factor > 100)
1013 {
1014 msg.body()[jss::info][jss::load_factor] = load_factor;
1015 if (load_factor < 1000)
1016 set_health(warning);
1017 else
1018 set_health(critical);
1019 }
1020
1021 switch (health)
1022 {
1023 case healthy:
1024 msg.result(boost::beast::http::status::ok);
1025 break;
1026 case warning:
1027 msg.result(boost::beast::http::status::service_unavailable);
1028 break;
1029 case critical:
1030 msg.result(boost::beast::http::status::internal_server_error);
1031 break;
1032 }
1033
1034 msg.prepare_payload();
1035 handoff.response = std::make_shared<SimpleWriter>(msg);
1036 return true;
1037}
1038
1039bool
1041{
1042 // Take advantage of || short-circuiting
1043 return processCrawl(req, handoff) || processValidatorList(req, handoff) ||
1044 processHealth(req, handoff);
1045}
1046
1049{
1051 ret.reserve(size());
1052
1053 for_each([&ret](std::shared_ptr<PeerImp>&& sp) {
1054 ret.emplace_back(std::move(sp));
1055 });
1056
1057 return ret;
1058}
1059
1062 std::set<Peer::id_t> const& toSkip,
1063 std::size_t& active,
1064 std::size_t& disabled,
1065 std::size_t& enabledInSkip) const
1066{
1068 std::lock_guard lock(mutex_);
1069
1070 active = ids_.size();
1071 disabled = enabledInSkip = 0;
1072 ret.reserve(ids_.size());
1073
1074 // NOTE The purpose of p is to delay the destruction of PeerImp
1076 for (auto& [id, w] : ids_)
1077 {
1078 if (p = w.lock(); p != nullptr)
1079 {
1080 bool const reduceRelayEnabled = p->txReduceRelayEnabled();
1081 // tx reduced relay feature disabled
1082 if (!reduceRelayEnabled)
1083 ++disabled;
1084
1085 if (toSkip.count(id) == 0)
1086 ret.emplace_back(std::move(p));
1087 else if (reduceRelayEnabled)
1088 ++enabledInSkip;
1089 }
1090 }
1091
1092 return ret;
1093}
1094
1095void
1097{
1098 for_each(
1099 [index](std::shared_ptr<PeerImp>&& sp) { sp->checkTracking(index); });
1100}
1101
1104{
1105 std::lock_guard lock(mutex_);
1106 auto const iter = ids_.find(id);
1107 if (iter != ids_.end())
1108 return iter->second.lock();
1109 return {};
1110}
1111
1112// A public key hash map was not used due to the peer connect/disconnect
1113// update overhead outweighing the performance of a small set linear search.
1116{
1117 std::lock_guard lock(mutex_);
1118 // NOTE The purpose of peer is to delay the destruction of PeerImp
1120 for (auto const& e : ids_)
1121 {
1122 if (peer = e.second.lock(); peer != nullptr)
1123 {
1124 if (peer->getNodePublic() == pubKey)
1125 return peer;
1126 }
1127 }
1128 return {};
1129}
1130
1131void
1132OverlayImpl::broadcast(protocol::TMProposeSet& m)
1133{
1134 auto const sm = std::make_shared<Message>(m, protocol::mtPROPOSE_LEDGER);
1135 for_each([&](std::shared_ptr<PeerImp>&& p) { p->send(sm); });
1136}
1137
1140 protocol::TMProposeSet& m,
1141 uint256 const& uid,
1142 PublicKey const& validator)
1143{
1144 if (auto const toSkip = app_.getHashRouter().shouldRelay(uid))
1145 {
1146 auto const sm =
1147 std::make_shared<Message>(m, protocol::mtPROPOSE_LEDGER, validator);
1149 if (toSkip->find(p->id()) == toSkip->end())
1150 p->send(sm);
1151 });
1152 return *toSkip;
1153 }
1154 return {};
1155}
1156
1157void
1158OverlayImpl::broadcast(protocol::TMValidation& m)
1159{
1160 auto const sm = std::make_shared<Message>(m, protocol::mtVALIDATION);
1161 for_each([sm](std::shared_ptr<PeerImp>&& p) { p->send(sm); });
1162}
1163
1166 protocol::TMValidation& m,
1167 uint256 const& uid,
1168 PublicKey const& validator)
1169{
1170 if (auto const toSkip = app_.getHashRouter().shouldRelay(uid))
1171 {
1172 auto const sm =
1173 std::make_shared<Message>(m, protocol::mtVALIDATION, validator);
1175 if (toSkip->find(p->id()) == toSkip->end())
1176 p->send(sm);
1177 });
1178 return *toSkip;
1179 }
1180 return {};
1181}
1182
1185{
1187
1188 if (auto seq = app_.validatorManifests().sequence();
1189 seq != manifestListSeq_)
1190 {
1191 protocol::TMManifests tm;
1192
1194 [&tm](std::size_t s) { tm.mutable_list()->Reserve(s); },
1195 [&tm, &hr = app_.getHashRouter()](Manifest const& manifest) {
1196 tm.add_list()->set_stobject(
1197 manifest.serialized.data(), manifest.serialized.size());
1198 hr.addSuppression(manifest.hash());
1199 });
1200
1202
1203 if (tm.list_size() != 0)
1205 std::make_shared<Message>(tm, protocol::mtMANIFESTS);
1206
1207 manifestListSeq_ = seq;
1208 }
1209
1210 return manifestMessage_;
1211}
1212
1213void
1215 uint256 const& hash,
1217 std::set<Peer::id_t> const& toSkip)
1218{
1219 bool relay = tx.has_value();
1220 if (relay)
1221 {
1222 auto& txn = tx->get();
1223 SerialIter sit(makeSlice(txn.rawtransaction()));
1224 relay = !isPseudoTx(STTx{sit});
1225 }
1226
1227 Overlay::PeerSequence peers = {};
1228 std::size_t total = 0;
1229 std::size_t disabled = 0;
1230 std::size_t enabledInSkip = 0;
1231
1232 if (!relay)
1233 {
1235 return;
1236
1237 peers = getActivePeers(toSkip, total, disabled, enabledInSkip);
1238 JLOG(journal_.trace())
1239 << "not relaying tx, total peers " << peers.size();
1240 for (auto const& p : peers)
1241 p->addTxQueue(hash);
1242 return;
1243 }
1244
1245 auto& txn = tx->get();
1246 auto const sm = std::make_shared<Message>(txn, protocol::mtTRANSACTION);
1247 peers = getActivePeers(toSkip, total, disabled, enabledInSkip);
1248 auto const minRelay = app_.config().TX_REDUCE_RELAY_MIN_PEERS + disabled;
1249
1250 if (!app_.config().TX_REDUCE_RELAY_ENABLE || total <= minRelay)
1251 {
1252 for (auto const& p : peers)
1253 p->send(sm);
1256 txMetrics_.addMetrics(total, toSkip.size(), 0);
1257 return;
1258 }
1259
1260 // We have more peers than the minimum (disabled + minimum enabled),
1261 // relay to all disabled and some randomly selected enabled that
1262 // do not have the transaction.
1263 auto const enabledTarget = app_.config().TX_REDUCE_RELAY_MIN_PEERS +
1264 (total - minRelay) * app_.config().TX_RELAY_PERCENTAGE / 100;
1265
1266 txMetrics_.addMetrics(enabledTarget, toSkip.size(), disabled);
1267
1268 if (enabledTarget > enabledInSkip)
1269 std::shuffle(peers.begin(), peers.end(), default_prng());
1270
1271 JLOG(journal_.trace()) << "relaying tx, total peers " << peers.size()
1272 << " selected " << enabledTarget << " skip "
1273 << toSkip.size() << " disabled " << disabled;
1274
1275 // count skipped peers with the enabled feature towards the quota
1276 std::uint16_t enabledAndRelayed = enabledInSkip;
1277 for (auto const& p : peers)
1278 {
1279 // always relay to a peer with the disabled feature
1280 if (!p->txReduceRelayEnabled())
1281 {
1282 p->send(sm);
1283 }
1284 else if (enabledAndRelayed < enabledTarget)
1285 {
1286 enabledAndRelayed++;
1287 p->send(sm);
1288 }
1289 else
1290 {
1291 p->addTxQueue(hash);
1292 }
1293 }
1294}
1295
1296//------------------------------------------------------------------------------
1297
1298void
1300{
1301 std::lock_guard lock(mutex_);
1302 list_.erase(&child);
1303 if (list_.empty())
1304 cond_.notify_all();
1305}
1306
1307void
1309{
1310 // Calling list_[].second->stop() may cause list_ to be modified
1311 // (OverlayImpl::remove() may be called on this same thread). So
1312 // iterating directly over list_ to call child->stop() could lead to
1313 // undefined behavior.
1314 //
1315 // Therefore we copy all of the weak/shared ptrs out of list_ before we
1316 // start calling stop() on them. That guarantees OverlayImpl::remove()
1317 // won't be called until vector<> children leaves scope.
1319 {
1320 std::lock_guard lock(mutex_);
1321 if (!work_)
1322 return;
1323 work_ = std::nullopt;
1324
1325 children.reserve(list_.size());
1326 for (auto const& element : list_)
1327 {
1328 children.emplace_back(element.second.lock());
1329 }
1330 } // lock released
1331
1332 for (auto const& child : children)
1333 {
1334 if (child != nullptr)
1335 child->stop();
1336 }
1337}
1338
1339void
1341{
1342 auto const result = m_peerFinder->autoconnect();
1343 for (auto addr : result)
1344 connect(addr);
1345}
1346
1347void
1349{
1350 auto const result = m_peerFinder->buildEndpointsForPeers();
1351 for (auto const& e : result)
1352 {
1354 {
1355 std::lock_guard lock(mutex_);
1356 auto const iter = m_peers.find(e.first);
1357 if (iter != m_peers.end())
1358 peer = iter->second.lock();
1359 }
1360 if (peer)
1361 peer->sendEndpoints(e.second.begin(), e.second.end());
1362 }
1363}
1364
1365void
1367{
1368 for_each([](auto const& p) {
1369 if (p->txReduceRelayEnabled())
1370 p->sendTxQueue();
1371 });
1372}
1373
1376 PublicKey const& validator,
1377 bool squelch,
1378 uint32_t squelchDuration)
1379{
1380 protocol::TMSquelch m;
1381 m.set_squelch(squelch);
1382 m.set_validatorpubkey(validator.data(), validator.size());
1383 if (squelch)
1384 m.set_squelchduration(squelchDuration);
1385 return std::make_shared<Message>(m, protocol::mtSQUELCH);
1386}
1387
1388void
1390{
1391 if (auto peer = findPeerByShortID(id);
1392 peer && app_.config().VP_REDUCE_RELAY_SQUELCH)
1393 {
1394 // optimize - multiple message with different
1395 // validator might be sent to the same peer
1396 peer->send(makeSquelchMessage(validator, false, 0));
1397 }
1398}
1399
1400void
1402 PublicKey const& validator,
1403 Peer::id_t id,
1404 uint32_t squelchDuration) const
1405{
1406 if (auto peer = findPeerByShortID(id);
1407 peer && app_.config().VP_REDUCE_RELAY_SQUELCH)
1408 {
1409 peer->send(makeSquelchMessage(validator, true, squelchDuration));
1410 }
1411}
1412
1413void
1415 uint256 const& key,
1416 PublicKey const& validator,
1417 std::set<Peer::id_t>&& peers,
1418 protocol::MessageType type)
1419{
1420 if (!strand_.running_in_this_thread())
1421 return post(
1422 strand_,
1423 [this, key, validator, peers = std::move(peers), type]() mutable {
1424 updateSlotAndSquelch(key, validator, std::move(peers), type);
1425 });
1426
1427 for (auto id : peers)
1428 slots_.updateSlotAndSquelch(key, validator, id, type);
1429}
1430
1431void
1433 uint256 const& key,
1434 PublicKey const& validator,
1435 Peer::id_t peer,
1436 protocol::MessageType type)
1437{
1438 if (!strand_.running_in_this_thread())
1439 return post(strand_, [this, key, validator, peer, type]() {
1440 updateSlotAndSquelch(key, validator, peer, type);
1441 });
1442
1443 slots_.updateSlotAndSquelch(key, validator, peer, type);
1444}
1445
1446void
1448{
1449 if (!strand_.running_in_this_thread())
1450 return post(strand_, std::bind(&OverlayImpl::deletePeer, this, id));
1451
1452 slots_.deletePeer(id, true);
1453}
1454
1455void
1457{
1458 if (!strand_.running_in_this_thread())
1459 return post(strand_, std::bind(&OverlayImpl::deleteIdlePeers, this));
1460
1461 slots_.deleteIdlePeers();
1462}
1463
1464//------------------------------------------------------------------------------
1465
1468{
1469 Overlay::Setup setup;
1470
1471 {
1472 auto const& section = config.section("overlay");
1473 setup.context = make_SSLContext("");
1474
1475 set(setup.ipLimit, "ip_limit", section);
1476 if (setup.ipLimit < 0)
1477 Throw<std::runtime_error>("Configured IP limit is invalid");
1478
1479 std::string ip;
1480 set(ip, "public_ip", section);
1481 if (!ip.empty())
1482 {
1483 boost::system::error_code ec;
1484 setup.public_ip = beast::IP::Address::from_string(ip, ec);
1485 if (ec || beast::IP::is_private(setup.public_ip))
1486 Throw<std::runtime_error>("Configured public IP is invalid");
1487 }
1488 }
1489
1490 {
1491 auto const& section = config.section("crawl");
1492 auto const& values = section.values();
1493
1494 if (values.size() > 1)
1495 {
1496 Throw<std::runtime_error>(
1497 "Configured [crawl] section is invalid, too many values");
1498 }
1499
1500 bool crawlEnabled = true;
1501
1502 // Only allow "0|1" as a value
1503 if (values.size() == 1)
1504 {
1505 try
1506 {
1507 crawlEnabled = boost::lexical_cast<bool>(values.front());
1508 }
1509 catch (boost::bad_lexical_cast const&)
1510 {
1511 Throw<std::runtime_error>(
1512 "Configured [crawl] section has invalid value: " +
1513 values.front());
1514 }
1515 }
1516
1517 if (crawlEnabled)
1518 {
1519 if (get<bool>(section, "overlay", true))
1520 {
1522 }
1523 if (get<bool>(section, "server", true))
1524 {
1526 }
1527 if (get<bool>(section, "counts", false))
1528 {
1530 }
1531 if (get<bool>(section, "unl", true))
1532 {
1534 }
1535 }
1536 }
1537 {
1538 auto const& section = config.section("vl");
1539
1540 set(setup.vlEnabled, "enabled", section);
1541 }
1542
1543 try
1544 {
1545 auto id = config.legacy("network_id");
1546
1547 if (!id.empty())
1548 {
1549 if (id == "main")
1550 id = "0";
1551
1552 if (id == "testnet")
1553 id = "1";
1554
1555 if (id == "devnet")
1556 id = "2";
1557
1558 setup.networkID = beast::lexicalCastThrow<std::uint32_t>(id);
1559 }
1560 }
1561 catch (...)
1562 {
1563 Throw<std::runtime_error>(
1564 "Configured [network_id] section is invalid: must be a number "
1565 "or one of the strings 'main', 'testnet' or 'devnet'.");
1566 }
1567
1568 return setup;
1569}
1570
1573 Application& app,
1574 Overlay::Setup const& setup,
1575 ServerHandler& serverHandler,
1576 Resource::Manager& resourceManager,
1577 Resolver& resolver,
1578 boost::asio::io_service& io_service,
1579 BasicConfig const& config,
1580 beast::insight::Collector::ptr const& collector)
1581{
1582 return std::make_unique<OverlayImpl>(
1583 app,
1584 setup,
1585 serverHandler,
1586 resourceManager,
1587 resolver,
1588 io_service,
1589 config,
1590 collector);
1591}
1592
1593} // namespace ripple
T begin(T... args)
T bind(T... args)
Represents a JSON value.
Definition: json_value.h:148
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:897
Value removeMember(const char *key)
Remove and return the named member.
Definition: json_value.cpp:922
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:949
A version-independent IP address and port combination.
Definition: IPEndpoint.h:39
A generic endpoint for log messages.
Definition: Journal.h:60
Stream debug() const
Definition: Journal.h:328
Stream info() const
Definition: Journal.h:334
Stream trace() const
Severity stream access functions.
Definition: Journal.h:322
std::string const & name() const
Returns the name of this source.
void add(Source &source)
Add a child source.
Wraps a Journal::Sink to prefix its output with a string.
Definition: WrappedSink.h:34
virtual Config & config()=0
virtual beast::Journal journal(std::string const &name)=0
virtual ValidatorSite & validatorSites()=0
virtual DatabaseCon & getWalletDB()=0
Retrieve the "wallet database".
virtual NetworkOPs & getOPs()=0
virtual ValidatorList & validators()=0
virtual std::optional< PublicKey const > getValidationPublicKey() const =0
virtual ManifestCache & validatorManifests()=0
virtual PeerReservationTable & peerReservations()=0
virtual Cluster & cluster()=0
virtual Logs & logs()=0
virtual HashRouter & getHashRouter()=0
Holds unparsed configuration information.
Definition: BasicConfig.h:218
Section & section(std::string const &name)
Returns the section with the given name.
void legacy(std::string const &section, std::string value)
Set a value that is not a key/value pair.
std::optional< std::string > member(PublicKey const &node) const
Determines whether a node belongs in the cluster.
Definition: Cluster.cpp:38
std::vector< std::string > IPS_FIXED
Definition: Config.h:144
std::vector< std::string > IPS
Definition: Config.h:141
bool standalone() const
Definition: Config.h:337
std::size_t TX_REDUCE_RELAY_MIN_PEERS
Definition: Config.h:269
bool TX_REDUCE_RELAY_ENABLE
Definition: Config.h:259
bool TX_REDUCE_RELAY_METRICS
Definition: Config.h:266
std::size_t TX_RELAY_PERCENTAGE
Definition: Config.h:272
LockedSociSession checkoutDb()
Definition: DatabaseCon.h:190
std::optional< std::set< PeerShortID > > shouldRelay(uint256 const &key)
Determines whether the hashed item should be relayed.
Definition: HashRouter.cpp:118
virtual void pubManifest(Manifest const &)=0
std::uint32_t sequence() const
A monotonically increasing number used to detect new manifests.
Definition: Manifest.h:278
void for_each_manifest(Function &&f) const
Invokes the callback once for every populated manifest.
Definition: Manifest.h:425
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
virtual Json::Value getServerInfo(bool human, bool admin, bool counters)=0
Child(OverlayImpl &overlay)
Definition: OverlayImpl.cpp:58
boost::system::error_code error_code
Definition: OverlayImpl.h:83
Json::Value getUnlInfo()
Returns information about the local server's UNL.
void stop() override
static std::string makePrefix(std::uint32_t id)
PeerFinder::Manager & peerFinder()
Definition: OverlayImpl.h:161
boost::asio::ip::tcp::endpoint endpoint_type
Definition: OverlayImpl.h:82
bool processHealth(http_request_type const &req, Handoff &handoff)
Handles health requests.
boost::asio::ip::address address_type
Definition: OverlayImpl.h:81
static bool is_upgrade(boost::beast::http::header< true, Fields > const &req)
Definition: OverlayImpl.h:320
std::condition_variable_any cond_
Definition: OverlayImpl.h:107
void onWrite(beast::PropertyStream::Map &stream) override
Subclass override.
void deleteIdlePeers()
Check if peers stopped relaying messages and if slots stopped receiving messages from the validator.
Resolver & m_resolver
Definition: OverlayImpl.h:118
void reportTraffic(TrafficCount::category cat, bool isInbound, int bytes)
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...
PeerSequence getActivePeers() const override
Returns a sequence representing the current list of peers.
void start() override
hash_map< std::shared_ptr< PeerFinder::Slot >, std::weak_ptr< PeerImp > > m_peers
Definition: OverlayImpl.h:116
void add_active(std::shared_ptr< PeerImp > const &peer)
std::shared_ptr< Peer > findPeerByPublicKey(PublicKey const &pubKey) override
Returns the peer with the matching public key, or null.
Resource::Manager & m_resourceManager
Definition: OverlayImpl.h:113
std::shared_ptr< Message > manifestMessage_
Definition: OverlayImpl.h:131
std::optional< std::uint32_t > manifestListSeq_
Definition: OverlayImpl.h:133
TrafficCount m_traffic
Definition: OverlayImpl.h:115
void squelch(PublicKey const &validator, Peer::id_t const id, std::uint32_t squelchDuration) const override
Squelch handler.
std::shared_ptr< Writer > makeErrorResponse(std::shared_ptr< PeerFinder::Slot > const &slot, http_request_type const &request, address_type remote_address, std::string msg)
reduce_relay::Slots< UptimeClock > slots_
Definition: OverlayImpl.h:125
void deletePeer(Peer::id_t id)
Called when the peer is deleted.
std::shared_ptr< Peer > findPeerByShortID(Peer::id_t const &id) const override
Returns the peer with the matching short id, or null.
std::atomic< Peer::id_t > next_id_
Definition: OverlayImpl.h:119
boost::asio::io_service & io_service_
Definition: OverlayImpl.h:103
Application & app_
Definition: OverlayImpl.h:102
std::weak_ptr< Timer > timer_
Definition: OverlayImpl.h:108
metrics::TxMetrics txMetrics_
Definition: OverlayImpl.h:128
void broadcast(protocol::TMProposeSet &m) override
Broadcast a proposal.
void onPeerDeactivate(Peer::id_t id)
std::mutex manifestLock_
Definition: OverlayImpl.h:135
bool processRequest(http_request_type const &req, Handoff &handoff)
Handles non-peer protocol requests.
std::recursive_mutex mutex_
Definition: OverlayImpl.h:106
void remove(std::shared_ptr< PeerFinder::Slot > const &slot)
void sendTxQueue()
Send once a second transactions' hashes aggregated by peers.
std::set< Peer::id_t > relay(protocol::TMProposeSet &m, uint256 const &uid, PublicKey const &validator) override
Relay a proposal.
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...
void unsquelch(PublicKey const &validator, Peer::id_t id) const override
Unsquelch handler.
std::shared_ptr< Writer > makeRedirectResponse(std::shared_ptr< PeerFinder::Slot > const &slot, http_request_type const &request, address_type remote_address)
void for_each(UnaryFunc &&f) const
Definition: OverlayImpl.h:278
std::optional< boost::asio::io_service::work > work_
Definition: OverlayImpl.h:104
Json::Value getOverlayInfo()
Returns information about peers on the overlay network.
Resource::Manager & resourceManager()
Definition: OverlayImpl.h:167
static bool isPeerUpgrade(http_request_type const &request)
Json::Value getServerCounts()
Returns information about the local server's performance counters.
boost::asio::io_service::strand strand_
Definition: OverlayImpl.h:105
void onManifests(std::shared_ptr< protocol::TMManifests > const &m, std::shared_ptr< PeerImp > const &from)
std::unique_ptr< PeerFinder::Manager > m_peerFinder
Definition: OverlayImpl.h:114
void connect(beast::IP::Endpoint const &remote_endpoint) override
Establish a peer connection to the specified endpoint.
Handoff onHandoff(std::unique_ptr< stream_type > &&bundle, http_request_type &&request, endpoint_type remote_endpoint) override
Conditionally accept an incoming HTTP request.
Setup const & setup() const
Definition: OverlayImpl.h:173
std::shared_ptr< Message > getManifestsMessage()
hash_map< Peer::id_t, std::weak_ptr< PeerImp > > ids_
Definition: OverlayImpl.h:117
Json::Value getServerInfo()
Returns information about the local server.
bool processValidatorList(http_request_type const &req, Handoff &handoff)
Handles validator list requests.
Json::Value json() override
Return diagnostics on the status of all peers.
void checkTracking(std::uint32_t) override
Calls the checkTracking function on each peer.
ServerHandler & serverHandler_
Definition: OverlayImpl.h:112
bool processCrawl(http_request_type const &req, Handoff &handoff)
Handles crawl requests.
int limit() override
Returns the maximum number of peers we are configured to allow.
void updateSlotAndSquelch(uint256 const &key, PublicKey const &validator, std::set< Peer::id_t > &&peers, protocol::MessageType type)
Updates message count for validator/peer.
OverlayImpl(Application &app, Setup const &setup, ServerHandler &serverHandler, Resource::Manager &resourceManager, Resolver &resolver, boost::asio::io_service &io_service, BasicConfig const &config, beast::insight::Collector::ptr const &collector)
beast::Journal const journal_
Definition: OverlayImpl.h:111
boost::container::flat_map< Child *, std::weak_ptr< Child > > list_
Definition: OverlayImpl.h:109
Manages the set of connected peers.
Definition: Overlay.h:49
virtual std::shared_ptr< Slot > new_outbound_slot(beast::IP::Endpoint const &remote_endpoint)=0
Create a new outbound slot with the specified remote endpoint.
bool contains(PublicKey const &nodeId)
A public key.
Definition: PublicKey.h:62
void resolve(std::vector< std::string > const &names, Handler handler)
resolve all hostnames on the list
Definition: Resolver.h:57
Tracks load and resource consumption.
virtual Consumer newInboundEndpoint(beast::IP::Endpoint const &address)=0
Create a new endpoint keyed by inbound IP address or the forwarded IP if proxied.
virtual Consumer newOutboundEndpoint(beast::IP::Endpoint const &address)=0
Create a new endpoint keyed by outbound IP address and port.
std::vector< std::string > const & values() const
Returns all the values in the section.
Definition: BasicConfig.h:79
void setup(Setup const &setup, beast::Journal journal)
auto const & getCounts() const
An up-to-date copy of all the counters.
Definition: TrafficCount.h:197
void addCount(category cat, bool inbound, int bytes)
Account for traffic associated with the given category.
Definition: TrafficCount.h:172
bool listed(PublicKey const &identity) const
Returns true if public key is included on any lists.
std::optional< Json::Value > getAvailable(std::string_view pubKey, std::optional< std::uint32_t > forceVersion={})
Returns the current valid list for the given publisher key, if available, as a Json object.
Json::Value getJson() const
Return a JSON representation of the state of the validator list.
Json::Value getJson() const
Return JSON representation of configured validator sites.
T count(T... args)
T data(T... args)
T emplace_back(T... args)
T empty(T... args)
T end(T... args)
T find_if(T... args)
T get(T... args)
T make_tuple(T... args)
@ nullValue
'null' value
Definition: json_value.h:37
@ arrayValue
array value (ordered list)
Definition: json_value.h:43
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:44
bool is_private(Address const &addr)
Returns true if the address is a private unroutable address.
Definition: IPAddress.h:75
Result split_commas(FwdIt first, FwdIt last)
Definition: rfc2616.h:201
bool is_keep_alive(boost::beast::http::message< isRequest, Body, Fields > const &m)
Definition: rfc2616.h:388
std::string const & getFullVersionString()
Full server version string.
Definition: BuildInfo.cpp:81
@ checkIdlePeers
How often we check for idle peers (seconds)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:114
std::optional< ProtocolVersion > negotiateProtocolVersion(std::vector< ProtocolVersion > const &versions)
Given a list of supported protocol versions, choose the one we prefer.
std::optional< Manifest > deserializeManifest(Slice s, beast::Journal journal)
Constructs Manifest from serialized string.
std::vector< ProtocolVersion > parseProtocolVersions(boost::beast::string_view const &value)
Parse a set of protocol versions.
bool isPseudoTx(STObject const &tx)
Check whether a transaction is a pseudo-transaction.
Definition: STTx.cpp:640
void addValidatorManifest(soci::session &session, std::string const &serialized)
addValidatorManifest Saves the manifest of a validator to the database.
Definition: Wallet.cpp:119
bool set(T &target, std::string const &name, Section const &section)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
Definition: BasicConfig.h:315
std::optional< uint256 > makeSharedValue(stream_type &ssl, beast::Journal journal)
Computes a shared value based on the SSL connection state.
Definition: Handshake.cpp:146
std::shared_ptr< boost::asio::ssl::context > make_SSLContext(std::string const &cipherList)
Create a self-signed SSL context that allows anonymous Diffie Hellman.
std::shared_ptr< Message > makeSquelchMessage(PublicKey const &validator, bool squelch, uint32_t squelchDuration)
std::string strHex(FwdIt begin, FwdIt end)
Definition: strHex.h:30
@ accepted
Manifest is valid.
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:244
std::string base64_encode(std::uint8_t const *data, std::size_t len)
Definition: base64.cpp:239
Stopwatch & stopwatch()
Returns an instance of a wall clock.
Definition: chrono.h:119
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
Definition: Handoff.h:33
Json::Value getCountsJson(Application &app, int minObjectCount)
Definition: GetCounts.cpp:62
std::string to_string(base_uint< Bits, Tag > const &a)
Definition: base_uint.h:630
PublicKey verifyHandshake(boost::beast::http::fields const &headers, ripple::uint256 const &sharedValue, std::optional< std::uint32_t > networkID, beast::IP::Address public_ip, beast::IP::Address remote, Application &app)
Validate header fields necessary for upgrading the link to the peer protocol.
Definition: Handshake.cpp:227
@ manifest
Manifest.
Overlay::Setup setup_Overlay(BasicConfig const &config)
constexpr Number squelch(Number const &x, Number const &limit) noexcept
Definition: Number.h:363
std::unique_ptr< Overlay > make_Overlay(Application &app, Overlay::Setup const &setup, ServerHandler &serverHandler, Resource::Manager &resourceManager, Resolver &resolver, boost::asio::io_service &io_service, BasicConfig const &config, beast::insight::Collector::ptr const &collector)
Creates the implementation of Overlay.
beast::xor_shift_engine & default_prng()
Return the default random engine.
STL namespace.
T push_back(T... args)
T shuffle(T... args)
T reserve(T... args)
T reset(T... args)
T setfill(T... args)
T setw(T... args)
T size(T... args)
T str(T... args)
static boost::asio::ip::tcp::endpoint to_asio_endpoint(IP::Endpoint const &address)
static IP::Endpoint from_asio(boost::asio::ip::address const &address)
Used to indicate the result of a server connection handoff.
Definition: Handoff.h:40
bool keep_alive
Definition: Handoff.h:46
std::shared_ptr< Writer > response
Definition: Handoff.h:49
void on_timer(error_code ec)
Definition: OverlayImpl.cpp:92
Timer(OverlayImpl &overlay)
Definition: OverlayImpl.cpp:69
beast::IP::Address public_ip
Definition: Overlay.h:69
std::uint32_t crawlOptions
Definition: Overlay.h:71
std::shared_ptr< boost::asio::ssl::context > context
Definition: Overlay.h:68
std::optional< std::uint32_t > networkID
Definition: Overlay.h:72
PeerFinder configuration settings.
static Config makeConfig(ripple::Config const &config, std::uint16_t port, bool validationPublicKey, int ipLimit)
Make PeerFinder::Config from configuration parameters.
void addMetrics(protocol::MessageType type, std::uint32_t val)
Add protocol message metrics.
Definition: TxMetrics.cpp:31
T substr(T... args)
T to_string(T... args)
T what(T... args)