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 // Pool of servers operated by XRPL Commons - https://xrpl-commons.org
508 bootstrapIps.push_back("hub.xrpl-commons.org 51235");
509 }
510
512 bootstrapIps,
513 [this](
514 std::string const& name,
515 std::vector<beast::IP::Endpoint> const& addresses) {
517 ips.reserve(addresses.size());
518 for (auto const& addr : addresses)
519 {
520 if (addr.port() == 0)
521 ips.push_back(to_string(addr.at_port(DEFAULT_PEER_PORT)));
522 else
523 ips.push_back(to_string(addr));
524 }
525
526 std::string const base("config: ");
527 if (!ips.empty())
528 m_peerFinder->addFallbackStrings(base + name, ips);
529 });
530
531 // Add the ips_fixed from the rippled.cfg file
533 {
536 [this](
537 std::string const& name,
538 std::vector<beast::IP::Endpoint> const& addresses) {
540 ips.reserve(addresses.size());
541
542 for (auto& addr : addresses)
543 {
544 if (addr.port() == 0)
545 ips.emplace_back(addr.address(), DEFAULT_PEER_PORT);
546 else
547 ips.emplace_back(addr);
548 }
549
550 if (!ips.empty())
551 m_peerFinder->addFixedPeer(name, ips);
552 });
553 }
554 auto const timer = std::make_shared<Timer>(*this);
556 list_.emplace(timer.get(), timer);
557 timer_ = timer;
558 timer->async_wait();
559}
560
561void
563{
565 {
566 std::unique_lock<decltype(mutex_)> lock(mutex_);
567 cond_.wait(lock, [this] { return list_.empty(); });
568 }
569 m_peerFinder->stop();
570}
571
572//------------------------------------------------------------------------------
573//
574// PropertyStream
575//
576//------------------------------------------------------------------------------
577
578void
580{
581 beast::PropertyStream::Set set("traffic", stream);
582 auto const stats = m_traffic.getCounts();
583 for (auto const& i : stats)
584 {
585 if (i)
586 {
588 item["category"] = i.name;
589 item["bytes_in"] = std::to_string(i.bytesIn.load());
590 item["messages_in"] = std::to_string(i.messagesIn.load());
591 item["bytes_out"] = std::to_string(i.bytesOut.load());
592 item["messages_out"] = std::to_string(i.messagesOut.load());
593 }
594 }
595}
596
597//------------------------------------------------------------------------------
603void
605{
606 // Now track this peer
607 {
609 auto const result(ids_.emplace(
610 std::piecewise_construct,
611 std::make_tuple(peer->id()),
612 std::make_tuple(peer)));
613 XRPL_ASSERT(
614 result.second,
615 "ripple::OverlayImpl::activate : peer ID is inserted");
616 (void)result.second;
617 }
618
619 JLOG(journal_.debug()) << "activated " << peer->getRemoteAddress() << " ("
620 << peer->id() << ":"
621 << toBase58(
622 TokenType::NodePublic, peer->getNodePublic())
623 << ")";
624
625 // We just accepted this peer so we have non-zero active peers
626 XRPL_ASSERT(size(), "ripple::OverlayImpl::activate : nonzero peers");
627}
628
629void
631{
633 ids_.erase(id);
634}
635
636void
639 std::shared_ptr<PeerImp> const& from)
640{
641 auto const n = m->list_size();
642 auto const& journal = from->pjournal();
643
644 protocol::TMManifests relay;
645
646 for (std::size_t i = 0; i < n; ++i)
647 {
648 auto& s = m->list().Get(i).stobject();
649
650 if (auto mo = deserializeManifest(s))
651 {
652 auto const serialized = mo->serialized;
653
654 auto const result =
655 app_.validatorManifests().applyManifest(std::move(*mo));
656
657 if (result == ManifestDisposition::accepted)
658 {
659 relay.add_list()->set_stobject(s);
660
661 // N.B.: this is important; the applyManifest call above moves
662 // the loaded Manifest out of the optional so we need to
663 // reload it here.
664 mo = deserializeManifest(serialized);
665 XRPL_ASSERT(
666 mo,
667 "ripple::OverlayImpl::onManifests : manifest "
668 "deserialization succeeded");
669
670 app_.getOPs().pubManifest(*mo);
671
672 if (app_.validators().listed(mo->masterKey))
673 {
674 auto db = app_.getWalletDB().checkoutDb();
675 addValidatorManifest(*db, serialized);
676 }
677 }
678 }
679 else
680 {
681 JLOG(journal.debug())
682 << "Malformed manifest #" << i + 1 << ": " << strHex(s);
683 continue;
684 }
685 }
686
687 if (!relay.list().empty())
688 for_each([m2 = std::make_shared<Message>(relay, protocol::mtMANIFESTS)](
689 std::shared_ptr<PeerImp>&& p) { p->send(m2); });
690}
691
692void
695 bool isInbound,
696 int number)
697{
698 m_traffic.addCount(cat, isInbound, number);
699}
700
707{
709 return ids_.size();
710}
711
712int
714{
715 return m_peerFinder->config().maxPeers;
716}
717
720{
721 using namespace std::chrono;
722 Json::Value jv;
723 auto& av = jv["active"] = Json::Value(Json::arrayValue);
724
726 auto& pv = av.append(Json::Value(Json::objectValue));
727 pv[jss::public_key] = base64_encode(
728 sp->getNodePublic().data(), sp->getNodePublic().size());
729 pv[jss::type] = sp->slot()->inbound() ? "in" : "out";
730 pv[jss::uptime] = static_cast<std::uint32_t>(
731 duration_cast<seconds>(sp->uptime()).count());
732 if (sp->crawl())
733 {
734 pv[jss::ip] = sp->getRemoteAddress().address().to_string();
735 if (sp->slot()->inbound())
736 {
737 if (auto port = sp->slot()->listening_port())
738 pv[jss::port] = *port;
739 }
740 else
741 {
742 pv[jss::port] = std::to_string(sp->getRemoteAddress().port());
743 }
744 }
745
746 {
747 auto version{sp->getVersion()};
748 if (!version.empty())
749 // Could move here if Json::value supported moving from strings
750 pv[jss::version] = std::string{version};
751 }
752
753 std::uint32_t minSeq, maxSeq;
754 sp->ledgerRange(minSeq, maxSeq);
755 if (minSeq != 0 || maxSeq != 0)
756 pv[jss::complete_ledgers] =
757 std::to_string(minSeq) + "-" + std::to_string(maxSeq);
758 });
759
760 return jv;
761}
762
765{
766 bool const humanReadable = false;
767 bool const admin = false;
768 bool const counters = false;
769
770 Json::Value server_info =
771 app_.getOPs().getServerInfo(humanReadable, admin, counters);
772
773 // Filter out some information
774 server_info.removeMember(jss::hostid);
775 server_info.removeMember(jss::load_factor_fee_escalation);
776 server_info.removeMember(jss::load_factor_fee_queue);
777 server_info.removeMember(jss::validation_quorum);
778
779 if (server_info.isMember(jss::validated_ledger))
780 {
781 Json::Value& validated_ledger = server_info[jss::validated_ledger];
782
783 validated_ledger.removeMember(jss::base_fee);
784 validated_ledger.removeMember(jss::reserve_base_xrp);
785 validated_ledger.removeMember(jss::reserve_inc_xrp);
786 }
787
788 return server_info;
789}
790
793{
794 return getCountsJson(app_, 10);
795}
796
799{
800 Json::Value validators = app_.validators().getJson();
801
802 if (validators.isMember(jss::publisher_lists))
803 {
804 Json::Value& publisher_lists = validators[jss::publisher_lists];
805
806 for (auto& publisher : publisher_lists)
807 {
808 publisher.removeMember(jss::list);
809 }
810 }
811
812 validators.removeMember(jss::signing_keys);
813 validators.removeMember(jss::trusted_validator_keys);
814 validators.removeMember(jss::validation_quorum);
815
816 Json::Value validatorSites = app_.validatorSites().getJson();
817
818 if (validatorSites.isMember(jss::validator_sites))
819 {
820 validators[jss::validator_sites] =
821 std::move(validatorSites[jss::validator_sites]);
822 }
823
824 return validators;
825}
826
827// Returns information on verified peers.
830{
832 for (auto const& peer : getActivePeers())
833 {
834 json.append(peer->json());
835 }
836 return json;
837}
838
839bool
841{
842 if (req.target() != "/crawl" ||
844 return false;
845
846 boost::beast::http::response<json_body> msg;
847 msg.version(req.version());
848 msg.result(boost::beast::http::status::ok);
849 msg.insert("Server", BuildInfo::getFullVersionString());
850 msg.insert("Content-Type", "application/json");
851 msg.insert("Connection", "close");
852 msg.body()["version"] = Json::Value(2u);
853
855 {
856 msg.body()["overlay"] = getOverlayInfo();
857 }
859 {
860 msg.body()["server"] = getServerInfo();
861 }
863 {
864 msg.body()["counts"] = getServerCounts();
865 }
867 {
868 msg.body()["unl"] = getUnlInfo();
869 }
870
871 msg.prepare_payload();
872 handoff.response = std::make_shared<SimpleWriter>(msg);
873 return true;
874}
875
876bool
878 http_request_type const& req,
879 Handoff& handoff)
880{
881 // If the target is in the form "/vl/<validator_list_public_key>",
882 // return the most recent validator list for that key.
883 constexpr std::string_view prefix("/vl/");
884
885 if (!req.target().starts_with(prefix.data()) || !setup_.vlEnabled)
886 return false;
887
888 std::uint32_t version = 1;
889
890 boost::beast::http::response<json_body> msg;
891 msg.version(req.version());
892 msg.insert("Server", BuildInfo::getFullVersionString());
893 msg.insert("Content-Type", "application/json");
894 msg.insert("Connection", "close");
895
896 auto fail = [&msg, &handoff](auto status) {
897 msg.result(status);
898 msg.insert("Content-Length", "0");
899
900 msg.body() = Json::nullValue;
901
902 msg.prepare_payload();
903 handoff.response = std::make_shared<SimpleWriter>(msg);
904 return true;
905 };
906
907 std::string_view key = req.target().substr(prefix.size());
908
909 if (auto slash = key.find('/'); slash != std::string_view::npos)
910 {
911 auto verString = key.substr(0, slash);
912 if (!boost::conversion::try_lexical_convert(verString, version))
913 return fail(boost::beast::http::status::bad_request);
914 key = key.substr(slash + 1);
915 }
916
917 if (key.empty())
918 return fail(boost::beast::http::status::bad_request);
919
920 // find the list
921 auto vl = app_.validators().getAvailable(key, version);
922
923 if (!vl)
924 {
925 // 404 not found
926 return fail(boost::beast::http::status::not_found);
927 }
928 else if (!*vl)
929 {
930 return fail(boost::beast::http::status::bad_request);
931 }
932 else
933 {
934 msg.result(boost::beast::http::status::ok);
935
936 msg.body() = *vl;
937
938 msg.prepare_payload();
939 handoff.response = std::make_shared<SimpleWriter>(msg);
940 return true;
941 }
942}
943
944bool
946{
947 if (req.target() != "/health")
948 return false;
949 boost::beast::http::response<json_body> msg;
950 msg.version(req.version());
951 msg.insert("Server", BuildInfo::getFullVersionString());
952 msg.insert("Content-Type", "application/json");
953 msg.insert("Connection", "close");
954
955 auto info = getServerInfo();
956
957 int last_validated_ledger_age = -1;
958 if (info.isMember(jss::validated_ledger))
959 last_validated_ledger_age =
960 info[jss::validated_ledger][jss::age].asInt();
961 bool amendment_blocked = false;
962 if (info.isMember(jss::amendment_blocked))
963 amendment_blocked = true;
964 int number_peers = info[jss::peers].asInt();
965 std::string server_state = info[jss::server_state].asString();
966 auto load_factor = info[jss::load_factor_server].asDouble() /
967 info[jss::load_base].asDouble();
968
969 enum { healthy, warning, critical };
970 int health = healthy;
971 auto set_health = [&health](int state) {
972 if (health < state)
973 health = state;
974 };
975
976 msg.body()[jss::info] = Json::objectValue;
977 if (last_validated_ledger_age >= 7 || last_validated_ledger_age < 0)
978 {
979 msg.body()[jss::info][jss::validated_ledger] =
980 last_validated_ledger_age;
981 if (last_validated_ledger_age < 20)
982 set_health(warning);
983 else
984 set_health(critical);
985 }
986
987 if (amendment_blocked)
988 {
989 msg.body()[jss::info][jss::amendment_blocked] = true;
990 set_health(critical);
991 }
992
993 if (number_peers <= 7)
994 {
995 msg.body()[jss::info][jss::peers] = number_peers;
996 if (number_peers != 0)
997 set_health(warning);
998 else
999 set_health(critical);
1000 }
1001
1002 if (!(server_state == "full" || server_state == "validating" ||
1003 server_state == "proposing"))
1004 {
1005 msg.body()[jss::info][jss::server_state] = server_state;
1006 if (server_state == "syncing" || server_state == "tracking" ||
1007 server_state == "connected")
1008 {
1009 set_health(warning);
1010 }
1011 else
1012 set_health(critical);
1013 }
1014
1015 if (load_factor > 100)
1016 {
1017 msg.body()[jss::info][jss::load_factor] = load_factor;
1018 if (load_factor < 1000)
1019 set_health(warning);
1020 else
1021 set_health(critical);
1022 }
1023
1024 switch (health)
1025 {
1026 case healthy:
1027 msg.result(boost::beast::http::status::ok);
1028 break;
1029 case warning:
1030 msg.result(boost::beast::http::status::service_unavailable);
1031 break;
1032 case critical:
1033 msg.result(boost::beast::http::status::internal_server_error);
1034 break;
1035 }
1036
1037 msg.prepare_payload();
1038 handoff.response = std::make_shared<SimpleWriter>(msg);
1039 return true;
1040}
1041
1042bool
1044{
1045 // Take advantage of || short-circuiting
1046 return processCrawl(req, handoff) || processValidatorList(req, handoff) ||
1047 processHealth(req, handoff);
1048}
1049
1052{
1054 ret.reserve(size());
1055
1056 for_each([&ret](std::shared_ptr<PeerImp>&& sp) {
1057 ret.emplace_back(std::move(sp));
1058 });
1059
1060 return ret;
1061}
1062
1065 std::set<Peer::id_t> const& toSkip,
1066 std::size_t& active,
1067 std::size_t& disabled,
1068 std::size_t& enabledInSkip) const
1069{
1071 std::lock_guard lock(mutex_);
1072
1073 active = ids_.size();
1074 disabled = enabledInSkip = 0;
1075 ret.reserve(ids_.size());
1076
1077 // NOTE The purpose of p is to delay the destruction of PeerImp
1079 for (auto& [id, w] : ids_)
1080 {
1081 if (p = w.lock(); p != nullptr)
1082 {
1083 bool const reduceRelayEnabled = p->txReduceRelayEnabled();
1084 // tx reduced relay feature disabled
1085 if (!reduceRelayEnabled)
1086 ++disabled;
1087
1088 if (toSkip.count(id) == 0)
1089 ret.emplace_back(std::move(p));
1090 else if (reduceRelayEnabled)
1091 ++enabledInSkip;
1092 }
1093 }
1094
1095 return ret;
1096}
1097
1098void
1100{
1101 for_each(
1102 [index](std::shared_ptr<PeerImp>&& sp) { sp->checkTracking(index); });
1103}
1104
1107{
1108 std::lock_guard lock(mutex_);
1109 auto const iter = ids_.find(id);
1110 if (iter != ids_.end())
1111 return iter->second.lock();
1112 return {};
1113}
1114
1115// A public key hash map was not used due to the peer connect/disconnect
1116// update overhead outweighing the performance of a small set linear search.
1119{
1120 std::lock_guard lock(mutex_);
1121 // NOTE The purpose of peer is to delay the destruction of PeerImp
1123 for (auto const& e : ids_)
1124 {
1125 if (peer = e.second.lock(); peer != nullptr)
1126 {
1127 if (peer->getNodePublic() == pubKey)
1128 return peer;
1129 }
1130 }
1131 return {};
1132}
1133
1134void
1135OverlayImpl::broadcast(protocol::TMProposeSet& m)
1136{
1137 auto const sm = std::make_shared<Message>(m, protocol::mtPROPOSE_LEDGER);
1138 for_each([&](std::shared_ptr<PeerImp>&& p) { p->send(sm); });
1139}
1140
1143 protocol::TMProposeSet& m,
1144 uint256 const& uid,
1145 PublicKey const& validator)
1146{
1147 if (auto const toSkip = app_.getHashRouter().shouldRelay(uid))
1148 {
1149 auto const sm =
1150 std::make_shared<Message>(m, protocol::mtPROPOSE_LEDGER, validator);
1152 if (toSkip->find(p->id()) == toSkip->end())
1153 p->send(sm);
1154 });
1155 return *toSkip;
1156 }
1157 return {};
1158}
1159
1160void
1161OverlayImpl::broadcast(protocol::TMValidation& m)
1162{
1163 auto const sm = std::make_shared<Message>(m, protocol::mtVALIDATION);
1164 for_each([sm](std::shared_ptr<PeerImp>&& p) { p->send(sm); });
1165}
1166
1169 protocol::TMValidation& m,
1170 uint256 const& uid,
1171 PublicKey const& validator)
1172{
1173 if (auto const toSkip = app_.getHashRouter().shouldRelay(uid))
1174 {
1175 auto const sm =
1176 std::make_shared<Message>(m, protocol::mtVALIDATION, validator);
1178 if (toSkip->find(p->id()) == toSkip->end())
1179 p->send(sm);
1180 });
1181 return *toSkip;
1182 }
1183 return {};
1184}
1185
1188{
1190
1191 if (auto seq = app_.validatorManifests().sequence();
1192 seq != manifestListSeq_)
1193 {
1194 protocol::TMManifests tm;
1195
1197 [&tm](std::size_t s) { tm.mutable_list()->Reserve(s); },
1198 [&tm, &hr = app_.getHashRouter()](Manifest const& manifest) {
1199 tm.add_list()->set_stobject(
1200 manifest.serialized.data(), manifest.serialized.size());
1201 hr.addSuppression(manifest.hash());
1202 });
1203
1205
1206 if (tm.list_size() != 0)
1208 std::make_shared<Message>(tm, protocol::mtMANIFESTS);
1209
1210 manifestListSeq_ = seq;
1211 }
1212
1213 return manifestMessage_;
1214}
1215
1216void
1218 uint256 const& hash,
1220 std::set<Peer::id_t> const& toSkip)
1221{
1222 bool relay = tx.has_value();
1223 if (relay)
1224 {
1225 auto& txn = tx->get();
1226 SerialIter sit(makeSlice(txn.rawtransaction()));
1227 relay = !isPseudoTx(STTx{sit});
1228 }
1229
1230 Overlay::PeerSequence peers = {};
1231 std::size_t total = 0;
1232 std::size_t disabled = 0;
1233 std::size_t enabledInSkip = 0;
1234
1235 if (!relay)
1236 {
1238 return;
1239
1240 peers = getActivePeers(toSkip, total, disabled, enabledInSkip);
1241 JLOG(journal_.trace())
1242 << "not relaying tx, total peers " << peers.size();
1243 for (auto const& p : peers)
1244 p->addTxQueue(hash);
1245 return;
1246 }
1247
1248 auto& txn = tx->get();
1249 auto const sm = std::make_shared<Message>(txn, protocol::mtTRANSACTION);
1250 peers = getActivePeers(toSkip, total, disabled, enabledInSkip);
1251 auto const minRelay = app_.config().TX_REDUCE_RELAY_MIN_PEERS + disabled;
1252
1253 if (!app_.config().TX_REDUCE_RELAY_ENABLE || total <= minRelay)
1254 {
1255 for (auto const& p : peers)
1256 p->send(sm);
1259 txMetrics_.addMetrics(total, toSkip.size(), 0);
1260 return;
1261 }
1262
1263 // We have more peers than the minimum (disabled + minimum enabled),
1264 // relay to all disabled and some randomly selected enabled that
1265 // do not have the transaction.
1266 auto const enabledTarget = app_.config().TX_REDUCE_RELAY_MIN_PEERS +
1267 (total - minRelay) * app_.config().TX_RELAY_PERCENTAGE / 100;
1268
1269 txMetrics_.addMetrics(enabledTarget, toSkip.size(), disabled);
1270
1271 if (enabledTarget > enabledInSkip)
1272 std::shuffle(peers.begin(), peers.end(), default_prng());
1273
1274 JLOG(journal_.trace()) << "relaying tx, total peers " << peers.size()
1275 << " selected " << enabledTarget << " skip "
1276 << toSkip.size() << " disabled " << disabled;
1277
1278 // count skipped peers with the enabled feature towards the quota
1279 std::uint16_t enabledAndRelayed = enabledInSkip;
1280 for (auto const& p : peers)
1281 {
1282 // always relay to a peer with the disabled feature
1283 if (!p->txReduceRelayEnabled())
1284 {
1285 p->send(sm);
1286 }
1287 else if (enabledAndRelayed < enabledTarget)
1288 {
1289 enabledAndRelayed++;
1290 p->send(sm);
1291 }
1292 else
1293 {
1294 p->addTxQueue(hash);
1295 }
1296 }
1297}
1298
1299//------------------------------------------------------------------------------
1300
1301void
1303{
1304 std::lock_guard lock(mutex_);
1305 list_.erase(&child);
1306 if (list_.empty())
1307 cond_.notify_all();
1308}
1309
1310void
1312{
1313 // Calling list_[].second->stop() may cause list_ to be modified
1314 // (OverlayImpl::remove() may be called on this same thread). So
1315 // iterating directly over list_ to call child->stop() could lead to
1316 // undefined behavior.
1317 //
1318 // Therefore we copy all of the weak/shared ptrs out of list_ before we
1319 // start calling stop() on them. That guarantees OverlayImpl::remove()
1320 // won't be called until vector<> children leaves scope.
1322 {
1323 std::lock_guard lock(mutex_);
1324 if (!work_)
1325 return;
1326 work_ = std::nullopt;
1327
1328 children.reserve(list_.size());
1329 for (auto const& element : list_)
1330 {
1331 children.emplace_back(element.second.lock());
1332 }
1333 } // lock released
1334
1335 for (auto const& child : children)
1336 {
1337 if (child != nullptr)
1338 child->stop();
1339 }
1340}
1341
1342void
1344{
1345 auto const result = m_peerFinder->autoconnect();
1346 for (auto addr : result)
1347 connect(addr);
1348}
1349
1350void
1352{
1353 auto const result = m_peerFinder->buildEndpointsForPeers();
1354 for (auto const& e : result)
1355 {
1357 {
1358 std::lock_guard lock(mutex_);
1359 auto const iter = m_peers.find(e.first);
1360 if (iter != m_peers.end())
1361 peer = iter->second.lock();
1362 }
1363 if (peer)
1364 peer->sendEndpoints(e.second.begin(), e.second.end());
1365 }
1366}
1367
1368void
1370{
1371 for_each([](auto const& p) {
1372 if (p->txReduceRelayEnabled())
1373 p->sendTxQueue();
1374 });
1375}
1376
1379 PublicKey const& validator,
1380 bool squelch,
1381 uint32_t squelchDuration)
1382{
1383 protocol::TMSquelch m;
1384 m.set_squelch(squelch);
1385 m.set_validatorpubkey(validator.data(), validator.size());
1386 if (squelch)
1387 m.set_squelchduration(squelchDuration);
1388 return std::make_shared<Message>(m, protocol::mtSQUELCH);
1389}
1390
1391void
1393{
1394 if (auto peer = findPeerByShortID(id);
1395 peer && app_.config().VP_REDUCE_RELAY_SQUELCH)
1396 {
1397 // optimize - multiple message with different
1398 // validator might be sent to the same peer
1399 peer->send(makeSquelchMessage(validator, false, 0));
1400 }
1401}
1402
1403void
1405 PublicKey const& validator,
1406 Peer::id_t id,
1407 uint32_t squelchDuration) const
1408{
1409 if (auto peer = findPeerByShortID(id);
1410 peer && app_.config().VP_REDUCE_RELAY_SQUELCH)
1411 {
1412 peer->send(makeSquelchMessage(validator, true, squelchDuration));
1413 }
1414}
1415
1416void
1418 uint256 const& key,
1419 PublicKey const& validator,
1420 std::set<Peer::id_t>&& peers,
1421 protocol::MessageType type)
1422{
1423 if (!strand_.running_in_this_thread())
1424 return post(
1425 strand_,
1426 [this, key, validator, peers = std::move(peers), type]() mutable {
1427 updateSlotAndSquelch(key, validator, std::move(peers), type);
1428 });
1429
1430 for (auto id : peers)
1431 slots_.updateSlotAndSquelch(key, validator, id, type);
1432}
1433
1434void
1436 uint256 const& key,
1437 PublicKey const& validator,
1438 Peer::id_t peer,
1439 protocol::MessageType type)
1440{
1441 if (!strand_.running_in_this_thread())
1442 return post(strand_, [this, key, validator, peer, type]() {
1443 updateSlotAndSquelch(key, validator, peer, type);
1444 });
1445
1446 slots_.updateSlotAndSquelch(key, validator, peer, type);
1447}
1448
1449void
1451{
1452 if (!strand_.running_in_this_thread())
1453 return post(strand_, std::bind(&OverlayImpl::deletePeer, this, id));
1454
1455 slots_.deletePeer(id, true);
1456}
1457
1458void
1460{
1461 if (!strand_.running_in_this_thread())
1462 return post(strand_, std::bind(&OverlayImpl::deleteIdlePeers, this));
1463
1464 slots_.deleteIdlePeers();
1465}
1466
1467//------------------------------------------------------------------------------
1468
1471{
1472 Overlay::Setup setup;
1473
1474 {
1475 auto const& section = config.section("overlay");
1476 setup.context = make_SSLContext("");
1477
1478 set(setup.ipLimit, "ip_limit", section);
1479 if (setup.ipLimit < 0)
1480 Throw<std::runtime_error>("Configured IP limit is invalid");
1481
1482 std::string ip;
1483 set(ip, "public_ip", section);
1484 if (!ip.empty())
1485 {
1486 boost::system::error_code ec;
1487 setup.public_ip = beast::IP::Address::from_string(ip, ec);
1488 if (ec || beast::IP::is_private(setup.public_ip))
1489 Throw<std::runtime_error>("Configured public IP is invalid");
1490 }
1491 }
1492
1493 {
1494 auto const& section = config.section("crawl");
1495 auto const& values = section.values();
1496
1497 if (values.size() > 1)
1498 {
1499 Throw<std::runtime_error>(
1500 "Configured [crawl] section is invalid, too many values");
1501 }
1502
1503 bool crawlEnabled = true;
1504
1505 // Only allow "0|1" as a value
1506 if (values.size() == 1)
1507 {
1508 try
1509 {
1510 crawlEnabled = boost::lexical_cast<bool>(values.front());
1511 }
1512 catch (boost::bad_lexical_cast const&)
1513 {
1514 Throw<std::runtime_error>(
1515 "Configured [crawl] section has invalid value: " +
1516 values.front());
1517 }
1518 }
1519
1520 if (crawlEnabled)
1521 {
1522 if (get<bool>(section, "overlay", true))
1523 {
1525 }
1526 if (get<bool>(section, "server", true))
1527 {
1529 }
1530 if (get<bool>(section, "counts", false))
1531 {
1533 }
1534 if (get<bool>(section, "unl", true))
1535 {
1537 }
1538 }
1539 }
1540 {
1541 auto const& section = config.section("vl");
1542
1543 set(setup.vlEnabled, "enabled", section);
1544 }
1545
1546 try
1547 {
1548 auto id = config.legacy("network_id");
1549
1550 if (!id.empty())
1551 {
1552 if (id == "main")
1553 id = "0";
1554
1555 if (id == "testnet")
1556 id = "1";
1557
1558 if (id == "devnet")
1559 id = "2";
1560
1561 setup.networkID = beast::lexicalCastThrow<std::uint32_t>(id);
1562 }
1563 }
1564 catch (...)
1565 {
1566 Throw<std::runtime_error>(
1567 "Configured [network_id] section is invalid: must be a number "
1568 "or one of the strings 'main', 'testnet' or 'devnet'.");
1569 }
1570
1571 return setup;
1572}
1573
1576 Application& app,
1577 Overlay::Setup const& setup,
1578 ServerHandler& serverHandler,
1579 Resource::Manager& resourceManager,
1580 Resolver& resolver,
1581 boost::asio::io_service& io_service,
1582 BasicConfig const& config,
1583 beast::insight::Collector::ptr const& collector)
1584{
1585 return std::make_unique<OverlayImpl>(
1586 app,
1587 setup,
1588 serverHandler,
1589 resourceManager,
1590 resolver,
1591 io_service,
1592 config,
1593 collector);
1594}
1595
1596} // 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)