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