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"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"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 {
|
||||
// 24 bytes for the fixed sized fields.
|
||||
buf := make([]byte, minMessageSize)
|
||||
if _, err := r.Read(buf); err != nil {
|
||||
n, err := r.Read(buf)
|
||||
if err != nil {
|
||||
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.Command = buf[4:16]
|
||||
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 {
|
||||
pbuf := make([]byte, m.Length)
|
||||
if _, err := r.Read(pbuf); err != nil {
|
||||
n, err := r.Read(pbuf)
|
||||
if err != nil {
|
||||
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.
|
||||
if !compareChecksum(m.Checksum, pbuf) {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
case cmdAddr:
|
||||
p = &payload.AddressList{}
|
||||
if err := p.UnmarshalBinary(pbuf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
m.Payload = p
|
||||
|
@ -201,10 +220,24 @@ func (m *Message) encode(w io.Writer) error {
|
|||
copy(buf[minMessageSize:minMessageSize+m.Length], payload)
|
||||
}
|
||||
|
||||
if _, err := w.Write(buf); err != nil {
|
||||
n, err := w.Write(buf)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -1,37 +1,70 @@
|
|||
package payload
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
"unsafe"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
// Endpoint host + port of a node.
|
||||
type Endpoint struct {
|
||||
IP [16]byte // TODO: make a uint128 type
|
||||
Port uint16
|
||||
}
|
||||
|
||||
// AddrWithTime payload
|
||||
type AddrWithTime struct {
|
||||
Timestamp uint32
|
||||
Services uint64
|
||||
Addr net.Addr
|
||||
Addr Endpoint
|
||||
}
|
||||
|
||||
// Size implements the payloader interface.
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// AddressList is a slice of AddrWithTime.
|
||||
type AddressList []*AddrWithTime
|
||||
|
||||
func (p AddressList) Encode(r io.Reader) error {
|
||||
return nil
|
||||
// MarshalBinary implements the Payloader interface.
|
||||
func (p *AddressList) MarshalBinary() ([]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p AddressList) Decode(w io.Writer) error {
|
||||
return nil
|
||||
// Size implements the Payloader interface.
|
||||
func (p *AddressList) Size() uint32 {
|
||||
return uint32(len(p.Addrs) * 30)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package payload
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
||||
. "github.com/anthdm/neo-go/pkg/util"
|
||||
)
|
||||
|
@ -47,6 +48,8 @@ func (p *Inventory) UnmarshalBinary(b []byte) error {
|
|||
// TODO: what byte is [1:2] ?
|
||||
// We have 1 byte for the type which is uint8 and 32 for the hash.
|
||||
// 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)
|
||||
p.Hash.UnmarshalBinary(b[2:len(b)])
|
||||
return nil
|
||||
|
|
|
@ -5,8 +5,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
lenUA = 12
|
||||
minVersionSize = 27 + lenUA
|
||||
minVersionSize = 27
|
||||
)
|
||||
|
||||
// Version payload.
|
||||
|
@ -21,7 +20,7 @@ type Version struct {
|
|||
Port uint16
|
||||
// it's used to distinguish the node from public IP
|
||||
Nonce uint32
|
||||
// client id currently 12 bytes \v/NEO:2.6.0/
|
||||
// client id
|
||||
UserAgent []byte
|
||||
// Height of the block chain
|
||||
StartHeight uint32
|
||||
|
@ -45,6 +44,12 @@ func NewVersion(id uint32, p uint16, ua string, h uint32, r bool) *Version {
|
|||
|
||||
// UnmarshalBinary implements the Payloader interface.
|
||||
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.Services = binary.LittleEndian.Uint64(b[4:12])
|
||||
p.Timestamp = binary.LittleEndian.Uint32(b[12:16])
|
||||
|
@ -87,6 +92,7 @@ func (p *Version) MarshalBinary() ([]byte, error) {
|
|||
return b, nil
|
||||
}
|
||||
|
||||
// Size implements the payloader interface.
|
||||
func (p *Version) Size() uint32 {
|
||||
return uint32(minVersionSize + len(p.UserAgent))
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/anthdm/neo-go/pkg/network/payload"
|
||||
"github.com/anthdm/neo-go/pkg/util"
|
||||
|
@ -182,6 +183,7 @@ func (s *Server) processMessage(msg *Message, peer *Peer) error {
|
|||
case cmdGetAddr:
|
||||
return s.handleGetAddrCmd(msg, peer)
|
||||
case cmdAddr:
|
||||
return s.handleAddrCmd(msg.Payload.(*payload.AddressList), peer)
|
||||
case cmdGetHeaders:
|
||||
case cmdHeaders:
|
||||
case cmdGetBlocks:
|
||||
|
@ -220,6 +222,12 @@ func (s *Server) handleVersionCmd(v *payload.Version, peer *Peer) error {
|
|||
verackMsg := newMessage(s.net, cmdVerack, nil)
|
||||
peer.send <- verackMsg
|
||||
|
||||
go s.startProtocol(peer)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) handleAddrCmd(addrList *payload.AddressList, peer *Peer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -240,6 +248,15 @@ func (s *Server) handleGetAddrCmd(msg *Message, peer *Peer) error {
|
|||
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 {
|
||||
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
|
||||
// tell the server there is message available for proccesing.
|
||||
for {
|
||||
msg := &Message{}
|
||||
for {
|
||||
if err := msg.decode(conn); err != nil {
|
||||
// remote connection probably closed.
|
||||
if err == io.EOF {
|
||||
|
|
Loading…
Reference in a new issue