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