diff --git a/libp2p/Host.cpp b/libp2p/Host.cpp index 392d02dc4..5f756f2a5 100644 --- a/libp2p/Host.cpp +++ b/libp2p/Host.cpp @@ -401,7 +401,7 @@ void Host::connect(NodeId const& _node, std::string const& _addr, unsigned short assert(_node); - auto n = m_nodes[_node]; + auto n = (*m_nodeTable)[_node]; // TODO: refactor into async_resolve m_ioService.post([=]() @@ -619,14 +619,8 @@ void Host::run(boost::system::error_code const&) if (auto pp = p.second.lock()) pp->serviceNodesRequest(); - if (chrono::steady_clock::now() - m_lastPing > chrono::seconds(30)) // ping every 30s. - { - for (auto p: m_peers) - if (auto pp = p.second.lock()) - if (chrono::steady_clock::now() - pp->m_lastReceived > chrono::seconds(60)) - pp->disconnect(PingTimeout); - pingAll(); - } + if (chrono::steady_clock::now() - m_lastPing >= chrono::seconds(30)) // ping every 30s. + keepAlivePeers(); auto runcb = [this](boost::system::error_code const& error) -> void { run(error); }; m_timer->expires_from_now(boost::posix_time::milliseconds(c_timerInterval)); @@ -680,12 +674,18 @@ void Host::doWork() m_ioService.run(); } -void Host::pingAll() +void Host::keepAlivePeers() { RecursiveGuard l(x_peers); - for (auto& i: m_peers) - if (auto j = i.second.lock()) - j->ping(); + for (auto p: m_peers) + if (auto pp = p.second.lock()) + { + if (chrono::steady_clock::now() - pp->m_lastReceived >= chrono::seconds(60)) + pp->disconnect(PingTimeout); + else + pp->ping(); + } + m_lastPing = chrono::steady_clock::now(); } diff --git a/libp2p/Host.h b/libp2p/Host.h index edfa79df3..5892b5b0d 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -165,8 +165,8 @@ public: /// Get number of peers connected; equivalent to, but faster than, peers().size(). size_t peerCount() const { RecursiveGuard l(x_peers); return m_peers.size(); } - /// Ping the peers, to update the latency information. - void pingAll(); + /// Ping the peers to update the latency information and disconnect peers which have timed out. + void keepAlivePeers(); /// Get the port we're listening on currently. unsigned short listenPort() const { return m_tcpPublic.port(); } diff --git a/libp2p/NodeTable.cpp b/libp2p/NodeTable.cpp index 53acc9dbe..1b74abbda 100644 --- a/libp2p/NodeTable.cpp +++ b/libp2p/NodeTable.cpp @@ -77,10 +77,11 @@ list NodeTable::state() const return move(ret); } -NodeEntry NodeTable::operator[](NodeId _id) +Node NodeTable::operator[](NodeId _id) { Guard l(x_nodes); - return *m_nodes[_id]; + auto n = m_nodes[_id]; + return !!n ? *n : Node(); } void NodeTable::requestNeighbours(NodeEntry const& _node, NodeId _target) const diff --git a/libp2p/NodeTable.h b/libp2p/NodeTable.h index 89bd68be1..79ce6a9e3 100644 --- a/libp2p/NodeTable.h +++ b/libp2p/NodeTable.h @@ -36,16 +36,20 @@ namespace p2p */ struct NodeIPEndpoint { + NodeIPEndpoint(): udp(bi::udp::endpoint()), tcp(bi::tcp::endpoint()) {} NodeIPEndpoint(bi::udp::endpoint _udp): udp(_udp) {} NodeIPEndpoint(bi::tcp::endpoint _tcp): tcp(_tcp) {} NodeIPEndpoint(bi::udp::endpoint _udp, bi::tcp::endpoint _tcp): udp(_udp), tcp(_tcp) {} bi::udp::endpoint udp; bi::tcp::endpoint tcp; + + operator bool() const { return udp.address().is_unspecified() && tcp.address().is_unspecified(); } }; struct Node { + Node(): endpoint(NodeIPEndpoint()) {}; Node(Public _pubk, NodeIPEndpoint _ip, bool _required = false): id(_pubk), endpoint(_ip), required(_required) {} Node(Public _pubk, bi::udp::endpoint _udp, bool _required = false): Node(_pubk, NodeIPEndpoint(_udp), _required) {} @@ -59,6 +63,8 @@ struct Node /// If true, node will not be removed from Node list. bool required = false; + + operator bool() const { return (bool)id; } }; @@ -151,7 +157,7 @@ public: std::list nodes() const; std::list state() const; - NodeEntry operator[](NodeId _id); + Node operator[](NodeId _id); protected: struct NodeBucket diff --git a/test/peer.cpp b/test/peer.cpp index 70d03e9bf..d13ea97f3 100644 --- a/test/peer.cpp +++ b/test/peer.cpp @@ -55,7 +55,7 @@ int peerTest(int argc, char** argv) { this_thread::sleep_for(chrono::milliseconds(100)); if (!(i % 10)) - ph.pingAll(); + ph.keepAlivePeers(); } return 0;