github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/network/capability/capability.go (about)

     1  package capability
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/nspcc-dev/neo-go/pkg/io"
     7  )
     8  
     9  // MaxCapabilities is the maximum number of capabilities per payload.
    10  const MaxCapabilities = 32
    11  
    12  // Capabilities is a list of Capability.
    13  type Capabilities []Capability
    14  
    15  // DecodeBinary implements io.Serializable.
    16  func (cs *Capabilities) DecodeBinary(br *io.BinReader) {
    17  	br.ReadArray(cs, MaxCapabilities)
    18  	br.Err = cs.checkUniqueCapabilities()
    19  }
    20  
    21  // EncodeBinary implements io.Serializable.
    22  func (cs *Capabilities) EncodeBinary(br *io.BinWriter) {
    23  	br.WriteArray(*cs)
    24  }
    25  
    26  // checkUniqueCapabilities checks whether payload capabilities have a unique type.
    27  func (cs Capabilities) checkUniqueCapabilities() error {
    28  	err := errors.New("capabilities with the same type are not allowed")
    29  	var isFullNode, isTCP, isWS bool
    30  	for _, cap := range cs {
    31  		switch cap.Type {
    32  		case FullNode:
    33  			if isFullNode {
    34  				return err
    35  			}
    36  			isFullNode = true
    37  		case TCPServer:
    38  			if isTCP {
    39  				return err
    40  			}
    41  			isTCP = true
    42  		case WSServer:
    43  			if isWS {
    44  				return err
    45  			}
    46  			isWS = true
    47  		}
    48  	}
    49  	return nil
    50  }
    51  
    52  // Capability describes a network service available for the node.
    53  type Capability struct {
    54  	Type Type
    55  	Data io.Serializable
    56  }
    57  
    58  // DecodeBinary implements io.Serializable.
    59  func (c *Capability) DecodeBinary(br *io.BinReader) {
    60  	c.Type = Type(br.ReadB())
    61  	switch c.Type {
    62  	case FullNode:
    63  		c.Data = &Node{}
    64  	case TCPServer, WSServer:
    65  		c.Data = &Server{}
    66  	default:
    67  		br.Err = errors.New("unknown node capability type")
    68  		return
    69  	}
    70  	c.Data.DecodeBinary(br)
    71  }
    72  
    73  // EncodeBinary implements io.Serializable.
    74  func (c *Capability) EncodeBinary(bw *io.BinWriter) {
    75  	if c.Data == nil {
    76  		bw.Err = errors.New("capability has no data")
    77  		return
    78  	}
    79  	bw.WriteB(byte(c.Type))
    80  	c.Data.EncodeBinary(bw)
    81  }
    82  
    83  // Node represents full node capability with a start height.
    84  type Node struct {
    85  	StartHeight uint32
    86  }
    87  
    88  // DecodeBinary implements io.Serializable.
    89  func (n *Node) DecodeBinary(br *io.BinReader) {
    90  	n.StartHeight = br.ReadU32LE()
    91  }
    92  
    93  // EncodeBinary implements io.Serializable.
    94  func (n *Node) EncodeBinary(bw *io.BinWriter) {
    95  	bw.WriteU32LE(n.StartHeight)
    96  }
    97  
    98  // Server represents TCP or WS server capability with a port.
    99  type Server struct {
   100  	// Port is the port this server is listening on.
   101  	Port uint16
   102  }
   103  
   104  // DecodeBinary implements io.Serializable.
   105  func (s *Server) DecodeBinary(br *io.BinReader) {
   106  	s.Port = br.ReadU16LE()
   107  }
   108  
   109  // EncodeBinary implements io.Serializable.
   110  func (s *Server) EncodeBinary(bw *io.BinWriter) {
   111  	bw.WriteU16LE(s.Port)
   112  }