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