github.com/okex/exchain@v1.8.0/libs/tendermint/p2p/netaddress.go (about)

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