func (a *AddrBook) groupKey(na *NetAddress) string {
	if a.routabilityStrict && na.Local() {
		return "local"
	}
	if a.routabilityStrict && !na.Routable() {
		return "unroutable"
	}

	if ipv4 := na.IP.To4(); ipv4 != nil {
		return (&net.IPNet{IP: na.IP, Mask: net.CIDRMask(16, 32)}).String()
	}
	if na.RFC6145() || na.RFC6052() {
		// last four bytes are the ip address
		ip := net.IP(na.IP[12:16])
		return (&net.IPNet{IP: ip, Mask: net.CIDRMask(16, 32)}).String()
	}

	if na.RFC3964() {
		ip := net.IP(na.IP[2:7])
		return (&net.IPNet{IP: ip, Mask: net.CIDRMask(16, 32)}).String()

	}
	if na.RFC4380() {
		// 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] {
			ip[i] = byte ^ 0xff
		}
		return (&net.IPNet{IP: ip, Mask: net.CIDRMask(16, 32)}).String()
	}

	// 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
	heNet := &net.IPNet{IP: net.ParseIP("2001:470::"),
		Mask: net.CIDRMask(32, 128)}
	if heNet.Contains(na.IP) {
		bits = 36
	}

	return (&net.IPNet{IP: na.IP, Mask: net.CIDRMask(bits, 128)}).String()
}
func (a *AddrBook) groupKey(na *NetAddress) string {
	if a.routabilityStrict && na.Local() {
		return "local"
	}
	if a.routabilityStrict && !na.Routable() {
		return "unroutable"
	}

	if ipv4 := na.IP.To4(); ipv4 != nil {
		return (&net.IPNet{IP: na.IP, Mask: net.CIDRMask(16, 32)}).String()
	}
	if na.RFC6145() || na.RFC6052() {
		
		ip := net.IP(na.IP[12:16])
		return (&net.IPNet{IP: ip, Mask: net.CIDRMask(16, 32)}).String()
	}

	if na.RFC3964() {
		ip := net.IP(na.IP[2:7])
		return (&net.IPNet{IP: ip, Mask: net.CIDRMask(16, 32)}).String()

	}
	if na.RFC4380() {
		
		
		ip := net.IP(make([]byte, 4))
		for i, byte := range na.IP[12:16] {
			ip[i] = byte ^ 0xff
		}
		return (&net.IPNet{IP: ip, Mask: net.CIDRMask(16, 32)}).String()
	}

	
	
	
	bits := 32
	heNet := &net.IPNet{IP: net.ParseIP("2001:470::"),
		Mask: net.CIDRMask(32, 128)}
	if heNet.Contains(na.IP) {
		bits = 36
	}

	return (&net.IPNet{IP: na.IP, Mask: net.CIDRMask(bits, 128)}).String()
}
func ( a * AddrBook ) groupKey ( na * NetAddress ) string { if a . routabilityStrict && na . Local ( ) { return " " } if a . routabilityStrict && ! na . Routable ( ) { return " " } if ipv4 := na . IP . To4 ( ) ; ipv4 != nil { return ( & net . IPNet { IP : na . IP , Mask : net . CIDRMask ( 16 , 32 ) } ) . String ( ) } if na . RFC6145 ( ) || na . RFC6052 ( ) { // last four bytes are the ip address ip := net . IP ( na . IP [ 12 : 16 ] ) return ( & net . IPNet { IP : ip , Mask : net . CIDRMask ( 16 , 32 ) } ) . String ( ) } if na . RFC3964 ( ) { ip := net . IP ( na . IP [ 2 : 7 ] ) return ( & net . IPNet { IP : ip , Mask : net . CIDRMask ( 16 , 32 ) } ) . String ( ) } if na . RFC4380 ( ) { // 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 ] { ip [ i ] = byte ^ 0xff } return ( & net . IPNet { IP : ip , Mask : net . CIDRMask ( 16 , 32 ) } ) . String ( ) } // 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 heNet := & net . IPNet { IP : net . ParseIP ( " " ) , Mask : net . CIDRMask ( 32 , 128 ) } if heNet . Contains ( na . IP ) { bits = 36 } return ( & net . IPNet { IP : na . IP , Mask : net . CIDRMask ( bits , 128 ) } ) . String ( ) }
// Return a string representing the network group of this address.
// This is the /16 for IPv6, the /32 (/36 for he.net) for IPv6, the string
// "local" for a local address and the string "unroutable for an unroutable
// address.
Return a string representing the network group of this address . This is the / 16 for IPv6 the / 32 ( / 36 for he . net ) for IPv6 the string local for a local address and the string unroutable for an unroutable address .