forked from TrueCloudLab/neoneo-go
unmarshal addressList
This commit is contained in:
parent
68088d816c
commit
9c152bae79
6 changed files with 113 additions and 21 deletions
|
@ -5,6 +5,7 @@ import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/anthdm/neo-go/pkg/network/payload"
|
"github.com/anthdm/neo-go/pkg/network/payload"
|
||||||
|
@ -137,10 +138,15 @@ func (m *Message) commandType() commandType {
|
||||||
func (m *Message) decode(r io.Reader) error {
|
func (m *Message) decode(r io.Reader) error {
|
||||||
// 24 bytes for the fixed sized fields.
|
// 24 bytes for the fixed sized fields.
|
||||||
buf := make([]byte, minMessageSize)
|
buf := make([]byte, minMessageSize)
|
||||||
if _, err := r.Read(buf); err != nil {
|
n, err := r.Read(buf)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if n != minMessageSize {
|
||||||
|
return fmt.Errorf("Expected to read exactly %d bytes got %d", minMessageSize, n)
|
||||||
|
}
|
||||||
|
|
||||||
m.Magic = NetMode(binary.LittleEndian.Uint32(buf[0:4]))
|
m.Magic = NetMode(binary.LittleEndian.Uint32(buf[0:4]))
|
||||||
m.Command = buf[4:16]
|
m.Command = buf[4:16]
|
||||||
m.Length = binary.LittleEndian.Uint32(buf[16:20])
|
m.Length = binary.LittleEndian.Uint32(buf[16:20])
|
||||||
|
@ -156,10 +162,18 @@ func (m *Message) decode(r io.Reader) error {
|
||||||
|
|
||||||
func (m *Message) unmarshalPayload(r io.Reader) error {
|
func (m *Message) unmarshalPayload(r io.Reader) error {
|
||||||
pbuf := make([]byte, m.Length)
|
pbuf := make([]byte, m.Length)
|
||||||
if _, err := r.Read(pbuf); err != nil {
|
n, err := r.Read(pbuf)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("incomming payload: %d bytes\n", len(pbuf))
|
||||||
|
fmt.Println(pbuf)
|
||||||
|
|
||||||
|
if uint32(n) != m.Length {
|
||||||
|
return fmt.Errorf("expected to have read exactly %d bytes got %d", m.Length, n)
|
||||||
|
}
|
||||||
|
|
||||||
// Compare the checksum of the payload.
|
// Compare the checksum of the payload.
|
||||||
if !compareChecksum(m.Checksum, pbuf) {
|
if !compareChecksum(m.Checksum, pbuf) {
|
||||||
return errors.New("checksum mismatch error")
|
return errors.New("checksum mismatch error")
|
||||||
|
@ -177,6 +191,11 @@ func (m *Message) unmarshalPayload(r io.Reader) error {
|
||||||
if err := p.UnmarshalBinary(pbuf); err != nil {
|
if err := p.UnmarshalBinary(pbuf); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
case cmdAddr:
|
||||||
|
p = &payload.AddressList{}
|
||||||
|
if err := p.UnmarshalBinary(pbuf); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m.Payload = p
|
m.Payload = p
|
||||||
|
@ -201,10 +220,24 @@ func (m *Message) encode(w io.Writer) error {
|
||||||
copy(buf[minMessageSize:minMessageSize+m.Length], payload)
|
copy(buf[minMessageSize:minMessageSize+m.Length], payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := w.Write(buf); err != nil {
|
n, err := w.Write(buf)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// safety check to if we have written enough bytes.
|
||||||
|
if m.Length > 0 {
|
||||||
|
expectWritten := minMessageSize + m.Length
|
||||||
|
if uint32(n) != expectWritten {
|
||||||
|
return fmt.Errorf("expected to written exactly %d did %d", expectWritten, n)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
expectWritten := minMessageSize
|
||||||
|
if n != expectWritten {
|
||||||
|
return fmt.Errorf("expected to written exactly %d did %d", expectWritten, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,37 +1,70 @@
|
||||||
package payload
|
package payload
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"bytes"
|
||||||
"net"
|
"encoding/binary"
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Endpoint host + port of a node.
|
||||||
|
type Endpoint struct {
|
||||||
|
IP [16]byte // TODO: make a uint128 type
|
||||||
|
Port uint16
|
||||||
|
}
|
||||||
|
|
||||||
// AddrWithTime payload
|
// AddrWithTime payload
|
||||||
type AddrWithTime struct {
|
type AddrWithTime struct {
|
||||||
Timestamp uint32
|
Timestamp uint32
|
||||||
Services uint64
|
Services uint64
|
||||||
Addr net.Addr
|
Addr Endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Size implements the payloader interface.
|
||||||
func (p *AddrWithTime) Size() uint32 {
|
func (p *AddrWithTime) Size() uint32 {
|
||||||
return 4 + 8 + uint32(unsafe.Sizeof(p.Addr))
|
return 30
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *AddrWithTime) Encode(r io.Reader) error {
|
// UnmarshalBinary implements the Payloader interface.
|
||||||
|
func (p *AddrWithTime) UnmarshalBinary(b []byte) error {
|
||||||
|
p.Timestamp = binary.LittleEndian.Uint32(b[0:4])
|
||||||
|
p.Services = binary.LittleEndian.Uint64(b[4:12])
|
||||||
|
binary.Read(bytes.NewReader(b[12:28]), binary.BigEndian, &p.Addr.IP)
|
||||||
|
p.Addr.Port = binary.LittleEndian.Uint16(b[28:30])
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *AddrWithTime) Decode(w io.Writer) error {
|
// MarshalBinary implements the Payloader interface.
|
||||||
|
func (p *AddrWithTime) MarshalBinary() ([]byte, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddressList contains a slice of AddrWithTime.
|
||||||
|
type AddressList struct {
|
||||||
|
Addrs []*AddrWithTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalBinary implements the Payloader interface.
|
||||||
|
func (p *AddressList) UnmarshalBinary(b []byte) error {
|
||||||
|
var lenList uint8
|
||||||
|
binary.Read(bytes.NewReader(b[0:1]), binary.LittleEndian, &lenList)
|
||||||
|
|
||||||
|
offset := 1 // skip the uint8 length byte.
|
||||||
|
size := 30 // size of AddrWithTime
|
||||||
|
for i := 0; i < int(lenList); i++ {
|
||||||
|
address := &AddrWithTime{}
|
||||||
|
address.UnmarshalBinary(b[offset : offset+size])
|
||||||
|
p.Addrs = append(p.Addrs, address)
|
||||||
|
offset += size
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddressList is a slice of AddrWithTime.
|
// MarshalBinary implements the Payloader interface.
|
||||||
type AddressList []*AddrWithTime
|
func (p *AddressList) MarshalBinary() ([]byte, error) {
|
||||||
|
return nil, nil
|
||||||
func (p AddressList) Encode(r io.Reader) error {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p AddressList) Decode(w io.Writer) error {
|
// Size implements the Payloader interface.
|
||||||
return nil
|
func (p *AddressList) Size() uint32 {
|
||||||
|
return uint32(len(p.Addrs) * 30)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package payload
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
. "github.com/anthdm/neo-go/pkg/util"
|
. "github.com/anthdm/neo-go/pkg/util"
|
||||||
)
|
)
|
||||||
|
@ -47,6 +48,8 @@ func (p *Inventory) UnmarshalBinary(b []byte) error {
|
||||||
// TODO: what byte is [1:2] ?
|
// TODO: what byte is [1:2] ?
|
||||||
// We have 1 byte for the type which is uint8 and 32 for the hash.
|
// We have 1 byte for the type which is uint8 and 32 for the hash.
|
||||||
// There is 1 byte left over.
|
// There is 1 byte left over.
|
||||||
|
fmt.Println(b[0:1])
|
||||||
|
fmt.Println(b[1:2])
|
||||||
binary.Read(bytes.NewReader(b), binary.LittleEndian, &p.Type)
|
binary.Read(bytes.NewReader(b), binary.LittleEndian, &p.Type)
|
||||||
p.Hash.UnmarshalBinary(b[2:len(b)])
|
p.Hash.UnmarshalBinary(b[2:len(b)])
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -5,8 +5,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
lenUA = 12
|
minVersionSize = 27
|
||||||
minVersionSize = 27 + lenUA
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version payload.
|
// Version payload.
|
||||||
|
@ -21,7 +20,7 @@ type Version struct {
|
||||||
Port uint16
|
Port uint16
|
||||||
// it's used to distinguish the node from public IP
|
// it's used to distinguish the node from public IP
|
||||||
Nonce uint32
|
Nonce uint32
|
||||||
// client id currently 12 bytes \v/NEO:2.6.0/
|
// client id
|
||||||
UserAgent []byte
|
UserAgent []byte
|
||||||
// Height of the block chain
|
// Height of the block chain
|
||||||
StartHeight uint32
|
StartHeight uint32
|
||||||
|
@ -45,6 +44,12 @@ func NewVersion(id uint32, p uint16, ua string, h uint32, r bool) *Version {
|
||||||
|
|
||||||
// UnmarshalBinary implements the Payloader interface.
|
// UnmarshalBinary implements the Payloader interface.
|
||||||
func (p *Version) UnmarshalBinary(b []byte) error {
|
func (p *Version) UnmarshalBinary(b []byte) error {
|
||||||
|
// Length of the user agent should be calculated dynamicaly.
|
||||||
|
// There is no information about the size or format of this.
|
||||||
|
// the only thing we know is by looking at the #c source code.
|
||||||
|
// /NEO:{0}/ => /NEO:2.6.0/
|
||||||
|
lenUA := len(b) - minVersionSize
|
||||||
|
|
||||||
p.Version = binary.LittleEndian.Uint32(b[0:4])
|
p.Version = binary.LittleEndian.Uint32(b[0:4])
|
||||||
p.Services = binary.LittleEndian.Uint64(b[4:12])
|
p.Services = binary.LittleEndian.Uint64(b[4:12])
|
||||||
p.Timestamp = binary.LittleEndian.Uint32(b[12:16])
|
p.Timestamp = binary.LittleEndian.Uint32(b[12:16])
|
||||||
|
@ -87,6 +92,7 @@ func (p *Version) MarshalBinary() ([]byte, error) {
|
||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Size implements the payloader interface.
|
||||||
func (p *Version) Size() uint32 {
|
func (p *Version) Size() uint32 {
|
||||||
return uint32(minVersionSize + len(p.UserAgent))
|
return uint32(minVersionSize + len(p.UserAgent))
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/anthdm/neo-go/pkg/network/payload"
|
"github.com/anthdm/neo-go/pkg/network/payload"
|
||||||
"github.com/anthdm/neo-go/pkg/util"
|
"github.com/anthdm/neo-go/pkg/util"
|
||||||
|
@ -182,6 +183,7 @@ func (s *Server) processMessage(msg *Message, peer *Peer) error {
|
||||||
case cmdGetAddr:
|
case cmdGetAddr:
|
||||||
return s.handleGetAddrCmd(msg, peer)
|
return s.handleGetAddrCmd(msg, peer)
|
||||||
case cmdAddr:
|
case cmdAddr:
|
||||||
|
return s.handleAddrCmd(msg.Payload.(*payload.AddressList), peer)
|
||||||
case cmdGetHeaders:
|
case cmdGetHeaders:
|
||||||
case cmdHeaders:
|
case cmdHeaders:
|
||||||
case cmdGetBlocks:
|
case cmdGetBlocks:
|
||||||
|
@ -220,6 +222,12 @@ func (s *Server) handleVersionCmd(v *payload.Version, peer *Peer) error {
|
||||||
verackMsg := newMessage(s.net, cmdVerack, nil)
|
verackMsg := newMessage(s.net, cmdVerack, nil)
|
||||||
peer.send <- verackMsg
|
peer.send <- verackMsg
|
||||||
|
|
||||||
|
go s.startProtocol(peer)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) handleAddrCmd(addrList *payload.AddressList, peer *Peer) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,6 +248,15 @@ func (s *Server) handleGetAddrCmd(msg *Message, peer *Peer) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) startProtocol(peer *Peer) {
|
||||||
|
for {
|
||||||
|
getaddrMsg := newMessage(s.net, cmdGetAddr, nil)
|
||||||
|
peer.send <- getaddrMsg
|
||||||
|
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func logo() string {
|
func logo() string {
|
||||||
return `
|
return `
|
||||||
_ ____________ __________
|
_ ____________ __________
|
||||||
|
|
|
@ -52,8 +52,8 @@ func handleConnection(s *Server, conn net.Conn, initiated bool) {
|
||||||
|
|
||||||
// Read from the connection and decode it into an RPCMessage and
|
// Read from the connection and decode it into an RPCMessage and
|
||||||
// tell the server there is message available for proccesing.
|
// tell the server there is message available for proccesing.
|
||||||
|
msg := &Message{}
|
||||||
for {
|
for {
|
||||||
msg := &Message{}
|
|
||||||
if err := msg.decode(conn); err != nil {
|
if err := msg.decode(conn); err != nil {
|
||||||
// remote connection probably closed.
|
// remote connection probably closed.
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
|
|
Loading…
Reference in a new issue