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