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