github.com/lbryio/lbcd@v0.22.119/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 "io" 10 "net" 11 "time" 12 ) 13 14 // maxNetAddressPayload returns the max payload size for a bitcoin NetAddress 15 // based on the protocol version. 16 func maxNetAddressPayload(pver uint32) uint32 { 17 // Services 8 bytes + ip 16 bytes + port 2 bytes. 18 plen := uint32(26) 19 20 // NetAddressTimeVersion added a timestamp field. 21 if pver >= NetAddressTimeVersion { 22 // Timestamp 4 bytes. 23 plen += 4 24 } 25 26 return plen 27 } 28 29 // NetAddress defines information about a peer on the network including the time 30 // it was last seen, the services it supports, its IP address, and port. 31 type NetAddress struct { 32 // Last time the address was seen. This is, unfortunately, encoded as a 33 // uint32 on the wire and therefore is limited to 2106. This field is 34 // not present in the bitcoin version message (MsgVersion) nor was it 35 // added until protocol version >= NetAddressTimeVersion. 36 Timestamp time.Time 37 38 // Bitfield which identifies the services supported by the address. 39 Services ServiceFlag 40 41 // IP address of the peer. 42 IP net.IP 43 44 // Port the peer is using. This is encoded in big endian on the wire 45 // which differs from most everything else. 46 Port uint16 47 } 48 49 // HasService returns whether the specified service is supported by the address. 50 func (na *NetAddress) HasService(service ServiceFlag) bool { 51 return na.Services&service == service 52 } 53 54 // AddService adds service as a supported service by the peer generating the 55 // message. 56 func (na *NetAddress) AddService(service ServiceFlag) { 57 na.Services |= service 58 } 59 60 // NewNetAddressIPPort returns a new NetAddress using the provided IP, port, and 61 // supported services with defaults for the remaining fields. 62 func NewNetAddressIPPort(ip net.IP, port uint16, services ServiceFlag) *NetAddress { 63 return NewNetAddressTimestamp(time.Now(), services, ip, port) 64 } 65 66 // NewNetAddressTimestamp returns a new NetAddress using the provided 67 // timestamp, IP, port, and supported services. The timestamp is rounded to 68 // single second precision. 69 func NewNetAddressTimestamp( 70 timestamp time.Time, services ServiceFlag, ip net.IP, port uint16) *NetAddress { 71 // Limit the timestamp to one second precision since the protocol 72 // doesn't support better. 73 na := NetAddress{ 74 Timestamp: time.Unix(timestamp.Unix(), 0), 75 Services: services, 76 IP: ip, 77 Port: port, 78 } 79 return &na 80 } 81 82 // NewNetAddress returns a new NetAddress using the provided TCP address and 83 // supported services with defaults for the remaining fields. 84 func NewNetAddress(addr *net.TCPAddr, services ServiceFlag) *NetAddress { 85 return NewNetAddressIPPort(addr.IP, uint16(addr.Port), services) 86 } 87 88 // readNetAddress reads an encoded NetAddress from r depending on the protocol 89 // version and whether or not the timestamp is included per ts. Some messages 90 // like version do not include the timestamp. 91 func readNetAddress(r io.Reader, pver uint32, na *NetAddress, ts bool) error { 92 var ip [16]byte 93 94 // NOTE: The bitcoin protocol uses a uint32 for the timestamp so it will 95 // stop working somewhere around 2106. Also timestamp wasn't added until 96 // protocol version >= NetAddressTimeVersion 97 if ts && pver >= NetAddressTimeVersion { 98 err := readElement(r, (*uint32Time)(&na.Timestamp)) 99 if err != nil { 100 return err 101 } 102 } 103 104 err := readElements(r, &na.Services, &ip) 105 if err != nil { 106 return err 107 } 108 // Sigh. Bitcoin protocol mixes little and big endian. 109 port, err := binarySerializer.Uint16(r, bigEndian) 110 if err != nil { 111 return err 112 } 113 114 *na = NetAddress{ 115 Timestamp: na.Timestamp, 116 Services: na.Services, 117 IP: net.IP(ip[:]), 118 Port: port, 119 } 120 return nil 121 } 122 123 // writeNetAddress serializes a NetAddress to w depending on the protocol 124 // version and whether or not the timestamp is included per ts. Some messages 125 // like version do not include the timestamp. 126 func writeNetAddress(w io.Writer, pver uint32, na *NetAddress, ts bool) error { 127 // NOTE: The bitcoin protocol uses a uint32 for the timestamp so it will 128 // stop working somewhere around 2106. Also timestamp wasn't added until 129 // until protocol version >= NetAddressTimeVersion. 130 if ts && pver >= NetAddressTimeVersion { 131 err := writeElement(w, uint32(na.Timestamp.Unix())) 132 if err != nil { 133 return err 134 } 135 } 136 137 // Ensure to always write 16 bytes even if the ip is nil. 138 var ip [16]byte 139 if na.IP != nil { 140 copy(ip[:], na.IP.To16()) 141 } 142 err := writeElements(w, na.Services, ip) 143 if err != nil { 144 return err 145 } 146 147 // Sigh. Bitcoin protocol mixes little and big endian. 148 return binary.Write(w, bigEndian, na.Port) 149 }