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  }