rippled
Loading...
Searching...
No Matches
PeerSet.cpp
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#include <xrpld/app/main/Application.h>
21#include <xrpld/app/misc/HashRouter.h>
22#include <xrpld/core/JobQueue.h>
23#include <xrpld/overlay/Overlay.h>
24#include <xrpld/overlay/PeerSet.h>
25#include <xrpl/protocol/digest.h>
26
27namespace ripple {
28
29class PeerSetImpl : public PeerSet
30{
31public:
33
34 void
36 std::size_t limit,
37 std::function<bool(std::shared_ptr<Peer> const&)> hasItem,
38 std::function<void(std::shared_ptr<Peer> const&)> onPeerAdded) override;
39
41 void
43 ::google::protobuf::Message const& message,
44 protocol::MessageType type,
45 std::shared_ptr<Peer> const& peer) override;
46
48 getPeerIds() const override;
49
50private:
51 // Used in this class for access to boost::asio::io_service and
52 // ripple::Overlay.
55
58};
59
61 : app_(app), journal_(app.journal("PeerSet"))
62{
63}
64
65void
67 std::size_t limit,
68 std::function<bool(std::shared_ptr<Peer> const&)> hasItem,
69 std::function<void(std::shared_ptr<Peer> const&)> onPeerAdded)
70{
71 using ScoredPeer = std::pair<int, std::shared_ptr<Peer>>;
72
73 auto const& overlay = app_.overlay();
74
76 pairs.reserve(overlay.size());
77
78 overlay.foreach([&](auto const& peer) {
79 auto const score = peer->getScore(hasItem(peer));
80 pairs.emplace_back(score, std::move(peer));
81 });
82
84 pairs.begin(),
85 pairs.end(),
86 [](ScoredPeer const& lhs, ScoredPeer const& rhs) {
87 return lhs.first > rhs.first;
88 });
89
91 for (auto const& pair : pairs)
92 {
93 auto const peer = pair.second;
94 if (!peers_.insert(peer->id()).second)
95 continue;
96 onPeerAdded(peer);
97 if (++accepted >= limit)
98 break;
99 }
100}
101
102void
104 ::google::protobuf::Message const& message,
105 protocol::MessageType type,
106 std::shared_ptr<Peer> const& peer)
107{
108 auto packet = std::make_shared<Message>(message, type);
109
110 auto const messageHash = [&]() {
111 auto const packetBuffer =
112 packet->getBuffer(compression::Compressed::Off);
113 return sha512Half(Slice(packetBuffer.data(), packetBuffer.size()));
114 }();
115
116 // Allow messages to be re-sent to the same peer after a delay
117 using namespace std::chrono_literals;
118 constexpr std::chrono::seconds interval = 30s;
119
120 if (peer)
121 {
123 messageHash, peer->id(), interval))
124 {
125 JLOG(journal_.trace())
126 << "Sending " << protocolMessageName(type) << " message to ["
127 << peer->id() << "]: " << messageHash;
128 peer->send(packet);
129 }
130 else
131 JLOG(journal_.debug())
132 << "Suppressing sending duplicate " << protocolMessageName(type)
133 << " message to [" << peer->id() << "]: " << messageHash;
134 return;
135 }
136
137 for (auto id : peers_)
138 {
139 if (auto p = app_.overlay().findPeerByShortID(id))
140 {
142 messageHash, p->id(), interval))
143 {
144 JLOG(journal_.trace())
145 << "Sending " << protocolMessageName(type)
146 << " message to [" << p->id() << "]: " << messageHash;
147 p->send(packet);
148 }
149 else
150 JLOG(journal_.debug())
151 << "Suppressing sending duplicate "
152 << protocolMessageName(type) << " message to [" << p->id()
153 << "]: " << messageHash;
154 }
155 }
156}
157
160{
161 return peers_;
162}
163
165{
166public:
168 {
169 }
170
172 build() override
173 {
174 return std::make_unique<PeerSetImpl>(app_);
175 }
176
177private:
179};
180
183{
184 return std::make_unique<PeerSetBuilderImpl>(app);
185}
186
187class DummyPeerSet : public PeerSet
188{
189public:
190 DummyPeerSet(Application& app) : j_(app.journal("DummyPeerSet"))
191 {
192 }
193
194 void
196 std::size_t limit,
197 std::function<bool(std::shared_ptr<Peer> const&)> hasItem,
198 std::function<void(std::shared_ptr<Peer> const&)> onPeerAdded) override
199 {
200 JLOG(j_.error()) << "DummyPeerSet addPeers should not be called";
201 }
202
203 void
205 ::google::protobuf::Message const& message,
206 protocol::MessageType type,
207 std::shared_ptr<Peer> const& peer) override
208 {
209 JLOG(j_.error()) << "DummyPeerSet sendRequest should not be called";
210 }
211
213 getPeerIds() const override
214 {
215 static std::set<Peer::id_t> emptyPeers;
216 JLOG(j_.error()) << "DummyPeerSet getPeerIds should not be called";
217 return emptyPeers;
218 }
219
220private:
222};
223
226{
227 return std::make_unique<DummyPeerSet>(app);
228}
229
230} // namespace ripple
T begin(T... args)
A generic endpoint for log messages.
Definition: Journal.h:59
Stream error() const
Definition: Journal.h:335
Stream debug() const
Definition: Journal.h:317
Stream trace() const
Severity stream access functions.
Definition: Journal.h:311
virtual Overlay & overlay()=0
virtual HashRouter & getHashRouter()=0
void addPeers(std::size_t limit, std::function< bool(std::shared_ptr< Peer > const &)> hasItem, std::function< void(std::shared_ptr< Peer > const &)> onPeerAdded) override
Try add more peers.
Definition: PeerSet.cpp:195
void sendRequest(::google::protobuf::Message const &message, protocol::MessageType type, std::shared_ptr< Peer > const &peer) override
Definition: PeerSet.cpp:204
DummyPeerSet(Application &app)
Definition: PeerSet.cpp:190
const std::set< Peer::id_t > & getPeerIds() const override
get the set of ids of previously added peers
Definition: PeerSet.cpp:213
beast::Journal j_
Definition: PeerSet.cpp:221
bool shouldProcessForPeer(uint256 const &key, PeerShortID peer, std::chrono::seconds interval)
Determines whether the hashed item should be processed for the given peer.
Definition: HashRouter.cpp:94
virtual std::shared_ptr< Peer > findPeerByShortID(Peer::id_t const &id) const =0
Returns the peer with the matching short id, or null.
virtual std::unique_ptr< PeerSet > build() override
Definition: PeerSet.cpp:172
PeerSetBuilderImpl(Application &app)
Definition: PeerSet.cpp:167
PeerSetImpl(Application &app)
Definition: PeerSet.cpp:60
void addPeers(std::size_t limit, std::function< bool(std::shared_ptr< Peer > const &)> hasItem, std::function< void(std::shared_ptr< Peer > const &)> onPeerAdded) override
Try add more peers.
Definition: PeerSet.cpp:66
void sendRequest(::google::protobuf::Message const &message, protocol::MessageType type, std::shared_ptr< Peer > const &peer) override
Send a message to one or all peers.
Definition: PeerSet.cpp:103
const std::set< Peer::id_t > & getPeerIds() const override
get the set of ids of previously added peers
Definition: PeerSet.cpp:159
beast::Journal journal_
Definition: PeerSet.cpp:54
std::set< Peer::id_t > peers_
The identifiers of the peers we are tracking.
Definition: PeerSet.cpp:57
Application & app_
Definition: PeerSet.cpp:53
Supports data retrieval by managing a set of peers.
Definition: PeerSet.h:45
An immutable linear range of bytes.
Definition: Slice.h:45
T emplace_back(T... args)
T end(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::string protocolMessageName(int type)
Returns the name of a protocol message given its type.
std::unique_ptr< PeerSet > make_DummyPeerSet(Application &app)
Make a dummy PeerSet that does not do anything.
Definition: PeerSet.cpp:225
std::unique_ptr< PeerSetBuilder > make_PeerSetBuilder(Application &app)
Definition: PeerSet.cpp:182
@ accepted
Manifest is valid.
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition: digest.h:223
T reserve(T... args)
T sort(T... args)