Fabcoin Core  0.16.2
P2P Digital Currency
Host.h
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
23 #pragma once
24 
25 #include <mutex>
26 #include <map>
27 #include <vector>
28 #include <set>
29 #include <memory>
30 #include <utility>
31 #include <thread>
32 #include <chrono>
33 
34 #include <libdevcore/Guards.h>
35 #include <libdevcore/Worker.h>
36 #include <libdevcrypto/Common.h>
37 #include <libdevcrypto/ECDHE.h>
38 #include "NodeTable.h"
39 #include "HostCapability.h"
40 #include "Network.h"
41 #include "Peer.h"
42 #include "RLPXSocket.h"
43 #include "RLPXFrameCoder.h"
44 #include "Common.h"
45 namespace ba = boost::asio;
46 namespace bi = ba::ip;
47 
48 namespace std
49 {
50 template<> struct hash<pair<dev::p2p::NodeID, string>>
51 {
52  size_t operator()(pair<dev::p2p::NodeID, string> const& _value) const
53  {
54  size_t ret = hash<dev::p2p::NodeID>()(_value.first);
55  return ret ^ (hash<string>()(_value.second) + 0x9e3779b9 + (ret << 6) + (ret >> 2));
56  }
57 };
58 }
59 
60 namespace dev
61 {
62 
63 namespace p2p
64 {
65 
66 class Host;
67 
69 {
70 public:
71  HostNodeTableHandler(Host& _host);
72 
73  Host const& host() const { return m_host; }
74 
75 private:
76  virtual void processEvent(NodeID const& _n, NodeTableEventType const& _e);
77 
79 };
80 
82 {
83  bool isRude = false;
84  int utility = 0;
86 };
87 
88 struct Reputation
89 {
90  std::unordered_map<std::string, SubReputation> subs;
91 };
92 
94 {
95 public:
97 
98  void noteRude(SessionFace const& _s, std::string const& _sub = std::string());
99  bool isRude(SessionFace const& _s, std::string const& _sub = std::string()) const;
100  void setData(SessionFace const& _s, std::string const& _sub, bytes const& _data);
101  bytes data(SessionFace const& _s, std::string const& _subs) const;
102 
103 private:
104  std::unordered_map<std::pair<p2p::NodeID, std::string>, Reputation> m_nodes;
106 };
107 
108 struct NodeInfo
109 {
110  NodeInfo() = default;
111  NodeInfo(NodeID const& _id, std::string const& _address, unsigned _port, std::string const& _version):
112  id(_id), address(_address), port(_port), version(_version) {}
113 
114  std::string enode() const { return "enode://" + id.hex() + "@" + address + ":" + toString(port); }
115 
117  std::string address;
118  unsigned port;
119  std::string version;
120 };
121 
129 class Host: public Worker
130 {
131  friend class HostNodeTableHandler;
132  friend class RLPXHandshake;
133 
134  friend class Session;
135  friend class HostCapabilityFace;
136 
137 public:
139  Host(
140  std::string const& _clientVersion,
142  bytesConstRef _restoreNetwork = bytesConstRef()
143  );
144 
147  Host(
148  std::string const& _clientVersion,
149  KeyPair const& _alias,
151  );
152 
154  virtual ~Host();
155 
157  static std::unordered_map<Public, std::string> pocHosts();
158 
160  template <class T> std::shared_ptr<T> registerCapability(std::shared_ptr<T> const& _t) { _t->m_host = this; m_capabilities[std::make_pair(T::staticName(), T::staticVersion())] = _t; return _t; }
161  template <class T> void addCapability(std::shared_ptr<T> const & _p, std::string const& _name, u256 const& _version) { m_capabilities[std::make_pair(_name, _version)] = _p; }
162 
163  bool haveCapability(CapDesc const& _name) const { return m_capabilities.count(_name) != 0; }
164  CapDescs caps() const { CapDescs ret; for (auto const& i: m_capabilities) ret.push_back(i.first); return ret; }
165  template <class T> std::shared_ptr<T> cap() const { try { return std::static_pointer_cast<T>(m_capabilities.at(std::make_pair(T::staticName(), T::staticVersion()))); } catch (...) { return nullptr; } }
166 
168  void addPeer(NodeSpec const& _s, PeerType _t);
169 
171  void addNode(NodeID const& _node, NodeIPEndpoint const& _endpoint);
172 
174  void requirePeer(NodeID const& _node, NodeIPEndpoint const& _endpoint);
175 
177  void requirePeer(NodeID const& _node, bi::address const& _addr, unsigned short _udpPort, unsigned short _tcpPort) { requirePeer(_node, NodeIPEndpoint(_addr, _udpPort, _tcpPort)); }
178 
180  void relinquishPeer(NodeID const& _node);
181 
183  void setIdealPeerCount(unsigned _n) { m_idealPeerCount = _n; }
184 
186  void setPeerStretch(unsigned _n) { m_stretchPeers = _n; }
187 
189  PeerSessionInfos peerSessionInfo() const;
190 
192  size_t peerCount() const;
193 
195  std::string listenAddress() const { return m_tcpPublic.address().is_unspecified() ? "0.0.0.0" : m_tcpPublic.address().to_string(); }
196 
198  unsigned short listenPort() const { return std::max(0, m_listenPort); }
199 
201  bytes saveNetwork() const;
202 
203  // TODO: P2P this should be combined with peers into a HostStat object of some kind; coalesce data, as it's only used for status information.
204  Peers getPeers() const { RecursiveGuard l(x_sessions); Peers ret; for (auto const& i: m_peers) ret.push_back(*i.second); return ret; }
205 
206  NetworkPreferences const& networkPreferences() const { return m_netPrefs; }
207 
208  void setNetworkPreferences(NetworkPreferences const& _p, bool _dropPeers = false) { m_dropPeers = _dropPeers; auto had = isStarted(); if (had) stop(); m_netPrefs = _p; if (had) start(); }
209 
211  void start();
212 
215  void stop();
216 
218  bool isStarted() const { return isWorking(); }
219 
221  ReputationManager& repMan() { return m_repMan; }
222 
224  bool haveNetwork() const { Guard l(x_runTimer); return m_run && !!m_nodeTable; }
225 
227  void startPeerSession(Public const& _id, RLP const& _hello, std::unique_ptr<RLPXFrameCoder>&& _io, std::shared_ptr<RLPXSocket> const& _s);
228 
230  std::shared_ptr<SessionFace> peerSession(NodeID const& _id) { RecursiveGuard l(x_sessions); return m_sessions.count(_id) ? m_sessions[_id].lock() : std::shared_ptr<SessionFace>(); }
231 
233  NodeID id() const { return m_alias.pub(); }
234 
236  bi::tcp::endpoint const& tcpPublic() const { return m_tcpPublic; }
237 
239  std::string enode() const { return "enode://" + id().hex() + "@" + (networkPreferences().publicIPAddress.empty() ? m_tcpPublic.address().to_string() : networkPreferences().publicIPAddress) + ":" + toString(m_tcpPublic.port()); }
240 
242  p2p::NodeInfo nodeInfo() const { return NodeInfo(id(), (networkPreferences().publicIPAddress.empty() ? m_tcpPublic.address().to_string() : networkPreferences().publicIPAddress), m_tcpPublic.port(), m_clientVersion); }
243 
244 protected:
245  void onNodeTableEvent(NodeID const& _n, NodeTableEventType const& _e);
246 
248  void restoreNetwork(bytesConstRef _b);
249 
250 private:
251  enum PeerSlotType { Egress, Ingress };
252 
253  unsigned peerSlots(PeerSlotType _type) { return _type == Egress ? m_idealPeerCount : m_idealPeerCount * m_stretchPeers; }
254 
255  bool havePeerSession(NodeID const& _id) { return !!peerSession(_id); }
256 
258  void determinePublic();
259 
260  void connect(std::shared_ptr<Peer> const& _p);
261 
263  bool peerSlotsAvailable(PeerSlotType _type = Ingress) { Guard l(x_pendingNodeConns); return peerCount() + m_pendingPeerConns.size() < peerSlots(_type); }
264 
266  void keepAlivePeers();
267 
269  void disconnectLatePeers();
270 
272  void runAcceptor();
273 
275  virtual void startedWorking();
277  void run(boost::system::error_code const& error);
278 
280  virtual void doWork();
281 
283  virtual void doneWorking();
284 
286  static KeyPair networkAlias(bytesConstRef _b);
287 
289 
290  bool m_run = false;
291  mutable std::mutex x_runTimer;
292 
293  std::string m_clientVersion;
294 
296 
298  std::set<bi::address> m_ifAddresses;
299 
300  int m_listenPort = -1;
301 
302  ba::io_service m_ioService;
303  bi::tcp::acceptor m_tcp4Acceptor;
304 
305  std::unique_ptr<boost::asio::deadline_timer> m_timer;
306  static const unsigned c_timerInterval = 100;
307 
308  std::set<Peer*> m_pendingPeerConns;
310 
311  bi::tcp::endpoint m_tcpPublic;
313  std::shared_ptr<NodeTable> m_nodeTable;
314 
316  std::unordered_map<NodeID, std::shared_ptr<Peer>> m_peers;
317 
319  std::set<NodeID> m_requiredPeers;
321 
324  mutable std::unordered_map<NodeID, std::weak_ptr<SessionFace>> m_sessions;
326 
327  std::list<std::weak_ptr<RLPXHandshake>> m_connecting;
329 
330  unsigned m_idealPeerCount = 11;
331  unsigned m_stretchPeers = 7;
332 
333  std::map<CapDesc, std::shared_ptr<HostCapabilityFace>> m_capabilities;
334 
336  std::list<std::shared_ptr<boost::asio::deadline_timer>> m_timers;
338 
340  bool m_accepting = false;
341  bool m_dropPeers = false;
342 
344 };
345 
346 }
347 }
bool peerSlotsAvailable(PeerSlotType _type=Ingress)
Returns true if pending and connected peer count is less than maximum.
Definition: Host.h:263
h512 NodeID
Definition: Common.h:62
Host const & host() const
Definition: Host.h:73
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
NodeInfo(NodeID const &_id, std::string const &_address, unsigned _port, std::string const &_version)
Definition: Host.h:111
bool error(const char *fmt, const Args &...args)
Definition: util.h:178
void setIdealPeerCount(unsigned _n)
Set ideal number of peers.
Definition: Host.h:183
SharedMutex x_nodes
Definition: Host.h:105
bi::tcp::endpoint m_tcpPublic
Our public listening endpoint.
Definition: Host.h:311
std::unique_ptr< boost::asio::deadline_timer > m_timer
Timer which, when network is running, calls scheduler() every c_timerInterval ms. ...
Definition: Host.h:305
std::shared_ptr< NodeTable > m_nodeTable
Node table (uses kademlia-like discovery).
Definition: Host.h:313
bool isStarted() const
Definition: Host.h:218
std::mutex x_runTimer
Start/stop mutex.
Definition: Host.h:291
CapDescs caps() const
Definition: Host.h:164
std::pair< std::string, u256 > CapDesc
Definition: Common.h:142
NetworkPreferences const & networkPreferences() const
Definition: Host.h:206
unsigned peerSlots(PeerSlotType _type)
Definition: Host.h:253
RecursiveMutex x_sessions
Definition: Host.h:325
#define T(i, x)
bool haveNetwork() const
Definition: Host.h:224
unsigned port
Definition: Host.h:118
Simple class that represents a "key pair".
Definition: Common.h:150
The Host class Capabilities should be registered prior to startNetwork, since m_capabilities is not t...
Definition: Host.h:129
std::vector< PeerSessionInfo > PeerSessionInfos
Definition: Common.h:164
std::map< CapDesc, std::shared_ptr< HostCapabilityFace > > m_capabilities
Each of the capabilities we support.
Definition: Host.h:333
Peers getPeers() const
Definition: Host.h:204
std::string m_clientVersion
Our version string.
Definition: Host.h:293
std::list< std::shared_ptr< boost::asio::deadline_timer > > m_timers
Deadline timers used for isolated network events. GC&#39;d by run.
Definition: Host.h:336
unsigned short listenPort() const
Get the port we&#39;re listening on currently.
Definition: Host.h:198
Mutex x_pendingNodeConns
Used only by connect(Peer&) to limit concurrently connecting to same node. See connect(shared_ptr<Pee...
Definition: Host.h:309
std::string listenAddress() const
Get the address we&#39;re listening on currently.
Definition: Host.h:195
bi::tcp::endpoint const & tcpPublic() const
Get the public TCP endpoint.
Definition: Host.h:236
std::hash for asio::adress
Definition: Common.h:323
NodeTableEventType
Definition: NodeTable.h:48
std::string toString(string32 const &_s)
Make normal string from fixed-length string.
Definition: CommonData.cpp:141
IPv4,UDP/TCP endpoints.
Definition: Common.h:175
NetworkPreferences m_netPrefs
Network settings.
Definition: Host.h:295
std::set< NodeID > m_requiredPeers
Peers we try to connect regardless of p2p network.
Definition: Host.h:319
void version()
Definition: main.cpp:53
std::set< bi::address > m_ifAddresses
Interface addresses (private, public)
Definition: Host.h:298
ba::io_service m_ioService
IOService for network stuff.
Definition: Host.h:302
bytes m_restoreNetwork
Set by constructor and used to set Host key and restore network peers & nodes.
Definition: Host.h:288
Mutex x_requiredPeers
Definition: Host.h:320
std::recursive_mutex RecursiveMutex
Definition: Guards.h:38
bool havePeerSession(NodeID const &_id)
Definition: Host.h:255
std::string enode() const
Definition: Host.h:114
NodeID id() const
Get our current node ID.
Definition: Host.h:233
std::vector< Peer > Peers
Definition: Peer.h:99
std::unordered_map< std::string, SubReputation > subs
Definition: Host.h:90
std::lock_guard< std::mutex > Guard
Definition: Guards.h:41
p2p::NodeInfo nodeInfo() const
Get the node information.
Definition: Host.h:242
void requirePeer(NodeID const &_node, bi::address const &_addr, unsigned short _udpPort, unsigned short _tcpPort)
Create Peer and attempt keeping peer connected.
Definition: Host.h:177
std::list< std::weak_ptr< RLPXHandshake > > m_connecting
Pending connections.
Definition: Host.h:327
std::vector< byte > bytes
Definition: Common.h:75
KeyPair m_alias
Alias for network communication. Network address is k*G. k is key material. TODO: Replace KeyPair...
Definition: Host.h:312
vector_ref< byte const > bytesConstRef
Definition: Common.h:77
void setPeerStretch(unsigned _n)
Set multipier for max accepted connections.
Definition: Host.h:186
bool haveCapability(CapDesc const &_name) const
Definition: Host.h:163
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void >> u256
Definition: Common.h:125
std::set< Peer * > m_pendingPeerConns
Definition: Host.h:308
std::vector< CapDesc > CapDescs
Definition: Common.h:144
void addCapability(std::shared_ptr< T > const &_p, std::string const &_name, u256 const &_version)
Definition: Host.h:161
ReputationManager m_repMan
Definition: Host.h:343
std::shared_ptr< T > registerCapability(std::shared_ptr< T > const &_t)
Register a peer-capability; all new peer connections will have this capability.
Definition: Host.h:160
std::string version
Definition: Host.h:119
PeerType
Definition: Common.h:166
size_t operator()(pair< dev::p2p::NodeID, string > const &_value) const
Definition: Host.h:52
std::unordered_map< NodeID, std::weak_ptr< SessionFace > > m_sessions
The nodes to which we are currently connected.
Definition: Host.h:324
std::string address
Definition: Host.h:117
boost::shared_mutex SharedMutex
Definition: Guards.h:39
clock::time_point time_point
Definition: bench.h:49
bi::tcp::acceptor m_tcp4Acceptor
Listening acceptor.
Definition: Host.h:303
std::shared_ptr< T > cap() const
Definition: Host.h:165
std::lock_guard< std::recursive_mutex > RecursiveGuard
Definition: Guards.h:43
std::string enode() const
Get the public endpoint information.
Definition: Host.h:239
Mutex x_timers
Definition: Host.h:337
dev::WithExisting max(dev::WithExisting _a, dev::WithExisting _b)
Definition: Common.h:326
Mutex x_connecting
Mutex for m_connecting.
Definition: Host.h:328
std::chrono::steady_clock::time_point m_lastPing
Time we sent the last ping to all peers.
Definition: Host.h:339
struct evm_uint160be address(struct evm_env *env)
Definition: capi.c:13
std::mutex Mutex
Definition: Guards.h:37
std::unordered_map< std::pair< p2p::NodeID, std::string >, Reputation > m_nodes
Nodes that were impolite while syncing. We avoid syncing from these if possible.
Definition: Host.h:104
void setNetworkPreferences(NetworkPreferences const &_p, bool _dropPeers=false)
Definition: Host.h:208
uint8_t const * data
Definition: sha3.h:19
Class for interpreting Recursive Linear-Prefix Data.
Definition: RLP.h:64
std::unordered_map< NodeID, std::shared_ptr< Peer > > m_peers
Shared storage of Peer objects. Peers are created or destroyed on demand by the Host. Active sessions maintain a shared_ptr to a Peer;.
Definition: Host.h:316
UniValue stop(const JSONRPCRequest &jsonRequest)
Definition: server.cpp:237
std::shared_ptr< SessionFace > peerSession(NodeID const &_id)
Get session by id.
Definition: Host.h:230
The Session class.
Definition: Session.h:90
ReputationManager & repMan()
Definition: Host.h:221
Setup inbound or outbound connection for communication over RLPXFrameCoder.
Definition: RLPxHandshake.h:51