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.

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