mirror of
https://github.com/btcsuite/btcd.git
synced 2024-11-19 01:40:07 +01:00
multi: update addrmgr, server to use NetAddressV2 instead of legacy
This commit is contained in:
parent
1ec4a1e77f
commit
201c0836ec
@ -70,7 +70,7 @@ type serializedAddrManager struct {
|
||||
}
|
||||
|
||||
type localAddress struct {
|
||||
na *wire.NetAddress
|
||||
na *wire.NetAddressV2
|
||||
score AddressPriority
|
||||
}
|
||||
|
||||
@ -163,7 +163,7 @@ const (
|
||||
|
||||
// updateAddress is a helper function to either update an address already known
|
||||
// to the address manager, or to add the address if not already known.
|
||||
func (a *AddrManager) updateAddress(netAddr, srcAddr *wire.NetAddress) {
|
||||
func (a *AddrManager) updateAddress(netAddr, srcAddr *wire.NetAddressV2) {
|
||||
// Filter out non-routable addresses. Note that non-routable
|
||||
// also includes invalid and local addresses.
|
||||
if !IsRoutable(netAddr) {
|
||||
@ -296,7 +296,7 @@ func (a *AddrManager) pickTried(bucket int) *list.Element {
|
||||
return oldestElem
|
||||
}
|
||||
|
||||
func (a *AddrManager) getNewBucket(netAddr, srcAddr *wire.NetAddress) int {
|
||||
func (a *AddrManager) getNewBucket(netAddr, srcAddr *wire.NetAddressV2) int {
|
||||
// bitcoind:
|
||||
// doublesha256(key + sourcegroup + int64(doublesha256(key + group + sourcegroup))%bucket_per_source_group) % num_new_buckets
|
||||
|
||||
@ -318,7 +318,7 @@ func (a *AddrManager) getNewBucket(netAddr, srcAddr *wire.NetAddress) int {
|
||||
return int(binary.LittleEndian.Uint64(hash2) % newBucketCount)
|
||||
}
|
||||
|
||||
func (a *AddrManager) getTriedBucket(netAddr *wire.NetAddress) int {
|
||||
func (a *AddrManager) getTriedBucket(netAddr *wire.NetAddressV2) int {
|
||||
// bitcoind hashes this as:
|
||||
// doublesha256(key + group + truncate_to_64bits(doublesha256(key)) % buckets_per_group) % num_buckets
|
||||
data1 := []byte{}
|
||||
@ -550,7 +550,7 @@ func (a *AddrManager) deserializePeers(filePath string) error {
|
||||
|
||||
// DeserializeNetAddress converts a given address string to a *wire.NetAddress.
|
||||
func (a *AddrManager) DeserializeNetAddress(addr string,
|
||||
services wire.ServiceFlag) (*wire.NetAddress, error) {
|
||||
services wire.ServiceFlag) (*wire.NetAddressV2, error) {
|
||||
|
||||
host, portStr, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
@ -599,7 +599,7 @@ func (a *AddrManager) Stop() error {
|
||||
// AddAddresses adds new addresses to the address manager. It enforces a max
|
||||
// number of addresses and silently ignores duplicate addresses. It is
|
||||
// safe for concurrent access.
|
||||
func (a *AddrManager) AddAddresses(addrs []*wire.NetAddress, srcAddr *wire.NetAddress) {
|
||||
func (a *AddrManager) AddAddresses(addrs []*wire.NetAddressV2, srcAddr *wire.NetAddressV2) {
|
||||
a.mtx.Lock()
|
||||
defer a.mtx.Unlock()
|
||||
|
||||
@ -611,7 +611,7 @@ func (a *AddrManager) AddAddresses(addrs []*wire.NetAddress, srcAddr *wire.NetAd
|
||||
// AddAddress adds a new address to the address manager. It enforces a max
|
||||
// number of addresses and silently ignores duplicate addresses. It is
|
||||
// safe for concurrent access.
|
||||
func (a *AddrManager) AddAddress(addr, srcAddr *wire.NetAddress) {
|
||||
func (a *AddrManager) AddAddress(addr, srcAddr *wire.NetAddressV2) {
|
||||
a.mtx.Lock()
|
||||
defer a.mtx.Unlock()
|
||||
|
||||
@ -635,7 +635,7 @@ func (a *AddrManager) AddAddressByIP(addrIP string) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid port %s: %v", portStr, err)
|
||||
}
|
||||
na := wire.NewNetAddressIPPort(ip, uint16(port), 0)
|
||||
na := wire.NetAddressV2FromBytes(time.Now(), 0, ip, uint16(port))
|
||||
a.AddAddress(na, na) // XXX use correct src address
|
||||
return nil
|
||||
}
|
||||
@ -664,7 +664,7 @@ func (a *AddrManager) NeedMoreAddresses() bool {
|
||||
|
||||
// AddressCache returns the current address cache. It must be treated as
|
||||
// read-only (but since it is a copy now, this is not as dangerous).
|
||||
func (a *AddrManager) AddressCache() []*wire.NetAddress {
|
||||
func (a *AddrManager) AddressCache() []*wire.NetAddressV2 {
|
||||
allAddr := a.getAddresses()
|
||||
|
||||
numAddresses := len(allAddr) * getAddrPercent / 100
|
||||
@ -686,7 +686,7 @@ func (a *AddrManager) AddressCache() []*wire.NetAddress {
|
||||
|
||||
// getAddresses returns all of the addresses currently found within the
|
||||
// manager's address cache.
|
||||
func (a *AddrManager) getAddresses() []*wire.NetAddress {
|
||||
func (a *AddrManager) getAddresses() []*wire.NetAddressV2 {
|
||||
a.mtx.RLock()
|
||||
defer a.mtx.RUnlock()
|
||||
|
||||
@ -695,7 +695,7 @@ func (a *AddrManager) getAddresses() []*wire.NetAddress {
|
||||
return nil
|
||||
}
|
||||
|
||||
addrs := make([]*wire.NetAddress, 0, addrIndexLen)
|
||||
addrs := make([]*wire.NetAddressV2, 0, addrIndexLen)
|
||||
for _, v := range a.addrIndex {
|
||||
addrs = append(addrs, v.na)
|
||||
}
|
||||
@ -722,20 +722,43 @@ func (a *AddrManager) reset() {
|
||||
// HostToNetAddress returns a netaddress given a host address. If the address
|
||||
// is a Tor .onion address this will be taken care of. Else if the host is
|
||||
// not an IP address it will be resolved (via Tor if required).
|
||||
func (a *AddrManager) HostToNetAddress(host string, port uint16, services wire.ServiceFlag) (*wire.NetAddress, error) {
|
||||
// Tor address is 16 char base32 + ".onion"
|
||||
var ip net.IP
|
||||
if len(host) == 22 && host[16:] == ".onion" {
|
||||
func (a *AddrManager) HostToNetAddress(host string, port uint16,
|
||||
services wire.ServiceFlag) (*wire.NetAddressV2, error) {
|
||||
|
||||
var (
|
||||
na *wire.NetAddressV2
|
||||
ip net.IP
|
||||
)
|
||||
|
||||
// Tor v2 address is 16 char base32 + ".onion"
|
||||
if len(host) == wire.TorV2EncodedSize && host[wire.TorV2EncodedSize-6:] == ".onion" {
|
||||
// go base32 encoding uses capitals (as does the rfc
|
||||
// but Tor and bitcoind tend to user lowercase, so we switch
|
||||
// case here.
|
||||
data, err := base32.StdEncoding.DecodeString(
|
||||
strings.ToUpper(host[:16]))
|
||||
strings.ToUpper(host[:wire.TorV2EncodedSize-6]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
prefix := []byte{0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43}
|
||||
ip = net.IP(append(prefix, data...))
|
||||
|
||||
na = wire.NetAddressV2FromBytes(
|
||||
time.Now(), services, data, port,
|
||||
)
|
||||
} else if len(host) == wire.TorV3EncodedSize && host[wire.TorV3EncodedSize-6:] == ".onion" {
|
||||
// Tor v3 addresses are 56 base32 characters with the 6 byte
|
||||
// onion suffix.
|
||||
data, err := base32.StdEncoding.DecodeString(
|
||||
strings.ToUpper(host[:wire.TorV3EncodedSize-6]),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The first 32 bytes is the ed25519 public key and is enough
|
||||
// to reconstruct the .onion address.
|
||||
na = wire.NetAddressV2FromBytes(
|
||||
time.Now(), services, data[:wire.TorV3Size], port,
|
||||
)
|
||||
} else if ip = net.ParseIP(host); ip == nil {
|
||||
ips, err := a.lookupFunc(host)
|
||||
if err != nil {
|
||||
@ -745,30 +768,23 @@ func (a *AddrManager) HostToNetAddress(host string, port uint16, services wire.S
|
||||
return nil, fmt.Errorf("no addresses found for %s", host)
|
||||
}
|
||||
ip = ips[0]
|
||||
|
||||
na = wire.NetAddressV2FromBytes(time.Now(), services, ip, port)
|
||||
} else {
|
||||
// This is an non-nil IP address that was parsed in the else if
|
||||
// above.
|
||||
na = wire.NetAddressV2FromBytes(time.Now(), services, ip, port)
|
||||
}
|
||||
|
||||
return wire.NewNetAddressIPPort(ip, port, services), nil
|
||||
}
|
||||
|
||||
// ipString returns a string for the ip from the provided NetAddress. If the
|
||||
// ip is in the range used for Tor addresses then it will be transformed into
|
||||
// the relevant .onion address.
|
||||
func ipString(na *wire.NetAddress) string {
|
||||
if IsOnionCatTor(na) {
|
||||
// We know now that na.IP is long enough.
|
||||
base32 := base32.StdEncoding.EncodeToString(na.IP[6:])
|
||||
return strings.ToLower(base32) + ".onion"
|
||||
}
|
||||
|
||||
return na.IP.String()
|
||||
return na, nil
|
||||
}
|
||||
|
||||
// NetAddressKey returns a string key in the form of ip:port for IPv4 addresses
|
||||
// or [ip]:port for IPv6 addresses.
|
||||
func NetAddressKey(na *wire.NetAddress) string {
|
||||
// or [ip]:port for IPv6 addresses. It also handles onion v2 and v3 addresses.
|
||||
func NetAddressKey(na *wire.NetAddressV2) string {
|
||||
port := strconv.FormatUint(uint64(na.Port), 10)
|
||||
|
||||
return net.JoinHostPort(ipString(na), port)
|
||||
return net.JoinHostPort(na.Addr.String(), port)
|
||||
}
|
||||
|
||||
// GetAddress returns a single address that should be routable. It picks a
|
||||
@ -842,13 +858,13 @@ func (a *AddrManager) GetAddress() *KnownAddress {
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AddrManager) find(addr *wire.NetAddress) *KnownAddress {
|
||||
func (a *AddrManager) find(addr *wire.NetAddressV2) *KnownAddress {
|
||||
return a.addrIndex[NetAddressKey(addr)]
|
||||
}
|
||||
|
||||
// Attempt increases the given address' attempt counter and updates
|
||||
// the last attempt time.
|
||||
func (a *AddrManager) Attempt(addr *wire.NetAddress) {
|
||||
func (a *AddrManager) Attempt(addr *wire.NetAddressV2) {
|
||||
a.mtx.Lock()
|
||||
defer a.mtx.Unlock()
|
||||
|
||||
@ -869,7 +885,7 @@ func (a *AddrManager) Attempt(addr *wire.NetAddress) {
|
||||
// Connected Marks the given address as currently connected and working at the
|
||||
// current time. The address must already be known to AddrManager else it will
|
||||
// be ignored.
|
||||
func (a *AddrManager) Connected(addr *wire.NetAddress) {
|
||||
func (a *AddrManager) Connected(addr *wire.NetAddressV2) {
|
||||
a.mtx.Lock()
|
||||
defer a.mtx.Unlock()
|
||||
|
||||
@ -894,7 +910,7 @@ func (a *AddrManager) Connected(addr *wire.NetAddress) {
|
||||
// Good marks the given address as good. To be called after a successful
|
||||
// connection and version exchange. If the address is unknown to the address
|
||||
// manager it will be ignored.
|
||||
func (a *AddrManager) Good(addr *wire.NetAddress) {
|
||||
func (a *AddrManager) Good(addr *wire.NetAddressV2) {
|
||||
a.mtx.Lock()
|
||||
defer a.mtx.Unlock()
|
||||
|
||||
@ -983,7 +999,7 @@ func (a *AddrManager) Good(addr *wire.NetAddress) {
|
||||
}
|
||||
|
||||
// SetServices sets the services for the giiven address to the provided value.
|
||||
func (a *AddrManager) SetServices(addr *wire.NetAddress, services wire.ServiceFlag) {
|
||||
func (a *AddrManager) SetServices(addr *wire.NetAddressV2, services wire.ServiceFlag) {
|
||||
a.mtx.Lock()
|
||||
defer a.mtx.Unlock()
|
||||
|
||||
@ -1005,9 +1021,11 @@ func (a *AddrManager) SetServices(addr *wire.NetAddress, services wire.ServiceFl
|
||||
|
||||
// AddLocalAddress adds na to the list of known local addresses to advertise
|
||||
// with the given priority.
|
||||
func (a *AddrManager) AddLocalAddress(na *wire.NetAddress, priority AddressPriority) error {
|
||||
func (a *AddrManager) AddLocalAddress(na *wire.NetAddressV2, priority AddressPriority) error {
|
||||
if !IsRoutable(na) {
|
||||
return fmt.Errorf("address %s is not routable", na.IP)
|
||||
return fmt.Errorf(
|
||||
"address %s is not routable", na.Addr.String(),
|
||||
)
|
||||
}
|
||||
|
||||
a.lamtx.Lock()
|
||||
@ -1030,7 +1048,7 @@ func (a *AddrManager) AddLocalAddress(na *wire.NetAddress, priority AddressPrior
|
||||
|
||||
// getReachabilityFrom returns the relative reachability of the provided local
|
||||
// address to the provided remote address.
|
||||
func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int {
|
||||
func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddressV2) int {
|
||||
const (
|
||||
Unreachable = 0
|
||||
Default = iota
|
||||
@ -1045,36 +1063,66 @@ func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int {
|
||||
return Unreachable
|
||||
}
|
||||
|
||||
if IsOnionCatTor(remoteAddr) {
|
||||
if IsOnionCatTor(localAddr) {
|
||||
if remoteAddr.IsTorV3() {
|
||||
if localAddr.IsTorV3() {
|
||||
return Private
|
||||
}
|
||||
|
||||
if IsRoutable(localAddr) && IsIPv4(localAddr) {
|
||||
lna := localAddr.ToLegacy()
|
||||
if IsOnionCatTor(lna) {
|
||||
// Modern v3 clients should not be able to connect to
|
||||
// deprecated v2 hidden services.
|
||||
return Unreachable
|
||||
}
|
||||
|
||||
if IsRoutable(localAddr) && IsIPv4(lna) {
|
||||
return Ipv4
|
||||
}
|
||||
|
||||
return Default
|
||||
}
|
||||
|
||||
if IsRFC4380(remoteAddr) {
|
||||
// We can't be sure if the remote party can actually connect to this
|
||||
// address or not.
|
||||
if localAddr.IsTorV3() {
|
||||
return Default
|
||||
}
|
||||
|
||||
// Convert the V2 addresses into legacy to access the network
|
||||
// functions.
|
||||
remoteLna := remoteAddr.ToLegacy()
|
||||
localLna := localAddr.ToLegacy()
|
||||
|
||||
if IsOnionCatTor(remoteLna) {
|
||||
if IsOnionCatTor(localLna) {
|
||||
return Private
|
||||
}
|
||||
|
||||
if IsRoutable(localAddr) && IsIPv4(localLna) {
|
||||
return Ipv4
|
||||
}
|
||||
|
||||
return Default
|
||||
}
|
||||
|
||||
if IsRFC4380(remoteLna) {
|
||||
if !IsRoutable(localAddr) {
|
||||
return Default
|
||||
}
|
||||
|
||||
if IsRFC4380(localAddr) {
|
||||
if IsRFC4380(localLna) {
|
||||
return Teredo
|
||||
}
|
||||
|
||||
if IsIPv4(localAddr) {
|
||||
if IsIPv4(localLna) {
|
||||
return Ipv4
|
||||
}
|
||||
|
||||
return Ipv6Weak
|
||||
}
|
||||
|
||||
if IsIPv4(remoteAddr) {
|
||||
if IsRoutable(localAddr) && IsIPv4(localAddr) {
|
||||
if IsIPv4(remoteLna) {
|
||||
if IsRoutable(localAddr) && IsIPv4(localLna) {
|
||||
return Ipv4
|
||||
}
|
||||
return Unreachable
|
||||
@ -1083,7 +1131,7 @@ func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int {
|
||||
/* ipv6 */
|
||||
var tunnelled bool
|
||||
// Is our v6 is tunnelled?
|
||||
if IsRFC3964(localAddr) || IsRFC6052(localAddr) || IsRFC6145(localAddr) {
|
||||
if IsRFC3964(localLna) || IsRFC6052(localLna) || IsRFC6145(localLna) {
|
||||
tunnelled = true
|
||||
}
|
||||
|
||||
@ -1091,11 +1139,11 @@ func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int {
|
||||
return Default
|
||||
}
|
||||
|
||||
if IsRFC4380(localAddr) {
|
||||
if IsRFC4380(localLna) {
|
||||
return Teredo
|
||||
}
|
||||
|
||||
if IsIPv4(localAddr) {
|
||||
if IsIPv4(localLna) {
|
||||
return Ipv4
|
||||
}
|
||||
|
||||
@ -1109,13 +1157,13 @@ func getReachabilityFrom(localAddr, remoteAddr *wire.NetAddress) int {
|
||||
|
||||
// GetBestLocalAddress returns the most appropriate local address to use
|
||||
// for the given remote address.
|
||||
func (a *AddrManager) GetBestLocalAddress(remoteAddr *wire.NetAddress) *wire.NetAddress {
|
||||
func (a *AddrManager) GetBestLocalAddress(remoteAddr *wire.NetAddressV2) *wire.NetAddressV2 {
|
||||
a.lamtx.Lock()
|
||||
defer a.lamtx.Unlock()
|
||||
|
||||
bestreach := 0
|
||||
var bestscore AddressPriority
|
||||
var bestAddress *wire.NetAddress
|
||||
var bestAddress *wire.NetAddressV2
|
||||
for _, la := range a.localAddresses {
|
||||
reach := getReachabilityFrom(la.na, remoteAddr)
|
||||
if reach > bestreach ||
|
||||
@ -1126,21 +1174,29 @@ func (a *AddrManager) GetBestLocalAddress(remoteAddr *wire.NetAddress) *wire.Net
|
||||
}
|
||||
}
|
||||
if bestAddress != nil {
|
||||
log.Debugf("Suggesting address %s:%d for %s:%d", bestAddress.IP,
|
||||
bestAddress.Port, remoteAddr.IP, remoteAddr.Port)
|
||||
log.Debugf("Suggesting address %s:%d for %s:%d",
|
||||
bestAddress.Addr.String(), bestAddress.Port,
|
||||
remoteAddr.Addr.String(), remoteAddr.Port)
|
||||
} else {
|
||||
log.Debugf("No worthy address for %s:%d", remoteAddr.IP,
|
||||
remoteAddr.Port)
|
||||
log.Debugf("No worthy address for %s:%d",
|
||||
remoteAddr.Addr.String(), remoteAddr.Port)
|
||||
|
||||
// Send something unroutable if nothing suitable.
|
||||
var ip net.IP
|
||||
if !IsIPv4(remoteAddr) && !IsOnionCatTor(remoteAddr) {
|
||||
ip = net.IPv6zero
|
||||
} else {
|
||||
if remoteAddr.IsTorV3() {
|
||||
ip = net.IPv4zero
|
||||
} else {
|
||||
remoteLna := remoteAddr.ToLegacy()
|
||||
if !IsIPv4(remoteLna) && !IsOnionCatTor(remoteLna) {
|
||||
ip = net.IPv6zero
|
||||
} else {
|
||||
ip = net.IPv4zero
|
||||
}
|
||||
}
|
||||
services := wire.SFNodeNetwork | wire.SFNodeWitness | wire.SFNodeBloom
|
||||
bestAddress = wire.NewNetAddressIPPort(ip, 0, services)
|
||||
bestAddress = wire.NetAddressV2FromBytes(
|
||||
time.Now(), services, ip, 0,
|
||||
)
|
||||
}
|
||||
|
||||
return bestAddress
|
||||
|
@ -6,12 +6,14 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
// randAddr generates a *wire.NetAddress backed by a random IPv4/IPv6 address.
|
||||
func randAddr(t *testing.T) *wire.NetAddress {
|
||||
// randAddr generates a *wire.NetAddressV2 backed by a random IPv4/IPv6
|
||||
// address.
|
||||
func randAddr(t *testing.T) *wire.NetAddressV2 {
|
||||
t.Helper()
|
||||
|
||||
ipv4 := rand.Intn(2) == 0
|
||||
@ -30,22 +32,26 @@ func randAddr(t *testing.T) *wire.NetAddress {
|
||||
ip = b[:]
|
||||
}
|
||||
|
||||
return &wire.NetAddress{
|
||||
Services: wire.ServiceFlag(rand.Uint64()),
|
||||
IP: ip,
|
||||
Port: uint16(rand.Uint32()),
|
||||
}
|
||||
services := wire.ServiceFlag(rand.Uint64())
|
||||
port := uint16(rand.Uint32())
|
||||
|
||||
return wire.NetAddressV2FromBytes(
|
||||
time.Now(), services, ip, port,
|
||||
)
|
||||
}
|
||||
|
||||
// assertAddr ensures that the two addresses match. The timestamp is not
|
||||
// checked as it does not affect uniquely identifying a specific address.
|
||||
func assertAddr(t *testing.T, got, expected *wire.NetAddress) {
|
||||
func assertAddr(t *testing.T, got, expected *wire.NetAddressV2) {
|
||||
if got.Services != expected.Services {
|
||||
t.Fatalf("expected address services %v, got %v",
|
||||
expected.Services, got.Services)
|
||||
}
|
||||
if !got.IP.Equal(expected.IP) {
|
||||
t.Fatalf("expected address IP %v, got %v", expected.IP, got.IP)
|
||||
gotAddr := got.Addr.String()
|
||||
expectedAddr := expected.Addr.String()
|
||||
if gotAddr != expectedAddr {
|
||||
t.Fatalf("expected address IP %v, got %v", expectedAddr,
|
||||
gotAddr)
|
||||
}
|
||||
if got.Port != expected.Port {
|
||||
t.Fatalf("expected address port %d, got %d", expected.Port,
|
||||
@ -56,7 +62,7 @@ func assertAddr(t *testing.T, got, expected *wire.NetAddress) {
|
||||
// assertAddrs ensures that the manager's address cache matches the given
|
||||
// expected addresses.
|
||||
func assertAddrs(t *testing.T, addrMgr *AddrManager,
|
||||
expectedAddrs map[string]*wire.NetAddress) {
|
||||
expectedAddrs map[string]*wire.NetAddressV2) {
|
||||
|
||||
t.Helper()
|
||||
|
||||
@ -96,7 +102,7 @@ func TestAddrManagerSerialization(t *testing.T) {
|
||||
// We'll be adding 5 random addresses to the manager.
|
||||
const numAddrs = 5
|
||||
|
||||
expectedAddrs := make(map[string]*wire.NetAddress, numAddrs)
|
||||
expectedAddrs := make(map[string]*wire.NetAddressV2, numAddrs)
|
||||
for i := 0; i < numAddrs; i++ {
|
||||
addr := randAddr(t)
|
||||
expectedAddrs[NetAddressKey(addr)] = addr
|
||||
@ -141,7 +147,7 @@ func TestAddrManagerV1ToV2(t *testing.T) {
|
||||
// each addresses' services will not be stored.
|
||||
const numAddrs = 5
|
||||
|
||||
expectedAddrs := make(map[string]*wire.NetAddress, numAddrs)
|
||||
expectedAddrs := make(map[string]*wire.NetAddressV2, numAddrs)
|
||||
for i := 0; i < numAddrs; i++ {
|
||||
addr := randAddr(t)
|
||||
expectedAddrs[NetAddressKey(addr)] = addr
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
// naTest is used to describe a test to be performed against the NetAddressKey
|
||||
// method.
|
||||
type naTest struct {
|
||||
in wire.NetAddress
|
||||
in wire.NetAddressV2
|
||||
want string
|
||||
}
|
||||
|
||||
@ -93,8 +93,10 @@ func addNaTests() {
|
||||
|
||||
func addNaTest(ip string, port uint16, want string) {
|
||||
nip := net.ParseIP(ip)
|
||||
na := *wire.NewNetAddressIPPort(nip, port, wire.SFNodeNetwork)
|
||||
test := naTest{na, want}
|
||||
na := wire.NetAddressV2FromBytes(
|
||||
time.Now(), wire.SFNodeNetwork, nip, port,
|
||||
)
|
||||
test := naTest{*na, want}
|
||||
naTests = append(naTests, test)
|
||||
}
|
||||
|
||||
@ -157,37 +159,49 @@ func TestAddAddressByIP(t *testing.T) {
|
||||
|
||||
func TestAddLocalAddress(t *testing.T) {
|
||||
var tests = []struct {
|
||||
address wire.NetAddress
|
||||
address wire.NetAddressV2
|
||||
priority addrmgr.AddressPriority
|
||||
valid bool
|
||||
}{
|
||||
{
|
||||
wire.NetAddress{IP: net.ParseIP("192.168.0.100")},
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("192.168.0.100"), 0,
|
||||
),
|
||||
addrmgr.InterfacePrio,
|
||||
false,
|
||||
},
|
||||
{
|
||||
wire.NetAddress{IP: net.ParseIP("204.124.1.1")},
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("204.124.1.1"), 0,
|
||||
),
|
||||
addrmgr.InterfacePrio,
|
||||
true,
|
||||
},
|
||||
{
|
||||
wire.NetAddress{IP: net.ParseIP("204.124.1.1")},
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("204.124.1.1"), 0,
|
||||
),
|
||||
addrmgr.BoundPrio,
|
||||
true,
|
||||
},
|
||||
{
|
||||
wire.NetAddress{IP: net.ParseIP("::1")},
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("::1"), 0,
|
||||
),
|
||||
addrmgr.InterfacePrio,
|
||||
false,
|
||||
},
|
||||
{
|
||||
wire.NetAddress{IP: net.ParseIP("fe80::1")},
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("fe80::1"), 0,
|
||||
),
|
||||
addrmgr.InterfacePrio,
|
||||
false,
|
||||
},
|
||||
{
|
||||
wire.NetAddress{IP: net.ParseIP("2620:100::1")},
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("2620:100::1"), 0,
|
||||
),
|
||||
addrmgr.InterfacePrio,
|
||||
true,
|
||||
},
|
||||
@ -197,12 +211,12 @@ func TestAddLocalAddress(t *testing.T) {
|
||||
result := amgr.AddLocalAddress(&test.address, test.priority)
|
||||
if result == nil && !test.valid {
|
||||
t.Errorf("TestAddLocalAddress test #%d failed: %s should have "+
|
||||
"been accepted", x, test.address.IP)
|
||||
"been accepted", x, test.address.Addr.String())
|
||||
continue
|
||||
}
|
||||
if result != nil && test.valid {
|
||||
t.Errorf("TestAddLocalAddress test #%d failed: %s should not have "+
|
||||
"been accepted", x, test.address.IP)
|
||||
"been accepted", x, test.address.Addr.String())
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -257,7 +271,7 @@ func TestNeedMoreAddresses(t *testing.T) {
|
||||
if !b {
|
||||
t.Errorf("Expected that we need more addresses")
|
||||
}
|
||||
addrs := make([]*wire.NetAddress, addrsToAdd)
|
||||
addrs := make([]*wire.NetAddressV2, addrsToAdd)
|
||||
|
||||
var err error
|
||||
for i := 0; i < addrsToAdd; i++ {
|
||||
@ -268,7 +282,9 @@ func TestNeedMoreAddresses(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
srcAddr := wire.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
|
||||
srcAddr := wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.IPv4(173, 144, 173, 111), 8333,
|
||||
)
|
||||
|
||||
n.AddAddresses(addrs, srcAddr)
|
||||
numAddrs := n.NumAddresses()
|
||||
@ -285,7 +301,7 @@ func TestNeedMoreAddresses(t *testing.T) {
|
||||
func TestGood(t *testing.T) {
|
||||
n := addrmgr.New("testgood", lookupFunc)
|
||||
addrsToAdd := 64 * 64
|
||||
addrs := make([]*wire.NetAddress, addrsToAdd)
|
||||
addrs := make([]*wire.NetAddressV2, addrsToAdd)
|
||||
|
||||
var err error
|
||||
for i := 0; i < addrsToAdd; i++ {
|
||||
@ -296,7 +312,9 @@ func TestGood(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
srcAddr := wire.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
|
||||
srcAddr := wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.IPv4(173, 144, 173, 111), 8333,
|
||||
)
|
||||
|
||||
n.AddAddresses(addrs, srcAddr)
|
||||
for _, addr := range addrs {
|
||||
@ -331,8 +349,8 @@ func TestGetAddress(t *testing.T) {
|
||||
if ka == nil {
|
||||
t.Fatalf("Did not get an address where there is one in the pool")
|
||||
}
|
||||
if ka.NetAddress().IP.String() != someIP {
|
||||
t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().IP.String(), someIP)
|
||||
if ka.NetAddress().Addr.String() != someIP {
|
||||
t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().Addr.String(), someIP)
|
||||
}
|
||||
|
||||
// Mark this as a good address and get it
|
||||
@ -341,8 +359,8 @@ func TestGetAddress(t *testing.T) {
|
||||
if ka == nil {
|
||||
t.Fatalf("Did not get an address where there is one in the pool")
|
||||
}
|
||||
if ka.NetAddress().IP.String() != someIP {
|
||||
t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().IP.String(), someIP)
|
||||
if ka.NetAddress().Addr.String() != someIP {
|
||||
t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().Addr.String(), someIP)
|
||||
}
|
||||
|
||||
numAddrs := n.NumAddresses()
|
||||
@ -352,43 +370,83 @@ func TestGetAddress(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetBestLocalAddress(t *testing.T) {
|
||||
localAddrs := []wire.NetAddress{
|
||||
{IP: net.ParseIP("192.168.0.100")},
|
||||
{IP: net.ParseIP("::1")},
|
||||
{IP: net.ParseIP("fe80::1")},
|
||||
{IP: net.ParseIP("2001:470::1")},
|
||||
localAddrs := []wire.NetAddressV2{
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("192.168.0.100"), 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("::1"), 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("fe80::1"), 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("2001:470::1"), 0,
|
||||
),
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
remoteAddr wire.NetAddress
|
||||
want0 wire.NetAddress
|
||||
want1 wire.NetAddress
|
||||
want2 wire.NetAddress
|
||||
want3 wire.NetAddress
|
||||
remoteAddr wire.NetAddressV2
|
||||
want0 wire.NetAddressV2
|
||||
want1 wire.NetAddressV2
|
||||
want2 wire.NetAddressV2
|
||||
want3 wire.NetAddressV2
|
||||
}{
|
||||
{
|
||||
// Remote connection from public IPv4
|
||||
wire.NetAddress{IP: net.ParseIP("204.124.8.1")},
|
||||
wire.NetAddress{IP: net.IPv4zero},
|
||||
wire.NetAddress{IP: net.IPv4zero},
|
||||
wire.NetAddress{IP: net.ParseIP("204.124.8.100")},
|
||||
wire.NetAddress{IP: net.ParseIP("fd87:d87e:eb43:25::1")},
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("204.124.8.1"), 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.IPv4zero, 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.IPv4zero, 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("204.124.8.100"), 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0,
|
||||
net.ParseIP("fd87:d87e:eb43:25::1"), 0,
|
||||
),
|
||||
},
|
||||
{
|
||||
// Remote connection from private IPv4
|
||||
wire.NetAddress{IP: net.ParseIP("172.16.0.254")},
|
||||
wire.NetAddress{IP: net.IPv4zero},
|
||||
wire.NetAddress{IP: net.IPv4zero},
|
||||
wire.NetAddress{IP: net.IPv4zero},
|
||||
wire.NetAddress{IP: net.IPv4zero},
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("172.16.0.254"), 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.IPv4zero, 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.IPv4zero, 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.IPv4zero, 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.IPv4zero, 0,
|
||||
),
|
||||
},
|
||||
{
|
||||
// Remote connection from public IPv6
|
||||
wire.NetAddress{IP: net.ParseIP("2602:100:abcd::102")},
|
||||
wire.NetAddress{IP: net.IPv6zero},
|
||||
wire.NetAddress{IP: net.ParseIP("2001:470::1")},
|
||||
wire.NetAddress{IP: net.ParseIP("2001:470::1")},
|
||||
wire.NetAddress{IP: net.ParseIP("2001:470::1")},
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0,
|
||||
net.ParseIP("2602:100:abcd::102"), 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.IPv6zero, 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("2001:470::1"), 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("2001:470::1"), 0,
|
||||
),
|
||||
*wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("2001:470::1"), 0,
|
||||
),
|
||||
},
|
||||
/* XXX
|
||||
{
|
||||
@ -406,9 +464,12 @@ func TestGetBestLocalAddress(t *testing.T) {
|
||||
// Test against default when there's no address
|
||||
for x, test := range tests {
|
||||
got := amgr.GetBestLocalAddress(&test.remoteAddr)
|
||||
if !test.want0.IP.Equal(got.IP) {
|
||||
wantAddr := test.want0.Addr.String()
|
||||
gotAddr := got.Addr.String()
|
||||
if wantAddr != gotAddr {
|
||||
remoteAddr := test.remoteAddr.Addr.String()
|
||||
t.Errorf("TestGetBestLocalAddress test1 #%d failed for remote address %s: want %s got %s",
|
||||
x, test.remoteAddr.IP, test.want1.IP, got.IP)
|
||||
x, remoteAddr, wantAddr, gotAddr)
|
||||
continue
|
||||
}
|
||||
}
|
||||
@ -420,23 +481,31 @@ func TestGetBestLocalAddress(t *testing.T) {
|
||||
// Test against want1
|
||||
for x, test := range tests {
|
||||
got := amgr.GetBestLocalAddress(&test.remoteAddr)
|
||||
if !test.want1.IP.Equal(got.IP) {
|
||||
wantAddr := test.want1.Addr.String()
|
||||
gotAddr := got.Addr.String()
|
||||
if wantAddr != gotAddr {
|
||||
remoteAddr := test.remoteAddr.Addr.String()
|
||||
t.Errorf("TestGetBestLocalAddress test1 #%d failed for remote address %s: want %s got %s",
|
||||
x, test.remoteAddr.IP, test.want1.IP, got.IP)
|
||||
x, remoteAddr, wantAddr, gotAddr)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Add a public IP to the list of local addresses.
|
||||
localAddr := wire.NetAddress{IP: net.ParseIP("204.124.8.100")}
|
||||
amgr.AddLocalAddress(&localAddr, addrmgr.InterfacePrio)
|
||||
localAddr := wire.NetAddressV2FromBytes(
|
||||
time.Now(), 0, net.ParseIP("204.124.8.100"), 0,
|
||||
)
|
||||
amgr.AddLocalAddress(localAddr, addrmgr.InterfacePrio)
|
||||
|
||||
// Test against want2
|
||||
for x, test := range tests {
|
||||
got := amgr.GetBestLocalAddress(&test.remoteAddr)
|
||||
if !test.want2.IP.Equal(got.IP) {
|
||||
wantAddr := test.want2.Addr.String()
|
||||
gotAddr := got.Addr.String()
|
||||
if wantAddr != gotAddr {
|
||||
remoteAddr := test.remoteAddr.Addr.String()
|
||||
t.Errorf("TestGetBestLocalAddress test2 #%d failed for remote address %s: want %s got %s",
|
||||
x, test.remoteAddr.IP, test.want2.IP, got.IP)
|
||||
x, remoteAddr, wantAddr, gotAddr)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ func TstKnownAddressChance(ka *KnownAddress) float64 {
|
||||
return ka.chance()
|
||||
}
|
||||
|
||||
func TstNewKnownAddress(na *wire.NetAddress, attempts int,
|
||||
func TstNewKnownAddress(na *wire.NetAddressV2, attempts int,
|
||||
lastattempt, lastsuccess time.Time, tried bool, refs int) *KnownAddress {
|
||||
return &KnownAddress{na: na, attempts: attempts, lastattempt: lastattempt,
|
||||
lastsuccess: lastsuccess, tried: tried, refs: refs}
|
||||
|
@ -15,8 +15,8 @@ import (
|
||||
// to determine how viable an address is.
|
||||
type KnownAddress struct {
|
||||
mtx sync.RWMutex // na and lastattempt
|
||||
na *wire.NetAddress
|
||||
srcAddr *wire.NetAddress
|
||||
na *wire.NetAddressV2
|
||||
srcAddr *wire.NetAddressV2
|
||||
attempts int
|
||||
lastattempt time.Time
|
||||
lastsuccess time.Time
|
||||
@ -24,9 +24,9 @@ type KnownAddress struct {
|
||||
refs int // reference count of new buckets
|
||||
}
|
||||
|
||||
// NetAddress returns the underlying wire.NetAddress associated with the
|
||||
// NetAddress returns the underlying wire.NetAddressV2 associated with the
|
||||
// known address.
|
||||
func (ka *KnownAddress) NetAddress() *wire.NetAddress {
|
||||
func (ka *KnownAddress) NetAddress() *wire.NetAddressV2 {
|
||||
ka.mtx.RLock()
|
||||
defer ka.mtx.RUnlock()
|
||||
return ka.na
|
||||
|
@ -21,27 +21,27 @@ func TestChance(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
//Test normal case
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)},
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(-35 * time.Second)},
|
||||
0, time.Now().Add(-30*time.Minute), time.Now(), false, 0),
|
||||
1.0,
|
||||
}, {
|
||||
//Test case in which lastseen < 0
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(20 * time.Second)},
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(20 * time.Second)},
|
||||
0, time.Now().Add(-30*time.Minute), time.Now(), false, 0),
|
||||
1.0,
|
||||
}, {
|
||||
//Test case in which lastattempt < 0
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)},
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(-35 * time.Second)},
|
||||
0, time.Now().Add(30*time.Minute), time.Now(), false, 0),
|
||||
1.0 * .01,
|
||||
}, {
|
||||
//Test case in which lastattempt < ten minutes
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)},
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(-35 * time.Second)},
|
||||
0, time.Now().Add(-5*time.Minute), time.Now(), false, 0),
|
||||
1.0 * .01,
|
||||
}, {
|
||||
//Test case with several failed attempts.
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)},
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddressV2{Timestamp: now.Add(-35 * time.Second)},
|
||||
2, time.Now().Add(-30*time.Minute), time.Now(), false, 0),
|
||||
1 / 1.5 / 1.5,
|
||||
},
|
||||
@ -65,10 +65,10 @@ func TestIsBad(t *testing.T) {
|
||||
hoursOld := now.Add(-5 * time.Hour)
|
||||
zeroTime := time.Time{}
|
||||
|
||||
futureNa := &wire.NetAddress{Timestamp: future}
|
||||
minutesOldNa := &wire.NetAddress{Timestamp: minutesOld}
|
||||
monthOldNa := &wire.NetAddress{Timestamp: monthOld}
|
||||
currentNa := &wire.NetAddress{Timestamp: secondsOld}
|
||||
futureNa := &wire.NetAddressV2{Timestamp: future}
|
||||
minutesOldNa := &wire.NetAddressV2{Timestamp: minutesOld}
|
||||
monthOldNa := &wire.NetAddressV2{Timestamp: monthOld}
|
||||
currentNa := &wire.NetAddressV2{Timestamp: secondsOld}
|
||||
|
||||
//Test addresses that have been tried in the last minute.
|
||||
if addrmgr.TstKnownAddressIsBad(addrmgr.TstNewKnownAddress(futureNa, 3, secondsOld, zeroTime, false, 0)) {
|
||||
|
@ -222,11 +222,20 @@ func IsValid(na *wire.NetAddress) bool {
|
||||
// IsRoutable returns whether or not the passed address is routable over
|
||||
// the public internet. This is true as long as the address is valid and is not
|
||||
// in any reserved ranges.
|
||||
func IsRoutable(na *wire.NetAddress) bool {
|
||||
return IsValid(na) && !(IsRFC1918(na) || IsRFC2544(na) ||
|
||||
IsRFC3927(na) || IsRFC4862(na) || IsRFC3849(na) ||
|
||||
IsRFC4843(na) || IsRFC5737(na) || IsRFC6598(na) ||
|
||||
IsLocal(na) || (IsRFC4193(na) && !IsOnionCatTor(na)))
|
||||
func IsRoutable(na *wire.NetAddressV2) bool {
|
||||
if na.IsTorV3() {
|
||||
// na is a torv3 address, return true.
|
||||
return true
|
||||
}
|
||||
|
||||
// Else na can be represented as a legacy NetAddress since i2p and
|
||||
// cjdns are unsupported.
|
||||
lna := na.ToLegacy()
|
||||
return IsValid(lna) && !(IsRFC1918(lna) || IsRFC2544(lna) ||
|
||||
IsRFC3927(lna) || IsRFC4862(lna) || IsRFC3849(lna) ||
|
||||
IsRFC4843(lna) || IsRFC5737(lna) || IsRFC6598(lna) ||
|
||||
IsLocal(lna) || (IsRFC4193(lna) &&
|
||||
!IsOnionCatTor(lna)))
|
||||
}
|
||||
|
||||
// GroupKey returns a string representing the network group an address is part
|
||||
@ -234,48 +243,56 @@ func IsRoutable(na *wire.NetAddress) bool {
|
||||
// "local" for a local address, the string "tor:key" where key is the /4 of the
|
||||
// onion address for Tor address, and the string "unroutable" for an unroutable
|
||||
// address.
|
||||
func GroupKey(na *wire.NetAddress) string {
|
||||
if IsLocal(na) {
|
||||
func GroupKey(na *wire.NetAddressV2) string {
|
||||
if na.IsTorV3() {
|
||||
// na is a torv3 address. Use the same network group keying as
|
||||
// for torv2.
|
||||
return fmt.Sprintf("tor:%d", na.TorV3Key()&((1<<4)-1))
|
||||
}
|
||||
|
||||
lna := na.ToLegacy()
|
||||
|
||||
if IsLocal(lna) {
|
||||
return "local"
|
||||
}
|
||||
if !IsRoutable(na) {
|
||||
return "unroutable"
|
||||
}
|
||||
if IsIPv4(na) {
|
||||
return na.IP.Mask(net.CIDRMask(16, 32)).String()
|
||||
if IsIPv4(lna) {
|
||||
return lna.IP.Mask(net.CIDRMask(16, 32)).String()
|
||||
}
|
||||
if IsRFC6145(na) || IsRFC6052(na) {
|
||||
if IsRFC6145(lna) || IsRFC6052(lna) {
|
||||
// last four bytes are the ip address
|
||||
ip := na.IP[12:16]
|
||||
ip := lna.IP[12:16]
|
||||
return ip.Mask(net.CIDRMask(16, 32)).String()
|
||||
}
|
||||
|
||||
if IsRFC3964(na) {
|
||||
ip := na.IP[2:6]
|
||||
if IsRFC3964(lna) {
|
||||
ip := lna.IP[2:6]
|
||||
return ip.Mask(net.CIDRMask(16, 32)).String()
|
||||
|
||||
}
|
||||
if IsRFC4380(na) {
|
||||
if IsRFC4380(lna) {
|
||||
// teredo tunnels have the last 4 bytes as the v4 address XOR
|
||||
// 0xff.
|
||||
ip := net.IP(make([]byte, 4))
|
||||
for i, byte := range na.IP[12:16] {
|
||||
for i, byte := range lna.IP[12:16] {
|
||||
ip[i] = byte ^ 0xff
|
||||
}
|
||||
return ip.Mask(net.CIDRMask(16, 32)).String()
|
||||
}
|
||||
if IsOnionCatTor(na) {
|
||||
if IsOnionCatTor(lna) {
|
||||
// group is keyed off the first 4 bits of the actual onion key.
|
||||
return fmt.Sprintf("tor:%d", na.IP[6]&((1<<4)-1))
|
||||
return fmt.Sprintf("tor:%d", lna.IP[6]&((1<<4)-1))
|
||||
}
|
||||
|
||||
// OK, so now we know ourselves to be a IPv6 address.
|
||||
// bitcoind uses /32 for everything, except for Hurricane Electric's
|
||||
// (he.net) IP range, which it uses /36 for.
|
||||
bits := 32
|
||||
if heNet.Contains(na.IP) {
|
||||
if heNet.Contains(lna.IP) {
|
||||
bits = 36
|
||||
}
|
||||
|
||||
return na.IP.Mask(net.CIDRMask(bits, 128)).String()
|
||||
return lna.IP.Mask(net.CIDRMask(bits, 128)).String()
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ package addrmgr_test
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/addrmgr"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
@ -136,7 +137,10 @@ func TestIPTypes(t *testing.T) {
|
||||
t.Errorf("IsValid %s\n got: %v want: %v", test.in.IP, rv, test.valid)
|
||||
}
|
||||
|
||||
if rv := addrmgr.IsRoutable(&test.in); rv != test.routable {
|
||||
currentNa := wire.NetAddressV2FromBytes(
|
||||
time.Now(), test.in.Services, test.in.IP, test.in.Port,
|
||||
)
|
||||
if rv := addrmgr.IsRoutable(currentNa); rv != test.routable {
|
||||
t.Errorf("IsRoutable %s\n got: %v want: %v", test.in.IP, rv, test.routable)
|
||||
}
|
||||
}
|
||||
@ -192,8 +196,10 @@ func TestGroupKey(t *testing.T) {
|
||||
|
||||
for i, test := range tests {
|
||||
nip := net.ParseIP(test.ip)
|
||||
na := *wire.NewNetAddressIPPort(nip, 8333, wire.SFNodeNetwork)
|
||||
if key := addrmgr.GroupKey(&na); key != test.expected {
|
||||
na := wire.NetAddressV2FromBytes(
|
||||
time.Now(), wire.SFNodeNetwork, nip, 8333,
|
||||
)
|
||||
if key := addrmgr.GroupKey(na); key != test.expected {
|
||||
t.Errorf("TestGroupKey #%d (%s): unexpected group key "+
|
||||
"- got '%s', want '%s'", i, test.name,
|
||||
key, test.expected)
|
||||
|
@ -24,7 +24,7 @@ const (
|
||||
|
||||
// OnSeed is the signature of the callback function which is invoked when DNS
|
||||
// seeding is succesfull.
|
||||
type OnSeed func(addrs []*wire.NetAddress)
|
||||
type OnSeed func(addrs []*wire.NetAddressV2)
|
||||
|
||||
// LookupFunc is the signature of the DNS lookup function.
|
||||
type LookupFunc func(string) ([]net.IP, error)
|
||||
@ -56,11 +56,11 @@ func SeedFromDNS(chainParams *chaincfg.Params, reqServices wire.ServiceFlag,
|
||||
if numPeers == 0 {
|
||||
return
|
||||
}
|
||||
addresses := make([]*wire.NetAddress, len(seedpeers))
|
||||
addresses := make([]*wire.NetAddressV2, len(seedpeers))
|
||||
// if this errors then we have *real* problems
|
||||
intPort, _ := strconv.Atoi(chainParams.DefaultPort)
|
||||
for i, peer := range seedpeers {
|
||||
addresses[i] = wire.NewNetAddressTimestamp(
|
||||
addresses[i] = wire.NetAddressV2FromBytes(
|
||||
// bitcoind seeds with addresses from
|
||||
// a time randomly selected between 3
|
||||
// and 7 days ago.
|
||||
|
@ -228,7 +228,7 @@ func (cm *rpcConnManager) RelayTransactions(txns []*mempool.TxDesc) {
|
||||
//
|
||||
// This function is safe for concurrent access and is part of the
|
||||
// rpcserverConnManager interface implementation.
|
||||
func (cm *rpcConnManager) NodeAddresses() []*wire.NetAddress {
|
||||
func (cm *rpcConnManager) NodeAddresses() []*wire.NetAddressV2 {
|
||||
return cm.server.addrManager.AddressCache()
|
||||
}
|
||||
|
||||
|
@ -2518,7 +2518,7 @@ func handleGetNodeAddresses(s *rpcServer, cmd interface{}, closeChan <-chan stru
|
||||
address := &btcjson.GetNodeAddressesResult{
|
||||
Time: node.Timestamp.Unix(),
|
||||
Services: uint64(node.Services),
|
||||
Address: node.IP.String(),
|
||||
Address: node.Addr.String(),
|
||||
Port: node.Port,
|
||||
}
|
||||
addresses = append(addresses, address)
|
||||
@ -4524,7 +4524,7 @@ type rpcserverConnManager interface {
|
||||
|
||||
// NodeAddresses returns an array consisting node addresses which can
|
||||
// potentially be used to find new nodes in the network.
|
||||
NodeAddresses() []*wire.NetAddress
|
||||
NodeAddresses() []*wire.NetAddressV2
|
||||
}
|
||||
|
||||
// rpcserverSyncManager represents a sync manager for use with the RPC server.
|
||||
|
80
server.go
80
server.go
@ -25,6 +25,8 @@ import (
|
||||
"github.com/btcsuite/btcd/addrmgr"
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/blockchain/indexers"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/btcutil/bloom"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/connmgr"
|
||||
@ -36,8 +38,7 @@ import (
|
||||
"github.com/btcsuite/btcd/peer"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/btcutil/bloom"
|
||||
"github.com/decred/dcrd/lru"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -274,7 +275,7 @@ type serverPeer struct {
|
||||
isWhitelisted bool
|
||||
filter *bloom.Filter
|
||||
addressesMtx sync.RWMutex
|
||||
knownAddresses map[string]struct{}
|
||||
knownAddresses lru.Cache
|
||||
banScore connmgr.DynamicBanScore
|
||||
quit chan struct{}
|
||||
// The following chans are used to sync blockmanager and server.
|
||||
@ -289,7 +290,7 @@ func newServerPeer(s *server, isPersistent bool) *serverPeer {
|
||||
server: s,
|
||||
persistent: isPersistent,
|
||||
filter: bloom.LoadFilter(nil),
|
||||
knownAddresses: make(map[string]struct{}),
|
||||
knownAddresses: lru.NewCache(5000),
|
||||
quit: make(chan struct{}),
|
||||
txProcessed: make(chan struct{}, 1),
|
||||
blockProcessed: make(chan struct{}, 1),
|
||||
@ -305,18 +306,18 @@ func (sp *serverPeer) newestBlock() (*chainhash.Hash, int32, error) {
|
||||
|
||||
// addKnownAddresses adds the given addresses to the set of known addresses to
|
||||
// the peer to prevent sending duplicate addresses.
|
||||
func (sp *serverPeer) addKnownAddresses(addresses []*wire.NetAddress) {
|
||||
func (sp *serverPeer) addKnownAddresses(addresses []*wire.NetAddressV2) {
|
||||
sp.addressesMtx.Lock()
|
||||
for _, na := range addresses {
|
||||
sp.knownAddresses[addrmgr.NetAddressKey(na)] = struct{}{}
|
||||
sp.knownAddresses.Add(addrmgr.NetAddressKey(na))
|
||||
}
|
||||
sp.addressesMtx.Unlock()
|
||||
}
|
||||
|
||||
// addressKnown true if the given address is already known to the peer.
|
||||
func (sp *serverPeer) addressKnown(na *wire.NetAddress) bool {
|
||||
func (sp *serverPeer) addressKnown(na *wire.NetAddressV2) bool {
|
||||
sp.addressesMtx.RLock()
|
||||
_, exists := sp.knownAddresses[addrmgr.NetAddressKey(na)]
|
||||
exists := sp.knownAddresses.Contains(addrmgr.NetAddressKey(na))
|
||||
sp.addressesMtx.RUnlock()
|
||||
return exists
|
||||
}
|
||||
@ -340,23 +341,45 @@ func (sp *serverPeer) relayTxDisabled() bool {
|
||||
return isDisabled
|
||||
}
|
||||
|
||||
// pushAddrMsg sends an addr message to the connected peer using the provided
|
||||
// addresses.
|
||||
func (sp *serverPeer) pushAddrMsg(addresses []*wire.NetAddress) {
|
||||
// Filter addresses already known to the peer.
|
||||
// pushAddrMsg sends a legacy addr message to the connected peer using the
|
||||
// provided addresses.
|
||||
func (sp *serverPeer) pushAddrMsg(addresses []*wire.NetAddressV2) {
|
||||
addrs := make([]*wire.NetAddress, 0, len(addresses))
|
||||
for _, addr := range addresses {
|
||||
if !sp.addressKnown(addr) {
|
||||
addrs = append(addrs, addr)
|
||||
// Filter addresses already known to the peer.
|
||||
if sp.addressKnown(addr) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Must skip the V3 addresses for legacy ADDR messages.
|
||||
if addr.IsTorV3() {
|
||||
continue
|
||||
}
|
||||
|
||||
// Convert the NetAddressV2 to a legacy address.
|
||||
addrs = append(addrs, addr.ToLegacy())
|
||||
}
|
||||
|
||||
known, err := sp.PushAddrMsg(addrs)
|
||||
if err != nil {
|
||||
peerLog.Errorf("Can't push address message to %s: %v", sp.Peer, err)
|
||||
peerLog.Errorf(
|
||||
"Can't push address message to %s: %v", sp.Peer, err,
|
||||
)
|
||||
sp.Disconnect()
|
||||
return
|
||||
}
|
||||
sp.addKnownAddresses(known)
|
||||
|
||||
// Convert all of the known addresses to NetAddressV2 to add them to
|
||||
// the set of known addresses.
|
||||
knownAddrs := make([]*wire.NetAddressV2, 0, len(known))
|
||||
for _, knownAddr := range known {
|
||||
currentKna := wire.NetAddressV2FromBytes(
|
||||
knownAddr.Timestamp, knownAddr.Services,
|
||||
knownAddr.IP, knownAddr.Port,
|
||||
)
|
||||
knownAddrs = append(knownAddrs, currentKna)
|
||||
}
|
||||
sp.addKnownAddresses(knownAddrs)
|
||||
}
|
||||
|
||||
// addBanScore increases the persistent and decaying ban score fields by the
|
||||
@ -1272,6 +1295,7 @@ func (sp *serverPeer) OnAddr(_ *peer.Peer, msg *wire.MsgAddr) {
|
||||
return
|
||||
}
|
||||
|
||||
addrs := make([]*wire.NetAddressV2, 0, len(msg.AddrList))
|
||||
for _, na := range msg.AddrList {
|
||||
// Don't add more address if we're disconnecting.
|
||||
if !sp.Connected() {
|
||||
@ -1286,8 +1310,14 @@ func (sp *serverPeer) OnAddr(_ *peer.Peer, msg *wire.MsgAddr) {
|
||||
na.Timestamp = now.Add(-1 * time.Hour * 24 * 5)
|
||||
}
|
||||
|
||||
// Add address to known addresses for this peer.
|
||||
sp.addKnownAddresses([]*wire.NetAddress{na})
|
||||
// Add address to known addresses for this peer. This is
|
||||
// converted to NetAddressV2 since that's what the address
|
||||
// manager uses.
|
||||
currentNa := wire.NetAddressV2FromBytes(
|
||||
na.Timestamp, na.Services, na.IP, na.Port,
|
||||
)
|
||||
addrs = append(addrs, currentNa)
|
||||
sp.addKnownAddresses([]*wire.NetAddressV2{currentNa})
|
||||
}
|
||||
|
||||
// Add addresses to server address manager. The address manager handles
|
||||
@ -1295,7 +1325,7 @@ func (sp *serverPeer) OnAddr(_ *peer.Peer, msg *wire.MsgAddr) {
|
||||
// addresses, and last seen updates.
|
||||
// XXX bitcoind gives a 2 hour time penalty here, do we want to do the
|
||||
// same?
|
||||
sp.server.addrManager.AddAddresses(msg.AddrList, sp.NA())
|
||||
sp.server.addrManager.AddAddresses(addrs, sp.NA())
|
||||
}
|
||||
|
||||
// OnRead is invoked when a peer receives a message and it is used to update
|
||||
@ -1700,7 +1730,7 @@ func (s *server) handleAddPeerMsg(state *peerState, sp *serverPeer) bool {
|
||||
lna := s.addrManager.GetBestLocalAddress(sp.NA())
|
||||
if addrmgr.IsRoutable(lna) {
|
||||
// Filter addresses the peer already knows about.
|
||||
addresses := []*wire.NetAddress{lna}
|
||||
addresses := []*wire.NetAddressV2{lna}
|
||||
sp.pushAddrMsg(addresses)
|
||||
}
|
||||
}
|
||||
@ -2152,7 +2182,7 @@ func (s *server) peerHandler() {
|
||||
if !cfg.DisableDNSSeed {
|
||||
// Add peers discovered through DNS to the address manager.
|
||||
connmgr.SeedFromDNS(activeNetParams.Params, defaultRequiredServices,
|
||||
btcdLookup, func(addrs []*wire.NetAddress) {
|
||||
btcdLookup, func(addrs []*wire.NetAddressV2) {
|
||||
// Bitcoind uses a lookup of the dns seeder here. This
|
||||
// is rather strange since the values looked up by the
|
||||
// DNS seed lookups will vary quite a lot.
|
||||
@ -2543,8 +2573,8 @@ out:
|
||||
srvrLog.Warnf("UPnP can't get external address: %v", err)
|
||||
continue out
|
||||
}
|
||||
na := wire.NewNetAddressIPPort(externalip, uint16(listenPort),
|
||||
s.services)
|
||||
na := wire.NetAddressV2FromBytes(time.Now(), s.services,
|
||||
externalip, uint16(listenPort))
|
||||
err = s.addrManager.AddLocalAddress(na, addrmgr.UpnpPrio)
|
||||
if err != nil {
|
||||
// XXX DeletePortMapping?
|
||||
@ -3117,7 +3147,9 @@ func addLocalAddress(addrMgr *addrmgr.AddrManager, addr string, services wire.Se
|
||||
continue
|
||||
}
|
||||
|
||||
netAddr := wire.NewNetAddressIPPort(ifaceIP, uint16(port), services)
|
||||
netAddr := wire.NetAddressV2FromBytes(
|
||||
time.Now(), services, ifaceIP, uint16(port),
|
||||
)
|
||||
addrMgr.AddLocalAddress(netAddr, addrmgr.BoundPrio)
|
||||
}
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user