You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

419 lines
12 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
p2p: implement new Transport interface (#5791) This implements a new `Transport` interface and related types for the P2P refactor in #5670. Previously, `conn.MConnection` was very tightly coupled to the `Peer` implementation -- in order to allow alternative non-multiplexed transports (e.g. QUIC), MConnection has now been moved below the `Transport` interface, as `MConnTransport`, and decoupled from the peer. Since the `p2p` package is not covered by our Go API stability, this is not considered a breaking change, and not listed in the changelog. The initial approach was to implement the new interface in its final form (which also involved possible protocol changes, see https://github.com/tendermint/spec/pull/227). However, it turned out that this would require a large amount of changes to existing P2P code because of the previous tight coupling between `Peer` and `MConnection` and the reliance on subtleties in the MConnection behavior. Instead, I have broadened the `Transport` interface to expose much of the existing MConnection interface, preserved much of the existing MConnection logic and behavior in the transport implementation, and tried to make as few changes to the rest of the P2P stack as possible. We will instead reduce this interface gradually as we refactor other parts of the P2P stack. The low-level transport code and protocol (e.g. MConnection, SecretConnection and so on) has not been significantly changed, and refactoring this is not a priority until we come up with a plan for QUIC adoption, as we may end up discarding the MConnection code entirely. There are no tests of the new `MConnTransport`, as this code is likely to evolve as we proceed with the P2P refactor, but tests should be added before a final release. The E2E tests are sufficient for basic validation in the meanwhile.
4 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. // Modified for Tendermint
  2. // Originally Copyright (c) 2013-2014 Conformal Systems LLC.
  3. // https://github.com/conformal/btcd/blob/master/LICENSE
  4. package p2p
  5. import (
  6. "errors"
  7. "flag"
  8. "fmt"
  9. "net"
  10. "strconv"
  11. "strings"
  12. "time"
  13. tmp2p "github.com/tendermint/tendermint/proto/tendermint/p2p"
  14. )
  15. // EmptyNetAddress defines the string representation of an empty NetAddress
  16. const EmptyNetAddress = "<nil-NetAddress>"
  17. // NetAddress defines information about a peer on the network
  18. // including its ID, IP address, and port.
  19. type NetAddress struct {
  20. ID NodeID `json:"id"`
  21. IP net.IP `json:"ip"`
  22. Port uint16 `json:"port"`
  23. }
  24. // IDAddressString returns id@hostPort. It strips the leading
  25. // protocol from protocolHostPort if it exists.
  26. func IDAddressString(id NodeID, protocolHostPort string) string {
  27. hostPort := removeProtocolIfDefined(protocolHostPort)
  28. return fmt.Sprintf("%s@%s", id, hostPort)
  29. }
  30. // NewNetAddress returns a new NetAddress using the provided TCP
  31. // address. When testing, other net.Addr (except TCP) will result in
  32. // using 0.0.0.0:0. When normal run, other net.Addr (except TCP) will
  33. // panic. Panics if ID is invalid.
  34. // TODO: socks proxies?
  35. func NewNetAddress(id NodeID, addr net.Addr) *NetAddress {
  36. tcpAddr, ok := addr.(*net.TCPAddr)
  37. if !ok {
  38. if flag.Lookup("test.v") == nil { // normal run
  39. panic(fmt.Sprintf("Only TCPAddrs are supported. Got: %v", addr))
  40. } else { // in testing
  41. netAddr := NewNetAddressIPPort(net.IP("127.0.0.1"), 0)
  42. netAddr.ID = id
  43. return netAddr
  44. }
  45. }
  46. if err := id.Validate(); err != nil {
  47. panic(fmt.Sprintf("Invalid ID %v: %v (addr: %v)", id, err, addr))
  48. }
  49. ip := tcpAddr.IP
  50. port := uint16(tcpAddr.Port)
  51. na := NewNetAddressIPPort(ip, port)
  52. na.ID = id
  53. return na
  54. }
  55. // NewNetAddressString returns a new NetAddress using the provided address in
  56. // the form of "ID@IP:Port".
  57. // Also resolves the host if host is not an IP.
  58. // Errors are of type ErrNetAddressXxx where Xxx is in (NoID, Invalid, Lookup)
  59. func NewNetAddressString(addr string) (*NetAddress, error) {
  60. addrWithoutProtocol := removeProtocolIfDefined(addr)
  61. spl := strings.Split(addrWithoutProtocol, "@")
  62. if len(spl) != 2 {
  63. return nil, ErrNetAddressNoID{addr}
  64. }
  65. id, err := NewNodeID(spl[0])
  66. if err != nil {
  67. return nil, ErrNetAddressInvalid{addrWithoutProtocol, err}
  68. }
  69. if err := id.Validate(); err != nil {
  70. return nil, ErrNetAddressInvalid{addrWithoutProtocol, err}
  71. }
  72. addrWithoutProtocol = spl[1]
  73. // get host and port
  74. host, portStr, err := net.SplitHostPort(addrWithoutProtocol)
  75. if err != nil {
  76. return nil, ErrNetAddressInvalid{addrWithoutProtocol, err}
  77. }
  78. if len(host) == 0 {
  79. return nil, ErrNetAddressInvalid{
  80. addrWithoutProtocol,
  81. errors.New("host is empty")}
  82. }
  83. ip := net.ParseIP(host)
  84. if ip == nil {
  85. ips, err := net.LookupIP(host)
  86. if err != nil {
  87. return nil, ErrNetAddressLookup{host, err}
  88. }
  89. ip = ips[0]
  90. }
  91. port, err := strconv.ParseUint(portStr, 10, 16)
  92. if err != nil {
  93. return nil, ErrNetAddressInvalid{portStr, err}
  94. }
  95. na := NewNetAddressIPPort(ip, uint16(port))
  96. na.ID = id
  97. return na, nil
  98. }
  99. // NewNetAddressStrings returns an array of NetAddress'es build using
  100. // the provided strings.
  101. func NewNetAddressStrings(addrs []string) ([]*NetAddress, []error) {
  102. netAddrs := make([]*NetAddress, 0)
  103. errs := make([]error, 0)
  104. for _, addr := range addrs {
  105. netAddr, err := NewNetAddressString(addr)
  106. if err != nil {
  107. errs = append(errs, err)
  108. } else {
  109. netAddrs = append(netAddrs, netAddr)
  110. }
  111. }
  112. return netAddrs, errs
  113. }
  114. // NewNetAddressIPPort returns a new NetAddress using the provided IP
  115. // and port number.
  116. func NewNetAddressIPPort(ip net.IP, port uint16) *NetAddress {
  117. return &NetAddress{
  118. IP: ip,
  119. Port: port,
  120. }
  121. }
  122. // NetAddressFromProto converts a Protobuf NetAddress into a native struct.
  123. func NetAddressFromProto(pb tmp2p.NetAddress) (*NetAddress, error) {
  124. ip := net.ParseIP(pb.IP)
  125. if ip == nil {
  126. return nil, fmt.Errorf("invalid IP address %v", pb.IP)
  127. }
  128. if pb.Port >= 1<<16 {
  129. return nil, fmt.Errorf("invalid port number %v", pb.Port)
  130. }
  131. return &NetAddress{
  132. ID: NodeID(pb.ID),
  133. IP: ip,
  134. Port: uint16(pb.Port),
  135. }, nil
  136. }
  137. // NetAddressesFromProto converts a slice of Protobuf NetAddresses into a native slice.
  138. func NetAddressesFromProto(pbs []tmp2p.NetAddress) ([]*NetAddress, error) {
  139. nas := make([]*NetAddress, 0, len(pbs))
  140. for _, pb := range pbs {
  141. na, err := NetAddressFromProto(pb)
  142. if err != nil {
  143. return nil, err
  144. }
  145. nas = append(nas, na)
  146. }
  147. return nas, nil
  148. }
  149. // NetAddressesToProto converts a slice of NetAddresses into a Protobuf slice.
  150. func NetAddressesToProto(nas []*NetAddress) []tmp2p.NetAddress {
  151. pbs := make([]tmp2p.NetAddress, 0, len(nas))
  152. for _, na := range nas {
  153. if na != nil {
  154. pbs = append(pbs, na.ToProto())
  155. }
  156. }
  157. return pbs
  158. }
  159. // ToProto converts a NetAddress to Protobuf.
  160. func (na *NetAddress) ToProto() tmp2p.NetAddress {
  161. return tmp2p.NetAddress{
  162. ID: string(na.ID),
  163. IP: na.IP.String(),
  164. Port: uint32(na.Port),
  165. }
  166. }
  167. // Equals reports whether na and other are the same addresses,
  168. // including their ID, IP, and Port.
  169. func (na *NetAddress) Equals(other interface{}) bool {
  170. if o, ok := other.(*NetAddress); ok {
  171. return na.String() == o.String()
  172. }
  173. return false
  174. }
  175. // Same returns true is na has the same non-empty ID or DialString as other.
  176. func (na *NetAddress) Same(other interface{}) bool {
  177. if o, ok := other.(*NetAddress); ok {
  178. if na.DialString() == o.DialString() {
  179. return true
  180. }
  181. if na.ID != "" && na.ID == o.ID {
  182. return true
  183. }
  184. }
  185. return false
  186. }
  187. // String representation: <ID>@<IP>:<PORT>
  188. func (na *NetAddress) String() string {
  189. if na == nil {
  190. return EmptyNetAddress
  191. }
  192. addrStr := na.DialString()
  193. if na.ID != "" {
  194. addrStr = IDAddressString(na.ID, addrStr)
  195. }
  196. return addrStr
  197. }
  198. func (na *NetAddress) DialString() string {
  199. if na == nil {
  200. return "<nil-NetAddress>"
  201. }
  202. return net.JoinHostPort(
  203. na.IP.String(),
  204. strconv.FormatUint(uint64(na.Port), 10),
  205. )
  206. }
  207. // Dial calls net.Dial on the address.
  208. func (na *NetAddress) Dial() (net.Conn, error) {
  209. conn, err := net.Dial("tcp", na.DialString())
  210. if err != nil {
  211. return nil, err
  212. }
  213. return conn, nil
  214. }
  215. // DialTimeout calls net.DialTimeout on the address.
  216. func (na *NetAddress) DialTimeout(timeout time.Duration) (net.Conn, error) {
  217. conn, err := net.DialTimeout("tcp", na.DialString(), timeout)
  218. if err != nil {
  219. return nil, err
  220. }
  221. return conn, nil
  222. }
  223. // Routable returns true if the address is routable.
  224. func (na *NetAddress) Routable() bool {
  225. if err := na.Valid(); err != nil {
  226. return false
  227. }
  228. // TODO(oga) bitcoind doesn't include RFC3849 here, but should we?
  229. return !(na.RFC1918() || na.RFC3927() || na.RFC4862() ||
  230. na.RFC4193() || na.RFC4843() || na.Local())
  231. }
  232. // For IPv4 these are either a 0 or all bits set address. For IPv6 a zero
  233. // address or one that matches the RFC3849 documentation address format.
  234. func (na *NetAddress) Valid() error {
  235. if err := na.ID.Validate(); err != nil {
  236. return fmt.Errorf("invalid ID: %w", err)
  237. }
  238. if na.IP == nil {
  239. return errors.New("no IP")
  240. }
  241. if na.IP.IsUnspecified() || na.RFC3849() || na.IP.Equal(net.IPv4bcast) {
  242. return errors.New("invalid IP")
  243. }
  244. return nil
  245. }
  246. // HasID returns true if the address has an ID.
  247. // NOTE: It does not check whether the ID is valid or not.
  248. func (na *NetAddress) HasID() bool {
  249. return string(na.ID) != ""
  250. }
  251. // Endpoint converts the address to an MConnection endpoint.
  252. func (na *NetAddress) Endpoint() Endpoint {
  253. return Endpoint{
  254. Protocol: MConnProtocol,
  255. PeerID: na.ID,
  256. IP: na.IP,
  257. Port: na.Port,
  258. }
  259. }
  260. // Local returns true if it is a local address.
  261. func (na *NetAddress) Local() bool {
  262. return na.IP.IsLoopback() || zero4.Contains(na.IP)
  263. }
  264. // ReachabilityTo checks whenever o can be reached from na.
  265. func (na *NetAddress) ReachabilityTo(o *NetAddress) int {
  266. const (
  267. Unreachable = 0
  268. Default = iota
  269. Teredo
  270. Ipv6Weak
  271. Ipv4
  272. Ipv6Strong
  273. )
  274. switch {
  275. case !na.Routable():
  276. return Unreachable
  277. case na.RFC4380():
  278. switch {
  279. case !o.Routable():
  280. return Default
  281. case o.RFC4380():
  282. return Teredo
  283. case o.IP.To4() != nil:
  284. return Ipv4
  285. default: // ipv6
  286. return Ipv6Weak
  287. }
  288. case na.IP.To4() != nil:
  289. if o.Routable() && o.IP.To4() != nil {
  290. return Ipv4
  291. }
  292. return Default
  293. default: /* ipv6 */
  294. var tunnelled bool
  295. // Is our v6 is tunnelled?
  296. if o.RFC3964() || o.RFC6052() || o.RFC6145() {
  297. tunnelled = true
  298. }
  299. switch {
  300. case !o.Routable():
  301. return Default
  302. case o.RFC4380():
  303. return Teredo
  304. case o.IP.To4() != nil:
  305. return Ipv4
  306. case tunnelled:
  307. // only prioritise ipv6 if we aren't tunnelling it.
  308. return Ipv6Weak
  309. }
  310. return Ipv6Strong
  311. }
  312. }
  313. // RFC1918: IPv4 Private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
  314. // RFC3849: IPv6 Documentation address (2001:0DB8::/32)
  315. // RFC3927: IPv4 Autoconfig (169.254.0.0/16)
  316. // RFC3964: IPv6 6to4 (2002::/16)
  317. // RFC4193: IPv6 unique local (FC00::/7)
  318. // RFC4380: IPv6 Teredo tunneling (2001::/32)
  319. // RFC4843: IPv6 ORCHID: (2001:10::/28)
  320. // RFC4862: IPv6 Autoconfig (FE80::/64)
  321. // RFC6052: IPv6 well known prefix (64:FF9B::/96)
  322. // RFC6145: IPv6 IPv4 translated address ::FFFF:0:0:0/96
  323. var rfc1918_10 = net.IPNet{IP: net.ParseIP("10.0.0.0"), Mask: net.CIDRMask(8, 32)}
  324. var rfc1918_192 = net.IPNet{IP: net.ParseIP("192.168.0.0"), Mask: net.CIDRMask(16, 32)}
  325. var rfc1918_172 = net.IPNet{IP: net.ParseIP("172.16.0.0"), Mask: net.CIDRMask(12, 32)}
  326. var rfc3849 = net.IPNet{IP: net.ParseIP("2001:0DB8::"), Mask: net.CIDRMask(32, 128)}
  327. var rfc3927 = net.IPNet{IP: net.ParseIP("169.254.0.0"), Mask: net.CIDRMask(16, 32)}
  328. var rfc3964 = net.IPNet{IP: net.ParseIP("2002::"), Mask: net.CIDRMask(16, 128)}
  329. var rfc4193 = net.IPNet{IP: net.ParseIP("FC00::"), Mask: net.CIDRMask(7, 128)}
  330. var rfc4380 = net.IPNet{IP: net.ParseIP("2001::"), Mask: net.CIDRMask(32, 128)}
  331. var rfc4843 = net.IPNet{IP: net.ParseIP("2001:10::"), Mask: net.CIDRMask(28, 128)}
  332. var rfc4862 = net.IPNet{IP: net.ParseIP("FE80::"), Mask: net.CIDRMask(64, 128)}
  333. var rfc6052 = net.IPNet{IP: net.ParseIP("64:FF9B::"), Mask: net.CIDRMask(96, 128)}
  334. var rfc6145 = net.IPNet{IP: net.ParseIP("::FFFF:0:0:0"), Mask: net.CIDRMask(96, 128)}
  335. var zero4 = net.IPNet{IP: net.ParseIP("0.0.0.0"), Mask: net.CIDRMask(8, 32)}
  336. var (
  337. // onionCatNet defines the IPv6 address block used to support Tor.
  338. // bitcoind encodes a .onion address as a 16 byte number by decoding the
  339. // address prior to the .onion (i.e. the key hash) base32 into a ten
  340. // byte number. It then stores the first 6 bytes of the address as
  341. // 0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43.
  342. //
  343. // This is the same range used by OnionCat, which is part part of the
  344. // RFC4193 unique local IPv6 range.
  345. //
  346. // In summary the format is:
  347. // { magic 6 bytes, 10 bytes base32 decode of key hash }
  348. onionCatNet = ipNet("fd87:d87e:eb43::", 48, 128)
  349. )
  350. // ipNet returns a net.IPNet struct given the passed IP address string, number
  351. // of one bits to include at the start of the mask, and the total number of bits
  352. // for the mask.
  353. func ipNet(ip string, ones, bits int) net.IPNet {
  354. return net.IPNet{IP: net.ParseIP(ip), Mask: net.CIDRMask(ones, bits)}
  355. }
  356. func (na *NetAddress) RFC1918() bool {
  357. return rfc1918_10.Contains(na.IP) ||
  358. rfc1918_192.Contains(na.IP) ||
  359. rfc1918_172.Contains(na.IP)
  360. }
  361. func (na *NetAddress) RFC3849() bool { return rfc3849.Contains(na.IP) }
  362. func (na *NetAddress) RFC3927() bool { return rfc3927.Contains(na.IP) }
  363. func (na *NetAddress) RFC3964() bool { return rfc3964.Contains(na.IP) }
  364. func (na *NetAddress) RFC4193() bool { return rfc4193.Contains(na.IP) }
  365. func (na *NetAddress) RFC4380() bool { return rfc4380.Contains(na.IP) }
  366. func (na *NetAddress) RFC4843() bool { return rfc4843.Contains(na.IP) }
  367. func (na *NetAddress) RFC4862() bool { return rfc4862.Contains(na.IP) }
  368. func (na *NetAddress) RFC6052() bool { return rfc6052.Contains(na.IP) }
  369. func (na *NetAddress) RFC6145() bool { return rfc6145.Contains(na.IP) }
  370. func (na *NetAddress) OnionCatTor() bool { return onionCatNet.Contains(na.IP) }
  371. func removeProtocolIfDefined(addr string) string {
  372. if strings.Contains(addr, "://") {
  373. return strings.Split(addr, "://")[1]
  374. }
  375. return addr
  376. }