msgaddr.go raw

   1  package wire
   2  
   3  import (
   4  	"fmt"
   5  	"io"
   6  )
   7  
   8  // MaxAddrPerMsg is the maximum number of addresses that can be in a single bitcoin addr message (MsgAddr).
   9  const MaxAddrPerMsg = 1000
  10  
  11  // MsgAddr implements the Message interface and represents a bitcoin addr message. It is used to provide a list of known
  12  // active peers on the network. An active peer is considered one that has transmitted a message within the last 3 hours.
  13  // Nodes which have not transmitted in that time frame should be forgotten. Each message is limited to a maximum number
  14  // of addresses, which is currently 1000. As a result, multiple messages must be used to relay the full list. Use the
  15  // AddAddress function to podbuild up the list of known addresses when sending an addr message to another peer.
  16  type MsgAddr struct {
  17  	AddrList []*NetAddress
  18  }
  19  
  20  // AddAddress adds a known active peer to the message.
  21  func (msg *MsgAddr) AddAddress(na *NetAddress) (e error) {
  22  	if len(msg.AddrList)+1 > MaxAddrPerMsg {
  23  		str := fmt.Sprintf(
  24  			"too many addresses in message [max %v]",
  25  			MaxAddrPerMsg,
  26  		)
  27  		return messageError("MsgAddr.AddAddress", str)
  28  	}
  29  	msg.AddrList = append(msg.AddrList, na)
  30  	return nil
  31  }
  32  
  33  // AddAddresses adds multiple known active peers to the message.
  34  func (msg *MsgAddr) AddAddresses(netAddrs ...*NetAddress) (e error) {
  35  	for _, na := range netAddrs {
  36  		e = msg.AddAddress(na)
  37  		if E.Chk(e) {
  38  			return
  39  		}
  40  	}
  41  	return
  42  }
  43  
  44  // ClearAddresses removes all addresses from the message.
  45  func (msg *MsgAddr) ClearAddresses() {
  46  	msg.AddrList = []*NetAddress{}
  47  }
  48  
  49  // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. This is part of the Message interface
  50  // implementation.
  51  func (msg *MsgAddr) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) (e error) {
  52  	var count uint64
  53  	if count, e = ReadVarInt(r, pver); E.Chk(e) {
  54  		return
  55  	}
  56  	// Limit to max addresses per message.
  57  	if count > MaxAddrPerMsg {
  58  		str := fmt.Sprintf(
  59  			"too many addresses for message "+
  60  				"[count %v, max %v]", count, MaxAddrPerMsg,
  61  		)
  62  		return messageError("MsgAddr.BtcDecode", str)
  63  	}
  64  	addrList := make([]NetAddress, count)
  65  	msg.AddrList = make([]*NetAddress, 0, count)
  66  	for i := uint64(0); i < count; i++ {
  67  		na := &addrList[i]
  68  		if e = readNetAddress(r, pver, na, true); E.Chk(e) {
  69  			return
  70  		}
  71  		if e = msg.AddAddress(na); E.Chk(e) {
  72  		}
  73  	}
  74  	return
  75  }
  76  
  77  // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. This is part of the Message interface
  78  // implementation.
  79  func (msg *MsgAddr) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) (e error) {
  80  	// Protocol versions before MultipleAddressVersion only allowed 1 address per message.
  81  	count := len(msg.AddrList)
  82  	if pver < MultipleAddressVersion && count > 1 {
  83  		str := fmt.Sprintf(
  84  			"too many addresses for message of "+
  85  				"protocol version %v [count %v, max 1]", pver, count,
  86  		)
  87  		return messageError("MsgAddr.BtcEncode", str)
  88  	}
  89  	if count > MaxAddrPerMsg {
  90  		str := fmt.Sprintf(
  91  			"too many addresses for message "+
  92  				"[count %v, max %v]", count, MaxAddrPerMsg,
  93  		)
  94  		return messageError("MsgAddr.BtcEncode", str)
  95  	}
  96  	if e = WriteVarInt(w, pver, uint64(count)); E.Chk(e) {
  97  		return
  98  	}
  99  	for _, na := range msg.AddrList {
 100  		if e = writeNetAddress(w, pver, na, true); E.Chk(e) {
 101  			return
 102  		}
 103  	}
 104  	return
 105  }
 106  
 107  // Command returns the protocol command string for the message. This is part of the Message interface implementation.
 108  func (msg *MsgAddr) Command() string {
 109  	return CmdAddr
 110  }
 111  
 112  // MaxPayloadLength returns the maximum length the payload can be for the receiver. This is part of the Message
 113  // interface implementation.
 114  func (msg *MsgAddr) MaxPayloadLength(pver uint32) uint32 {
 115  	if pver < MultipleAddressVersion {
 116  		// Num addresses (varInt) + a single net addresses.
 117  		return MaxVarIntPayload + maxNetAddressPayload(pver)
 118  	}
 119  	// Num addresses (varInt) + max allowed addresses.
 120  	return MaxVarIntPayload + (MaxAddrPerMsg * maxNetAddressPayload(pver))
 121  }
 122  
 123  // NewMsgAddr returns a new bitcoin addr message that conforms to the Message interface. See MsgAddr for details.
 124  func NewMsgAddr() *MsgAddr {
 125  	return &MsgAddr{
 126  		AddrList: make([]*NetAddress, 0, MaxAddrPerMsg),
 127  	}
 128  }
 129