diff --git a/libp2p/Host.h b/libp2p/Host.h index b24f1343c..baf8f0585 100644 --- a/libp2p/Host.h +++ b/libp2p/Host.h @@ -37,6 +37,7 @@ #include "NodeTable.h" #include "HostCapability.h" #include "Network.h" +#include "Peer.h" #include "Common.h" namespace ba = boost::asio; namespace bi = ba::ip; @@ -44,81 +45,11 @@ namespace bi = ba::ip; namespace dev { -class RLPStream; - namespace p2p { class Host; -/** - * @brief Representation of connectivity state and all other pertinent Peer metadata. - * A Peer represents connectivity between two nodes, which in this case, are the host - * and remote nodes. - * - * State information necessary for loading network topology is maintained by NodeTable. - * - * @todo Implement 'bool required' - * @todo reputation: Move score, rating to capability-specific map (&& remove friend class) - * @todo reputation: implement via origin-tagged events - * @todo Populate metadata upon construction; save when destroyed. - * @todo Metadata for peers needs to be handled via a storage backend. - * Specifically, peers can be utilized in a variety of - * many-to-many relationships while also needing to modify shared instances of - * those peers. Modifying these properties via a storage backend alleviates - * Host of the responsibility. (&& remove save/restoreNetwork) - * @todo reimplement recording of historical session information on per-transport basis - * @todo rebuild nodetable when localNetworking is enabled/disabled - * @todo move attributes into protected - */ -class Peer: public Node -{ - friend class Session; /// Allows Session to update score and rating. - friend class Host; /// For Host: saveNetwork(), restoreNetwork() -public: - bool isOffline() const { return !m_session.lock(); } - - bi::tcp::endpoint const& peerEndpoint() const { return endpoint.tcp; } - - int m_score = 0; ///< All time cumulative. - int m_rating = 0; ///< Trending. - - /// Network Availability - - std::chrono::system_clock::time_point m_lastConnected; - std::chrono::system_clock::time_point m_lastAttempted; - unsigned m_failedAttempts = 0; - DisconnectReason m_lastDisconnect = NoDisconnect; ///< Reason for disconnect that happened last. - - virtual bool operator<(Peer const& _p) const - { - if (isOffline() != _p.isOffline()) - return isOffline(); - else if (isOffline()) - if (m_lastAttempted == _p.m_lastAttempted) - return m_failedAttempts < _p.m_failedAttempts; - else - return m_lastAttempted < _p.m_lastAttempted; - else - if (m_score == _p.m_score) - if (m_rating == _p.m_rating) - if (m_failedAttempts == _p.m_failedAttempts) - return id < _p.id; - else - return m_failedAttempts < _p.m_failedAttempts; - else - return m_rating < _p.m_rating; - else - return m_score < _p.m_score; - } - -protected: - /// Used by isOffline() and (todo) for peer to emit session information. - std::weak_ptr m_session; -}; -using Peers = std::vector; - - class HostNodeTableHandler: public NodeTableEventHandler { public: @@ -131,7 +62,7 @@ private: Host& m_host; }; - + /** * @brief The Host class * Capabilities should be registered prior to startNetwork, since m_capabilities is not thread-safe. diff --git a/libp2p/Peer.cpp b/libp2p/Peer.cpp new file mode 100644 index 000000000..1811da930 --- /dev/null +++ b/libp2p/Peer.cpp @@ -0,0 +1,57 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file Peer.cpp + * @author Alex Leverington + * @author Gav Wood + * @date 2014 + */ + +#include "Peer.h" +using namespace std; +using namespace dev; +using namespace dev::p2p; + +namespace dev +{ + +namespace p2p +{ + +bool Peer::operator<(Peer const& _p) const +{ + if (isOffline() != _p.isOffline()) + return isOffline(); + else if (isOffline()) + if (m_lastAttempted == _p.m_lastAttempted) + return m_failedAttempts < _p.m_failedAttempts; + else + return m_lastAttempted < _p.m_lastAttempted; + else + if (m_score == _p.m_score) + if (m_rating == _p.m_rating) + if (m_failedAttempts == _p.m_failedAttempts) + return id < _p.id; + else + return m_failedAttempts < _p.m_failedAttempts; + else + return m_rating < _p.m_rating; + else + return m_score < _p.m_score; +} + +} +} diff --git a/libp2p/Peer.h b/libp2p/Peer.h new file mode 100644 index 000000000..f3db9d7e1 --- /dev/null +++ b/libp2p/Peer.h @@ -0,0 +1,82 @@ +/* + This file is part of cpp-ethereum. + + cpp-ethereum is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + cpp-ethereum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with cpp-ethereum. If not, see . +*/ +/** @file Peer.h + * @author Alex Leverington + * @author Gav Wood + * @date 2014 + */ + +#pragma once + +#include "Common.h" + +namespace dev +{ + +namespace p2p +{ + +/** + * @brief Representation of connectivity state and all other pertinent Peer metadata. + * A Peer represents connectivity between two nodes, which in this case, are the host + * and remote nodes. + * + * State information necessary for loading network topology is maintained by NodeTable. + * + * @todo Implement 'bool required' + * @todo reputation: Move score, rating to capability-specific map (&& remove friend class) + * @todo reputation: implement via origin-tagged events + * @todo Populate metadata upon construction; save when destroyed. + * @todo Metadata for peers needs to be handled via a storage backend. + * Specifically, peers can be utilized in a variety of + * many-to-many relationships while also needing to modify shared instances of + * those peers. Modifying these properties via a storage backend alleviates + * Host of the responsibility. (&& remove save/restoreNetwork) + * @todo reimplement recording of historical session information on per-transport basis + * @todo rebuild nodetable when localNetworking is enabled/disabled + * @todo move attributes into protected + */ +class Peer: public Node +{ + friend class Session; /// Allows Session to update score and rating. + friend class Host; /// For Host: saveNetwork(), restoreNetwork() + +public: + bool isOffline() const { return !m_session.lock(); } + + bi::tcp::endpoint const& peerEndpoint() const { return endpoint.tcp; } + + virtual bool operator<(Peer const& _p) const; + +protected: + int m_score = 0; ///< All time cumulative. + int m_rating = 0; ///< Trending. + + /// Network Availability + + std::chrono::system_clock::time_point m_lastConnected; + std::chrono::system_clock::time_point m_lastAttempted; + unsigned m_failedAttempts = 0; + DisconnectReason m_lastDisconnect = NoDisconnect; ///< Reason for disconnect that happened last. + + /// Used by isOffline() and (todo) for peer to emit session information. + std::weak_ptr m_session; +}; +using Peers = std::vector; + +} +} diff --git a/test/whisperTopic.cpp b/test/whisperTopic.cpp index ab0cdc115..be93174ec 100644 --- a/test/whisperTopic.cpp +++ b/test/whisperTopic.cpp @@ -243,17 +243,20 @@ BOOST_AUTO_TEST_CASE(asyncforwarding) }); while (!startedForwarder) - this_thread::sleep_for(chrono::milliseconds(50)); - - Host host2("Sender", NetworkPreferences(30300, "", false, true)); - host2.setIdealPeerCount(1); - shared_ptr whost2 = host2.registerCapability(new WhisperHost()); - host2.start(); - while (!host2.isStarted()) this_thread::sleep_for(chrono::milliseconds(2)); - host2.addNode(host1.id(), "127.0.0.1", 30305, 30305); { + Host host2("Sender", NetworkPreferences(30300, "", false, true)); + host2.setIdealPeerCount(1); + shared_ptr whost2 = host2.registerCapability(new WhisperHost()); + host2.start(); + while (!host2.isStarted()) + this_thread::sleep_for(chrono::milliseconds(2)); + host2.addNode(host1.id(), "127.0.0.1", 30305, 30305); + + while (!host2.peerCount()) + this_thread::sleep_for(chrono::milliseconds(5)); + KeyPair us = KeyPair::create(); whost2->post(us.sec(), RLPStream().append(1).out(), BuildTopic("test")); this_thread::sleep_for(chrono::milliseconds(250));