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