@ -100,23 +100,15 @@ inline std::ostream& operator<<(std::ostream& _out, NodeTable const& _nodeTable)
* NodeTable accepts a port for UDP and will listen to the port on all available
* interfaces .
*
*
* [ Integration ]
* @ todo TCP endpoints
* @ todo GC uniform 1 / 32 entires at 112500 ms interval
*
* [ Optimization ]
* @ todo serialize evictions per - bucket
* @ todo store evictions in map , unit - test eviction logic
* @ todo store root node in table
* @ todo encapsulate discover into NetworkAlgorithm ( task )
* @ todo Pong to include ip : port where ping was received
* @ todo expiration and sha3 ( id ) ' to ' for messages which are replies ( prevents replay )
* @ todo cache Ping and FindSelf
*
* [ Networking ]
* @ todo node - endpoint updates
* @ todo TCP endpoints
* @ todo eth / upnp / natpmp / stun / ice / etc for public - discovery
* @ todo firewall
*
@ -131,7 +123,7 @@ class NodeTable: UDPSocketEvents, public std::enable_shared_from_this<NodeTable>
using TimePoint = std : : chrono : : steady_clock : : time_point ; ///< Steady time point.
using NodeIdTimePoint = std : : pair < NodeId , TimePoint > ;
using EvictionTimeout = std : : pair < NodeIdTimePoint , NodeId > ; ///< First NodeId (NodeIdTimePoint) may be evicted and replaced with second NodeId.
public :
enum NodeRelation { Unknown = 0 , Known } ;
@ -148,9 +140,6 @@ public:
/// Called by implementation which provided handler to process NodeEntryAdded/NodeEntryDropped events. Events are coalesced by type whereby old events are ignored.
void processEvents ( ) ;
/// Add node. Node will be pinged and empty shared_ptr is returned if NodeId is uknown.
std : : shared_ptr < NodeEntry > addNode ( Public const & _pubk , NodeIPEndpoint const & _ep ) ;
/// Add node. Node will be pinged and empty shared_ptr is returned if node has never been seen or NodeId is empty.
std : : shared_ptr < NodeEntry > addNode ( Node const & _node , NodeRelation _relation = NodeRelation : : Unknown ) ;
@ -206,7 +195,7 @@ private:
} ;
/// Used to ping endpoint.
void ping ( bi : : udp : : e ndpoint _to ) const ;
void ping ( NodeIPE ndpoint _to ) const ;
/// Used ping known node. Used by node table when refreshing buckets and as part of eviction process (see evict).
void ping ( NodeEntry * _n ) const ;
@ -301,30 +290,21 @@ struct InvalidRLP: public Exception {};
* a given bucket which is full , the least - responsive node is pinged .
* If the pinged node doesn ' t respond , then it is removed and the new
* node is inserted .
*
* RLP Encoded Items : 3
* Minimum Encoded Size : 18 bytes
* Maximum Encoded Size : bytes // todo after u128 addresses
*
* signature : Signature of message .
* ipAddress : Our IP address .
* port : Our port .
*
* @ todo uint128_t for ip address ( < - > integer ipv4 / 6 , asio - address , asio - endpoint )
*
*/
struct PingNode : RLPXDatagram < PingNode >
{
PingNode ( bi : : udp : : endpoint _ep ) : RLPXDatagram < PingNode > ( _ep ) { }
PingNode ( bi : : udp : : endpoint _ep , std : : string _src , uint16_t _srcPort , std : : chrono : : seconds _ts = std : : chrono : : seconds ( 60 ) ) : RLPXDatagram < PingNode > ( _ep ) , ipAddress ( _src ) , tcpPort ( _srcPort ) , ts ( futureFromEpoch ( _ts ) ) { }
/// Constructor used for sending PingNode.
PingNode ( NodeIPEndpoint _src , NodeIPEndpoint _dest ) : RLPXDatagram < PingNode > ( _dest ) , source ( _src ) , destination ( _dest ) , ts ( futureFromEpoch ( std : : chrono : : seconds ( 60 ) ) ) { }
/// Constructor used to create empty PingNode for parsing inbound packets.
PingNode ( bi : : udp : : endpoint _ep ) : RLPXDatagram < PingNode > ( _ep ) , source ( UnspecifiedNodeIPEndpoint ) , destination ( UnspecifiedNodeIPEndpoint ) { }
static const uint8_t type = 1 ;
unsigned version = 0 ;
std : : string ipAddress ;
// uint16_t udpPort;
uint16_t tcpPort ;
unsigned ts ;
NodeIPEndpoint source ;
NodeIPEndpoint destination ;
uint32_t ts = 0 ;
void streamRLP ( RLPStream & _s ) const override ;
void interpretRLP ( bytesConstRef _bytes ) override ;
@ -332,22 +312,20 @@ struct PingNode: RLPXDatagram<PingNode>
/**
* Pong packet : Sent in response to ping
*
* RLP Encoded Items : 2
* Minimum Encoded Size : 33 bytes
* Maximum Encoded Size : 33 bytes
*/
struct Pong : RLPXDatagram < Pong >
{
Pong ( bi : : udp : : endpoint _ep ) : RLPXDatagram < Pong > ( _ep ) , ts ( futureFromEpoch ( std : : chrono : : seconds ( 60 ) ) ) { }
Pong ( bi : : udp : : endpoint const & _ep ) : RLPXDatagram < Pong > ( _ep ) , destination ( UnspecifiedNodeIPEndpoint ) { }
Pong ( NodeIPEndpoint const & _dest ) : RLPXDatagram < Pong > ( ( bi : : udp : : endpoint ) _dest ) , destination ( _dest ) , ts ( futureFromEpoch ( std : : chrono : : seconds ( 60 ) ) ) { }
static const uint8_t type = 2 ;
NodeIPEndpoint destination ;
h256 echo ; ///< MCD of PingNode
unsigned ts ;
uint32_t ts = 0 ;
void streamRLP ( RLPStream & _s ) const { _s . appendList ( 2 ) ; _s < < echo < < ts ; }
void interpretRLP ( bytesConstRef _bytes ) { RLP r ( _bytes ) ; echo = ( h256 ) r [ 0 ] ; ts = r [ 1 ] . toInt < unsigned > ( ) ; }
void streamRLP ( RLPStream & _s ) const ;
void interpretRLP ( bytesConstRef _bytes ) ;
} ;
/**
@ -365,58 +343,63 @@ struct Pong: RLPXDatagram<Pong>
struct FindNode : RLPXDatagram < FindNode >
{
FindNode ( bi : : udp : : endpoint _ep ) : RLPXDatagram < FindNode > ( _ep ) { }
FindNode ( bi : : udp : : endpoint _ep , NodeId _target , std : : chrono : : seconds _ts = std : : chrono : : seconds ( 60 ) ) : RLPXDatagram < FindNode > ( _ep ) , target ( _target ) , ts ( futureFromEpoch ( _ts ) ) { }
FindNode ( bi : : udp : : endpoint _ep , NodeId _target ) : RLPXDatagram < FindNode > ( _ep ) , target ( _target ) , ts ( futureFromEpoch ( std : : chrono : : seconds ( 60 ) ) ) { }
static const uint8_t type = 3 ;
h512 target ;
unsigned ts ;
uint32_t ts = 0 ;
void streamRLP ( RLPStream & _s ) const { _s . appendList ( 2 ) ; _s < < target < < ts ; }
void interpretRLP ( bytesConstRef _bytes ) { RLP r ( _bytes ) ; target = r [ 0 ] . toHash < h512 > ( ) ; ts = r [ 1 ] . toInt < unsigned > ( ) ; }
void interpretRLP ( bytesConstRef _bytes ) { RLP r ( _bytes ) ; target = r [ 0 ] . toHash < h512 > ( ) ; ts = r [ 1 ] . toInt < uint32_t > ( ) ; }
} ;
/**
* Node Packet : Multiple node packets are sent in response to FindNode .
*
* RLP Encoded Items : 2 ( first item is list )
* Minimum Encoded Size : 10 bytes
* Node Packet : One or more node packets are sent in response to FindNode .
*/
struct Neighbours : RLPXDatagram < Neighbours >
{
struct Node
struct Neighbour
{
Node ( ) = default ;
Node ( RLP const & _r ) { interpretRLP ( _r ) ; }
std : : string ipAddress ;
uint16_t udpPort ;
// uint16_t tcpPort;
Neighbour ( Node const & _node ) : endpoint ( _node . endpoint ) , node ( _node . id ) { }
Neighbour ( RLP const & _r ) : endpoint ( _r ) { node = h512 ( _r [ 3 ] . toBytes ( ) ) ; }
NodeIPEndpoint endpoint ;
NodeId node ;
void streamRLP ( RLPStream & _s ) const { _s . appendList ( 3 ) ; _s < < ipAddress < < udpPort < < node ; }
void interpretRLP ( RLP const & _r ) { ipAddress = _r [ 0 ] . toString ( ) ; udpPort = _r [ 1 ] . toInt < uint16_t > ( ) ; node = h512 ( _r [ 2 ] . toBytes ( ) ) ; }
void streamRLP ( RLPStream & _s ) const { _s . appendList ( 4 ) ; endpoint . streamRLP ( _s , NodeIPEndpoint : : StreamInline ) ; _s < < node ; }
} ;
Neighbours ( bi : : udp : : endpoint _ep ) : RLPXDatagram < Neighbours > ( _ep ) , ts ( futureFromEpoch ( std : : chrono : : seconds ( 30 ) ) ) { }
Neighbours ( bi : : udp : : endpoint _to , std : : vector < std : : shared_ptr < NodeEntry > > const & _nearest , unsigned _offset = 0 , unsigned _limit = 0 ) : RLPXDatagram < Neighbours > ( _to ) , ts ( futureFromEpoch ( std : : chrono : : seconds ( 3 0) ) )
Neighbours ( bi : : udp : : endpoint _ep ) : RLPXDatagram < Neighbours > ( _ep ) , ts ( secondsSinceEpoch ( ) ) { }
Neighbours ( bi : : udp : : endpoint _to , std : : vector < std : : shared_ptr < NodeEntry > > const & _nearest , unsigned _offset = 0 , unsigned _limit = 0 ) : RLPXDatagram < Neighbours > ( _to ) , ts ( futureFromEpoch ( std : : chrono : : seconds ( 6 0) ) )
{
auto limit = _limit ? std : : min ( _nearest . size ( ) , ( size_t ) ( _offset + _limit ) ) : _nearest . size ( ) ;
for ( auto i = _offset ; i < limit ; i + + )
{
Node node ;
node . ipAddress = _nearest [ i ] - > endpoint . address . to_string ( ) ;
node . udpPort = _nearest [ i ] - > endpoint . udpPort ;
node . node = _nearest [ i ] - > publicKey ( ) ;
nodes . push_back ( node ) ;
}
neighbours . push_back ( Neighbour ( * _nearest [ i ] ) ) ;
}
static const uint8_t type = 4 ;
std : : vector < Node > node s ;
unsigned ts = 1 ;
std : : vector < Neighbour > neighbours ;
uint32_t ts = 0 ;
void streamRLP ( RLPStream & _s ) const { _s . appendList ( 2 ) ; _s . appendList ( node s . size ( ) ) ; for ( auto & n : node s ) n . streamRLP ( _s ) ; _s < < ts ; }
void interpretRLP ( bytesConstRef _bytes ) { RLP r ( _bytes ) ; for ( auto n : r [ 0 ] ) node s . push_back ( Node ( n ) ) ; ts = r [ 1 ] . toInt < unsigned > ( ) ; }
void streamRLP ( RLPStream & _s ) const { _s . appendList ( 2 ) ; _s . appendList ( neighbour s . size ( ) ) ; for ( auto & n : neighbour s ) n . streamRLP ( _s ) ; _s < < ts ; }
void interpretRLP ( bytesConstRef _bytes ) { RLP r ( _bytes ) ; for ( auto n : r [ 0 ] ) neighbour s . push_back ( Neighbour ( n ) ) ; ts = r [ 1 ] . toInt < uint32_t > ( ) ; }
} ;
namespace compat
{
/**
* Pong packet [ compatability ] : Sent in response to ping
*/
struct Pong : RLPXDatagram < Pong >
{
Pong ( bi : : udp : : endpoint const & _ep ) : RLPXDatagram < Pong > ( _ep ) { }
Pong ( NodeIPEndpoint const & _dest ) : RLPXDatagram < Pong > ( ( bi : : udp : : endpoint ) _dest ) , ts ( futureFromEpoch ( std : : chrono : : seconds ( 60 ) ) ) { }
static const uint8_t type = 2 ;
h256 echo ;
uint32_t ts = 0 ;
void streamRLP ( RLPStream & _s ) const { _s . appendList ( 2 ) ; _s < < echo < < ts ; }
void interpretRLP ( bytesConstRef _bytes ) ;
} ;
}
struct NodeTableWarn : public LogChannel { static const char * name ( ) ; static const int verbosity = 0 ; } ;
struct NodeTableNote : public LogChannel { static const char * name ( ) ; static const int verbosity = 1 ; } ;