diff --git a/libp2p/NodeTable.cpp b/libp2p/NodeTable.cpp index 8024f0151..64aabc2bb 100644 --- a/libp2p/NodeTable.cpp +++ b/libp2p/NodeTable.cpp @@ -306,7 +306,7 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes // h256 + Signature + RLP if (_packet.size() < 100) { - clog(NodeTableMessageSummary) << "Invalid Message size received from " << _from.address().to_string() << ":" << _from.port(); + clog(NodeTableMessageSummary) << "Invalid Message size from " << _from.address().to_string() << ":" << _from.port(); return; } @@ -314,11 +314,10 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes h256 hashSigned(sha3(signedBytes)); if (!_packet.cropped(0, h256::size).contentsEqual(hashSigned.asBytes())) { - clog(NodeTableMessageSummary) << "Invalid Message hash received from " << _from.address().to_string() << ":" << _from.port(); + clog(NodeTableMessageSummary) << "Invalid Message hash from " << _from.address().to_string() << ":" << _from.port(); return; } - - // 3 items is PingNode, 2 items w/no lists is FindNode, 2 items w/first item as list is Neighbors, 1 item is Pong + bytesConstRef rlpBytes(signedBytes.cropped(Signature::size, signedBytes.size() - Signature::size)); RLP rlp(rlpBytes); unsigned itemCount = rlp.itemCount(); @@ -327,7 +326,7 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes Public nodeid(dev::recover(*(Signature const*)sigBytes.data(), sha3(rlpBytes))); if (!nodeid) { - clog(NodeTableMessageSummary) << "Invalid Message Signature from " << _from.address().to_string() << ":" << _from.port(); + clog(NodeTableMessageSummary) << "Invalid Message signature from " << _from.address().to_string() << ":" << _from.port(); return; } noteNode(nodeid, _from); @@ -347,7 +346,6 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes case 2: if (rlp[0].isList()) { - // todo: chunk neighbors packet Neighbors in = Neighbors::fromBytesConstRef(_from, rlpBytes); clog(NodeTableMessageSummary) << "Received " << in.nodes.size() << " Neighbors from " << _from.address().to_string() << ":" << _from.port(); for (auto n: in.nodes) @@ -359,9 +357,13 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes FindNode in = FindNode::fromBytesConstRef(_from, rlpBytes); std::vector> nearest = findNearest(in.target); - Neighbors out(_from, nearest); - out.sign(m_secret); - m_socketPtr->send(out); + static unsigned const nlimit = (m_socketPtr->maxDatagramSize - 11) / 86; + for (unsigned offset = 0; offset < nearest.size(); offset += nlimit) + { + Neighbors out(_from, nearest, offset, nlimit); + out.sign(m_secret); + m_socketPtr->send(out); + } } break; @@ -384,7 +386,7 @@ void NodeTable::onReceived(UDPSocketFace*, bi::udp::endpoint const& _from, bytes } catch (...) { - + // likely culprit is invalid rlp encoding } } diff --git a/libp2p/NodeTable.h b/libp2p/NodeTable.h index 399b48eaa..d8e886c31 100644 --- a/libp2p/NodeTable.h +++ b/libp2p/NodeTable.h @@ -21,6 +21,7 @@ #pragma once +#include #include #include #include @@ -109,15 +110,15 @@ public: /// Constants for Kademlia, mostly derived from address space. - static constexpr unsigned s_addressByteSize = sizeof(NodeEntry::id); ///< Size of address type in bytes. - static constexpr unsigned s_bits = 8 * s_addressByteSize; ///< Denoted by n in [Kademlia]. - static constexpr unsigned s_bins = s_bits - 1; ///< Size of m_state (excludes root, which is us). - static constexpr unsigned s_maxSteps = boost::static_log2::value; ///< Max iterations of discovery. (doFindNode) + static unsigned const s_addressByteSize = sizeof(NodeEntry::id); ///< Size of address type in bytes. + static unsigned const s_bits = 8 * s_addressByteSize; ///< Denoted by n in [Kademlia]. + static unsigned const s_bins = s_bits - 1; ///< Size of m_state (excludes root, which is us). + static unsigned const s_maxSteps = boost::static_log2::value; ///< Max iterations of discovery. (doFindNode) /// Chosen constants - static constexpr unsigned s_bucketSize = 16; ///< Denoted by k in [Kademlia]. Number of nodes stored in each bucket. - static constexpr unsigned s_alpha = 3; ///< Denoted by \alpha in [Kademlia]. Number of concurrent FindNode requests. + static unsigned const s_bucketSize = 16; ///< Denoted by k in [Kademlia]. Number of nodes stored in each bucket. + static unsigned const s_alpha = 3; ///< Denoted by \alpha in [Kademlia]. Number of concurrent FindNode requests. /// Intervals @@ -312,16 +313,26 @@ struct Neighbors: RLPXDatagram }; using RLPXDatagram::RLPXDatagram; - Neighbors(bi::udp::endpoint _to, std::vector> const& _nearest): RLPXDatagram(_to) + Neighbors(bi::udp::endpoint _to, std::vector> const& _nearest, unsigned _offset = 0, unsigned _limit = 0): RLPXDatagram(_to) { - for (auto& n: _nearest) + auto limit = _limit ? std::min(_nearest.size(), (size_t)(_offset + _limit)) : _nearest.size(); + for (auto i = _offset; i < limit; i++) { Node node; - node.ipAddress = n->endpoint.udp.address().to_string(); - node.port = n->endpoint.udp.port(); - node.node = n->publicKey(); + node.ipAddress = _nearest[i]->endpoint.udp.address().to_string(); + node.port = _nearest[i]->endpoint.udp.port(); + node.node = _nearest[i]->publicKey(); nodes.push_back(node); } + +// for (auto& n: _nearest) +// { +// Node node; +// node.ipAddress = n->endpoint.udp.address().to_string(); // 16 +// node.port = n->endpoint.udp.port(); // 3 +// node.node = n->publicKey();// 67 +// nodes.push_back(node); +// } } std::list nodes; diff --git a/libp2p/UDP.h b/libp2p/UDP.h index 82b89b9c8..6efe1908d 100644 --- a/libp2p/UDP.h +++ b/libp2p/UDP.h @@ -110,7 +110,7 @@ template class UDPSocket: UDPSocketFace, public std::enable_shared_from_this> { public: - static constexpr unsigned maxDatagramSize = MaxDatagramSize; + enum { maxDatagramSize = MaxDatagramSize }; static_assert(maxDatagramSize < 65507, "UDP datagrams cannot be larger than 65507 bytes"); UDPSocket(ba::io_service& _io, UDPSocketEvents& _host, unsigned _port): m_host(_host), m_endpoint(bi::udp::v4(), _port), m_socket(_io) { m_started.store(false); m_closed.store(true); };