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