neoneo-go/pkg/network/payload/version.go

93 lines
2.3 KiB
Go
Raw Normal View History

2018-01-27 15:00:28 +00:00
package payload
import (
"encoding/binary"
)
2018-01-27 15:47:43 +00:00
const (
lenUA = 12
minVersionSize = 27 + lenUA
)
2018-01-27 15:00:28 +00:00
// Version payload.
type Version struct {
// currently the version of the protocol is 0
Version uint32
// currently 1
Services uint64
// timestamp
Timestamp uint32
// port this server is listening on
Port uint16
// it's used to distinguish the node from public IP
Nonce uint32
2018-01-27 15:47:43 +00:00
// client id currently 12 bytes \v/NEO:2.6.0/
2018-01-27 15:00:28 +00:00
UserAgent []byte
// Height of the block chain
StartHeight uint32
// Whether to receive and forward
Relay bool
}
// NewVersion returns a pointer to a Version payload.
2018-01-28 07:03:18 +00:00
func NewVersion(id uint32, p uint16, ua string, h uint32, r bool) *Version {
2018-01-27 15:00:28 +00:00
return &Version{
Version: 0,
Services: 1,
Timestamp: 12345,
Port: p,
2018-01-28 07:03:18 +00:00
Nonce: id,
2018-01-27 15:00:28 +00:00
UserAgent: []byte(ua),
StartHeight: 0,
Relay: r,
}
}
2018-01-28 07:03:18 +00:00
// UnmarshalBinary implements the Payloader interface.
func (p *Version) UnmarshalBinary(b []byte) error {
2018-01-27 15:00:28 +00:00
p.Version = binary.LittleEndian.Uint32(b[0:4])
p.Services = binary.LittleEndian.Uint64(b[4:12])
p.Timestamp = binary.LittleEndian.Uint32(b[12:16])
// FIXME: port's byteorder should be big endian according to the docs.
// but when connecting to the privnet docker image it's little endian.
p.Port = binary.LittleEndian.Uint16(b[16:18])
p.Nonce = binary.LittleEndian.Uint32(b[18:22])
p.UserAgent = b[22 : 22+lenUA]
curlen := 22 + lenUA
p.StartHeight = binary.LittleEndian.Uint32(b[curlen : curlen+4])
p.Relay = b[len(b)-1 : len(b)][0] == 1
return nil
}
2018-01-28 07:03:18 +00:00
// MarshalBinary implements the Payloader interface.
func (p *Version) MarshalBinary() ([]byte, error) {
b := make([]byte, p.Size())
2018-01-27 15:00:28 +00:00
2018-01-28 07:03:18 +00:00
binary.LittleEndian.PutUint32(b[0:4], p.Version)
binary.LittleEndian.PutUint64(b[4:12], p.Services)
binary.LittleEndian.PutUint32(b[12:16], p.Timestamp)
2018-01-27 15:00:28 +00:00
// FIXME: byte order (little / big)?
2018-01-28 07:03:18 +00:00
binary.LittleEndian.PutUint16(b[16:18], p.Port)
binary.LittleEndian.PutUint32(b[18:22], p.Nonce)
copy(b[22:22+len(p.UserAgent)], p.UserAgent) //
2018-01-27 15:00:28 +00:00
curLen := 22 + len(p.UserAgent)
2018-01-28 07:03:18 +00:00
binary.LittleEndian.PutUint32(b[curLen:curLen+4], p.StartHeight)
2018-01-27 15:00:28 +00:00
// yikes
2018-01-28 07:03:18 +00:00
var bln []byte
2018-01-27 15:00:28 +00:00
if p.Relay {
2018-01-28 07:03:18 +00:00
bln = []byte{1}
2018-01-27 15:00:28 +00:00
} else {
2018-01-28 07:03:18 +00:00
bln = []byte{0}
2018-01-27 15:00:28 +00:00
}
2018-01-28 07:03:18 +00:00
copy(b[curLen+4:len(b)], bln)
return b, nil
}
2018-01-27 15:00:28 +00:00
2018-01-28 07:03:18 +00:00
func (p *Version) Size() uint32 {
return uint32(minVersionSize + len(p.UserAgent))
2018-01-27 15:00:28 +00:00
}