@ -1,69 +0,0 @@ | |||||
package mock | |||||
import ( | |||||
"net" | |||||
"github.com/tendermint/tendermint/internal/p2p" | |||||
"github.com/tendermint/tendermint/libs/service" | |||||
"github.com/tendermint/tendermint/types" | |||||
) | |||||
type Peer struct { | |||||
*service.BaseService | |||||
ip net.IP | |||||
id types.NodeID | |||||
addr *p2p.NetAddress | |||||
kv map[string]interface{} | |||||
Outbound, Persistent bool | |||||
} | |||||
// NewPeer creates and starts a new mock peer. If the ip | |||||
// is nil, random routable address is used. | |||||
func NewPeer(ip net.IP) *Peer { | |||||
var netAddr *p2p.NetAddress | |||||
if ip == nil { | |||||
_, netAddr = p2p.CreateRoutableAddr() | |||||
} else { | |||||
netAddr = types.NewNetAddressIPPort(ip, 26656) | |||||
} | |||||
nodeKey := types.GenNodeKey() | |||||
netAddr.ID = nodeKey.ID | |||||
mp := &Peer{ | |||||
ip: ip, | |||||
id: nodeKey.ID, | |||||
addr: netAddr, | |||||
kv: make(map[string]interface{}), | |||||
} | |||||
mp.BaseService = service.NewBaseService(nil, "MockPeer", mp) | |||||
if err := mp.Start(); err != nil { | |||||
panic(err) | |||||
} | |||||
return mp | |||||
} | |||||
func (mp *Peer) FlushStop() { mp.Stop() } //nolint:errcheck //ignore error | |||||
func (mp *Peer) TrySend(chID byte, msgBytes []byte) bool { return true } | |||||
func (mp *Peer) Send(chID byte, msgBytes []byte) bool { return true } | |||||
func (mp *Peer) NodeInfo() types.NodeInfo { | |||||
return types.NodeInfo{ | |||||
NodeID: mp.addr.ID, | |||||
ListenAddr: mp.addr.DialString(), | |||||
} | |||||
} | |||||
func (mp *Peer) ID() types.NodeID { return mp.id } | |||||
func (mp *Peer) IsOutbound() bool { return mp.Outbound } | |||||
func (mp *Peer) IsPersistent() bool { return mp.Persistent } | |||||
func (mp *Peer) Get(key string) interface{} { | |||||
if value, ok := mp.kv[key]; ok { | |||||
return value | |||||
} | |||||
return nil | |||||
} | |||||
func (mp *Peer) Set(key string, value interface{}) { | |||||
mp.kv[key] = value | |||||
} | |||||
func (mp *Peer) RemoteIP() net.IP { return mp.ip } | |||||
func (mp *Peer) SocketAddr() *p2p.NetAddress { return mp.addr } | |||||
func (mp *Peer) RemoteAddr() net.Addr { return &net.TCPAddr{IP: mp.ip, Port: 8800} } | |||||
func (mp *Peer) CloseConn() error { return nil } |
@ -1,319 +0,0 @@ | |||||
// Code generated by mockery. DO NOT EDIT. | |||||
package mocks | |||||
import ( | |||||
log "github.com/tendermint/tendermint/libs/log" | |||||
mock "github.com/stretchr/testify/mock" | |||||
net "net" | |||||
types "github.com/tendermint/tendermint/types" | |||||
) | |||||
// Peer is an autogenerated mock type for the Peer type | |||||
type Peer struct { | |||||
mock.Mock | |||||
} | |||||
// CloseConn provides a mock function with given fields: | |||||
func (_m *Peer) CloseConn() error { | |||||
ret := _m.Called() | |||||
var r0 error | |||||
if rf, ok := ret.Get(0).(func() error); ok { | |||||
r0 = rf() | |||||
} else { | |||||
r0 = ret.Error(0) | |||||
} | |||||
return r0 | |||||
} | |||||
// FlushStop provides a mock function with given fields: | |||||
func (_m *Peer) FlushStop() { | |||||
_m.Called() | |||||
} | |||||
// Get provides a mock function with given fields: _a0 | |||||
func (_m *Peer) Get(_a0 string) interface{} { | |||||
ret := _m.Called(_a0) | |||||
var r0 interface{} | |||||
if rf, ok := ret.Get(0).(func(string) interface{}); ok { | |||||
r0 = rf(_a0) | |||||
} else { | |||||
if ret.Get(0) != nil { | |||||
r0 = ret.Get(0).(interface{}) | |||||
} | |||||
} | |||||
return r0 | |||||
} | |||||
// ID provides a mock function with given fields: | |||||
func (_m *Peer) ID() types.NodeID { | |||||
ret := _m.Called() | |||||
var r0 types.NodeID | |||||
if rf, ok := ret.Get(0).(func() types.NodeID); ok { | |||||
r0 = rf() | |||||
} else { | |||||
r0 = ret.Get(0).(types.NodeID) | |||||
} | |||||
return r0 | |||||
} | |||||
// IsOutbound provides a mock function with given fields: | |||||
func (_m *Peer) IsOutbound() bool { | |||||
ret := _m.Called() | |||||
var r0 bool | |||||
if rf, ok := ret.Get(0).(func() bool); ok { | |||||
r0 = rf() | |||||
} else { | |||||
r0 = ret.Get(0).(bool) | |||||
} | |||||
return r0 | |||||
} | |||||
// IsPersistent provides a mock function with given fields: | |||||
func (_m *Peer) IsPersistent() bool { | |||||
ret := _m.Called() | |||||
var r0 bool | |||||
if rf, ok := ret.Get(0).(func() bool); ok { | |||||
r0 = rf() | |||||
} else { | |||||
r0 = ret.Get(0).(bool) | |||||
} | |||||
return r0 | |||||
} | |||||
// IsRunning provides a mock function with given fields: | |||||
func (_m *Peer) IsRunning() bool { | |||||
ret := _m.Called() | |||||
var r0 bool | |||||
if rf, ok := ret.Get(0).(func() bool); ok { | |||||
r0 = rf() | |||||
} else { | |||||
r0 = ret.Get(0).(bool) | |||||
} | |||||
return r0 | |||||
} | |||||
// NodeInfo provides a mock function with given fields: | |||||
func (_m *Peer) NodeInfo() types.NodeInfo { | |||||
ret := _m.Called() | |||||
var r0 types.NodeInfo | |||||
if rf, ok := ret.Get(0).(func() types.NodeInfo); ok { | |||||
r0 = rf() | |||||
} else { | |||||
r0 = ret.Get(0).(types.NodeInfo) | |||||
} | |||||
return r0 | |||||
} | |||||
// OnReset provides a mock function with given fields: | |||||
func (_m *Peer) OnReset() error { | |||||
ret := _m.Called() | |||||
var r0 error | |||||
if rf, ok := ret.Get(0).(func() error); ok { | |||||
r0 = rf() | |||||
} else { | |||||
r0 = ret.Error(0) | |||||
} | |||||
return r0 | |||||
} | |||||
// OnStart provides a mock function with given fields: | |||||
func (_m *Peer) OnStart() error { | |||||
ret := _m.Called() | |||||
var r0 error | |||||
if rf, ok := ret.Get(0).(func() error); ok { | |||||
r0 = rf() | |||||
} else { | |||||
r0 = ret.Error(0) | |||||
} | |||||
return r0 | |||||
} | |||||
// OnStop provides a mock function with given fields: | |||||
func (_m *Peer) OnStop() { | |||||
_m.Called() | |||||
} | |||||
// Quit provides a mock function with given fields: | |||||
func (_m *Peer) Quit() <-chan struct{} { | |||||
ret := _m.Called() | |||||
var r0 <-chan struct{} | |||||
if rf, ok := ret.Get(0).(func() <-chan struct{}); ok { | |||||
r0 = rf() | |||||
} else { | |||||
if ret.Get(0) != nil { | |||||
r0 = ret.Get(0).(<-chan struct{}) | |||||
} | |||||
} | |||||
return r0 | |||||
} | |||||
// RemoteAddr provides a mock function with given fields: | |||||
func (_m *Peer) RemoteAddr() net.Addr { | |||||
ret := _m.Called() | |||||
var r0 net.Addr | |||||
if rf, ok := ret.Get(0).(func() net.Addr); ok { | |||||
r0 = rf() | |||||
} else { | |||||
if ret.Get(0) != nil { | |||||
r0 = ret.Get(0).(net.Addr) | |||||
} | |||||
} | |||||
return r0 | |||||
} | |||||
// RemoteIP provides a mock function with given fields: | |||||
func (_m *Peer) RemoteIP() net.IP { | |||||
ret := _m.Called() | |||||
var r0 net.IP | |||||
if rf, ok := ret.Get(0).(func() net.IP); ok { | |||||
r0 = rf() | |||||
} else { | |||||
if ret.Get(0) != nil { | |||||
r0 = ret.Get(0).(net.IP) | |||||
} | |||||
} | |||||
return r0 | |||||
} | |||||
// Reset provides a mock function with given fields: | |||||
func (_m *Peer) Reset() error { | |||||
ret := _m.Called() | |||||
var r0 error | |||||
if rf, ok := ret.Get(0).(func() error); ok { | |||||
r0 = rf() | |||||
} else { | |||||
r0 = ret.Error(0) | |||||
} | |||||
return r0 | |||||
} | |||||
// Send provides a mock function with given fields: _a0, _a1 | |||||
func (_m *Peer) Send(_a0 byte, _a1 []byte) bool { | |||||
ret := _m.Called(_a0, _a1) | |||||
var r0 bool | |||||
if rf, ok := ret.Get(0).(func(byte, []byte) bool); ok { | |||||
r0 = rf(_a0, _a1) | |||||
} else { | |||||
r0 = ret.Get(0).(bool) | |||||
} | |||||
return r0 | |||||
} | |||||
// Set provides a mock function with given fields: _a0, _a1 | |||||
func (_m *Peer) Set(_a0 string, _a1 interface{}) { | |||||
_m.Called(_a0, _a1) | |||||
} | |||||
// SetLogger provides a mock function with given fields: _a0 | |||||
func (_m *Peer) SetLogger(_a0 log.Logger) { | |||||
_m.Called(_a0) | |||||
} | |||||
// SocketAddr provides a mock function with given fields: | |||||
func (_m *Peer) SocketAddr() *types.NetAddress { | |||||
ret := _m.Called() | |||||
var r0 *types.NetAddress | |||||
if rf, ok := ret.Get(0).(func() *types.NetAddress); ok { | |||||
r0 = rf() | |||||
} else { | |||||
if ret.Get(0) != nil { | |||||
r0 = ret.Get(0).(*types.NetAddress) | |||||
} | |||||
} | |||||
return r0 | |||||
} | |||||
// Start provides a mock function with given fields: | |||||
func (_m *Peer) Start() error { | |||||
ret := _m.Called() | |||||
var r0 error | |||||
if rf, ok := ret.Get(0).(func() error); ok { | |||||
r0 = rf() | |||||
} else { | |||||
r0 = ret.Error(0) | |||||
} | |||||
return r0 | |||||
} | |||||
// Stop provides a mock function with given fields: | |||||
func (_m *Peer) Stop() error { | |||||
ret := _m.Called() | |||||
var r0 error | |||||
if rf, ok := ret.Get(0).(func() error); ok { | |||||
r0 = rf() | |||||
} else { | |||||
r0 = ret.Error(0) | |||||
} | |||||
return r0 | |||||
} | |||||
// String provides a mock function with given fields: | |||||
func (_m *Peer) String() string { | |||||
ret := _m.Called() | |||||
var r0 string | |||||
if rf, ok := ret.Get(0).(func() string); ok { | |||||
r0 = rf() | |||||
} else { | |||||
r0 = ret.Get(0).(string) | |||||
} | |||||
return r0 | |||||
} | |||||
// TrySend provides a mock function with given fields: _a0, _a1 | |||||
func (_m *Peer) TrySend(_a0 byte, _a1 []byte) bool { | |||||
ret := _m.Called(_a0, _a1) | |||||
var r0 bool | |||||
if rf, ok := ret.Get(0).(func(byte, []byte) bool); ok { | |||||
r0 = rf(_a0, _a1) | |||||
} else { | |||||
r0 = ret.Get(0).(bool) | |||||
} | |||||
return r0 | |||||
} | |||||
// Wait provides a mock function with given fields: | |||||
func (_m *Peer) Wait() { | |||||
_m.Called() | |||||
} |
@ -1,11 +0,0 @@ | |||||
// Modified for Tendermint | |||||
// Originally Copyright (c) 2013-2014 Conformal Systems LLC. | |||||
// https://github.com/conformal/btcd/blob/master/LICENSE | |||||
package p2p | |||||
import ( | |||||
"github.com/tendermint/tendermint/types" | |||||
) | |||||
type NetAddress = types.NetAddress |
@ -1,78 +0,0 @@ | |||||
package pex | |||||
import ( | |||||
"errors" | |||||
"fmt" | |||||
"github.com/tendermint/tendermint/internal/p2p" | |||||
) | |||||
type ErrAddrBookNonRoutable struct { | |||||
Addr *p2p.NetAddress | |||||
} | |||||
func (err ErrAddrBookNonRoutable) Error() string { | |||||
return fmt.Sprintf("Cannot add non-routable address %v", err.Addr) | |||||
} | |||||
type ErrAddrBookSelf struct { | |||||
Addr *p2p.NetAddress | |||||
} | |||||
func (err ErrAddrBookSelf) Error() string { | |||||
return fmt.Sprintf("Cannot add ourselves with address %v", err.Addr) | |||||
} | |||||
type ErrAddrBookPrivate struct { | |||||
Addr *p2p.NetAddress | |||||
} | |||||
func (err ErrAddrBookPrivate) Error() string { | |||||
return fmt.Sprintf("Cannot add private peer with address %v", err.Addr) | |||||
} | |||||
func (err ErrAddrBookPrivate) PrivateAddr() bool { | |||||
return true | |||||
} | |||||
type ErrAddrBookPrivateSrc struct { | |||||
Src *p2p.NetAddress | |||||
} | |||||
func (err ErrAddrBookPrivateSrc) Error() string { | |||||
return fmt.Sprintf("Cannot add peer coming from private peer with address %v", err.Src) | |||||
} | |||||
func (err ErrAddrBookPrivateSrc) PrivateAddr() bool { | |||||
return true | |||||
} | |||||
type ErrAddrBookNilAddr struct { | |||||
Addr *p2p.NetAddress | |||||
Src *p2p.NetAddress | |||||
} | |||||
func (err ErrAddrBookNilAddr) Error() string { | |||||
return fmt.Sprintf("Cannot add a nil address. Got (addr, src) = (%v, %v)", err.Addr, err.Src) | |||||
} | |||||
type ErrAddrBookInvalidAddr struct { | |||||
Addr *p2p.NetAddress | |||||
AddrErr error | |||||
} | |||||
func (err ErrAddrBookInvalidAddr) Error() string { | |||||
return fmt.Sprintf("Cannot add invalid address %v: %v", err.Addr, err.AddrErr) | |||||
} | |||||
// ErrAddressBanned is thrown when the address has been banned and therefore cannot be used | |||||
type ErrAddressBanned struct { | |||||
Addr *p2p.NetAddress | |||||
} | |||||
func (err ErrAddressBanned) Error() string { | |||||
return fmt.Sprintf("Address: %v is currently banned", err.Addr) | |||||
} | |||||
// ErrUnsolicitedList is thrown when a peer provides a list of addresses that have not been asked for. | |||||
var ErrUnsolicitedList = errors.New("unsolicited pexAddrsMessage") |
@ -1,32 +0,0 @@ | |||||
package p2p | |||||
import ( | |||||
"fmt" | |||||
mrand "math/rand" | |||||
tmrand "github.com/tendermint/tendermint/libs/rand" | |||||
"github.com/tendermint/tendermint/types" | |||||
) | |||||
//------------------------------------------------ | |||||
// nolint:gosec // G404: Use of weak random number generator | |||||
func CreateRoutableAddr() (addr string, netAddr *NetAddress) { | |||||
for { | |||||
var err error | |||||
addr = fmt.Sprintf("%X@%v.%v.%v.%v:26656", | |||||
tmrand.Bytes(20), | |||||
mrand.Int()%256, | |||||
mrand.Int()%256, | |||||
mrand.Int()%256, | |||||
mrand.Int()%256) | |||||
netAddr, err = types.NewNetAddressString(addr) | |||||
if err != nil { | |||||
panic(err) | |||||
} | |||||
if netAddr.Routable() { | |||||
break | |||||
} | |||||
} | |||||
return | |||||
} |
@ -1,329 +0,0 @@ | |||||
// Modified for Tendermint | |||||
// Originally Copyright (c) 2013-2014 Conformal Systems LLC. | |||||
// https://github.com/conformal/btcd/blob/master/LICENSE | |||||
package types | |||||
import ( | |||||
"errors" | |||||
"flag" | |||||
"fmt" | |||||
"net" | |||||
"strconv" | |||||
"strings" | |||||
"time" | |||||
) | |||||
// EmptyNetAddress defines the string representation of an empty NetAddress | |||||
const EmptyNetAddress = "<nil-NetAddress>" | |||||
// NetAddress defines information about a peer on the network | |||||
// including its ID, IP address, and port. | |||||
type NetAddress struct { | |||||
ID NodeID `json:"id"` | |||||
IP net.IP `json:"ip"` | |||||
Port uint16 `json:"port"` | |||||
} | |||||
// NewNetAddress returns a new NetAddress using the provided TCP | |||||
// address. When testing, other net.Addr (except TCP) will result in | |||||
// using 0.0.0.0:0. When normal run, other net.Addr (except TCP) will | |||||
// panic. Panics if ID is invalid. | |||||
// TODO: socks proxies? | |||||
func NewNetAddress(id NodeID, addr net.Addr) *NetAddress { | |||||
tcpAddr, ok := addr.(*net.TCPAddr) | |||||
if !ok { | |||||
if flag.Lookup("test.v") == nil { // normal run | |||||
panic(fmt.Sprintf("Only TCPAddrs are supported. Got: %v", addr)) | |||||
} else { // in testing | |||||
netAddr := NewNetAddressIPPort(net.IP("127.0.0.1"), 0) | |||||
netAddr.ID = id | |||||
return netAddr | |||||
} | |||||
} | |||||
if err := id.Validate(); err != nil { | |||||
panic(fmt.Sprintf("Invalid ID %v: %v (addr: %v)", id, err, addr)) | |||||
} | |||||
ip := tcpAddr.IP | |||||
port := uint16(tcpAddr.Port) | |||||
na := NewNetAddressIPPort(ip, port) | |||||
na.ID = id | |||||
return na | |||||
} | |||||
// NewNetAddressIPPort returns a new NetAddress using the provided IP | |||||
// and port number. | |||||
func NewNetAddressIPPort(ip net.IP, port uint16) *NetAddress { | |||||
return &NetAddress{ | |||||
IP: ip, | |||||
Port: port, | |||||
} | |||||
} | |||||
// NewNetAddressString returns a new NetAddress using the provided address in | |||||
// the form of "ID@IP:Port". | |||||
// Also resolves the host if host is not an IP. | |||||
// Errors are of type ErrNetAddressXxx where Xxx is in (NoID, Invalid, Lookup) | |||||
func NewNetAddressString(addr string) (*NetAddress, error) { | |||||
addrWithoutProtocol := removeProtocolIfDefined(addr) | |||||
spl := strings.Split(addrWithoutProtocol, "@") | |||||
if len(spl) != 2 { | |||||
return nil, ErrNetAddressNoID{addr} | |||||
} | |||||
id, err := NewNodeID(spl[0]) | |||||
if err != nil { | |||||
return nil, ErrNetAddressInvalid{addrWithoutProtocol, err} | |||||
} | |||||
if err := id.Validate(); err != nil { | |||||
return nil, ErrNetAddressInvalid{addrWithoutProtocol, err} | |||||
} | |||||
addrWithoutProtocol = spl[1] | |||||
// get host and port | |||||
host, portStr, err := net.SplitHostPort(addrWithoutProtocol) | |||||
if err != nil { | |||||
return nil, ErrNetAddressInvalid{addrWithoutProtocol, err} | |||||
} | |||||
if len(host) == 0 { | |||||
return nil, ErrNetAddressInvalid{ | |||||
addrWithoutProtocol, | |||||
errors.New("host is empty")} | |||||
} | |||||
ip := net.ParseIP(host) | |||||
if ip == nil { | |||||
ips, err := net.LookupIP(host) | |||||
if err != nil { | |||||
return nil, ErrNetAddressLookup{host, err} | |||||
} | |||||
ip = ips[0] | |||||
} | |||||
port, err := strconv.ParseUint(portStr, 10, 16) | |||||
if err != nil { | |||||
return nil, ErrNetAddressInvalid{portStr, err} | |||||
} | |||||
na := NewNetAddressIPPort(ip, uint16(port)) | |||||
na.ID = id | |||||
return na, nil | |||||
} | |||||
// Equals reports whether na and other are the same addresses, | |||||
// including their ID, IP, and Port. | |||||
func (na *NetAddress) Equals(other interface{}) bool { | |||||
if o, ok := other.(*NetAddress); ok { | |||||
return na.String() == o.String() | |||||
} | |||||
return false | |||||
} | |||||
// Same returns true is na has the same non-empty ID or DialString as other. | |||||
func (na *NetAddress) Same(other interface{}) bool { | |||||
if o, ok := other.(*NetAddress); ok { | |||||
if na.DialString() == o.DialString() { | |||||
return true | |||||
} | |||||
if na.ID != "" && na.ID == o.ID { | |||||
return true | |||||
} | |||||
} | |||||
return false | |||||
} | |||||
// String representation: <ID>@<IP>:<PORT> | |||||
func (na *NetAddress) String() string { | |||||
if na == nil { | |||||
return EmptyNetAddress | |||||
} | |||||
addrStr := na.DialString() | |||||
if na.ID != "" { | |||||
addrStr = na.ID.AddressString(addrStr) | |||||
} | |||||
return addrStr | |||||
} | |||||
func (na *NetAddress) DialString() string { | |||||
if na == nil { | |||||
return "<nil-NetAddress>" | |||||
} | |||||
return net.JoinHostPort( | |||||
na.IP.String(), | |||||
strconv.FormatUint(uint64(na.Port), 10), | |||||
) | |||||
} | |||||
// Dial calls net.Dial on the address. | |||||
func (na *NetAddress) Dial() (net.Conn, error) { | |||||
conn, err := net.Dial("tcp", na.DialString()) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
return conn, nil | |||||
} | |||||
// DialTimeout calls net.DialTimeout on the address. | |||||
func (na *NetAddress) DialTimeout(timeout time.Duration) (net.Conn, error) { | |||||
conn, err := net.DialTimeout("tcp", na.DialString(), timeout) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
return conn, nil | |||||
} | |||||
// Routable returns true if the address is routable. | |||||
func (na *NetAddress) Routable() bool { | |||||
if err := na.Valid(); err != nil { | |||||
return false | |||||
} | |||||
// TODO(oga) bitcoind doesn't include RFC3849 here, but should we? | |||||
return !(na.RFC1918() || na.RFC3927() || na.RFC4862() || | |||||
na.RFC4193() || na.RFC4843() || na.Local()) | |||||
} | |||||
// For IPv4 these are either a 0 or all bits set address. For IPv6 a zero | |||||
// address or one that matches the RFC3849 documentation address format. | |||||
func (na *NetAddress) Valid() error { | |||||
if err := na.ID.Validate(); err != nil { | |||||
return fmt.Errorf("invalid ID: %w", err) | |||||
} | |||||
if na.IP == nil { | |||||
return errors.New("no IP") | |||||
} | |||||
if na.IP.IsUnspecified() || na.RFC3849() || na.IP.Equal(net.IPv4bcast) { | |||||
return errors.New("invalid IP") | |||||
} | |||||
return nil | |||||
} | |||||
// Local returns true if it is a local address. | |||||
func (na *NetAddress) Local() bool { | |||||
return na.IP.IsLoopback() || zero4.Contains(na.IP) | |||||
} | |||||
// ReachabilityTo checks whenever o can be reached from na. | |||||
func (na *NetAddress) ReachabilityTo(o *NetAddress) int { | |||||
const ( | |||||
Unreachable = 0 | |||||
Default = iota | |||||
Teredo | |||||
Ipv6Weak | |||||
Ipv4 | |||||
Ipv6Strong | |||||
) | |||||
switch { | |||||
case !na.Routable(): | |||||
return Unreachable | |||||
case na.RFC4380(): | |||||
switch { | |||||
case !o.Routable(): | |||||
return Default | |||||
case o.RFC4380(): | |||||
return Teredo | |||||
case o.IP.To4() != nil: | |||||
return Ipv4 | |||||
default: // ipv6 | |||||
return Ipv6Weak | |||||
} | |||||
case na.IP.To4() != nil: | |||||
if o.Routable() && o.IP.To4() != nil { | |||||
return Ipv4 | |||||
} | |||||
return Default | |||||
default: /* ipv6 */ | |||||
var tunneled bool | |||||
// Is our v6 is tunneled? | |||||
if o.RFC3964() || o.RFC6052() || o.RFC6145() { | |||||
tunneled = true | |||||
} | |||||
switch { | |||||
case !o.Routable(): | |||||
return Default | |||||
case o.RFC4380(): | |||||
return Teredo | |||||
case o.IP.To4() != nil: | |||||
return Ipv4 | |||||
case tunneled: | |||||
// only prioritize ipv6 if we aren't tunneling it. | |||||
return Ipv6Weak | |||||
} | |||||
return Ipv6Strong | |||||
} | |||||
} | |||||
// RFC1918: IPv4 Private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12) | |||||
// RFC3849: IPv6 Documentation address (2001:0DB8::/32) | |||||
// RFC3927: IPv4 Autoconfig (169.254.0.0/16) | |||||
// RFC3964: IPv6 6to4 (2002::/16) | |||||
// RFC4193: IPv6 unique local (FC00::/7) | |||||
// RFC4380: IPv6 Teredo tunneling (2001::/32) | |||||
// RFC4843: IPv6 ORCHID: (2001:10::/28) | |||||
// RFC4862: IPv6 Autoconfig (FE80::/64) | |||||
// RFC6052: IPv6 well known prefix (64:FF9B::/96) | |||||
// RFC6145: IPv6 IPv4 translated address ::FFFF:0:0:0/96 | |||||
var rfc1918_10 = net.IPNet{IP: net.ParseIP("10.0.0.0"), Mask: net.CIDRMask(8, 32)} | |||||
var rfc1918_192 = net.IPNet{IP: net.ParseIP("192.168.0.0"), Mask: net.CIDRMask(16, 32)} | |||||
var rfc1918_172 = net.IPNet{IP: net.ParseIP("172.16.0.0"), Mask: net.CIDRMask(12, 32)} | |||||
var rfc3849 = net.IPNet{IP: net.ParseIP("2001:0DB8::"), Mask: net.CIDRMask(32, 128)} | |||||
var rfc3927 = net.IPNet{IP: net.ParseIP("169.254.0.0"), Mask: net.CIDRMask(16, 32)} | |||||
var rfc3964 = net.IPNet{IP: net.ParseIP("2002::"), Mask: net.CIDRMask(16, 128)} | |||||
var rfc4193 = net.IPNet{IP: net.ParseIP("FC00::"), Mask: net.CIDRMask(7, 128)} | |||||
var rfc4380 = net.IPNet{IP: net.ParseIP("2001::"), Mask: net.CIDRMask(32, 128)} | |||||
var rfc4843 = net.IPNet{IP: net.ParseIP("2001:10::"), Mask: net.CIDRMask(28, 128)} | |||||
var rfc4862 = net.IPNet{IP: net.ParseIP("FE80::"), Mask: net.CIDRMask(64, 128)} | |||||
var rfc6052 = net.IPNet{IP: net.ParseIP("64:FF9B::"), Mask: net.CIDRMask(96, 128)} | |||||
var rfc6145 = net.IPNet{IP: net.ParseIP("::FFFF:0:0:0"), Mask: net.CIDRMask(96, 128)} | |||||
var zero4 = net.IPNet{IP: net.ParseIP("0.0.0.0"), Mask: net.CIDRMask(8, 32)} | |||||
var ( | |||||
// onionCatNet defines the IPv6 address block used to support Tor. | |||||
// bitcoind encodes a .onion address as a 16 byte number by decoding the | |||||
// address prior to the .onion (i.e. the key hash) base32 into a ten | |||||
// byte number. It then stores the first 6 bytes of the address as | |||||
// 0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43. | |||||
// | |||||
// This is the same range used by OnionCat, which is part part of the | |||||
// RFC4193 unique local IPv6 range. | |||||
// | |||||
// In summary the format is: | |||||
// { magic 6 bytes, 10 bytes base32 decode of key hash } | |||||
onionCatNet = ipNet("fd87:d87e:eb43::", 48, 128) | |||||
) | |||||
func (na *NetAddress) RFC1918() bool { | |||||
return rfc1918_10.Contains(na.IP) || | |||||
rfc1918_192.Contains(na.IP) || | |||||
rfc1918_172.Contains(na.IP) | |||||
} | |||||
func (na *NetAddress) RFC3849() bool { return rfc3849.Contains(na.IP) } | |||||
func (na *NetAddress) RFC3927() bool { return rfc3927.Contains(na.IP) } | |||||
func (na *NetAddress) RFC3964() bool { return rfc3964.Contains(na.IP) } | |||||
func (na *NetAddress) RFC4193() bool { return rfc4193.Contains(na.IP) } | |||||
func (na *NetAddress) RFC4380() bool { return rfc4380.Contains(na.IP) } | |||||
func (na *NetAddress) RFC4843() bool { return rfc4843.Contains(na.IP) } | |||||
func (na *NetAddress) RFC4862() bool { return rfc4862.Contains(na.IP) } | |||||
func (na *NetAddress) RFC6052() bool { return rfc6052.Contains(na.IP) } | |||||
func (na *NetAddress) RFC6145() bool { return rfc6145.Contains(na.IP) } | |||||
func (na *NetAddress) OnionCatTor() bool { return onionCatNet.Contains(na.IP) } | |||||
func removeProtocolIfDefined(addr string) string { | |||||
if strings.Contains(addr, "://") { | |||||
return strings.Split(addr, "://")[1] | |||||
} | |||||
return addr | |||||
} | |||||
// ipNet returns a net.IPNet struct given the passed IP address string, number | |||||
// of one bits to include at the start of the mask, and the total number of bits | |||||
// for the mask. | |||||
func ipNet(ip string, ones, bits int) net.IPNet { | |||||
return net.IPNet{IP: net.ParseIP(ip), Mask: net.CIDRMask(ones, bits)} | |||||
} |
@ -1,183 +0,0 @@ | |||||
package types | |||||
import ( | |||||
"net" | |||||
"sync" | |||||
"testing" | |||||
"github.com/stretchr/testify/assert" | |||||
"github.com/stretchr/testify/require" | |||||
) | |||||
func TestNetAddress_String(t *testing.T) { | |||||
tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:8080") | |||||
require.Nil(t, err) | |||||
netAddr := NewNetAddress("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef", tcpAddr) | |||||
var wg sync.WaitGroup | |||||
for i := 0; i < 10; i++ { | |||||
wg.Add(1) | |||||
go func() { | |||||
defer wg.Done() | |||||
_ = netAddr.String() | |||||
}() | |||||
} | |||||
wg.Wait() | |||||
s := netAddr.String() | |||||
require.Equal(t, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", s) | |||||
} | |||||
func TestNewNetAddress(t *testing.T) { | |||||
tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:8080") | |||||
require.Nil(t, err) | |||||
assert.Panics(t, func() { | |||||
NewNetAddress("", tcpAddr) | |||||
}) | |||||
addr := NewNetAddress("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef", tcpAddr) | |||||
assert.Equal(t, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", addr.String()) | |||||
assert.NotPanics(t, func() { | |||||
NewNetAddress("", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8000}) | |||||
}, "Calling NewNetAddress with UDPAddr should not panic in testing") | |||||
} | |||||
func TestNewNetAddressString(t *testing.T) { | |||||
testCases := []struct { | |||||
name string | |||||
addr string | |||||
expected string | |||||
correct bool | |||||
}{ | |||||
{"no node id and no protocol", "127.0.0.1:8080", "", false}, | |||||
{"no node id w/ tcp input", "tcp://127.0.0.1:8080", "", false}, | |||||
{"no node id w/ udp input", "udp://127.0.0.1:8080", "", false}, | |||||
{ | |||||
"no protocol", | |||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", | |||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", | |||||
true, | |||||
}, | |||||
{ | |||||
"tcp input", | |||||
"tcp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", | |||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", | |||||
true, | |||||
}, | |||||
{ | |||||
"udp input", | |||||
"udp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", | |||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", | |||||
true, | |||||
}, | |||||
{"malformed tcp input", "tcp//deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false}, | |||||
{"malformed udp input", "udp//deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false}, | |||||
// {"127.0.0:8080", false}, | |||||
{"invalid host", "notahost", "", false}, | |||||
{"invalid port", "127.0.0.1:notapath", "", false}, | |||||
{"invalid host w/ port", "notahost:8080", "", false}, | |||||
{"just a port", "8082", "", false}, | |||||
{"non-existent port", "127.0.0:8080000", "", false}, | |||||
{"too short nodeId", "deadbeef@127.0.0.1:8080", "", false}, | |||||
{"too short, not hex nodeId", "this-isnot-hex@127.0.0.1:8080", "", false}, | |||||
{"not hex nodeId", "xxxxbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false}, | |||||
{"too short nodeId w/tcp", "tcp://deadbeef@127.0.0.1:8080", "", false}, | |||||
{"too short notHex nodeId w/tcp", "tcp://this-isnot-hex@127.0.0.1:8080", "", false}, | |||||
{"notHex nodeId w/tcp", "tcp://xxxxbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", "", false}, | |||||
{ | |||||
"correct nodeId w/tcp", | |||||
"tcp://deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", | |||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", | |||||
true, | |||||
}, | |||||
{"no node id", "tcp://@127.0.0.1:8080", "", false}, | |||||
{"no node id or IP", "tcp://@", "", false}, | |||||
{"tcp no host, w/ port", "tcp://:26656", "", false}, | |||||
{"empty", "", "", false}, | |||||
{"node id delimiter 1", "@", "", false}, | |||||
{"node id delimiter 2", " @", "", false}, | |||||
{"node id delimiter 3", " @ ", "", false}, | |||||
} | |||||
for _, tc := range testCases { | |||||
tc := tc | |||||
t.Run(tc.name, func(t *testing.T) { | |||||
addr, err := NewNetAddressString(tc.addr) | |||||
if tc.correct { | |||||
if assert.Nil(t, err, tc.addr) { | |||||
assert.Equal(t, tc.expected, addr.String()) | |||||
} | |||||
} else { | |||||
assert.NotNil(t, err, tc.addr) | |||||
} | |||||
}) | |||||
} | |||||
} | |||||
func TestNewNetAddressIPPort(t *testing.T) { | |||||
addr := NewNetAddressIPPort(net.ParseIP("127.0.0.1"), 8080) | |||||
assert.Equal(t, "127.0.0.1:8080", addr.String()) | |||||
} | |||||
func TestNetAddressProperties(t *testing.T) { | |||||
// TODO add more test cases | |||||
testCases := []struct { | |||||
addr string | |||||
valid bool | |||||
local bool | |||||
routable bool | |||||
}{ | |||||
{"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", true, true, false}, | |||||
{"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@ya.ru:80", true, false, true}, | |||||
} | |||||
for _, tc := range testCases { | |||||
addr, err := NewNetAddressString(tc.addr) | |||||
require.Nil(t, err) | |||||
err = addr.Valid() | |||||
if tc.valid { | |||||
assert.NoError(t, err) | |||||
} else { | |||||
assert.Error(t, err) | |||||
} | |||||
assert.Equal(t, tc.local, addr.Local()) | |||||
assert.Equal(t, tc.routable, addr.Routable()) | |||||
} | |||||
} | |||||
func TestNetAddressReachabilityTo(t *testing.T) { | |||||
// TODO add more test cases | |||||
testCases := []struct { | |||||
addr string | |||||
other string | |||||
reachability int | |||||
}{ | |||||
{ | |||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", | |||||
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8081", | |||||
0, | |||||
}, | |||||
{"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@ya.ru:80", "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef@127.0.0.1:8080", 1}, | |||||
} | |||||
for _, tc := range testCases { | |||||
addr, err := NewNetAddressString(tc.addr) | |||||
require.Nil(t, err) | |||||
other, err := NewNetAddressString(tc.other) | |||||
require.Nil(t, err) | |||||
assert.Equal(t, tc.reachability, addr.ReachabilityTo(other)) | |||||
} | |||||
} |