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.

422 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 PexAddress into a native struct.
  123. // FIXME: Remove this when legacy PEX reactor is removed.
  124. func NetAddressFromProto(pb tmp2p.PexAddress) (*NetAddress, error) {
  125. ip := net.ParseIP(pb.IP)
  126. if ip == nil {
  127. return nil, fmt.Errorf("invalid IP address %v", pb.IP)
  128. }
  129. if pb.Port >= 1<<16 {
  130. return nil, fmt.Errorf("invalid port number %v", pb.Port)
  131. }
  132. return &NetAddress{
  133. ID: NodeID(pb.ID),
  134. IP: ip,
  135. Port: uint16(pb.Port),
  136. }, nil
  137. }
  138. // NetAddressesFromProto converts a slice of Protobuf PexAddresses into a native slice.
  139. // FIXME: Remove this when legacy PEX reactor is removed.
  140. func NetAddressesFromProto(pbs []tmp2p.PexAddress) ([]*NetAddress, error) {
  141. nas := make([]*NetAddress, 0, len(pbs))
  142. for _, pb := range pbs {
  143. na, err := NetAddressFromProto(pb)
  144. if err != nil {
  145. return nil, err
  146. }
  147. nas = append(nas, na)
  148. }
  149. return nas, nil
  150. }
  151. // NetAddressesToProto converts a slice of NetAddresses into a Protobuf PexAddress slice.
  152. // FIXME: Remove this when legacy PEX reactor is removed.
  153. func NetAddressesToProto(nas []*NetAddress) []tmp2p.PexAddress {
  154. pbs := make([]tmp2p.PexAddress, 0, len(nas))
  155. for _, na := range nas {
  156. if na != nil {
  157. pbs = append(pbs, na.ToProto())
  158. }
  159. }
  160. return pbs
  161. }
  162. // ToProto converts a NetAddress to a Protobuf PexAddress.
  163. // FIXME: Remove this when legacy PEX reactor is removed.
  164. func (na *NetAddress) ToProto() tmp2p.PexAddress {
  165. return tmp2p.PexAddress{
  166. ID: string(na.ID),
  167. IP: na.IP.String(),
  168. Port: uint32(na.Port),
  169. }
  170. }
  171. // Equals reports whether na and other are the same addresses,
  172. // including their ID, IP, and Port.
  173. func (na *NetAddress) Equals(other interface{}) bool {
  174. if o, ok := other.(*NetAddress); ok {
  175. return na.String() == o.String()
  176. }
  177. return false
  178. }
  179. // Same returns true is na has the same non-empty ID or DialString as other.
  180. func (na *NetAddress) Same(other interface{}) bool {
  181. if o, ok := other.(*NetAddress); ok {
  182. if na.DialString() == o.DialString() {
  183. return true
  184. }
  185. if na.ID != "" && na.ID == o.ID {
  186. return true
  187. }
  188. }
  189. return false
  190. }
  191. // String representation: <ID>@<IP>:<PORT>
  192. func (na *NetAddress) String() string {
  193. if na == nil {
  194. return EmptyNetAddress
  195. }
  196. addrStr := na.DialString()
  197. if na.ID != "" {
  198. addrStr = IDAddressString(na.ID, addrStr)
  199. }
  200. return addrStr
  201. }
  202. func (na *NetAddress) DialString() string {
  203. if na == nil {
  204. return "<nil-NetAddress>"
  205. }
  206. return net.JoinHostPort(
  207. na.IP.String(),
  208. strconv.FormatUint(uint64(na.Port), 10),
  209. )
  210. }
  211. // Dial calls net.Dial on the address.
  212. func (na *NetAddress) Dial() (net.Conn, error) {
  213. conn, err := net.Dial("tcp", na.DialString())
  214. if err != nil {
  215. return nil, err
  216. }
  217. return conn, nil
  218. }
  219. // DialTimeout calls net.DialTimeout on the address.
  220. func (na *NetAddress) DialTimeout(timeout time.Duration) (net.Conn, error) {
  221. conn, err := net.DialTimeout("tcp", na.DialString(), timeout)
  222. if err != nil {
  223. return nil, err
  224. }
  225. return conn, nil
  226. }
  227. // Routable returns true if the address is routable.
  228. func (na *NetAddress) Routable() bool {
  229. if err := na.Valid(); err != nil {
  230. return false
  231. }
  232. // TODO(oga) bitcoind doesn't include RFC3849 here, but should we?
  233. return !(na.RFC1918() || na.RFC3927() || na.RFC4862() ||
  234. na.RFC4193() || na.RFC4843() || na.Local())
  235. }
  236. // For IPv4 these are either a 0 or all bits set address. For IPv6 a zero
  237. // address or one that matches the RFC3849 documentation address format.
  238. func (na *NetAddress) Valid() error {
  239. if err := na.ID.Validate(); err != nil {
  240. return fmt.Errorf("invalid ID: %w", err)
  241. }
  242. if na.IP == nil {
  243. return errors.New("no IP")
  244. }
  245. if na.IP.IsUnspecified() || na.RFC3849() || na.IP.Equal(net.IPv4bcast) {
  246. return errors.New("invalid IP")
  247. }
  248. return nil
  249. }
  250. // HasID returns true if the address has an ID.
  251. // NOTE: It does not check whether the ID is valid or not.
  252. func (na *NetAddress) HasID() bool {
  253. return string(na.ID) != ""
  254. }
  255. // Endpoint converts the address to an MConnection endpoint.
  256. func (na *NetAddress) Endpoint() Endpoint {
  257. return Endpoint{
  258. Protocol: MConnProtocol,
  259. IP: na.IP,
  260. Port: na.Port,
  261. }
  262. }
  263. // Local returns true if it is a local address.
  264. func (na *NetAddress) Local() bool {
  265. return na.IP.IsLoopback() || zero4.Contains(na.IP)
  266. }
  267. // ReachabilityTo checks whenever o can be reached from na.
  268. func (na *NetAddress) ReachabilityTo(o *NetAddress) int {
  269. const (
  270. Unreachable = 0
  271. Default = iota
  272. Teredo
  273. Ipv6Weak
  274. Ipv4
  275. Ipv6Strong
  276. )
  277. switch {
  278. case !na.Routable():
  279. return Unreachable
  280. case na.RFC4380():
  281. switch {
  282. case !o.Routable():
  283. return Default
  284. case o.RFC4380():
  285. return Teredo
  286. case o.IP.To4() != nil:
  287. return Ipv4
  288. default: // ipv6
  289. return Ipv6Weak
  290. }
  291. case na.IP.To4() != nil:
  292. if o.Routable() && o.IP.To4() != nil {
  293. return Ipv4
  294. }
  295. return Default
  296. default: /* ipv6 */
  297. var tunnelled bool
  298. // Is our v6 is tunnelled?
  299. if o.RFC3964() || o.RFC6052() || o.RFC6145() {
  300. tunnelled = true
  301. }
  302. switch {
  303. case !o.Routable():
  304. return Default
  305. case o.RFC4380():
  306. return Teredo
  307. case o.IP.To4() != nil:
  308. return Ipv4
  309. case tunnelled:
  310. // only prioritise ipv6 if we aren't tunnelling it.
  311. return Ipv6Weak
  312. }
  313. return Ipv6Strong
  314. }
  315. }
  316. // RFC1918: IPv4 Private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
  317. // RFC3849: IPv6 Documentation address (2001:0DB8::/32)
  318. // RFC3927: IPv4 Autoconfig (169.254.0.0/16)
  319. // RFC3964: IPv6 6to4 (2002::/16)
  320. // RFC4193: IPv6 unique local (FC00::/7)
  321. // RFC4380: IPv6 Teredo tunneling (2001::/32)
  322. // RFC4843: IPv6 ORCHID: (2001:10::/28)
  323. // RFC4862: IPv6 Autoconfig (FE80::/64)
  324. // RFC6052: IPv6 well known prefix (64:FF9B::/96)
  325. // RFC6145: IPv6 IPv4 translated address ::FFFF:0:0:0/96
  326. var rfc1918_10 = net.IPNet{IP: net.ParseIP("10.0.0.0"), Mask: net.CIDRMask(8, 32)}
  327. var rfc1918_192 = net.IPNet{IP: net.ParseIP("192.168.0.0"), Mask: net.CIDRMask(16, 32)}
  328. var rfc1918_172 = net.IPNet{IP: net.ParseIP("172.16.0.0"), Mask: net.CIDRMask(12, 32)}
  329. var rfc3849 = net.IPNet{IP: net.ParseIP("2001:0DB8::"), Mask: net.CIDRMask(32, 128)}
  330. var rfc3927 = net.IPNet{IP: net.ParseIP("169.254.0.0"), Mask: net.CIDRMask(16, 32)}
  331. var rfc3964 = net.IPNet{IP: net.ParseIP("2002::"), Mask: net.CIDRMask(16, 128)}
  332. var rfc4193 = net.IPNet{IP: net.ParseIP("FC00::"), Mask: net.CIDRMask(7, 128)}
  333. var rfc4380 = net.IPNet{IP: net.ParseIP("2001::"), Mask: net.CIDRMask(32, 128)}
  334. var rfc4843 = net.IPNet{IP: net.ParseIP("2001:10::"), Mask: net.CIDRMask(28, 128)}
  335. var rfc4862 = net.IPNet{IP: net.ParseIP("FE80::"), Mask: net.CIDRMask(64, 128)}
  336. var rfc6052 = net.IPNet{IP: net.ParseIP("64:FF9B::"), Mask: net.CIDRMask(96, 128)}
  337. var rfc6145 = net.IPNet{IP: net.ParseIP("::FFFF:0:0:0"), Mask: net.CIDRMask(96, 128)}
  338. var zero4 = net.IPNet{IP: net.ParseIP("0.0.0.0"), Mask: net.CIDRMask(8, 32)}
  339. var (
  340. // onionCatNet defines the IPv6 address block used to support Tor.
  341. // bitcoind encodes a .onion address as a 16 byte number by decoding the
  342. // address prior to the .onion (i.e. the key hash) base32 into a ten
  343. // byte number. It then stores the first 6 bytes of the address as
  344. // 0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43.
  345. //
  346. // This is the same range used by OnionCat, which is part part of the
  347. // RFC4193 unique local IPv6 range.
  348. //
  349. // In summary the format is:
  350. // { magic 6 bytes, 10 bytes base32 decode of key hash }
  351. onionCatNet = ipNet("fd87:d87e:eb43::", 48, 128)
  352. )
  353. // ipNet returns a net.IPNet struct given the passed IP address string, number
  354. // of one bits to include at the start of the mask, and the total number of bits
  355. // for the mask.
  356. func ipNet(ip string, ones, bits int) net.IPNet {
  357. return net.IPNet{IP: net.ParseIP(ip), Mask: net.CIDRMask(ones, bits)}
  358. }
  359. func (na *NetAddress) RFC1918() bool {
  360. return rfc1918_10.Contains(na.IP) ||
  361. rfc1918_192.Contains(na.IP) ||
  362. rfc1918_172.Contains(na.IP)
  363. }
  364. func (na *NetAddress) RFC3849() bool { return rfc3849.Contains(na.IP) }
  365. func (na *NetAddress) RFC3927() bool { return rfc3927.Contains(na.IP) }
  366. func (na *NetAddress) RFC3964() bool { return rfc3964.Contains(na.IP) }
  367. func (na *NetAddress) RFC4193() bool { return rfc4193.Contains(na.IP) }
  368. func (na *NetAddress) RFC4380() bool { return rfc4380.Contains(na.IP) }
  369. func (na *NetAddress) RFC4843() bool { return rfc4843.Contains(na.IP) }
  370. func (na *NetAddress) RFC4862() bool { return rfc4862.Contains(na.IP) }
  371. func (na *NetAddress) RFC6052() bool { return rfc6052.Contains(na.IP) }
  372. func (na *NetAddress) RFC6145() bool { return rfc6145.Contains(na.IP) }
  373. func (na *NetAddress) OnionCatTor() bool { return onionCatNet.Contains(na.IP) }
  374. func removeProtocolIfDefined(addr string) string {
  375. if strings.Contains(addr, "://") {
  376. return strings.Split(addr, "://")[1]
  377. }
  378. return addr
  379. }