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.

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