27 #include <boost/integer/static_log2.hpp> 65 std::list<std::pair<NodeID, NodeTableEventType>> events;
68 if (!m_nodeEventHandler.size())
70 m_nodeEventHandler.unique();
71 for (
auto const& n: m_nodeEventHandler)
72 events.push_back(std::make_pair(n,m_events[n]));
73 m_nodeEventHandler.clear();
76 for (
auto const&
e: events)
77 processEvent(
e.first,
e.second);
85 std::unordered_map<NodeID, NodeTableEventType>
m_events;
144 void processEvents();
147 std::shared_ptr<NodeEntry> addNode(
Node const& _node,
NodeRelation _relation = NodeRelation::Unknown);
150 std::list<NodeID> nodes()
const;
153 unsigned count()
const {
return m_nodes.size(); }
156 std::list<NodeEntry> snapshot()
const;
164 #if defined(BOOST_AUTO_TEST_SUITE) || defined(_MSC_VER) // MSVC includes access specifier in symbol name 173 static unsigned const s_bits = 8 * s_addressByteSize;
174 static unsigned const s_bins = s_bits - 1;
175 static unsigned const s_maxSteps = boost::static_log2<s_bits>::value;
179 static unsigned const s_bucketSize = 16;
180 static unsigned const s_alpha = 3;
185 std::chrono::milliseconds
const c_evictionCheckInterval = std::chrono::milliseconds(75);
186 std::chrono::milliseconds
const c_reqTimeout = std::chrono::milliseconds(300);
187 std::chrono::milliseconds
const c_bucketRefresh = std::chrono::milliseconds(7200);
192 std::list<std::weak_ptr<NodeEntry>>
nodes;
205 std::shared_ptr<NodeEntry> nodeEntry(
NodeID _id);
209 void doDiscover(
NodeID _target,
unsigned _round = 0, std::shared_ptr<std::set<std::shared_ptr<NodeEntry>>> _tried = std::shared_ptr<std::set<std::shared_ptr<NodeEntry>>>());
212 std::vector<std::shared_ptr<NodeEntry>> nearestNodeEntries(
NodeID _target);
215 void evict(std::shared_ptr<NodeEntry> _leastSeen, std::shared_ptr<NodeEntry> _new);
218 void noteActiveNode(
Public const& _pubk, bi::udp::endpoint
const& _endpoint);
221 void dropNode(std::shared_ptr<NodeEntry> _n);
239 void doCheckEvictions();
250 std::unordered_map<NodeID, std::shared_ptr<NodeEntry>>
m_nodes;
275 _out << n.address() <<
"\t" << n.distance <<
"\t" << n.endpoint.address <<
":" << n.endpoint.udpPort << std::endl;
294 bool isExpired()
const {
return secondsSinceEpoch() > ts; }
297 static std::unique_ptr<DiscoveryDatagram> interpretUDP(bi::udp::endpoint
const& _from,
bytesConstRef _packet);
333 version = r[0].
toInt<
unsigned>();
336 ts = r[3].
toInt<uint32_t>();
365 ts = r[2].
toInt<uint32_t>();
399 ts = r[1].
toInt<uint32_t>();
408 Neighbours(bi::udp::endpoint _to, std::vector<std::shared_ptr<NodeEntry>>
const& _nearest,
unsigned _offset = 0,
unsigned _limit = 0):
DiscoveryDatagram(_to)
410 auto limit = _limit ?
std::min(_nearest.size(), (size_t)(_offset + _limit)) : _nearest.size();
411 for (
auto i = _offset; i < limit; i++)
412 neighbours.push_back(
Neighbour(*_nearest[i]));
435 for (
auto const& n: neighbours)
442 for (
auto const& n: r[0])
443 neighbours.emplace_back(n);
444 ts = r[1].toInt<uint32_t>();
void setEventHandler(NodeTableEventHandler *_handler)
Set event handler for NodeEntryAdded and NodeEntryDropped events.
void streamRLP(RLPStream &_s, RLPAppend _append=StreamList) const
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
std::list< NodeIdTimePoint > m_findNodeTimeout
Timeouts for pending Ping and FindNode requests.
void interpretRLP(RLP const &_r)
void streamRLP(RLPStream &_s) const
Neighbours(bi::udp::endpoint const &_from, NodeID const &_fromid, h256 const &_echo)
std::pair< NodeIdTimePoint, NodeID > EvictionTimeout
First NodeID (NodeIdTimePoint) may be evicted and replaced with second NodeID.
NodeIPEndpoint destination
PingNode(bi::udp::endpoint const &_from, NodeID const &_fromid, h256 const &_echo)
void interpretRLP(bytesConstRef _bytes)
Node m_node
This node. LOCK x_state if endpoint access or mutation is required. Do not modify id...
UDP Interface Handler must implement UDPSocketEvents.
Simple class that represents a "key pair".
void interpretRLP(bytesConstRef _bytes)
std::unordered_map< NodeID, NodeTableEventType > m_events
NodeEntry center() const
Returns center node entry which describes this node and used with dist() to calculate xor metric for ...
std::chrono::steady_clock::time_point TimePoint
Steady time point.
uint8_t packetType() const
std::unordered_map< bi::address, TimePoint > m_pubkDiscoverPings
List of pending pings where node entry wasn't created due to unkown pubk.
std::pair< NodeID, TimePoint > NodeIdTimePoint
std::hash for asio::adress
bool pending
Node will be ignored until Pong is received.
const unsigned c_protocolVersion
Peer network protocol version.
NodeSocket * m_socketPointer
Set to m_socket.get(). Socket is created in constructor and disconnected in destructor to ensure acce...
std::list< NodeID > m_nodeEventHandler
unsigned const distance
Node's distance (xor of _src as integer).
FindNode(bi::udp::endpoint const &_from, NodeID const &_fromid, h256 const &_echo)
static unsigned distance(NodeID const &_a, NodeID const &_b)
Returns distance based on xor metric two node ids. Used by NodeEntry and NodeTable.
Mutex x_pubkDiscoverPings
LOCK x_nodes first if both x_nodes and x_pubkDiscoverPings locks are required.
_N toHash(int _flags=Strict) const
std::list< std::weak_ptr< NodeEntry > > nodes
Ping packet: Sent to check if node is alive.
Pong(bi::udp::endpoint const &_from, NodeID const &_fromid, h256 const &_echo)
std::lock_guard< std::mutex > Guard
void interpretRLP(bytesConstRef _bytes)
void streamRLP(RLPStream &_s) const
void processEvents()
Called by NodeTable on behalf of an implementation (Host) to process new events without blocking node...
NodeTable using modified kademlia for node discovery and preference.
std::shared_ptr< NodeSocket > m_socket
Shared pointer for our UDPSocket; ASIO requires shared_ptr.
uint8_t packetType() const
PingNode(NodeIPEndpoint const &_src, NodeIPEndpoint const &_dest)
RLPStream & appendList(size_t _items)
Appends a list.
Mutex x_evictions
LOCK x_evictions first if both x_nodes and x_evictions locks are required.
Mutex x_nodes
LOCK x_state first if both locks are required. Mutable for thread-safe copy in nodes() const...
RLPX Datagram which can be signed.
UniValue ping(const JSONRPCRequest &request)
bool haveNode(NodeID const &_id)
Returns true if node id is in node table.
DiscoveryDatagram(bi::udp::endpoint const &_to)
Constructor used for sending.
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void >> u256
Pong(NodeIPEndpoint const &_dest)
std::unique_ptr< NodeTableEventHandler > m_nodeEventHandler
Event handler for node events.
std::vector< Neighbour > neighbours
DeadlineOps m_timers
this should be the last member - it must be destroyed first
PlatformStyle::TableColorType type
virtual NodeID const & address() const
void streamRLP(RLPStream &_s) const
Secret m_secret
This nodes secret key.
FindNode(bi::udp::endpoint _to, h512 _target)
clock::time_point time_point
bool sha3(bytesConstRef _input, bytesRef o_output)
Calculate SHA3-256 hash of the given input and load it into the given output.
DiscoveryDatagram(bi::udp::endpoint const &_from, NodeID const &_fromid, h256 const &_echo)
Constructor used for parsing inbound packets.
unsigned count() const
Returns node count.
void interpretRLP(bytesConstRef _bytes)
uint8_t packetType() const
The default logging channels.
Neighbours(bi::udp::endpoint const &_to)
void streamRLP(RLPStream &_s) const
std::array< NodeBucket, s_bins > m_state
State of p2p node network.
Interface which UDPSocket will implement.
Neighbour(Node const &_node)
Pong packet: Sent in response to ping.
void onDisconnected(UDPSocketFace *)
Called by m_socket when socket is disconnected.
uint8_t packetType() const
std::ostream & operator<<(std::ostream &_out, NodeTable const &_nodeTable)
_T toInt(int _flags=Strict) const
Converts to int of type given; if isString(), decodes as big-endian bytestream.
Class for writing to an RLP bytestream.
virtual void appendEvent(NodeID _n, NodeTableEventType _e)
Called by NodeTable to append event.
UniValue echo(const JSONRPCRequest &request)
Class for interpreting Recursive Linear-Prefix Data.
Neighbours(bi::udp::endpoint _to, std::vector< std::shared_ptr< NodeEntry >> const &_nearest, unsigned _offset=0, unsigned _limit=0)
NodeIPEndpoint destination
Mutex x_state
LOCK x_state first if both x_nodes and x_state locks are required.
FindNode Packet: Request k-nodes, closest to the target.
std::list< NodeEntry > snapshot() const
Returns snapshot of table.
std::unordered_map< NodeID, std::shared_ptr< NodeEntry > > m_nodes
Known Node Endpoints.
NodeEntry(NodeID const &_src, Public const &_pubk, NodeIPEndpoint const &_gw)
std::deque< EvictionTimeout > m_evictions
Eviction timeouts.
Node Packet: One or more node packets are sent in response to FindNode.
NodeIPEndpoint endpoint
Endpoints by which we expect to reach node.
Interface which a UDPSocket's owner must implement.
void streamRLP(RLPStream &_s) const