Common.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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 Common.cpp
  15. * @author Gav Wood <i@gavwood.com>
  16. * @date 2014
  17. */
  18. #include "Common.h"
  19. #include "Network.h"
  20. using namespace std;
  21. using namespace dev;
  22. using namespace dev::p2p;
  23. const unsigned dev::p2p::c_protocolVersion = 4;
  24. const unsigned dev::p2p::c_defaultIPPort = 30303;
  25. static_assert(dev::p2p::c_protocolVersion == 4, "Replace v3 compatbility with v4 compatibility before updating network version.");
  26. const dev::p2p::NodeIPEndpoint dev::p2p::UnspecifiedNodeIPEndpoint = NodeIPEndpoint(bi::address(), 0, 0);
  27. const dev::p2p::Node dev::p2p::UnspecifiedNode = dev::p2p::Node(NodeID(), UnspecifiedNodeIPEndpoint);
  28. bool dev::p2p::NodeIPEndpoint::test_allowLocal = false;
  29. //⊳⊲◀▶■▣▢□▷◁▧▨▩▲◆◉◈◇◎●◍◌○◼☑☒☎☢☣☰☀♽♥♠✩✭❓✔✓✖✕✘✓✔✅⚒⚡⦸⬌∅⁕«««»»»⚙━┅┉▬
  30. #if defined(_WIN32)
  31. const char* NetWarn::name() { return EthYellow "N" EthRed " X"; }
  32. const char* NetImpolite::name() { return EthYellow "N" EthRed " !"; }
  33. const char* NetNote::name() { return EthYellow "N" EthBlue " i"; }
  34. const char* NetConnect::name() { return EthYellow "N" EthYellow " C"; }
  35. const char* NetMessageSummary::name() { return EthYellow "N" EthWhite " ."; }
  36. const char* NetMessageDetail::name() { return EthYellow "N" EthGray " o"; }
  37. const char* NetTriviaSummary::name() { return EthYellow "N" EthGray " O"; }
  38. const char* NetTriviaDetail::name() { return EthYellow "N" EthCoal " 0"; }
  39. const char* NetAllDetail::name() { return EthYellow "N" EthCoal " A"; }
  40. const char* NetRight::name() { return EthYellow "N" EthGreen "->"; }
  41. const char* NetLeft::name() { return EthYellow "N" EthNavy "<-"; }
  42. const char* NetP2PWarn::name() { return EthYellow "N" EthRed " X"; }
  43. const char* NetP2PNote::name() { return EthYellow "N" EthBlue " i"; }
  44. const char* NetP2PConnect::name() { return EthYellow "N" EthYellow " C"; }
  45. #else
  46. const char* NetWarn::name() { return EthYellow "⧎" EthRed " ✘"; }
  47. const char* NetImpolite::name() { return EthYellow "⧎" EthRed " !"; }
  48. const char* NetNote::name() { return EthYellow "⧎" EthBlue " ℹ"; }
  49. const char* NetConnect::name() { return EthYellow "⧎" EthYellow " ▢"; }
  50. const char* NetMessageSummary::name() { return EthYellow "⧎" EthWhite " ◌"; }
  51. const char* NetMessageDetail::name() { return EthYellow "⧎" EthGray " ○"; }
  52. const char* NetTriviaSummary::name() { return EthYellow "⧎" EthGray " ◎"; }
  53. const char* NetTriviaDetail::name() { return EthYellow "⧎" EthCoal " ◍"; }
  54. const char* NetAllDetail::name() { return EthYellow "⧎" EthCoal " ●"; }
  55. const char* NetRight::name() { return EthYellow "⧎" EthGreen "▬▶"; }
  56. const char* NetLeft::name() { return EthYellow "⧎" EthNavy "◀▬"; }
  57. const char* NetP2PWarn::name() { return EthYellow "⧎" EthRed " ✘"; }
  58. const char* NetP2PNote::name() { return EthYellow "⧎" EthBlue " ℹ"; }
  59. const char* NetP2PConnect::name() { return EthYellow "⧎" EthYellow " ▢"; }
  60. #endif
  61. bool p2p::isPublicAddress(std::string const& _addressToCheck)
  62. {
  63. return _addressToCheck.empty() ? false : isPublicAddress(bi::address::from_string(_addressToCheck));
  64. }
  65. bool p2p::isPublicAddress(bi::address const& _addressToCheck)
  66. {
  67. return !(isPrivateAddress(_addressToCheck) || isLocalHostAddress(_addressToCheck));
  68. }
  69. // Helper function to determine if an address falls within one of the reserved ranges
  70. // For V4:
  71. // Class A "10.*", Class B "172.[16->31].*", Class C "192.168.*"
  72. bool p2p::isPrivateAddress(bi::address const& _addressToCheck)
  73. {
  74. if (_addressToCheck.is_v4())
  75. {
  76. bi::address_v4 v4Address = _addressToCheck.to_v4();
  77. bi::address_v4::bytes_type bytesToCheck = v4Address.to_bytes();
  78. if (bytesToCheck[0] == 10 || bytesToCheck[0] == 127)
  79. return true;
  80. if (bytesToCheck[0] == 172 && (bytesToCheck[1] >= 16 && bytesToCheck[1] <= 31))
  81. return true;
  82. if (bytesToCheck[0] == 192 && bytesToCheck[1] == 168)
  83. return true;
  84. }
  85. else if (_addressToCheck.is_v6())
  86. {
  87. bi::address_v6 v6Address = _addressToCheck.to_v6();
  88. bi::address_v6::bytes_type bytesToCheck = v6Address.to_bytes();
  89. if (bytesToCheck[0] == 0xfd && bytesToCheck[1] == 0)
  90. return true;
  91. if (!bytesToCheck[0] && !bytesToCheck[1] && !bytesToCheck[2] && !bytesToCheck[3] && !bytesToCheck[4] && !bytesToCheck[5] && !bytesToCheck[6] && !bytesToCheck[7]
  92. && !bytesToCheck[8] && !bytesToCheck[9] && !bytesToCheck[10] && !bytesToCheck[11] && !bytesToCheck[12] && !bytesToCheck[13] && !bytesToCheck[14] && (bytesToCheck[15] == 0 || bytesToCheck[15] == 1))
  93. return true;
  94. }
  95. return false;
  96. }
  97. bool p2p::isPrivateAddress(std::string const& _addressToCheck)
  98. {
  99. return _addressToCheck.empty() ? false : isPrivateAddress(bi::address::from_string(_addressToCheck));
  100. }
  101. // Helper function to determine if an address is localhost
  102. bool p2p::isLocalHostAddress(bi::address const& _addressToCheck)
  103. {
  104. // @todo: ivp6 link-local adresses (macos), ex: fe80::1%lo0
  105. static const set<bi::address> c_rejectAddresses = {
  106. {bi::address_v4::from_string("127.0.0.1")},
  107. {bi::address_v4::from_string("0.0.0.0")},
  108. {bi::address_v6::from_string("::1")},
  109. {bi::address_v6::from_string("::")}
  110. };
  111. return find(c_rejectAddresses.begin(), c_rejectAddresses.end(), _addressToCheck) != c_rejectAddresses.end();
  112. }
  113. bool p2p::isLocalHostAddress(std::string const& _addressToCheck)
  114. {
  115. return _addressToCheck.empty() ? false : isLocalHostAddress(bi::address::from_string(_addressToCheck));
  116. }
  117. std::string p2p::reasonOf(DisconnectReason _r)
  118. {
  119. switch (_r)
  120. {
  121. case DisconnectRequested: return "Disconnect was requested.";
  122. case TCPError: return "Low-level TCP communication error.";
  123. case BadProtocol: return "Data format error.";
  124. case UselessPeer: return "Peer had no use for this node.";
  125. case TooManyPeers: return "Peer had too many connections.";
  126. case DuplicatePeer: return "Peer was already connected.";
  127. case IncompatibleProtocol: return "Peer protocol versions are incompatible.";
  128. case NullIdentity: return "Null identity given.";
  129. case ClientQuit: return "Peer is exiting.";
  130. case UnexpectedIdentity: return "Unexpected identity given.";
  131. case LocalIdentity: return "Connected to ourselves.";
  132. case UserReason: return "Subprotocol reason.";
  133. case NoDisconnect: return "(No disconnect has happened.)";
  134. default: return "Unknown reason.";
  135. }
  136. }
  137. void NodeIPEndpoint::streamRLP(RLPStream& _s, RLPAppend _append) const
  138. {
  139. if (_append == StreamList)
  140. _s.appendList(3);
  141. if (address.is_v4())
  142. _s << bytesConstRef(&address.to_v4().to_bytes()[0], 4);
  143. else if (address.is_v6())
  144. _s << bytesConstRef(&address.to_v6().to_bytes()[0], 16);
  145. else
  146. _s << bytes();
  147. _s << udpPort << tcpPort;
  148. }
  149. void NodeIPEndpoint::interpretRLP(RLP const& _r)
  150. {
  151. if (_r[0].size() == 4)
  152. address = bi::address_v4(*(bi::address_v4::bytes_type*)_r[0].toBytes().data());
  153. else if (_r[0].size() == 16)
  154. address = bi::address_v6(*(bi::address_v6::bytes_type*)_r[0].toBytes().data());
  155. else
  156. address = bi::address();
  157. udpPort = _r[1].toInt<uint16_t>();
  158. tcpPort = _r[2].toInt<uint16_t>();
  159. }
  160. void DeadlineOps::reap()
  161. {
  162. if (m_stopped)
  163. return;
  164. Guard l(x_timers);
  165. std::vector<DeadlineOp>::iterator t = m_timers.begin();
  166. while (t != m_timers.end())
  167. if (t->expired())
  168. {
  169. t->wait();
  170. t = m_timers.erase(t);
  171. }
  172. else
  173. t++;
  174. m_timers.emplace_back(m_io, m_reapIntervalMs, [this](boost::system::error_code const& ec)
  175. {
  176. if (!ec && !m_stopped)
  177. reap();
  178. });
  179. }
  180. Node::Node(NodeSpec const& _s, PeerType _p):
  181. id(_s.id()),
  182. endpoint(_s.nodeIPEndpoint()),
  183. peerType(_p)
  184. {}
  185. NodeSpec::NodeSpec(string const& _user)
  186. {
  187. m_address = _user;
  188. if (m_address.substr(0, 8) == "enode://" && m_address.find('@') == 136)
  189. {
  190. m_id = p2p::NodeID(m_address.substr(8, 128));
  191. m_address = m_address.substr(137);
  192. }
  193. size_t colon = m_address.find_first_of(":");
  194. if (colon != string::npos)
  195. {
  196. string ports = m_address.substr(colon + 1);
  197. m_address = m_address.substr(0, colon);
  198. size_t p2 = ports.find_first_of(".");
  199. if (p2 != string::npos)
  200. {
  201. m_udpPort = stoi(ports.substr(p2 + 1));
  202. m_tcpPort = stoi(ports.substr(0, p2));
  203. }
  204. else
  205. m_tcpPort = m_udpPort = stoi(ports);
  206. }
  207. }
  208. NodeIPEndpoint NodeSpec::nodeIPEndpoint() const
  209. {
  210. return NodeIPEndpoint(p2p::Network::resolveHost(m_address).address(), m_udpPort, m_tcpPort);
  211. }
  212. std::string NodeSpec::enode() const
  213. {
  214. string ret = m_address;
  215. if (m_tcpPort)
  216. if (m_udpPort && m_tcpPort != m_udpPort)
  217. ret += ":" + toString(m_tcpPort) + "." + toString(m_udpPort);
  218. else
  219. ret += ":" + toString(m_tcpPort);
  220. else if (m_udpPort)
  221. ret += ":" + toString(m_udpPort);
  222. if (m_id)
  223. return "enode://" + m_id.hex() + "@" + ret;
  224. return ret;
  225. }
  226. namespace dev
  227. {
  228. std::ostream& operator<<(std::ostream& _out, dev::p2p::NodeIPEndpoint const& _ep)
  229. {
  230. _out << _ep.address << _ep.udpPort << _ep.tcpPort;
  231. return _out;
  232. }
  233. }