rippled
ValidatorSite.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2016 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/misc/ValidatorList.h>
21 #include <ripple/app/misc/ValidatorSite.h>
22 #include <ripple/app/misc/detail/WorkFile.h>
23 #include <ripple/app/misc/detail/WorkPlain.h>
24 #include <ripple/app/misc/detail/WorkSSL.h>
25 #include <ripple/basics/base64.h>
26 #include <ripple/basics/Slice.h>
27 #include <ripple/json/json_reader.h>
28 #include <ripple/protocol/digest.h>
29 #include <ripple/protocol/jss.h>
30 #include <boost/algorithm/clamp.hpp>
31 #include <boost/regex.hpp>
32 #include <algorithm>
33 
34 namespace ripple {
35 
38 unsigned short constexpr max_redirects = 3;
39 
41  : uri {std::move(uri_)}
42 {
43  if (! parseUrl (pUrl, uri))
44  throw std::runtime_error("URI '" + uri + "' cannot be parsed");
45 
46  if (pUrl.scheme == "file")
47  {
48  if (!pUrl.domain.empty())
49  throw std::runtime_error("file URI cannot contain a hostname");
50 
51 #if BOOST_OS_WINDOWS
52  // Paths on Windows need the leading / removed
53  if (pUrl.path[0] == '/')
54  pUrl.path = pUrl.path.substr(1);
55 #endif
56 
57  if (pUrl.path.empty())
58  throw std::runtime_error("file URI must contain a path");
59  }
60  else if (pUrl.scheme == "http")
61  {
62  if (pUrl.domain.empty())
63  throw std::runtime_error("http URI must contain a hostname");
64 
65  if (!pUrl.port)
66  pUrl.port = 80;
67  }
68  else if (pUrl.scheme == "https")
69  {
70  if (pUrl.domain.empty())
71  throw std::runtime_error("https URI must contain a hostname");
72 
73  if (!pUrl.port)
74  pUrl.port = 443;
75  }
76  else
77  throw std::runtime_error ("Unsupported scheme: '" + pUrl.scheme + "'");
78 }
79 
81  : loadedResource {std::make_shared<Resource>(std::move(uri))}
82  , startingResource {loadedResource}
83  , redirCount {0}
84  , refreshInterval {default_refresh_interval}
85  , nextRefresh {clock_type::now()}
86 {
87 }
88 
90  Application& app,
91  boost::optional<beast::Journal> j,
92  std::chrono::seconds timeout)
93  : app_ {app}
94  , j_ {j ? *j : app_.logs().journal("ValidatorSite") }
95  , timer_ {app_.getIOService()}
96  , fetching_ {false}
97  , pending_ {false}
98  , stopping_ {false}
99  , requestTimeout_ {timeout}
100 {
101 }
102 
104 {
106  if (timer_.expires_at() > clock_type::time_point{})
107  {
108  if (! stopping_)
109  {
110  lock.unlock();
111  stop();
112  }
113  else
114  {
115  cv_.wait(lock, [&]{ return ! fetching_; });
116  }
117  }
118 }
119 
120 bool
122 {
123  auto const sites = app_.validators().loadLists();
124  return sites.empty() || load(sites);
125 }
126 
127 bool
129  std::vector<std::string> const& siteURIs)
130 {
131  // If no sites are provided, act as if a site failed to load.
132  if (siteURIs.empty())
133  {
134  return missingSite();
135  }
136 
137  JLOG (j_.debug()) <<
138  "Loading configured validator list sites";
139 
141 
142  for (auto const& uri : siteURIs)
143  {
144  try
145  {
146  sites_.emplace_back (uri);
147  }
148  catch (std::exception const& e)
149  {
150  JLOG (j_.error()) <<
151  "Invalid validator site uri: " << uri <<
152  ": " << e.what();
153  return false;
154  }
155  }
156 
157  JLOG (j_.debug()) <<
158  "Loaded " << siteURIs.size() << " sites";
159 
160  return true;
161 }
162 
163 void
165 {
167  if (timer_.expires_at() == clock_type::time_point{})
168  setTimer (lock);
169 }
170 
171 void
173 {
175  cv_.wait(lock, [&]{ return ! pending_; });
176 }
177 
178 void
180 {
182  stopping_ = true;
183  // work::cancel() must be called before the
184  // cv wait in order to kick any asio async operations
185  // that might be pending.
186  if(auto sp = work_.lock())
187  sp->cancel();
188  cv_.wait(lock, [&]{ return ! fetching_; });
189 
190  // docs indicate cancel() can throw, but this should be
191  // reconsidered if it changes to noexcept
192  try
193  {
194  timer_.cancel();
195  }
196  catch (boost::system::system_error const&)
197  {
198  }
199  stopping_ = false;
200  pending_ = false;
201  cv_.notify_all();
202 }
203 
204 void
206 {
208 
209  auto next = std::min_element(sites_.begin(), sites_.end(),
210  [](Site const& a, Site const& b)
211  {
212  return a.nextRefresh < b.nextRefresh;
213  });
214 
215  if (next != sites_.end ())
216  {
217  pending_ = next->nextRefresh <= clock_type::now();
218  cv_.notify_all();
219  timer_.expires_at (next->nextRefresh);
220  auto idx = std::distance (sites_.begin (), next);
221  timer_.async_wait ([this, idx] (boost::system::error_code const& ec)
222  {
223  this->onTimer (idx, ec);
224  });
225  }
226 }
227 
228 void
231  std::size_t siteIdx,
232  std::lock_guard<std::mutex>& sites_lock)
233 {
234  fetching_ = true;
235  sites_[siteIdx].activeResource = resource;
237  auto timeoutCancel =
238  [this] ()
239  {
240  std::lock_guard lock_state{state_mutex_};
241  // docs indicate cancel_one() can throw, but this
242  // should be reconsidered if it changes to noexcept
243  try
244  {
245  timer_.cancel_one();
246  }
247  catch (boost::system::system_error const&)
248  {
249  }
250  };
251  auto onFetch =
252  [this, siteIdx, timeoutCancel] (
253  error_code const& err, detail::response_type&& resp)
254  {
255  timeoutCancel ();
256  onSiteFetch (err, std::move(resp), siteIdx);
257  };
258 
259  auto onFetchFile =
260  [this, siteIdx, timeoutCancel] (
261  error_code const& err, std::string const& resp)
262  {
263  timeoutCancel ();
264  onTextFetch (err, resp, siteIdx);
265  };
266 
267  JLOG (j_.debug()) << "Starting request for " << resource->uri;
268 
269  if (resource->pUrl.scheme == "https")
270  {
271  // can throw...
272  sp = std::make_shared<detail::WorkSSL>(
273  resource->pUrl.domain,
274  resource->pUrl.path,
275  std::to_string(*resource->pUrl.port),
276  app_.getIOService(),
277  j_,
278  app_.config(),
279  onFetch);
280  }
281  else if(resource->pUrl.scheme == "http")
282  {
283  sp = std::make_shared<detail::WorkPlain>(
284  resource->pUrl.domain,
285  resource->pUrl.path,
286  std::to_string(*resource->pUrl.port),
287  app_.getIOService(),
288  onFetch);
289  }
290  else
291  {
292  BOOST_ASSERT(resource->pUrl.scheme == "file");
293  sp = std::make_shared<detail::WorkFile>(
294  resource->pUrl.path,
295  app_.getIOService(),
296  onFetchFile);
297  }
298 
299  work_ = sp;
300  sp->run ();
301  // start a timer for the request, which shouldn't take more
302  // than requestTimeout_ to complete
303  std::lock_guard lock_state{state_mutex_};
304  timer_.expires_after (requestTimeout_);
305  timer_.async_wait ([this, siteIdx] (boost::system::error_code const& ec)
306  {
307  this->onRequestTimeout (siteIdx, ec);
308  });
309 }
310 
311 void
313  std::size_t siteIdx,
314  error_code const& ec)
315 {
316  if (ec)
317  return;
318 
319  {
320  std::lock_guard lock_site{sites_mutex_};
321  JLOG (j_.warn()) <<
322  "Request for " << sites_[siteIdx].activeResource->uri <<
323  " took too long";
324  }
325 
326  std::lock_guard lock_state{state_mutex_};
327  if(auto sp = work_.lock())
328  sp->cancel();
329 }
330 
331 void
333  std::size_t siteIdx,
334  error_code const& ec)
335 {
336  if (ec)
337  {
338  // Restart the timer if any errors are encountered, unless the error
339  // is from the wait operating being aborted due to a shutdown request.
340  if (ec != boost::asio::error::operation_aborted)
341  onSiteFetch(ec, detail::response_type {}, siteIdx);
342  return;
343  }
344 
345  try
346  {
348  sites_[siteIdx].nextRefresh =
349  clock_type::now() + sites_[siteIdx].refreshInterval;
350  sites_[siteIdx].redirCount = 0;
351  // the WorkSSL client ctor can throw if SSL init fails
352  makeRequest(sites_[siteIdx].startingResource, siteIdx, lock);
353  }
354  catch (std::exception &)
355  {
356  onSiteFetch(
357  boost::system::error_code {-1, boost::system::generic_category()},
359  siteIdx);
360  }
361 }
362 
363 void
365  std::string const& res,
366  std::size_t siteIdx,
367  std::lock_guard<std::mutex>& sites_lock)
368 {
369  Json::Reader r;
370  Json::Value body;
371  if (! r.parse(res.data(), body))
372  {
373  JLOG (j_.warn()) <<
374  "Unable to parse JSON response from " <<
375  sites_[siteIdx].activeResource->uri;
376  throw std::runtime_error{"bad json"};
377  }
378 
379  if( ! body.isObject () ||
380  ! body.isMember("blob") || ! body["blob"].isString () ||
381  ! body.isMember("manifest") || ! body["manifest"].isString () ||
382  ! body.isMember("signature") || ! body["signature"].isString() ||
383  ! body.isMember("version") || ! body["version"].isInt())
384  {
385  JLOG (j_.warn()) <<
386  "Missing fields in JSON response from " <<
387  sites_[siteIdx].activeResource->uri;
388  throw std::runtime_error{"missing fields"};
389  }
390 
391  auto const manifest = body["manifest"].asString ();
392  auto const blob = body["blob"].asString ();
393  auto const signature = body["signature"].asString();
394  auto const version = body["version"].asUInt();
395  auto const& uri = sites_[siteIdx].activeResource->uri;
396  auto const hash = sha512Half(manifest, blob, signature, version);
397  auto const applyResult = app_.validators().applyListAndBroadcast (
398  manifest,
399  blob,
400  signature,
401  version,
402  uri,
403  hash,
404  app_.overlay(),
405  app_.getHashRouter());
406  auto const disp = applyResult.disposition;
407 
408  sites_[siteIdx].lastRefreshStatus.emplace(
409  Site::Status{clock_type::now(), disp, ""});
410 
411  switch (disp)
412  {
414  JLOG (j_.debug()) <<
415  "Applied new validator list from " <<
416  uri;
417  break;
419  JLOG (j_.debug()) <<
420  "Validator list with current sequence from " <<
421  uri;
422  break;
424  JLOG (j_.warn()) <<
425  "Stale validator list from " <<
426  uri;
427  break;
429  JLOG (j_.warn()) <<
430  "Untrusted validator list from " <<
431  uri;
432  break;
434  JLOG (j_.warn()) <<
435  "Invalid validator list from " <<
436  uri;
437  break;
439  JLOG (j_.warn()) <<
440  "Unsupported version validator list from " <<
441  uri;
442  break;
443  default:
444  BOOST_ASSERT(false);
445  }
446 
447  if (body.isMember ("refresh_interval") &&
448  body["refresh_interval"].isNumeric ())
449  {
450  using namespace std::chrono_literals;
451  std::chrono::minutes const refresh =
452  boost::algorithm::clamp(
453  std::chrono::minutes {body["refresh_interval"].asUInt ()},
454  1min,
455  24h);
456  sites_[siteIdx].refreshInterval = refresh;
457  sites_[siteIdx].nextRefresh =
458  clock_type::now() + sites_[siteIdx].refreshInterval;
459  }
460 }
461 
465  std::size_t siteIdx,
466  std::lock_guard<std::mutex>& sites_lock)
467 {
468  using namespace boost::beast::http;
470  if (res.find(field::location) == res.end() ||
471  res[field::location].empty())
472  {
473  JLOG (j_.warn()) <<
474  "Request for validator list at " <<
475  sites_[siteIdx].activeResource->uri <<
476  " returned a redirect with no Location.";
477  throw std::runtime_error{"missing location"};
478  }
479 
480  if (sites_[siteIdx].redirCount == max_redirects)
481  {
482  JLOG (j_.warn()) <<
483  "Exceeded max redirects for validator list at " <<
484  sites_[siteIdx].loadedResource->uri ;
485  throw std::runtime_error{"max redirects"};
486  }
487 
488  JLOG (j_.debug()) <<
489  "Got redirect for validator list from " <<
490  sites_[siteIdx].activeResource->uri <<
491  " to new location " << res[field::location];
492 
493  try
494  {
495  newLocation = std::make_shared<Site::Resource>(
496  std::string(res[field::location]));
497  ++sites_[siteIdx].redirCount;
498  if (newLocation->pUrl.scheme != "http" &&
499  newLocation->pUrl.scheme != "https")
500  throw std::runtime_error("invalid scheme in redirect " +
501  newLocation->pUrl.scheme);
502  }
503  catch (std::exception &)
504  {
505  JLOG (j_.error()) <<
506  "Invalid redirect location: " << res[field::location];
507  throw;
508  }
509  return newLocation;
510 }
511 
512 void
514  boost::system::error_code const& ec,
515  detail::response_type&& res,
516  std::size_t siteIdx)
517 {
518  {
519  std::lock_guard lock_sites{sites_mutex_};
520  JLOG (j_.debug()) << "Got completion for "
521  << sites_[siteIdx].activeResource->uri;
522  auto onError = [&](std::string const& errMsg, bool retry)
523  {
524  sites_[siteIdx].lastRefreshStatus.emplace(
527  errMsg});
528  if (retry)
529  sites_[siteIdx].nextRefresh =
531 
532  // See if there's a copy saved locally from last time we
533  // saw the list.
534  missingSite();
535  };
536  if (ec)
537  {
538  JLOG (j_.warn()) <<
539  "Problem retrieving from " <<
540  sites_[siteIdx].activeResource->uri <<
541  " " <<
542  ec.value() <<
543  ":" <<
544  ec.message();
545  onError("fetch error", true);
546  }
547  else
548  {
549  try
550  {
551  using namespace boost::beast::http;
552  switch (res.result())
553  {
554  case status::ok:
555  parseJsonResponse(res.body(), siteIdx, lock_sites);
556  break;
557  case status::moved_permanently :
558  case status::permanent_redirect :
559  case status::found :
560  case status::temporary_redirect :
561  {
562  auto newLocation =
563  processRedirect (res, siteIdx, lock_sites);
564  assert(newLocation);
565  // for perm redirects, also update our starting URI
566  if (res.result() == status::moved_permanently ||
567  res.result() == status::permanent_redirect)
568  {
569  sites_[siteIdx].startingResource = newLocation;
570  }
571  makeRequest(newLocation, siteIdx, lock_sites);
572  return; // we are still fetching, so skip
573  // state update/notify below
574  }
575  default:
576  {
577  JLOG (j_.warn()) <<
578  "Request for validator list at " <<
579  sites_[siteIdx].activeResource->uri <<
580  " returned bad status: " <<
581  res.result_int();
582  onError("bad result code", true);
583  }
584  }
585  }
586  catch (std::exception& ex)
587  {
588  onError(ex.what(), false);
589  }
590  }
591  sites_[siteIdx].activeResource.reset();
592  }
593 
594  std::lock_guard lock_state{state_mutex_};
595  fetching_ = false;
596  if (! stopping_)
597  setTimer (lock_state);
598  cv_.notify_all();
599 }
600 
601 void
603  boost::system::error_code const& ec,
604  std::string const& res,
605  std::size_t siteIdx)
606 {
607  {
608  std::lock_guard lock_sites{sites_mutex_};
609  try
610  {
611  if (ec)
612  {
613  JLOG (j_.warn()) <<
614  "Problem retrieving from " <<
615  sites_[siteIdx].activeResource->uri <<
616  " " <<
617  ec.value() <<
618  ": " <<
619  ec.message();
620  throw std::runtime_error{"fetch error"};
621  }
622 
623  parseJsonResponse(res, siteIdx, lock_sites);
624  }
625  catch (std::exception& ex)
626  {
627  sites_[siteIdx].lastRefreshStatus.emplace(
630  ex.what()});
631  }
632  sites_[siteIdx].activeResource.reset();
633  }
634 
635  std::lock_guard lock_state{state_mutex_};
636  fetching_ = false;
637  if (! stopping_)
638  setTimer (lock_state);
639  cv_.notify_all();
640 }
641 
644 {
645  using namespace std::chrono;
646  using Int = Json::Value::Int;
647 
649  Json::Value& jSites = (jrr[jss::validator_sites] = Json::arrayValue);
650  {
652  for (Site const& site : sites_)
653  {
654  Json::Value& v = jSites.append(Json::objectValue);
655  std::stringstream uri;
656  uri << site.loadedResource->uri;
657  if (site.loadedResource != site.startingResource)
658  uri << " (redirects to " << site.startingResource->uri + ")";
659  v[jss::uri] = uri.str();
660  v[jss::next_refresh_time] = to_string(site.nextRefresh);
661  if (site.lastRefreshStatus)
662  {
663  v[jss::last_refresh_time] =
664  to_string(site.lastRefreshStatus->refreshed);
665  v[jss::last_refresh_status] =
666  to_string(site.lastRefreshStatus->disposition);
667  if (! site.lastRefreshStatus->message.empty())
668  v[jss::last_refresh_message] =
669  site.lastRefreshStatus->message;
670  }
671  v[jss::refresh_interval_min] =
672  static_cast<Int>(site.refreshInterval.count());
673  }
674  }
675  return jrr;
676 }
677 } // ripple
Json::Value::isInt
bool isInt() const
Definition: json_value.cpp:1012
Json::Value::Int
Json::Int Int
Definition: json_value.h:150
ripple::Application
Definition: Application.h:85
ripple::ValidatorSite::Site
Definition: ValidatorSite.h:75
Json::Value::isObject
bool isObject() const
Definition: json_value.cpp:1069
std::string
STL class.
std::shared_ptr
STL class.
Json::Value::isString
bool isString() const
Definition: json_value.cpp:1049
std::exception
STL class.
ripple::ValidatorSite::timer_
boost::asio::basic_waitable_timer< clock_type > timer_
Definition: ValidatorSite.h:120
ripple::ValidatorList::PublisherListStats::disposition
ListDisposition disposition
Definition: ValidatorList.h:198
ripple::ValidatorSite::onSiteFetch
void onSiteFetch(boost::system::error_code const &ec, detail::response_type &&res, std::size_t siteIdx)
Store latest list fetched from site.
Definition: ValidatorSite.cpp:513
ripple::ListDisposition::stale
@ stale
Trusted publisher key, but seq is too old.
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:44
ripple::HashPrefix::manifest
@ manifest
Manifest.
std::vector< std::string >
ripple::max_redirects
unsigned constexpr short max_redirects
Definition: ValidatorSite.cpp:38
ripple::ValidatorSite::stop
void stop()
Stop fetching lists from sites.
Definition: ValidatorSite.cpp:179
std::chrono::minutes
ripple::ValidatorSite::onRequestTimeout
void onRequestTimeout(std::size_t siteIdx, error_code const &ec)
request took too long
Definition: ValidatorSite.cpp:312
ripple::ValidatorSite::Site::Resource::uri
const std::string uri
Definition: ValidatorSite.h:87
std::stringstream
STL class.
beast::Journal::warn
Stream warn() const
Definition: Journal.h:302
ripple::ValidatorSite::work_
std::weak_ptr< detail::Work > work_
Definition: ValidatorSite.h:119
std::lock_guard
STL class.
std::distance
T distance(T... args)
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
Json::Reader
Unserialize a JSON document into a Value.
Definition: json_reader.h:36
ripple::parsedURL::path
std::string path
Definition: StringUtilities.h:131
ripple::ValidatorSite::processRedirect
std::shared_ptr< Site::Resource > processRedirect(detail::response_type &res, std::size_t siteIdx, std::lock_guard< std::mutex > &lock)
Interpret a redirect response.
Definition: ValidatorSite.cpp:463
ripple::ValidatorSite::state_mutex_
std::mutex state_mutex_
Definition: ValidatorSite.h:116
algorithm
ripple::ValidatorSite::fetching_
std::atomic< bool > fetching_
Definition: ValidatorSite.h:123
ripple::ValidatorSite::~ValidatorSite
~ValidatorSite()
Definition: ValidatorSite.cpp:103
ripple::detail::response_type
boost::beast::http::response< boost::beast::http::string_body > response_type
Definition: Work.h:31
ripple::ValidatorSite::app_
Application & app_
Definition: ValidatorSite.h:112
Json::Value::append
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:907
ripple::ValidatorSite::parseJsonResponse
void parseJsonResponse(std::string const &res, std::size_t siteIdx, std::lock_guard< std::mutex > &lock)
Parse json response from validator list site.
Definition: ValidatorSite.cpp:364
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:45
ripple::ValidatorSite::pending_
std::atomic< bool > pending_
Definition: ValidatorSite.h:126
ripple::ValidatorSite::ValidatorSite
ValidatorSite(Application &app, boost::optional< beast::Journal > j=boost::none, std::chrono::seconds timeout=std::chrono::seconds{20})
Definition: ValidatorSite.cpp:89
ripple::Application::config
virtual Config & config()=0
std::min_element
T min_element(T... args)
ripple::ValidatorSite::getJson
Json::Value getJson() const
Return JSON representation of configured validator sites.
Definition: ValidatorSite.cpp:643
std::unique_lock
STL class.
ripple::ValidatorSite::j_
const beast::Journal j_
Definition: ValidatorSite.h:113
std::to_string
T to_string(T... args)
ripple::ValidatorSite::cv_
std::condition_variable cv_
Definition: ValidatorSite.h:118
ripple::parseUrl
bool parseUrl(parsedURL &pUrl, std::string const &strUrl)
Definition: StringUtilities.cpp:53
beast::Journal::error
Stream error() const
Definition: Journal.h:307
std::runtime_error
STL class.
ripple::ListDisposition::untrusted
@ untrusted
List signed by untrusted publisher key.
Json::Value::isMember
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:961
ripple::ValidatorSite::join
void join()
Wait for current fetches from sites to complete.
Definition: ValidatorSite.cpp:172
ripple::ValidatorList::applyListAndBroadcast
PublisherListStats applyListAndBroadcast(std::string const &manifest, std::string const &blob, std::string const &signature, std::uint32_t version, std::string siteUri, uint256 const &hash, Overlay &overlay, HashRouter &hashRouter)
Apply published list of public keys, then broadcast it to all peers that have not seen it or sent it.
Definition: ValidatorList.cpp:244
std::condition_variable::wait
T wait(T... args)
ripple::error_retry_interval
constexpr auto error_retry_interval
Definition: ValidatorSite.cpp:37
ripple::ValidatorSite::sites_mutex_
std::mutex sites_mutex_
Definition: ValidatorSite.h:115
ripple::ListDisposition::unsupported_version
@ unsupported_version
List version is not supported.
ripple::Application::validators
virtual ValidatorList & validators()=0
ripple::ValidatorSite::sites_
std::vector< Site > sites_
Definition: ValidatorSite.h:130
ripple::Application::getIOService
virtual boost::asio::io_service & getIOService()=0
ripple::ValidatorSite::makeRequest
void makeRequest(std::shared_ptr< Site::Resource > resource, std::size_t siteIdx, std::lock_guard< std::mutex > &lock)
Initiate request to given resource.
Definition: ValidatorSite.cpp:229
ripple::parsedURL::port
boost::optional< std::uint16_t > port
Definition: StringUtilities.h:130
ripple::ValidatorList::loadLists
std::vector< std::string > loadLists()
Definition: ValidatorList.cpp:456
ripple::ValidatorSite::requestTimeout_
const std::chrono::seconds requestTimeout_
Definition: ValidatorSite.h:133
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
Json::Value::isNumeric
bool isNumeric() const
Definition: json_value.cpp:1042
ripple::ListDisposition::same_sequence
@ same_sequence
Same sequence as current list.
ripple::ValidatorSite::Site::Resource::Resource
Resource(std::string uri_)
Definition: ValidatorSite.cpp:40
ripple::ValidatorSite::onTextFetch
void onTextFetch(boost::system::error_code const &ec, std::string const &res, std::size_t siteIdx)
Store latest list fetched from anywhere.
Definition: ValidatorSite.cpp:602
ripple::ValidatorSite::Site::loadedResource
std::shared_ptr< Resource > loadedResource
the original uri as loaded from config
Definition: ValidatorSite.h:94
ripple::ValidatorSite::stopping_
std::atomic< bool > stopping_
Definition: ValidatorSite.h:127
ripple::sha512Half
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition: digest.h:268
Json::Value::asUInt
UInt asUInt() const
Definition: json_value.cpp:555
ripple::ListDisposition::invalid
@ invalid
Invalid format or signature.
Json::Reader::parse
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Definition: json_reader.cpp:76
ripple::ValidatorSite::Site::Site
Site(std::string uri)
Definition: ValidatorSite.cpp:80
ripple::ValidatorSite::missingSite
bool missingSite()
If no sites are provided, or a site fails to load, get a list of local cache files from the Validator...
Definition: ValidatorSite.cpp:121
ripple::Application::overlay
virtual Overlay & overlay()=0
std::vector::empty
T empty(T... args)
ripple::ValidatorSite::Site::Resource::pUrl
parsedURL pUrl
Definition: ValidatorSite.h:88
ripple::ValidatorSite::Site::Status
Definition: ValidatorSite.h:77
std::stringstream::str
T str(T... args)
ripple::parsedURL::scheme
std::string scheme
Definition: StringUtilities.h:126
beast::Journal::debug
Stream debug() const
Definition: Journal.h:292
std::size_t
ripple::ValidatorSite::start
void start()
Start fetching lists from sites.
Definition: ValidatorSite.cpp:164
ripple::ValidatorSite::onTimer
void onTimer(std::size_t siteIdx, error_code const &ec)
Fetch site whose time has come.
Definition: ValidatorSite.cpp:332
ripple::parsedURL::domain
std::string domain
Definition: StringUtilities.h:129
ripple::ValidatorSite::error_code
boost::system::error_code error_code
Definition: ValidatorSite.h:72
ripple::ValidatorSite::setTimer
void setTimer(std::lock_guard< std::mutex > &)
Queue next site to be fetched lock over state_mutex_ required.
Definition: ValidatorSite.cpp:205
std::string::data
T data(T... args)
std::condition_variable::notify_all
T notify_all(T... args)
ripple::ValidatorSite::load
bool load(std::vector< std::string > const &siteURIs)
Load configured site URIs.
Definition: ValidatorSite.cpp:128
ripple::Application::getHashRouter
virtual HashRouter & getHashRouter()=0
ripple::ListDisposition::accepted
@ accepted
List is valid.
ripple::default_refresh_interval
constexpr auto default_refresh_interval
Definition: ValidatorSite.cpp:36
std::exception::what
T what(T... args)
Json::Value
Represents a JSON value.
Definition: json_value.h:141
Json::Value::asString
std::string asString() const
Returns the unquoted string value.
Definition: json_value.cpp:482
std::chrono
std::chrono::system_clock::now
T now(T... args)