WebThree.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /** @file WebThree.h
  15. * @author Gav Wood <i@gavwood.com>
  16. * @date 2014
  17. */
  18. #pragma once
  19. #include <thread>
  20. #include <mutex>
  21. #include <list>
  22. #include <atomic>
  23. #include <boost/asio.hpp> // Make sure boost/asio.hpp is included before windows.h.
  24. #include <boost/utility.hpp>
  25. #include <libdevcore/Common.h>
  26. #include <libdevcore/CommonIO.h>
  27. #include <libdevcore/Guards.h>
  28. #include <libdevcore/Exceptions.h>
  29. #include <libp2p/Host.h>
  30. #include <libwhisper/WhisperHost.h>
  31. #include <libethereum/Client.h>
  32. #include <libethereum/ChainParams.h>
  33. namespace dev
  34. {
  35. enum WorkState
  36. {
  37. Active = 0,
  38. Deleting,
  39. Deleted
  40. };
  41. namespace eth { class Interface; }
  42. namespace shh { class Interface; }
  43. namespace bzz { class Interface; class Client; }
  44. class Support;
  45. class NetworkFace
  46. {
  47. public:
  48. /// Get information concerning this node.
  49. virtual p2p::NodeInfo nodeInfo() const = 0;
  50. /// Get information on the current peer set.
  51. virtual std::vector<p2p::PeerSessionInfo> peers() = 0;
  52. /// Same as peers().size(), but more efficient.
  53. virtual size_t peerCount() const = 0;
  54. /// Generalised peer addition.
  55. virtual void addPeer(p2p::NodeSpec const& _node, p2p::PeerType _t) = 0;
  56. /// Add node to connect to.
  57. virtual void addNode(p2p::NodeID const& _node, bi::tcp::endpoint const& _hostEndpoint) = 0;
  58. /// Require connection to peer.
  59. virtual void requirePeer(p2p::NodeID const& _node, bi::tcp::endpoint const& _endpoint) = 0;
  60. /// Save peers
  61. virtual dev::bytes saveNetwork() = 0;
  62. /// Sets the ideal number of peers.
  63. virtual void setIdealPeerCount(size_t _n) = 0;
  64. virtual bool haveNetwork() const = 0;
  65. virtual p2p::NetworkPreferences const& networkPreferences() const = 0;
  66. virtual void setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers) = 0;
  67. virtual p2p::NodeID id() const = 0;
  68. /// Get network id
  69. virtual u256 networkId() const = 0;
  70. /// Gets the nodes.
  71. virtual p2p::Peers nodes() const = 0;
  72. /// Start the network subsystem.
  73. virtual void startNetwork() = 0;
  74. /// Stop the network subsystem.
  75. virtual void stopNetwork() = 0;
  76. /// Is network working? there may not be any peers yet.
  77. virtual bool isNetworkStarted() const = 0;
  78. /// Get enode string.
  79. virtual std::string enode() const = 0;
  80. };
  81. /**
  82. * @brief Main API hub for interfacing with Web 3 components. This doesn't do any local multiplexing, so you can only have one
  83. * running on any given machine for the provided DB path.
  84. *
  85. * Keeps a libp2p Host going (administering the work thread with m_workNet).
  86. *
  87. * Encapsulates a bunch of P2P protocols (interfaces), each using the same underlying libp2p Host.
  88. *
  89. * Provides a baseline for the multiplexed multi-protocol session class, WebThree.
  90. */
  91. class WebThreeDirect: public NetworkFace
  92. {
  93. public:
  94. /// Constructor for private instance. If there is already another process on the machine using @a _dbPath, then this will throw an exception.
  95. /// ethereum() may be safely static_cast()ed to a eth::Client*.
  96. WebThreeDirect(
  97. std::string const& _clientVersion,
  98. std::string const& _dbPath,
  99. eth::ChainParams const& _params,
  100. WithExisting _we = WithExisting::Trust,
  101. std::set<std::string> const& _interfaces = {"eth", "shh", "bzz"},
  102. p2p::NetworkPreferences const& _n = p2p::NetworkPreferences(),
  103. bytesConstRef _network = bytesConstRef(),
  104. bool _testing = false
  105. );
  106. /// Destructor.
  107. ~WebThreeDirect();
  108. // The mainline interfaces:
  109. eth::Client* ethereum() const { if (!m_ethereum) BOOST_THROW_EXCEPTION(InterfaceNotSupported("eth")); return m_ethereum.get(); }
  110. std::shared_ptr<shh::WhisperHost> whisper() const { auto w = m_whisper.lock(); if (!w) BOOST_THROW_EXCEPTION(InterfaceNotSupported("shh")); return w; }
  111. bzz::Interface* swarm() const;
  112. Support* support() const { return m_support.get(); }
  113. // Misc stuff:
  114. static std::string composeClientVersion(std::string const& _client);
  115. std::string const& clientVersion() const { return m_clientVersion; }
  116. void setClientVersion(std::string const& _name) { m_clientVersion = _name; }
  117. // Network stuff:
  118. /// Get information on the current peer set.
  119. std::vector<p2p::PeerSessionInfo> peers() override;
  120. /// Same as peers().size(), but more efficient.
  121. size_t peerCount() const override;
  122. /// Generalised peer addition.
  123. virtual void addPeer(p2p::NodeSpec const& _node, p2p::PeerType _t) override;
  124. /// Add node to connect to.
  125. virtual void addNode(p2p::NodeID const& _node, bi::tcp::endpoint const& _hostEndpoint) override;
  126. /// Add node to connect to.
  127. void addNode(p2p::NodeID const& _node, std::string const& _hostString) { addNode(_node, p2p::Network::resolveHost(_hostString)); }
  128. /// Add node to connect to.
  129. void addNode(bi::tcp::endpoint const& _endpoint) { addNode(p2p::NodeID(), _endpoint); }
  130. /// Add node to connect to.
  131. void addNode(std::string const& _hostString) { addNode(p2p::NodeID(), _hostString); }
  132. /// Require connection to peer.
  133. void requirePeer(p2p::NodeID const& _node, bi::tcp::endpoint const& _endpoint) override;
  134. /// Require connection to peer.
  135. void requirePeer(p2p::NodeID const& _node, std::string const& _hostString) { requirePeer(_node, p2p::Network::resolveHost(_hostString)); }
  136. /// Save peers
  137. dev::bytes saveNetwork() override;
  138. /// Sets the ideal number of peers.
  139. void setIdealPeerCount(size_t _n) override;
  140. /// Experimental. Sets ceiling for incoming connections to multiple of ideal peer count.
  141. void setPeerStretch(size_t _n);
  142. bool haveNetwork() const override { return m_net.haveNetwork(); }
  143. p2p::NetworkPreferences const& networkPreferences() const override;
  144. void setNetworkPreferences(p2p::NetworkPreferences const& _n, bool _dropPeers = false) override;
  145. p2p::NodeInfo nodeInfo() const override { return m_net.nodeInfo(); }
  146. p2p::NodeID id() const override { return m_net.id(); }
  147. u256 networkId() const override { return m_ethereum.get()->networkId(); }
  148. std::string enode() const override { return m_net.enode(); }
  149. /// Gets the nodes.
  150. p2p::Peers nodes() const override { return m_net.getPeers(); }
  151. /// Start the network subsystem.
  152. void startNetwork() override { m_net.start(); }
  153. /// Stop the network subsystem.
  154. void stopNetwork() override { m_net.stop(); }
  155. /// Is network working? there may not be any peers yet.
  156. bool isNetworkStarted() const override { return m_net.isStarted(); }
  157. private:
  158. std::string m_clientVersion; ///< Our end-application client's name/version.
  159. p2p::Host m_net; ///< Should run in background and send us events when blocks found and allow us to send blocks as required.
  160. std::unique_ptr<eth::Client> m_ethereum; ///< Client for Ethereum ("eth") protocol.
  161. std::weak_ptr<shh::WhisperHost> m_whisper; ///< Client for Whisper ("shh") protocol.
  162. std::shared_ptr<bzz::Client> m_swarm; ///< Client for Swarm ("bzz") protocol.
  163. std::shared_ptr<Support> m_support;
  164. };
  165. // TODO, probably move into libdevrpc:
  166. class RPCSlave {};
  167. class RPCMaster {};
  168. // TODO, probably move into eth:
  169. class EthereumSlave: public eth::Interface
  170. {
  171. public:
  172. EthereumSlave(RPCSlave*) {}
  173. // TODO: implement all of the virtuals with the RLPClient link.
  174. };
  175. class EthereumMaster
  176. {
  177. public:
  178. EthereumMaster(RPCMaster*) {}
  179. // TODO: implement the master-end of whatever the RLPClient link will send over.
  180. };
  181. // TODO, probably move into shh:
  182. class WhisperSlave: public shh::Interface
  183. {
  184. public:
  185. WhisperSlave(RPCSlave*) {}
  186. // TODO: implement all of the virtuals with the RLPClient link.
  187. };
  188. class WhisperMaster
  189. {
  190. public:
  191. WhisperMaster(RPCMaster*) {}
  192. // TODO: implement the master-end of whatever the RLPClient link will send over.
  193. };
  194. /**
  195. * @brief Main API hub for interfacing with Web 3 components.
  196. *
  197. * This does transparent local multiplexing, so you can have as many running on the
  198. * same machine all working from a single DB path.
  199. */
  200. class WebThree
  201. {
  202. public:
  203. /// Constructor for public instance. This will be shared across the local machine.
  204. WebThree();
  205. /// Destructor.
  206. ~WebThree();
  207. // The mainline interfaces.
  208. eth::Interface* ethereum() const { if (!m_ethereum) BOOST_THROW_EXCEPTION(InterfaceNotSupported("eth")); return m_ethereum; }
  209. shh::Interface* whisper() const { if (!m_whisper) BOOST_THROW_EXCEPTION(InterfaceNotSupported("shh")); return m_whisper; }
  210. bzz::Interface* swarm() const { BOOST_THROW_EXCEPTION(InterfaceNotSupported("bzz")); }
  211. // Peer network stuff - forward through RPCSlave, probably with P2PNetworkSlave/Master classes like Whisper & Ethereum.
  212. /// Get information on the current peer set.
  213. std::vector<p2p::PeerSessionInfo> peers();
  214. /// Same as peers().size(), but more efficient.
  215. size_t peerCount() const;
  216. /// Connect to a particular peer.
  217. void connect(std::string const& _seedHost, unsigned short _port = 30303);
  218. /// Is the network subsystem up?
  219. bool haveNetwork();
  220. /// Save peers
  221. dev::bytes savePeers();
  222. /// Restore peers
  223. void restorePeers(bytesConstRef _saved);
  224. private:
  225. EthereumSlave* m_ethereum = nullptr;
  226. WhisperSlave* m_whisper = nullptr;
  227. // TODO:
  228. RPCSlave m_rpcSlave;
  229. };
  230. }