rippled
Handouts.h
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 #ifndef RIPPLE_PEERFINDER_HANDOUTS_H_INCLUDED
21 #define RIPPLE_PEERFINDER_HANDOUTS_H_INCLUDED
22 
23 #include <ripple/beast/container/aged_set.h>
24 #include <ripple/peerfinder/impl/SlotImp.h>
25 #include <ripple/peerfinder/impl/Tuning.h>
26 #include <cassert>
27 #include <iterator>
28 #include <type_traits>
29 
30 namespace ripple {
31 namespace PeerFinder {
32 
33 namespace detail {
34 
39 // VFALCO TODO specialization that handles std::list for SequenceContainer
40 // using splice for optimization over erase/push_back
41 //
42 template <class Target, class HopContainer>
44 handout_one(Target& t, HopContainer& h)
45 {
46  assert(!t.full());
47  for (auto it = h.begin(); it != h.end(); ++it)
48  {
49  auto const& e = *it;
50  if (t.try_insert(e))
51  {
52  h.move_back(it);
53  return 1;
54  }
55  }
56  return 0;
57 }
58 
59 } // namespace detail
60 
65 template <class TargetFwdIter, class SeqFwdIter>
66 void
68  TargetFwdIter first,
69  TargetFwdIter last,
70  SeqFwdIter seq_first,
71  SeqFwdIter seq_last)
72 {
73  for (;;)
74  {
75  std::size_t n(0);
76  for (auto si = seq_first; si != seq_last; ++si)
77  {
78  auto c = *si;
79  bool all_full(true);
80  for (auto ti = first; ti != last; ++ti)
81  {
82  auto& t = *ti;
83  if (!t.full())
84  {
85  n += detail::handout_one(t, c);
86  all_full = false;
87  }
88  }
89  if (all_full)
90  return;
91  }
92  if (!n)
93  break;
94  }
95 }
96 
97 //------------------------------------------------------------------------------
98 
103 {
104 public:
105  template <class = void>
106  explicit RedirectHandouts(SlotImp::ptr const& slot);
107 
108  template <class = void>
109  bool
110  try_insert(Endpoint const& ep);
111 
112  bool
113  full() const
114  {
116  }
117 
118  SlotImp::ptr const&
119  slot() const
120  {
121  return slot_;
122  }
123 
126  {
127  return list_;
128  }
129 
130  std::vector<Endpoint> const&
131  list() const
132  {
133  return list_;
134  }
135 
136 private:
139 };
140 
141 template <class>
143 {
145 }
146 
147 template <class>
148 bool
150 {
151  if (full())
152  return false;
153 
154  // VFALCO NOTE This check can be removed when we provide the
155  // addresses in a peer HTTP handshake instead of
156  // the tmENDPOINTS message.
157  //
158  if (ep.hops > Tuning::maxHops)
159  return false;
160 
161  // Don't send them our address
162  if (ep.hops == 0)
163  return false;
164 
165  // Don't send them their own address
166  if (slot_->remote_endpoint().address() == ep.address.address())
167  return false;
168 
169  // Make sure the address isn't already in our list
170  if (std::any_of(list_.begin(), list_.end(), [&ep](Endpoint const& other) {
171  // Ignore port for security reasons
172  return other.address.address() == ep.address.address();
173  }))
174  {
175  return false;
176  }
177 
178  list_.emplace_back(ep.address, ep.hops);
179 
180  return true;
181 }
182 
183 //------------------------------------------------------------------------------
184 
187 {
188 public:
189  template <class = void>
190  explicit SlotHandouts(SlotImp::ptr const& slot);
191 
192  template <class = void>
193  bool
194  try_insert(Endpoint const& ep);
195 
196  bool
197  full() const
198  {
200  }
201 
202  void
203  insert(Endpoint const& ep)
204  {
205  list_.push_back(ep);
206  }
207 
208  SlotImp::ptr const&
209  slot() const
210  {
211  return slot_;
212  }
213 
214  std::vector<Endpoint> const&
215  list() const
216  {
217  return list_;
218  }
219 
220 private:
223 };
224 
225 template <class>
226 SlotHandouts::SlotHandouts(SlotImp::ptr const& slot) : slot_(slot)
227 {
229 }
230 
231 template <class>
232 bool
234 {
235  if (full())
236  return false;
237 
238  if (ep.hops > Tuning::maxHops)
239  return false;
240 
241  if (slot_->recent.filter(ep.address, ep.hops))
242  return false;
243 
244  // Don't send them their own address
245  if (slot_->remote_endpoint().address() == ep.address.address())
246  return false;
247 
248  // Make sure the address isn't already in our list
249  if (std::any_of(list_.begin(), list_.end(), [&ep](Endpoint const& other) {
250  // Ignore port for security reasons
251  return other.address.address() == ep.address.address();
252  }))
253  return false;
254 
255  list_.emplace_back(ep.address, ep.hops);
256 
257  // Insert into this slot's recent table. Although the endpoint
258  // didn't come from the slot, adding it to the slot's table
259  // prevents us from sending it again until it has expired from
260  // the other end's cache.
261  //
262  slot_->recent.insert(ep.address, ep.hops);
263 
264  return true;
265 }
266 
267 //------------------------------------------------------------------------------
268 
271 {
272 public:
273  // Keeps track of addresses we have made outgoing connections
274  // to, for the purposes of not connecting to them too frequently.
276 
278 
279 private:
283 
284 public:
285  template <class = void>
286  ConnectHandouts(std::size_t needed, Squelches& squelches);
287 
288  template <class = void>
289  bool
290  try_insert(beast::IP::Endpoint const& endpoint);
291 
292  bool
293  empty() const
294  {
295  return m_list.empty();
296  }
297 
298  bool
299  full() const
300  {
301  return m_list.size() >= m_needed;
302  }
303 
304  bool
305  try_insert(Endpoint const& endpoint)
306  {
307  return try_insert(endpoint.address);
308  }
309 
310  list_type&
312  {
313  return m_list;
314  }
315 
316  list_type const&
317  list() const
318  {
319  return m_list;
320  }
321 };
322 
323 template <class>
325  : m_needed(needed), m_squelches(squelches)
326 {
327  m_list.reserve(needed);
328 }
329 
330 template <class>
331 bool
333 {
334  if (full())
335  return false;
336 
337  // Make sure the address isn't already in our list
338  if (std::any_of(
339  m_list.begin(),
340  m_list.end(),
341  [&endpoint](beast::IP::Endpoint const& other) {
342  // Ignore port for security reasons
343  return other.address() == endpoint.address();
344  }))
345  {
346  return false;
347  }
348 
349  // Add to squelch list so we don't try it too often.
350  // If its already there, then make try_insert fail.
351  auto const result(m_squelches.insert(endpoint.address()));
352  if (!result.second)
353  return false;
354 
355  m_list.push_back(endpoint);
356 
357  return true;
358 }
359 
360 } // namespace PeerFinder
361 } // namespace ripple
362 
363 #endif
ripple::PeerFinder::SlotHandouts::full
bool full() const
Definition: Handouts.h:197
ripple::PeerFinder::ConnectHandouts::full
bool full() const
Definition: Handouts.h:299
ripple::PeerFinder::SlotHandouts::try_insert
bool try_insert(Endpoint const &ep)
Definition: Handouts.h:233
ripple::PeerFinder::SlotHandouts
Receives endpoints for a slot during periodic handouts.
Definition: Handouts.h:186
ripple::PeerFinder::Tuning::redirectEndpointCount
constexpr std::uint32_t redirectEndpointCount
Definition: peerfinder/impl/Tuning.h:120
ripple::PeerFinder::ConnectHandouts::m_list
list_type m_list
Definition: Handouts.h:282
ripple::PeerFinder::ConnectHandouts::ConnectHandouts
ConnectHandouts(std::size_t needed, Squelches &squelches)
Definition: Handouts.h:324
ripple::PeerFinder::ConnectHandouts::empty
bool empty() const
Definition: Handouts.h:293
std::shared_ptr< SlotImp >
ripple::PeerFinder::ConnectHandouts
Receives handouts for making automatic connections.
Definition: Handouts.h:270
std::vector::reserve
T reserve(T... args)
std::vector< Endpoint >
std::vector::size
T size(T... args)
ripple::PeerFinder::RedirectHandouts::full
bool full() const
Definition: Handouts.h:113
ripple::PeerFinder::RedirectHandouts
Receives handouts for redirecting a connection.
Definition: Handouts.h:102
iterator
beast::IP::Endpoint::address
Address const & address() const
Returns the address portion of this endpoint.
Definition: IPEndpoint.h:76
beast::detail::aged_ordered_container::insert
auto insert(value_type const &value) -> typename std::enable_if<!maybe_multi, std::pair< iterator, bool >>::type
Definition: aged_ordered_container.h:1747
ripple::PeerFinder::SlotHandouts::slot
SlotImp::ptr const & slot() const
Definition: Handouts.h:209
ripple::PeerFinder::RedirectHandouts::RedirectHandouts
RedirectHandouts(SlotImp::ptr const &slot)
Definition: Handouts.h:142
std::any_of
T any_of(T... args)
ripple::PeerFinder::RedirectHandouts::list
std::vector< Endpoint > const & list() const
Definition: Handouts.h:131
ripple::PeerFinder::ConnectHandouts::list_type
std::vector< beast::IP::Endpoint > list_type
Definition: Handouts.h:277
ripple::PeerFinder::SlotHandouts::slot_
SlotImp::ptr slot_
Definition: Handouts.h:221
std::vector::push_back
T push_back(T... args)
ripple::PeerFinder::SlotHandouts::list
std::vector< Endpoint > const & list() const
Definition: Handouts.h:215
ripple::PeerFinder::detail::handout_one
std::size_t handout_one(Target &t, HopContainer &h)
Try to insert one object in the target.
Definition: Handouts.h:44
ripple::PeerFinder::ConnectHandouts::try_insert
bool try_insert(Endpoint const &endpoint)
Definition: Handouts.h:305
ripple::PeerFinder::RedirectHandouts::list
std::vector< Endpoint > & list()
Definition: Handouts.h:125
ripple::PeerFinder::RedirectHandouts::try_insert
bool try_insert(Endpoint const &ep)
Definition: Handouts.h:149
ripple::PeerFinder::ConnectHandouts::list
list_type & list()
Definition: Handouts.h:311
ripple::PeerFinder::Endpoint::hops
std::uint32_t hops
Definition: PeerfinderManager.h:119
ripple::PeerFinder::RedirectHandouts::list_
std::vector< Endpoint > list_
Definition: Handouts.h:138
ripple::PeerFinder::SlotHandouts::SlotHandouts
SlotHandouts(SlotImp::ptr const &slot)
Definition: Handouts.h:226
ripple::PeerFinder::handout
void handout(TargetFwdIter first, TargetFwdIter last, SeqFwdIter seq_first, SeqFwdIter seq_last)
Distributes objects to targets according to business rules.
Definition: Handouts.h:67
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::PeerFinder::RedirectHandouts::slot_
SlotImp::ptr slot_
Definition: Handouts.h:137
beast::detail::aged_ordered_container
Associative container where each element is also indexed by time.
Definition: aged_ordered_container.h:82
ripple::PeerFinder::ConnectHandouts::try_insert
bool try_insert(beast::IP::Endpoint const &endpoint)
Definition: Handouts.h:332
std::vector::begin
T begin(T... args)
ripple::PeerFinder::RedirectHandouts::slot
SlotImp::ptr const & slot() const
Definition: Handouts.h:119
cassert
std::vector::empty
T empty(T... args)
ripple::PeerFinder::ConnectHandouts::m_needed
std::size_t m_needed
Definition: Handouts.h:280
std::size_t
ripple::PeerFinder::ConnectHandouts::list
list_type const & list() const
Definition: Handouts.h:317
beast::IP::Endpoint
A version-independent IP address and port combination.
Definition: IPEndpoint.h:38
std::vector::end
T end(T... args)
ripple::PeerFinder::SlotHandouts::list_
std::vector< Endpoint > list_
Definition: Handouts.h:222
ripple::PeerFinder::Tuning::maxHops
constexpr std::uint32_t maxHops
Definition: peerfinder/impl/Tuning.h:110
ripple::PeerFinder::Endpoint
Describes a connectible peer address along with some metadata.
Definition: PeerfinderManager.h:113
ripple::PeerFinder::ConnectHandouts::m_squelches
Squelches & m_squelches
Definition: Handouts.h:281
ripple::PeerFinder::Tuning::numberOfEndpoints
constexpr std::uint32_t numberOfEndpoints
Definition: peerfinder/impl/Tuning.h:113
ripple::PeerFinder::Endpoint::address
beast::IP::Endpoint address
Definition: PeerfinderManager.h:120
type_traits
ripple::PeerFinder::SlotHandouts::insert
void insert(Endpoint const &ep)
Definition: Handouts.h:203