github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/wire/netaddress.go (about) 1 // Copyright (c) 2013-2015 The btcsuite developers 2 // Copyright (c) 2016 The Dash developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package wire 7 8 import ( 9 "encoding/binary" 10 "errors" 11 "io" 12 "net" 13 "time" 14 ) 15 16 // ErrInvalidNetAddr describes an error that indicates the caller didn't specify 17 // a TCP address as required. 18 var ErrInvalidNetAddr = errors.New("provided net.Addr is not a net.TCPAddr") 19 20 // maxNetAddressPayload returns the max payload size for a bitcoin NetAddress 21 // based on the protocol version. 22 func maxNetAddressPayload(pver uint32) uint32 { 23 // Services 8 bytes + ip 16 bytes + port 2 bytes. 24 plen := uint32(26) 25 26 // NetAddressTimeVersion added a timestamp field. 27 if pver >= NetAddressTimeVersion { 28 // Timestamp 4 bytes. 29 plen += 4 30 } 31 32 return plen 33 } 34 35 // NetAddress defines information about a peer on the network including the time 36 // it was last seen, the services it supports, its IP address, and port. 37 type NetAddress struct { 38 // Last time the address was seen. This is, unfortunately, encoded as a 39 // uint32 on the wire and therefore is limited to 2106. This field is 40 // not present in the bitcoin version message (MsgVersion) nor was it 41 // added until protocol version >= NetAddressTimeVersion. 42 Timestamp time.Time 43 44 // Bitfield which identifies the services supported by the address. 45 Services ServiceFlag 46 47 // IP address of the peer. 48 IP net.IP 49 50 // Port the peer is using. This is encoded in big endian on the wire 51 // which differs from most everything else. 52 Port uint16 53 } 54 55 // HasService returns whether the specified service is supported by the address. 56 func (na *NetAddress) HasService(service ServiceFlag) bool { 57 if na.Services&service == service { 58 return true 59 } 60 return false 61 } 62 63 // AddService adds service as a supported service by the peer generating the 64 // message. 65 func (na *NetAddress) AddService(service ServiceFlag) { 66 na.Services |= service 67 } 68 69 // SetAddress is a convenience function to set the IP address and port in one 70 // call. 71 func (na *NetAddress) SetAddress(ip net.IP, port uint16) { 72 na.IP = ip 73 na.Port = port 74 } 75 76 // NewNetAddressIPPort returns a new NetAddress using the provided IP, port, and 77 // supported services with defaults for the remaining fields. 78 func NewNetAddressIPPort(ip net.IP, port uint16, services ServiceFlag) *NetAddress { 79 // Limit the timestamp to one second precision since the protocol 80 // doesn't support better. 81 na := NetAddress{ 82 Timestamp: time.Unix(time.Now().Unix(), 0), 83 Services: services, 84 IP: ip, 85 Port: port, 86 } 87 return &na 88 } 89 90 // NewNetAddress returns a new NetAddress using the provided TCP address and 91 // supported services with defaults for the remaining fields. 92 // 93 // Note that addr must be a net.TCPAddr. An ErrInvalidNetAddr is returned 94 // if it is not. 95 func NewNetAddress(addr net.Addr, services ServiceFlag) (*NetAddress, error) { 96 tcpAddr, ok := addr.(*net.TCPAddr) 97 if !ok { 98 return nil, ErrInvalidNetAddr 99 } 100 101 na := NewNetAddressIPPort(tcpAddr.IP, uint16(tcpAddr.Port), services) 102 return na, nil 103 } 104 105 // readNetAddress reads an encoded NetAddress from r depending on the protocol 106 // version and whether or not the timestamp is included per ts. Some messages 107 // like version do not include the timestamp. 108 func readNetAddress(r io.Reader, pver uint32, na *NetAddress, ts bool) error { 109 var services ServiceFlag 110 var ip [16]byte 111 112 // NOTE: The bitcoin protocol uses a uint32 for the timestamp so it will 113 // stop working somewhere around 2106. Also timestamp wasn't added until 114 // protocol version >= NetAddressTimeVersion 115 if ts && pver >= NetAddressTimeVersion { 116 err := readElement(r, (*uint32Time)(&na.Timestamp)) 117 if err != nil { 118 return err 119 } 120 } 121 122 err := readElements(r, &services, &ip) 123 if err != nil { 124 return err 125 } 126 // Sigh. Bitcoin protocol mixes little and big endian. 127 port, err := binarySerializer.Uint16(r, bigEndian) 128 if err != nil { 129 return err 130 } 131 132 na.Services = services 133 na.SetAddress(net.IP(ip[:]), port) 134 return nil 135 } 136 137 // writeNetAddress serializes a NetAddress to w depending on the protocol 138 // version and whether or not the timestamp is included per ts. Some messages 139 // like version do not include the timestamp. 140 func writeNetAddress(w io.Writer, pver uint32, na *NetAddress, ts bool) error { 141 // NOTE: The bitcoin protocol uses a uint32 for the timestamp so it will 142 // stop working somewhere around 2106. Also timestamp wasn't added until 143 // until protocol version >= NetAddressTimeVersion. 144 if ts && pver >= NetAddressTimeVersion { 145 err := writeElement(w, uint32(na.Timestamp.Unix())) 146 if err != nil { 147 return err 148 } 149 } 150 151 // Ensure to always write 16 bytes even if the ip is nil. 152 var ip [16]byte 153 if na.IP != nil { 154 copy(ip[:], na.IP.To16()) 155 } 156 err := writeElements(w, na.Services, ip) 157 if err != nil { 158 return err 159 } 160 161 // Sigh. Bitcoin protocol mixes little and big endian. 162 err = binary.Write(w, bigEndian, na.Port) 163 if err != nil { 164 return err 165 } 166 167 return nil 168 }