2020-05-22 09:17:17 +00:00
|
|
|
package capability
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
|
|
|
)
|
|
|
|
|
2021-05-12 20:17:03 +00:00
|
|
|
// MaxCapabilities is the maximum number of capabilities per payload.
|
2020-05-22 09:17:17 +00:00
|
|
|
const MaxCapabilities = 32
|
|
|
|
|
2021-05-12 20:17:03 +00:00
|
|
|
// Capabilities is a list of Capability.
|
2020-05-22 09:17:17 +00:00
|
|
|
type Capabilities []Capability
|
|
|
|
|
|
|
|
// DecodeBinary implements Serializable interface.
|
|
|
|
func (cs *Capabilities) DecodeBinary(br *io.BinReader) {
|
|
|
|
br.ReadArray(cs, MaxCapabilities)
|
|
|
|
br.Err = cs.checkUniqueCapabilities()
|
|
|
|
}
|
|
|
|
|
|
|
|
// EncodeBinary implements Serializable interface.
|
|
|
|
func (cs *Capabilities) EncodeBinary(br *io.BinWriter) {
|
|
|
|
br.WriteArray(*cs)
|
|
|
|
}
|
|
|
|
|
|
|
|
// checkUniqueCapabilities checks whether payload capabilities have unique type.
|
|
|
|
func (cs Capabilities) checkUniqueCapabilities() error {
|
|
|
|
err := errors.New("capabilities with the same type are not allowed")
|
|
|
|
var isFullNode, isTCP, isWS bool
|
|
|
|
for _, cap := range cs {
|
|
|
|
switch cap.Type {
|
|
|
|
case FullNode:
|
|
|
|
if isFullNode {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
isFullNode = true
|
|
|
|
case TCPServer:
|
|
|
|
if isTCP {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
isTCP = true
|
|
|
|
case WSServer:
|
|
|
|
if isWS {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
isWS = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-05-12 20:17:03 +00:00
|
|
|
// Capability describes network service available for node.
|
2020-05-22 09:17:17 +00:00
|
|
|
type Capability struct {
|
|
|
|
Type Type
|
|
|
|
Data io.Serializable
|
|
|
|
}
|
|
|
|
|
|
|
|
// DecodeBinary implements Serializable interface.
|
|
|
|
func (c *Capability) DecodeBinary(br *io.BinReader) {
|
|
|
|
c.Type = Type(br.ReadB())
|
|
|
|
switch c.Type {
|
|
|
|
case FullNode:
|
|
|
|
c.Data = &Node{}
|
|
|
|
case TCPServer, WSServer:
|
|
|
|
c.Data = &Server{}
|
|
|
|
default:
|
|
|
|
br.Err = errors.New("unknown node capability type")
|
capability: prevent panic on wrong capabilities receival
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0xad7b95]
goroutine 134 [running]:
github.com/nspcc-dev/neo-go/pkg/network/capability.(*Capability).DecodeBinary(0xc00024a300, 0xc00015c900)
/home/rik/dev/neo-go/pkg/network/capability/capability.go:69 +0x85
github.com/nspcc-dev/neo-go/pkg/io.(*BinReader).ReadArray(0xc00015c900, 0xd54880, 0xc00018ecd8, 0xc00071fbe0, 0x1, 0x1)
/home/rik/dev/neo-go/pkg/io/binaryReader.go:141 +0x22f
github.com/nspcc-dev/neo-go/pkg/network/capability.(*Capabilities).DecodeBinary(0xc00018ecd8, 0xc00015c900)
/home/rik/dev/neo-go/pkg/network/capability/capability.go:17 +0x6d
github.com/nspcc-dev/neo-go/pkg/network/payload.(*AddressAndTime).DecodeBinary(0xc00018ecc0, 0xc00015c900)
/home/rik/dev/neo-go/pkg/network/payload/address.go:34 +0x59
github.com/nspcc-dev/neo-go/pkg/io.(*BinReader).ReadArray(0xc00015c900, 0xcb9e00, 0xc00024a2a0, 0x0, 0x0, 0x0)
/home/rik/dev/neo-go/pkg/io/binaryReader.go:141 +0x22f
github.com/nspcc-dev/neo-go/pkg/network/payload.(*AddressList).DecodeBinary(0xc00024a2a0, 0xc00015c900)
/home/rik/dev/neo-go/pkg/network/payload/address.go:78 +0x54
github.com/nspcc-dev/neo-go/pkg/network.(*Message).decodePayload(0xc000277890, 0xc000292020, 0xc0003da000)
/home/rik/dev/neo-go/pkg/network/message.go:158 +0x31a
github.com/nspcc-dev/neo-go/pkg/network.(*Message).Decode(0xc000277890, 0xc00071ff48, 0xc00036e090, 0xc000276e40)
/home/rik/dev/neo-go/pkg/network/message.go:114 +0x19b
github.com/nspcc-dev/neo-go/pkg/network.(*TCPPeer).handleConn(0xc00036e090)
/home/rik/dev/neo-go/pkg/network/tcp_peer.go:154 +0x244
created by github.com/nspcc-dev/neo-go/pkg/network.(*TCPTransport).Dial
/home/rik/dev/neo-go/pkg/network/tcp_transport.go:40 +0x1ad
2020-05-28 21:11:54 +00:00
|
|
|
return
|
2020-05-22 09:17:17 +00:00
|
|
|
}
|
|
|
|
c.Data.DecodeBinary(br)
|
|
|
|
}
|
|
|
|
|
|
|
|
// EncodeBinary implements Serializable interface.
|
|
|
|
func (c *Capability) EncodeBinary(bw *io.BinWriter) {
|
|
|
|
if c.Data == nil {
|
|
|
|
bw.Err = errors.New("capability has no data")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
bw.WriteB(byte(c.Type))
|
|
|
|
c.Data.EncodeBinary(bw)
|
|
|
|
}
|
|
|
|
|
2021-05-12 20:17:03 +00:00
|
|
|
// Node represents full node capability with start height.
|
2020-05-22 09:17:17 +00:00
|
|
|
type Node struct {
|
|
|
|
StartHeight uint32
|
|
|
|
}
|
|
|
|
|
|
|
|
// DecodeBinary implements Serializable interface.
|
|
|
|
func (n *Node) DecodeBinary(br *io.BinReader) {
|
|
|
|
n.StartHeight = br.ReadU32LE()
|
|
|
|
}
|
|
|
|
|
|
|
|
// EncodeBinary implements Serializable interface.
|
|
|
|
func (n *Node) EncodeBinary(bw *io.BinWriter) {
|
|
|
|
bw.WriteU32LE(n.StartHeight)
|
|
|
|
}
|
|
|
|
|
2021-05-12 20:17:03 +00:00
|
|
|
// Server represents TCP or WS server capability with port.
|
2020-05-22 09:17:17 +00:00
|
|
|
type Server struct {
|
2021-05-12 20:17:03 +00:00
|
|
|
// Port is the port this server is listening on.
|
2020-05-22 09:17:17 +00:00
|
|
|
Port uint16
|
|
|
|
}
|
|
|
|
|
|
|
|
// DecodeBinary implements Serializable interface.
|
|
|
|
func (s *Server) DecodeBinary(br *io.BinReader) {
|
|
|
|
s.Port = br.ReadU16LE()
|
|
|
|
}
|
|
|
|
|
|
|
|
// EncodeBinary implements Serializable interface.
|
|
|
|
func (s *Server) EncodeBinary(bw *io.BinWriter) {
|
|
|
|
bw.WriteU16LE(s.Port)
|
|
|
|
}
|