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