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