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::checkSeconds) == 0)
104  overlay_.check();
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  , m_stats(
143  std::bind(&OverlayImpl::collect_metrics, this),
144  collector,
145  [counts = m_traffic.getCounts(), collector]() {
147  ret.reserve(counts.size());
148 
149  for (size_t i = 0; i < counts.size(); ++i)
150  {
151  ret.push_back(TrafficGauges(counts[i].name, collector));
152  }
153 
154  return ret;
155  }())
156 {
158 }
159 
161 {
162  stop();
163 
164  // Block until dependent objects have been destroyed.
165  // This is just to catch improper use of the Stoppable API.
166  //
167  std::unique_lock<decltype(mutex_)> lock(mutex_);
168  cond_.wait(lock, [this] { return list_.empty(); });
169 }
170 
171 //------------------------------------------------------------------------------
172 
173 Handoff
175  std::unique_ptr<stream_type>&& stream_ptr,
176  http_request_type&& request,
177  endpoint_type remote_endpoint)
178 {
179  auto const id = next_id_++;
180  beast::WrappedSink sink(app_.logs()["Peer"], makePrefix(id));
181  beast::Journal journal(sink);
182 
183  Handoff handoff;
184  if (processRequest(request, handoff))
185  return handoff;
186  if (!isPeerUpgrade(request))
187  return handoff;
188 
189  handoff.moved = true;
190 
191  JLOG(journal.debug()) << "Peer connection upgrade from " << remote_endpoint;
192 
193  error_code ec;
194  auto const local_endpoint(
195  stream_ptr->next_layer().socket().local_endpoint(ec));
196  if (ec)
197  {
198  JLOG(journal.debug()) << remote_endpoint << " failed: " << ec.message();
199  return handoff;
200  }
201 
202  auto consumer = m_resourceManager.newInboundEndpoint(
203  beast::IPAddressConversion::from_asio(remote_endpoint));
204  if (consumer.disconnect())
205  return handoff;
206 
207  auto const slot = m_peerFinder->new_inbound_slot(
209  beast::IPAddressConversion::from_asio(remote_endpoint));
210 
211  if (slot == nullptr)
212  {
213  // self-connect, close
214  handoff.moved = false;
215  return handoff;
216  }
217 
218  // Validate HTTP request
219 
220  {
221  auto const types = beast::rfc2616::split_commas(request["Connect-As"]);
222  if (std::find_if(types.begin(), types.end(), [](std::string const& s) {
223  return boost::iequals(s, "peer");
224  }) == types.end())
225  {
226  handoff.moved = false;
227  handoff.response =
228  makeRedirectResponse(slot, request, remote_endpoint.address());
229  handoff.keep_alive = beast::rfc2616::is_keep_alive(request);
230  return handoff;
231  }
232  }
233 
234  auto const negotiatedVersion = negotiateProtocolVersion(request["Upgrade"]);
235  if (!negotiatedVersion)
236  {
237  m_peerFinder->on_closed(slot);
238  handoff.moved = false;
239  handoff.response = makeErrorResponse(
240  slot,
241  request,
242  remote_endpoint.address(),
243  "Unable to agree on a protocol version");
244  handoff.keep_alive = false;
245  return handoff;
246  }
247 
248  auto const sharedValue = makeSharedValue(*stream_ptr, journal);
249  if (!sharedValue)
250  {
251  m_peerFinder->on_closed(slot);
252  handoff.moved = false;
253  handoff.response = makeErrorResponse(
254  slot,
255  request,
256  remote_endpoint.address(),
257  "Incorrect security cookie");
258  handoff.keep_alive = false;
259  return handoff;
260  }
261 
262  try
263  {
264  auto publicKey = verifyHandshake(
265  request,
266  *sharedValue,
269  remote_endpoint.address(),
270  app_);
271 
272  {
273  // The node gets a reserved slot if it is in our cluster
274  // or if it has a reservation.
275  bool const reserved =
276  static_cast<bool>(app_.cluster().member(publicKey)) ||
277  app_.peerReservations().contains(publicKey);
278  auto const result =
279  m_peerFinder->activate(slot, publicKey, reserved);
280  if (result != PeerFinder::Result::success)
281  {
282  m_peerFinder->on_closed(slot);
283  JLOG(journal.debug())
284  << "Peer " << remote_endpoint << " redirected, slots full";
285  handoff.moved = false;
286  handoff.response = makeRedirectResponse(
287  slot, request, remote_endpoint.address());
288  handoff.keep_alive = false;
289  return handoff;
290  }
291  }
292 
293  auto const peer = std::make_shared<PeerImp>(
294  app_,
295  id,
296  slot,
297  std::move(request),
298  publicKey,
299  *negotiatedVersion,
300  consumer,
301  std::move(stream_ptr),
302  *this);
303  {
304  // As we are not on the strand, run() must be called
305  // while holding the lock, otherwise new I/O can be
306  // queued after a call to stop().
307  std::lock_guard<decltype(mutex_)> lock(mutex_);
308  {
309  auto const result = m_peers.emplace(peer->slot(), peer);
310  assert(result.second);
311  (void)result.second;
312  }
313  list_.emplace(peer.get(), peer);
314 
315  peer->run();
316  }
317  handoff.moved = true;
318  return handoff;
319  }
320  catch (std::exception const& e)
321  {
322  JLOG(journal.debug()) << "Peer " << remote_endpoint
323  << " fails handshake (" << e.what() << ")";
324 
325  m_peerFinder->on_closed(slot);
326  handoff.moved = false;
327  handoff.response = makeErrorResponse(
328  slot, request, remote_endpoint.address(), e.what());
329  handoff.keep_alive = false;
330  return handoff;
331  }
332 }
333 
334 //------------------------------------------------------------------------------
335 
336 bool
338 {
339  if (!is_upgrade(request))
340  return false;
341  auto const versions = parseProtocolVersions(request["Upgrade"]);
342  return !versions.empty();
343 }
344 
347 {
349  ss << "[" << std::setfill('0') << std::setw(3) << id << "] ";
350  return ss.str();
351 }
352 
356  http_request_type const& request,
357  address_type remote_address)
358 {
359  boost::beast::http::response<json_body> msg;
360  msg.version(request.version());
361  msg.result(boost::beast::http::status::service_unavailable);
362  msg.insert("Server", BuildInfo::getFullVersionString());
363  {
364  std::ostringstream ostr;
365  ostr << remote_address;
366  msg.insert("Remote-Address", ostr.str());
367  }
368  msg.insert("Content-Type", "application/json");
369  msg.insert(boost::beast::http::field::connection, "close");
370  msg.body() = Json::objectValue;
371  {
372  Json::Value& ips = (msg.body()["peer-ips"] = Json::arrayValue);
373  for (auto const& _ : m_peerFinder->redirect(slot))
374  ips.append(_.address.to_string());
375  }
376  msg.prepare_payload();
377  return std::make_shared<SimpleWriter>(msg);
378 }
379 
383  http_request_type const& request,
384  address_type remote_address,
385  std::string text)
386 {
387  boost::beast::http::response<boost::beast::http::empty_body> msg;
388  msg.version(request.version());
389  msg.result(boost::beast::http::status::bad_request);
390  msg.reason("Bad Request (" + text + ")");
391  msg.insert("Server", BuildInfo::getFullVersionString());
392  msg.insert("Remote-Address", remote_address.to_string());
393  msg.insert(boost::beast::http::field::connection, "close");
394  msg.prepare_payload();
395  return std::make_shared<SimpleWriter>(msg);
396 }
397 
398 //------------------------------------------------------------------------------
399 
400 void
402 {
403  assert(work_);
404 
405  auto usage = resourceManager().newOutboundEndpoint(remote_endpoint);
406  if (usage.disconnect())
407  {
408  JLOG(journal_.info()) << "Over resource limit: " << remote_endpoint;
409  return;
410  }
411 
412  auto const slot = peerFinder().new_outbound_slot(remote_endpoint);
413  if (slot == nullptr)
414  {
415  JLOG(journal_.debug()) << "Connect: No slot for " << remote_endpoint;
416  return;
417  }
418 
419  auto const p = std::make_shared<ConnectAttempt>(
420  app_,
421  io_service_,
423  usage,
424  setup_.context,
425  next_id_++,
426  slot,
427  app_.journal("Peer"),
428  *this);
429 
430  std::lock_guard lock(mutex_);
431  list_.emplace(p.get(), p);
432  p->run();
433 }
434 
435 //------------------------------------------------------------------------------
436 
437 // Adds a peer that is already handshaked and active
438 void
440 {
441  std::lock_guard lock(mutex_);
442 
443  {
444  auto const result = m_peers.emplace(peer->slot(), peer);
445  assert(result.second);
446  (void)result.second;
447  }
448 
449  {
450  auto const result = ids_.emplace(
451  std::piecewise_construct,
452  std::make_tuple(peer->id()),
453  std::make_tuple(peer));
454  assert(result.second);
455  (void)result.second;
456  }
457 
458  list_.emplace(peer.get(), peer);
459 
460  JLOG(journal_.debug()) << "activated " << peer->getRemoteAddress() << " ("
461  << peer->id() << ":"
462  << toBase58(
463  TokenType::NodePublic, peer->getNodePublic())
464  << ")";
465 
466  // As we are not on the strand, run() must be called
467  // while holding the lock, otherwise new I/O can be
468  // queued after a call to stop().
469  peer->run();
470 }
471 
472 void
474 {
475  std::lock_guard lock(mutex_);
476  auto const iter = m_peers.find(slot);
477  assert(iter != m_peers.end());
478  m_peers.erase(iter);
479 }
480 
481 //------------------------------------------------------------------------------
482 //
483 // Stoppable
484 //
485 //------------------------------------------------------------------------------
486 
487 // Caller must hold the mutex
488 void
490 {
491  if (isStopping() && areChildrenStopped() && list_.empty())
492  stopped();
493 }
494 
495 void
497 {
498  PeerFinder::Config config;
499 
500  if (app_.config().PEERS_MAX != 0)
501  config.maxPeers = app_.config().PEERS_MAX;
502 
503  config.outPeers = config.calcOutPeers();
504 
505  auto const port = serverHandler_.setup().overlay.port;
506 
507  config.peerPrivate = app_.config().PEER_PRIVATE;
508 
509  // Servers with peer privacy don't want to allow incoming connections
510  config.wantIncoming = (!config.peerPrivate) && (port != 0);
511 
512  // This will cause servers configured as validators to request that
513  // peers they connect to never report their IP address. We set this
514  // after we set the 'wantIncoming' because we want a "soft" version
515  // of peer privacy unless the operator explicitly asks for it.
517  config.peerPrivate = true;
518 
519  // if it's a private peer or we are running as standalone
520  // automatic connections would defeat the purpose.
521  config.autoConnect =
523  config.listeningPort = port;
524  config.features = "";
525  config.ipLimit = setup_.ipLimit;
526 
527  // Enforce business rules
528  config.applyTuning();
529 
530  m_peerFinder->setConfig(config);
531 
532  // Populate our boot cache: if there are no entries in [ips] then we use
533  // the entries in [ips_fixed].
534  auto bootstrapIps =
536 
537  // If nothing is specified, default to several well-known high-capacity
538  // servers to serve as bootstrap:
539  if (bootstrapIps.empty())
540  {
541  // Pool of servers operated by Ripple Labs Inc. - https://ripple.com
542  bootstrapIps.push_back("r.ripple.com 51235");
543 
544  // Pool of servers operated by Alloy Networks - https://www.alloy.ee
545  bootstrapIps.push_back("zaphod.alloy.ee 51235");
546 
547  // Pool of servers operated by ISRDC - https://isrdc.in
548  bootstrapIps.push_back("sahyadri.isrdc.in 51235");
549  }
550 
552  bootstrapIps,
553  [this](
554  std::string const& name,
555  std::vector<beast::IP::Endpoint> const& addresses) {
557  ips.reserve(addresses.size());
558  for (auto const& addr : addresses)
559  {
560  if (addr.port() == 0)
561  ips.push_back(to_string(addr.at_port(DEFAULT_PEER_PORT)));
562  else
563  ips.push_back(to_string(addr));
564  }
565 
566  std::string const base("config: ");
567  if (!ips.empty())
568  m_peerFinder->addFallbackStrings(base + name, ips);
569  });
570 
571  // Add the ips_fixed from the rippled.cfg file
572  if (!app_.config().standalone() && !app_.config().IPS_FIXED.empty())
573  {
576  [this](
577  std::string const& name,
578  std::vector<beast::IP::Endpoint> const& addresses) {
580  ips.reserve(addresses.size());
581 
582  for (auto& addr : addresses)
583  {
584  if (addr.port() == 0)
585  ips.emplace_back(addr.address(), DEFAULT_PEER_PORT);
586  else
587  ips.emplace_back(addr);
588  }
589 
590  if (!ips.empty())
591  m_peerFinder->addFixedPeer(name, ips);
592  });
593  }
594 }
595 
596 void
598 {
599  auto const timer = std::make_shared<Timer>(*this);
600  std::lock_guard lock(mutex_);
601  list_.emplace(timer.get(), timer);
602  timer_ = timer;
603  timer->run();
604 }
605 
606 void
608 {
609  strand_.dispatch(std::bind(&OverlayImpl::stop, this));
610 }
611 
612 void
614 {
615  std::lock_guard lock(mutex_);
616  checkStopped();
617 }
618 
619 //------------------------------------------------------------------------------
620 //
621 // PropertyStream
622 //
623 //------------------------------------------------------------------------------
624 
625 void
627 {
628  beast::PropertyStream::Set set("traffic", stream);
629  auto const stats = m_traffic.getCounts();
630  for (auto const& i : stats)
631  {
632  if (i)
633  {
635  item["category"] = i.name;
636  item["bytes_in"] = std::to_string(i.bytesIn.load());
637  item["messages_in"] = std::to_string(i.messagesIn.load());
638  item["bytes_out"] = std::to_string(i.bytesOut.load());
639  item["messages_out"] = std::to_string(i.messagesOut.load());
640  }
641  }
642 }
643 
644 //------------------------------------------------------------------------------
650 void
652 {
653  // Now track this peer
654  {
655  std::lock_guard lock(mutex_);
656  auto const result(ids_.emplace(
657  std::piecewise_construct,
658  std::make_tuple(peer->id()),
659  std::make_tuple(peer)));
660  assert(result.second);
661  (void)result.second;
662  }
663 
664  JLOG(journal_.debug()) << "activated " << peer->getRemoteAddress() << " ("
665  << peer->id() << ":"
666  << toBase58(
667  TokenType::NodePublic, peer->getNodePublic())
668  << ")";
669 
670  // We just accepted this peer so we have non-zero active peers
671  assert(size() != 0);
672 }
673 
674 void
676 {
677  std::lock_guard lock(mutex_);
678  ids_.erase(id);
679 }
680 
681 void
684  std::shared_ptr<PeerImp> const& from)
685 {
686  auto& hashRouter = app_.getHashRouter();
687  auto const n = m->list_size();
688  auto const& journal = from->pjournal();
689 
690  JLOG(journal.debug()) << "TMManifest, " << n
691  << (n == 1 ? " item" : " items");
692 
693  for (std::size_t i = 0; i < n; ++i)
694  {
695  auto& s = m->list().Get(i).stobject();
696 
697  if (auto mo = deserializeManifest(s))
698  {
699  uint256 const hash = mo->hash();
700  if (!hashRouter.addSuppressionPeer(hash, from->id()))
701  {
702  JLOG(journal.info()) << "Duplicate manifest #" << i + 1;
703  continue;
704  }
705 
706  if (!app_.validators().listed(mo->masterKey))
707  {
708  JLOG(journal.info()) << "Untrusted manifest #" << i + 1;
709  app_.getOPs().pubManifest(*mo);
710  continue;
711  }
712 
713  auto const serialized = mo->serialized;
714 
715  auto const result =
716  app_.validatorManifests().applyManifest(std::move(*mo));
717 
718  if (result == ManifestDisposition::accepted)
719  {
720  app_.getOPs().pubManifest(*deserializeManifest(serialized));
721  }
722 
723  if (result == ManifestDisposition::accepted)
724  {
725  auto db = app_.getWalletDB().checkoutDb();
726 
727  soci::transaction tr(*db);
728  static const char* const sql =
729  "INSERT INTO ValidatorManifests (RawData) VALUES "
730  "(:rawData);";
731  soci::blob rawData(*db);
732  convert(serialized, rawData);
733  *db << sql, soci::use(rawData);
734  tr.commit();
735 
736  protocol::TMManifests o;
737  o.add_list()->set_stobject(s);
738 
739  auto const toSkip = hashRouter.shouldRelay(hash);
740  if (toSkip)
741  foreach(send_if_not(
742  std::make_shared<Message>(o, protocol::mtMANIFESTS),
743  peer_in_set(*toSkip)));
744  }
745  else
746  {
747  JLOG(journal.info())
748  << "Bad manifest #" << i + 1 << ": " << to_string(result);
749  }
750  }
751  else
752  {
753  JLOG(journal.warn()) << "Malformed manifest #" << i + 1;
754  continue;
755  }
756  }
757 }
758 
759 void
762  bool isInbound,
763  int number)
764 {
765  m_traffic.addCount(cat, isInbound, number);
766 }
767 
770 {
771  using namespace std::chrono;
772  using namespace std::chrono_literals;
773 
775  auto const numPeers{size()};
776  if (numPeers == 0)
777  return jv;
778 
779  // If greater than a hop away, we may need to gather or freshen data
780  if (hops > 0)
781  {
782  // Prevent crawl spamming
783  clock_type::time_point const last(csLast_.load());
784  if ((clock_type::now() - last) > 60s)
785  {
786  auto const timeout(seconds((hops * hops) * 10));
788 
789  // Check if already requested
790  if (csIDs_.empty())
791  {
792  {
793  std::lock_guard lock{mutex_};
794  for (auto& id : ids_)
795  csIDs_.emplace(id.first);
796  }
797 
798  // Relay request to active peers
799  protocol::TMGetPeerShardInfo tmGPS;
800  tmGPS.set_hops(hops);
801  foreach(send_always(std::make_shared<Message>(
802  tmGPS, protocol::mtGET_PEER_SHARD_INFO)));
803 
804  if (csCV_.wait_for(l, timeout) == std::cv_status::timeout)
805  {
806  csIDs_.clear();
807  csCV_.notify_all();
808  }
809  csLast_ = duration_cast<seconds>(
810  clock_type::now().time_since_epoch());
811  }
812  else
813  csCV_.wait_for(l, timeout);
814  }
815  }
816 
817  // Combine the shard info from peers and their sub peers
819  for_each([&](std::shared_ptr<PeerImp> const& peer) {
820  if (auto psi = peer->getPeerShardInfo())
821  {
822  // e is non-const so it may be moved from
823  for (auto& e : *psi)
824  {
825  auto it{peerShardInfo.find(e.first)};
826  if (it != peerShardInfo.end())
827  // The key exists so join the shard indexes.
828  it->second.shardIndexes += e.second.shardIndexes;
829  else
830  peerShardInfo.emplace(std::move(e));
831  }
832  }
833  });
834 
835  // Prepare json reply
836  auto& av = jv[jss::peers] = Json::Value(Json::arrayValue);
837  for (auto const& e : peerShardInfo)
838  {
839  auto& pv{av.append(Json::Value(Json::objectValue))};
840  if (pubKey)
841  pv[jss::public_key] = toBase58(TokenType::NodePublic, e.first);
842 
843  auto const& address{e.second.endpoint.address()};
844  if (!address.is_unspecified())
845  pv[jss::ip] = address.to_string();
846 
847  pv[jss::complete_shards] = to_string(e.second.shardIndexes);
848  }
849 
850  return jv;
851 }
852 
853 void
855 {
856  // Notify threads when every peer has received a last link.
857  // This doesn't account for every node that might reply but
858  // it is adequate.
860  if (csIDs_.erase(id) && csIDs_.empty())
861  csCV_.notify_all();
862 }
863 
870 {
871  std::lock_guard lock(mutex_);
872  return ids_.size();
873 }
874 
875 int
877 {
878  return m_peerFinder->config().maxPeers;
879 }
880 
883 {
884  using namespace std::chrono;
885  Json::Value jv;
886  auto& av = jv["active"] = Json::Value(Json::arrayValue);
887 
889  auto& pv = av.append(Json::Value(Json::objectValue));
890  pv[jss::public_key] = base64_encode(
891  sp->getNodePublic().data(), sp->getNodePublic().size());
892  pv[jss::type] = sp->slot()->inbound() ? "in" : "out";
893  pv[jss::uptime] = static_cast<std::uint32_t>(
894  duration_cast<seconds>(sp->uptime()).count());
895  if (sp->crawl())
896  {
897  pv[jss::ip] = sp->getRemoteAddress().address().to_string();
898  if (sp->slot()->inbound())
899  {
900  if (auto port = sp->slot()->listening_port())
901  pv[jss::port] = *port;
902  }
903  else
904  {
905  pv[jss::port] = std::to_string(sp->getRemoteAddress().port());
906  }
907  }
908 
909  {
910  auto version{sp->getVersion()};
911  if (!version.empty())
912  // Could move here if Json::value supported moving from strings
913  pv[jss::version] = version;
914  }
915 
916  std::uint32_t minSeq, maxSeq;
917  sp->ledgerRange(minSeq, maxSeq);
918  if (minSeq != 0 || maxSeq != 0)
919  pv[jss::complete_ledgers] =
920  std::to_string(minSeq) + "-" + std::to_string(maxSeq);
921 
922  if (auto shardIndexes = sp->getShardIndexes())
923  pv[jss::complete_shards] = to_string(*shardIndexes);
924  });
925 
926  return jv;
927 }
928 
931 {
932  bool const humanReadable = false;
933  bool const admin = false;
934  bool const counters = false;
935 
936  Json::Value server_info =
937  app_.getOPs().getServerInfo(humanReadable, admin, counters);
938 
939  // Filter out some information
940  server_info.removeMember(jss::hostid);
941  server_info.removeMember(jss::load_factor_fee_escalation);
942  server_info.removeMember(jss::load_factor_fee_queue);
943  server_info.removeMember(jss::validation_quorum);
944 
945  if (server_info.isMember(jss::validated_ledger))
946  {
947  Json::Value& validated_ledger = server_info[jss::validated_ledger];
948 
949  validated_ledger.removeMember(jss::base_fee);
950  validated_ledger.removeMember(jss::reserve_base_xrp);
951  validated_ledger.removeMember(jss::reserve_inc_xrp);
952  }
953 
954  return server_info;
955 }
956 
959 {
960  return getCountsJson(app_, 10);
961 }
962 
965 {
966  Json::Value validators = app_.validators().getJson();
967 
968  if (validators.isMember(jss::publisher_lists))
969  {
970  Json::Value& publisher_lists = validators[jss::publisher_lists];
971 
972  for (auto& publisher : publisher_lists)
973  {
974  publisher.removeMember(jss::list);
975  }
976  }
977 
978  validators.removeMember(jss::signing_keys);
979  validators.removeMember(jss::trusted_validator_keys);
980  validators.removeMember(jss::validation_quorum);
981 
982  Json::Value validatorSites = app_.validatorSites().getJson();
983 
984  if (validatorSites.isMember(jss::validator_sites))
985  {
986  validators[jss::validator_sites] =
987  std::move(validatorSites[jss::validator_sites]);
988  }
989 
990  return validators;
991 }
992 
993 // Returns information on verified peers.
996 {
998  for (auto const& peer : getActivePeers())
999  {
1000  json.append(peer->json());
1001  }
1002  return json;
1003 }
1004 
1005 bool
1007 {
1008  if (req.target() != "/crawl" ||
1010  return false;
1011 
1012  boost::beast::http::response<json_body> msg;
1013  msg.version(req.version());
1014  msg.result(boost::beast::http::status::ok);
1015  msg.insert("Server", BuildInfo::getFullVersionString());
1016  msg.insert("Content-Type", "application/json");
1017  msg.insert("Connection", "close");
1018  msg.body()["version"] = Json::Value(2u);
1019 
1021  {
1022  msg.body()["overlay"] = getOverlayInfo();
1023  }
1025  {
1026  msg.body()["server"] = getServerInfo();
1027  }
1029  {
1030  msg.body()["counts"] = getServerCounts();
1031  }
1033  {
1034  msg.body()["unl"] = getUnlInfo();
1035  }
1036 
1037  msg.prepare_payload();
1038  handoff.response = std::make_shared<SimpleWriter>(msg);
1039  return true;
1040 }
1041 
1042 bool
1044  http_request_type const& req,
1045  Handoff& handoff)
1046 {
1047  // If the target is in the form "/vl/<validator_list_public_key>",
1048  // return the most recent validator list for that key.
1049  constexpr std::string_view prefix("/vl/");
1050 
1051  if (!req.target().starts_with(prefix.data()) || !setup_.vlEnabled)
1052  return false;
1053 
1054  auto key = req.target().substr(prefix.size());
1055 
1056  if (key.empty())
1057  return false;
1058 
1059  // find the list
1060  auto vl = app_.validators().getAvailable(key);
1061 
1062  boost::beast::http::response<json_body> msg;
1063  msg.version(req.version());
1064  msg.insert("Server", BuildInfo::getFullVersionString());
1065  msg.insert("Content-Type", "application/json");
1066  msg.insert("Connection", "close");
1067 
1068  if (!vl)
1069  {
1070  // 404 not found
1071  msg.result(boost::beast::http::status::not_found);
1072  msg.insert("Content-Length", "0");
1073 
1074  msg.body() = Json::nullValue;
1075  }
1076  else
1077  {
1078  msg.result(boost::beast::http::status::ok);
1079 
1080  msg.body() = *vl;
1081  }
1082 
1083  msg.prepare_payload();
1084  handoff.response = std::make_shared<SimpleWriter>(msg);
1085  return true;
1086 }
1087 
1088 bool
1090 {
1091  if (req.target() != "/health")
1092  return false;
1093  boost::beast::http::response<json_body> msg;
1094  msg.version(req.version());
1095  msg.insert("Server", BuildInfo::getFullVersionString());
1096  msg.insert("Content-Type", "application/json");
1097  msg.insert("Connection", "close");
1098 
1099  auto info = getServerInfo();
1100 
1101  int last_validated_ledger_age = -1;
1102  if (info.isMember("validated_ledger"))
1103  last_validated_ledger_age = info["validated_ledger"]["age"].asInt();
1104  bool amendment_blocked = false;
1105  if (info.isMember("amendment_blocked"))
1106  amendment_blocked = true;
1107  int number_peers = info["peers"].asInt();
1108  std::string server_state = info["server_state"].asString();
1109  auto load_factor =
1110  info["load_factor"].asDouble() / info["load_base"].asDouble();
1111 
1112  enum { healthy, warning, critical };
1113  int health = healthy;
1114  auto set_health = [&health](int state) {
1115  if (health < state)
1116  health = state;
1117  };
1118 
1119  msg.body()[jss::info] = Json::objectValue;
1120  if (last_validated_ledger_age >= 7 || last_validated_ledger_age < 0)
1121  {
1122  msg.body()[jss::info]["validated_ledger"] = last_validated_ledger_age;
1123  if (last_validated_ledger_age < 20)
1124  set_health(warning);
1125  else
1126  set_health(critical);
1127  }
1128 
1129  if (amendment_blocked)
1130  {
1131  msg.body()[jss::info]["amendment_blocked"] = true;
1132  set_health(critical);
1133  }
1134 
1135  if (number_peers <= 7)
1136  {
1137  msg.body()[jss::info]["peers"] = number_peers;
1138  if (number_peers != 0)
1139  set_health(warning);
1140  else
1141  set_health(critical);
1142  }
1143 
1144  if (!(server_state == "full" || server_state == "validating" ||
1145  server_state == "proposing"))
1146  {
1147  msg.body()[jss::info]["server_state"] = server_state;
1148  if (server_state == "syncing" || server_state == "tracking" ||
1149  server_state == "connected")
1150  {
1151  set_health(warning);
1152  }
1153  else
1154  set_health(critical);
1155  }
1156 
1157  if (load_factor > 100)
1158  {
1159  msg.body()[jss::info]["load_factor"] = load_factor;
1160  if (load_factor < 1000)
1161  set_health(warning);
1162  else
1163  set_health(critical);
1164  }
1165 
1166  switch (health)
1167  {
1168  case healthy:
1169  msg.result(boost::beast::http::status::ok);
1170  break;
1171  case warning:
1172  msg.result(boost::beast::http::status::service_unavailable);
1173  break;
1174  case critical:
1175  msg.result(boost::beast::http::status::internal_server_error);
1176  break;
1177  }
1178 
1179  msg.prepare_payload();
1180  handoff.response = std::make_shared<SimpleWriter>(msg);
1181  return true;
1182 }
1183 
1184 bool
1186 {
1187  // Take advantage of || short-circuiting
1188  return processCrawl(req, handoff) || processValidatorList(req, handoff) ||
1189  processHealth(req, handoff);
1190 }
1191 
1194 {
1196  ret.reserve(size());
1197 
1198  for_each([&ret](std::shared_ptr<PeerImp>&& sp) {
1199  ret.emplace_back(std::move(sp));
1200  });
1201 
1202  return ret;
1203 }
1204 
1205 void
1207 {
1208  for_each(
1209  [index](std::shared_ptr<PeerImp>&& sp) { sp->checkSanity(index); });
1210 }
1211 
1212 void
1214 {
1215  for_each([](std::shared_ptr<PeerImp>&& sp) { sp->check(); });
1216 }
1217 
1220 {
1221  std::lock_guard lock(mutex_);
1222  auto const iter = ids_.find(id);
1223  if (iter != ids_.end())
1224  return iter->second.lock();
1225  return {};
1226 }
1227 
1228 // A public key hash map was not used due to the peer connect/disconnect
1229 // update overhead outweighing the performance of a small set linear search.
1232 {
1233  std::lock_guard lock(mutex_);
1234  for (auto const& e : ids_)
1235  {
1236  if (auto peer = e.second.lock())
1237  {
1238  if (peer->getNodePublic() == pubKey)
1239  return peer;
1240  }
1241  }
1242  return {};
1243 }
1244 
1245 void
1246 OverlayImpl::broadcast(protocol::TMProposeSet& m)
1247 {
1248  auto const sm = std::make_shared<Message>(m, protocol::mtPROPOSE_LEDGER);
1249  for_each([&](std::shared_ptr<PeerImp>&& p) { p->send(sm); });
1250 }
1251 
1252 void
1253 OverlayImpl::relay(protocol::TMProposeSet& m, uint256 const& uid)
1254 {
1255  if (auto const toSkip = app_.getHashRouter().shouldRelay(uid))
1256  {
1257  auto const sm =
1258  std::make_shared<Message>(m, protocol::mtPROPOSE_LEDGER);
1260  if (toSkip->find(p->id()) == toSkip->end())
1261  p->send(sm);
1262  });
1263  }
1264 }
1265 
1266 void
1267 OverlayImpl::broadcast(protocol::TMValidation& m)
1268 {
1269  auto const sm = std::make_shared<Message>(m, protocol::mtVALIDATION);
1270  for_each([sm](std::shared_ptr<PeerImp>&& p) { p->send(sm); });
1271 }
1272 
1273 void
1274 OverlayImpl::relay(protocol::TMValidation& m, uint256 const& uid)
1275 {
1276  if (auto const toSkip = app_.getHashRouter().shouldRelay(uid))
1277  {
1278  auto const sm = std::make_shared<Message>(m, protocol::mtVALIDATION);
1280  if (toSkip->find(p->id()) == toSkip->end())
1281  p->send(sm);
1282  });
1283  }
1284 }
1285 
1286 //------------------------------------------------------------------------------
1287 
1288 void
1290 {
1291  std::lock_guard lock(mutex_);
1292  list_.erase(&child);
1293  if (list_.empty())
1294  checkStopped();
1295 }
1296 
1297 void
1299 {
1300  // Calling list_[].second->stop() may cause list_ to be modified
1301  // (OverlayImpl::remove() may be called on this same thread). So
1302  // iterating directly over list_ to call child->stop() could lead to
1303  // undefined behavior.
1304  //
1305  // Therefore we copy all of the weak/shared ptrs out of list_ before we
1306  // start calling stop() on them. That guarantees OverlayImpl::remove()
1307  // won't be called until vector<> children leaves scope.
1309  {
1310  std::lock_guard lock(mutex_);
1311  if (!work_)
1312  return;
1313  work_ = boost::none;
1314 
1315  children.reserve(list_.size());
1316  for (auto const& element : list_)
1317  {
1318  children.emplace_back(element.second.lock());
1319  }
1320  } // lock released
1321 
1322  for (auto const& child : children)
1323  {
1324  if (child != nullptr)
1325  child->stop();
1326  }
1327 }
1328 
1329 void
1331 {
1332  auto const result = m_peerFinder->autoconnect();
1333  for (auto addr : result)
1334  connect(addr);
1335 }
1336 
1337 void
1339 {
1340  auto const result = m_peerFinder->buildEndpointsForPeers();
1341  for (auto const& e : result)
1342  {
1344  {
1345  std::lock_guard lock(mutex_);
1346  auto const iter = m_peers.find(e.first);
1347  if (iter != m_peers.end())
1348  peer = iter->second.lock();
1349  }
1350  if (peer)
1351  peer->sendEndpoints(e.second.begin(), e.second.end());
1352  }
1353 }
1354 
1357 {
1359 
1360  {
1361  auto const& section = config.section("overlay");
1363 
1364  set(setup.ipLimit, "ip_limit", section);
1365  if (setup.ipLimit < 0)
1366  Throw<std::runtime_error>("Configured IP limit is invalid");
1367 
1368  std::string ip;
1369  set(ip, "public_ip", section);
1370  if (!ip.empty())
1371  {
1372  boost::system::error_code ec;
1373  setup.public_ip = beast::IP::Address::from_string(ip, ec);
1375  Throw<std::runtime_error>("Configured public IP is invalid");
1376  }
1377  }
1378 
1379  {
1380  auto const& section = config.section("crawl");
1381  auto const& values = section.values();
1382 
1383  if (values.size() > 1)
1384  {
1385  Throw<std::runtime_error>(
1386  "Configured [crawl] section is invalid, too many values");
1387  }
1388 
1389  bool crawlEnabled = true;
1390 
1391  // Only allow "0|1" as a value
1392  if (values.size() == 1)
1393  {
1394  try
1395  {
1396  crawlEnabled = boost::lexical_cast<bool>(values.front());
1397  }
1398  catch (boost::bad_lexical_cast const&)
1399  {
1400  Throw<std::runtime_error>(
1401  "Configured [crawl] section has invalid value: " +
1402  values.front());
1403  }
1404  }
1405 
1406  if (crawlEnabled)
1407  {
1408  if (get<bool>(section, "overlay", true))
1409  {
1411  }
1412  if (get<bool>(section, "server", true))
1413  {
1415  }
1416  if (get<bool>(section, "counts", false))
1417  {
1419  }
1420  if (get<bool>(section, "unl", true))
1421  {
1423  }
1424  }
1425  }
1426  {
1427  auto const& section = config.section("vl");
1428 
1429  set(setup.vlEnabled, "enabled", section);
1430  }
1431 
1432  try
1433  {
1434  auto id = config.legacy("network_id");
1435 
1436  if (!id.empty())
1437  {
1438  if (id == "main")
1439  id = "0";
1440 
1441  if (id == "testnet")
1442  id = "1";
1443 
1444  if (id == "devnet")
1445  id = "2";
1446 
1447  setup.networkID = beast::lexicalCastThrow<std::uint32_t>(id);
1448  }
1449  }
1450  catch (...)
1451  {
1452  Throw<std::runtime_error>(
1453  "Configured [network_id] section is invalid: must be a number "
1454  "or one of the strings 'main', 'testnet' or 'devnet'.");
1455  }
1456 
1457  return setup;
1458 }
1459 
1462  Application& app,
1463  Overlay::Setup const& setup,
1464  Stoppable& parent,
1467  Resolver& resolver,
1468  boost::asio::io_service& io_service,
1469  BasicConfig const& config,
1470  beast::insight::Collector::ptr const& collector)
1471 {
1472  return std::make_unique<OverlayImpl>(
1473  app,
1474  setup,
1475  parent,
1476  serverHandler,
1478  resolver,
1479  io_service,
1480  config,
1481  collector);
1482 }
1483 
1484 } // 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::OverlayImpl::findPeerByShortID
std::shared_ptr< Peer > findPeerByShortID(Peer::id_t const &id) override
Returns the peer with the matching short id, or null.
Definition: OverlayImpl.cpp:1219
ripple::OverlayImpl::relay
void relay(protocol::TMProposeSet &m, uint256 const &uid) override
Relay a proposal.
Definition: OverlayImpl.cpp:1253
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:958
ripple::OverlayImpl::journal_
const beast::Journal journal_
Definition: OverlayImpl.h:104
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:75
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
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:97
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:526
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:285
ripple::OverlayImpl::ids_
hash_map< Peer::id_t, std::weak_ptr< PeerImp > > ids_
Definition: OverlayImpl.h:110
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::autoConnect
void autoConnect()
Definition: OverlayImpl.cpp:1330
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::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:123
ripple::OverlayImpl::m_resolver
Resolver & m_resolver
Definition: OverlayImpl.h:111
ripple::OverlayImpl::mutex_
std::recursive_mutex mutex_
Definition: OverlayImpl.h:99
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:112
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:1461
ripple::OverlayImpl::makePrefix
static std::string makePrefix(std::uint32_t id)
Definition: OverlayImpl.cpp:346
ripple::PeerFinder::Config::features
std::string features
The set of features we advertise.
Definition: PeerfinderManager.h:73
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:174
std::chrono::seconds
ripple::Config::PEER_PRIVATE
bool PEER_PRIVATE
Definition: Config.h:144
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:121
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:98
std::shared_ptr::get
T get(T... args)
ripple::OverlayImpl::getServerInfo
Json::Value getServerInfo()
Returns information about the local server.
Definition: OverlayImpl.cpp:930
std::lock_guard
STL class.
ripple::OverlayImpl::onStart
void onStart() override
Override called during start.
Definition: OverlayImpl.cpp:597
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:1246
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:401
ripple::OverlayImpl::json
Json::Value json() override
Return diagnostics on the status of all peers.
Definition: OverlayImpl.cpp:995
ripple::OverlayImpl::setup
Setup const & setup() const
Definition: OverlayImpl.h:166
ripple::OverlayImpl::timer_count_
int timer_count_
Definition: OverlayImpl.h:113
ripple::PeerFinder::Config::peerPrivate
bool peerPrivate
true if we want our IP address kept private.
Definition: PeerfinderManager.h:61
ripple::OverlayImpl::processValidatorList
bool processValidatorList(http_request_type const &req, Handoff &handoff)
Handles validator list requests.
Definition: OverlayImpl.cpp:1043
beast::PropertyStream::Set
Definition: PropertyStream.h:308
ripple::peer_in_set
Select all peers that are in the specified set.
Definition: predicates.h:160
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:108
ripple::OverlayImpl::processHealth
bool processHealth(http_request_type const &req, Handoff &handoff)
Handles health requests.
Definition: OverlayImpl.cpp:1089
ripple::OverlayImpl::setup_
Setup setup_
Definition: OverlayImpl.h:103
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:613
ripple::OverlayImpl::cond_
std::condition_variable_any cond_
Definition: OverlayImpl.h:100
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:152
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:148
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:869
beast::rfc2616::is_keep_alive
bool is_keep_alive(boost::beast::http::message< isRequest, Body, Fields > const &m)
Definition: rfc2616.h:475
ripple::setup_Overlay
Overlay::Setup setup_Overlay(BasicConfig const &config)
Definition: OverlayImpl.cpp:1356
ripple::OverlayImpl::csMutex_
std::mutex csMutex_
Definition: OverlayImpl.h:120
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:682
ripple::Stoppable
Provides an interface for starting and stopping.
Definition: Stoppable.h:200
ripple::Overlay::Setup::public_ip
beast::IP::Address public_ip
Definition: Overlay.h:75
ripple::PeerFinder::Config::wantIncoming
bool wantIncoming
true if we want to accept incoming connections.
Definition: PeerfinderManager.h:64
ripple::DatabaseCon::checkoutDb
LockedSociSession checkoutDb()
Definition: DatabaseCon.h:176
ripple::OverlayImpl::resourceManager
Resource::Manager & resourceManager()
Definition: OverlayImpl.h:154
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:882
ripple::OverlayImpl::io_service_
boost::asio::io_service & io_service_
Definition: OverlayImpl.h:96
ripple::Application::config
virtual Config & config()=0
ripple::ValidatorSite::getJson
Json::Value getJson() const
Return JSON representation of configured validator sites.
Definition: ValidatorSite.cpp:587
ripple::Config::IPS_FIXED
std::vector< std::string > IPS_FIXED
Definition: Config.h:120
ripple::ServerHandlerImp
Definition: ServerHandlerImp.h:46
ripple::Config::standalone
bool standalone() const
Definition: Config.h:222
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:521
ripple::OverlayImpl::serverHandler
ServerHandler & serverHandler()
Definition: OverlayImpl.h:160
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:964
ripple::OverlayImpl::checkStopped
void checkStopped()
Definition: OverlayImpl.cpp:489
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
ripple::PeerFinder::Config::outPeers
double outPeers
The number of automatic outbound connections to maintain.
Definition: PeerfinderManager.h:58
ripple::PeerFinder::Config::maxPeers
int maxPeers
The largest number of public peer slots to allow.
Definition: PeerfinderManager.h:46
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::OverlayImpl::app_
Application & app_
Definition: OverlayImpl.h:95
ripple::OverlayImpl::m_peerFinder
std::unique_ptr< PeerFinder::Manager > m_peerFinder
Definition: OverlayImpl.h:107
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:105
ripple::OverlayImpl::onPrepare
void onPrepare() override
Override called during preparation.
Definition: OverlayImpl.cpp:496
std::uint32_t
std::condition_variable_any::wait
T wait(T... args)
ripple::OverlayImpl::TrafficGauges
Definition: OverlayImpl.h:485
ripple::OverlayImpl::Child::Child
Child(OverlayImpl &overlay)
Definition: OverlayImpl.cpp:56
ripple::HashRouter::shouldRelay
boost::optional< std::set< PeerShortID > > shouldRelay(uint256 const &key)
Determines whether the hashed item should be relayed.
Definition: HashRouter.cpp:112
ripple::OverlayImpl::getActivePeers
PeerSequence getActivePeers() const override
Returns a sequence representing the current list of peers.
Definition: OverlayImpl.cpp:1193
beast::rfc2616::split_commas
Result split_commas(FwdIt first, FwdIt last)
Definition: rfc2616.h:288
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::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:1185
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::PeerFinder::Config::applyTuning
void applyTuning()
Adjusts the values so they follow the business rules.
Definition: PeerfinderConfig.cpp:44
ripple::Config::PEERS_MAX
std::size_t PEERS_MAX
Definition: Config.h:145
ripple::OverlayImpl::~OverlayImpl
~OverlayImpl()
Definition: OverlayImpl.cpp:160
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:106
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::deserializeManifest
boost::optional< Manifest > deserializeManifest(Slice s)
Constructs Manifest from serialized string.
Definition: app/misc/impl/Manifest.cpp:38
ripple::OverlayImpl::checkSanity
void checkSanity(std::uint32_t) override
Calls the checkSanity function on each peer.
Definition: OverlayImpl.cpp:1206
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
Json::Value::removeMember
Value removeMember(const char *key)
Remove and return the named member.
Definition: json_value.cpp:907
ripple::PeerFinder::Config::listeningPort
std::uint16_t listeningPort
The listening port number.
Definition: PeerfinderManager.h:70
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:473
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:651
ripple::PeerFinder::Config::calcOutPeers
double calcOutPeers() const
Returns a suitable value for outPeers according to the rules.
Definition: PeerfinderConfig.cpp:37
ripple::OverlayImpl::onPeerDeactivate
void onPeerDeactivate(Peer::id_t id)
Definition: OverlayImpl.cpp:675
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:102
ripple::OverlayImpl::lastLink
void lastLink(std::uint32_t id)
Called when the last link from a peer chain is received.
Definition: OverlayImpl.cpp:854
ripple::OverlayImpl::check
void check() override
Calls the check function on each peer.
Definition: OverlayImpl.cpp:1213
ripple::OverlayImpl::Timer::Timer
Timer(OverlayImpl &overlay)
Definition: OverlayImpl.cpp:67
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:1231
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:119
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:354
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:101
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::autoConnect
bool autoConnect
true if we want to establish connections automatically
Definition: PeerfinderManager.h:67
ripple::PeerFinder::Config
PeerFinder configuration settings.
Definition: PeerfinderManager.h:40
ripple::OverlayImpl::csLast_
std::atomic< std::chrono::seconds > csLast_
Definition: OverlayImpl.h:119
std::setw
T setw(T... args)
ripple::OverlayImpl
Definition: OverlayImpl.h:55
ripple::OverlayImpl::reportTraffic
void reportTraffic(TrafficCount::category cat, bool isInbound, int bytes)
Definition: OverlayImpl.cpp:760
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:769
ripple::TrafficCount::addCount
void addCount(category cat, bool inbound, int bytes)
Account for traffic associated with the given category.
Definition: TrafficCount.h:156
ripple::OverlayImpl::Child
Definition: OverlayImpl.h:58
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:361
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:381
ripple::Tuning::checkSeconds
@ checkSeconds
How often we check connections (seconds)
Definition: overlay/impl/Tuning.h:54
ripple::OverlayImpl::m_peers
hash_map< std::shared_ptr< PeerFinder::Slot >, std::weak_ptr< PeerImp > > m_peers
Definition: OverlayImpl.h:109
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:337
ripple::OverlayImpl::add_active
void add_active(std::shared_ptr< PeerImp > const &peer)
Definition: OverlayImpl.cpp:439
ripple::OverlayImpl::error_code
boost::system::error_code error_code
Definition: OverlayImpl.h:77
ripple::PeerFinder::Config::ipLimit
int ipLimit
Limit how many incoming connections we allow per IP.
Definition: PeerfinderManager.h:76
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:626
ripple::Application::getHashRouter
virtual HashRouter & getHashRouter()=0
ripple::BasicConfig
Holds unparsed configuration information.
Definition: BasicConfig.h:178
ripple::OverlayImpl::sendEndpoints
void sendEndpoints()
Definition: OverlayImpl.cpp:1338
ripple::OverlayImpl::for_each
void for_each(UnaryFunc &&f) const
Definition: OverlayImpl.h:243
ripple::OverlayImpl::onStop
void onStop() override
Override called when the stop notification is issued.
Definition: OverlayImpl.cpp:607
ripple::OverlayImpl::stop
void stop()
Definition: OverlayImpl.cpp:1298
std::exception::what
T what(T... args)
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:876
ripple::OverlayImpl::processCrawl
bool processCrawl(http_request_type const &req, Handoff &handoff)
Handles crawl requests.
Definition: OverlayImpl.cpp:1006
ripple::OverlayImpl::endpoint_type
boost::asio::ip::tcp::endpoint endpoint_type
Definition: OverlayImpl.h:76
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
std::chrono
std::chrono::steady_clock::now
T now(T... args)