fix serialization + boost codes
Signed-off-by: Ciro S. Costa <utxobr@protonmail.com>
This commit is contained in:
parent
79029ea95b
commit
598a420bed
|
@ -18,9 +18,9 @@ const (
|
|||
|
||||
BoostSerializeTypeDouble byte = 0x9
|
||||
|
||||
BoostSerializeTypeString byte = 0x10
|
||||
BoostSerializeTypeBool byte = 0x11
|
||||
BoostSerializeTypeObject byte = 0x12
|
||||
BoostSerializeTypeString byte = 0x0a
|
||||
BoostSerializeTypeBool byte = 0x0b
|
||||
BoostSerializeTypeObject byte = 0x0c
|
||||
|
||||
BoostSerializeTypeArray byte = 0x13
|
||||
BoostSerializeFlagArray byte = 0x80
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -47,52 +48,21 @@ func (c *Client) Handshake(ctx context.Context) error {
|
|||
Name: "node_data",
|
||||
Serializable: &Section{
|
||||
Entries: []Entry{
|
||||
{
|
||||
Name: "local_time",
|
||||
Serializable: BoostUint64(time.Now().Unix()),
|
||||
},
|
||||
{
|
||||
Name: "my_port",
|
||||
Serializable: BoostUint32(0),
|
||||
},
|
||||
{
|
||||
Name: "network_id",
|
||||
Serializable: BoostString(string(MainnetNetworkId)),
|
||||
},
|
||||
{
|
||||
Name: "peer_id",
|
||||
Serializable: BoostUint64(12343332),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
Name: "payload_data",
|
||||
Serializable: &Section{
|
||||
Entries: []Entry{
|
||||
{
|
||||
Name: "cumulative_difficulty",
|
||||
Serializable: BoostUint64(1),
|
||||
},
|
||||
{
|
||||
Name: "current_height",
|
||||
Serializable: BoostUint64(1),
|
||||
},
|
||||
{
|
||||
Name: "top_id",
|
||||
Serializable: BoostString(MainnetGenesisTx),
|
||||
},
|
||||
{
|
||||
Name: "top_version",
|
||||
Serializable: BoostByte(1),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}).Bytes()
|
||||
|
||||
for _, b := range payload {
|
||||
fmt.Printf("%x ", b)
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
reqHeaderB := NewRequestHeader(CommandHandshake, uint64(len(payload))).Bytes()
|
||||
|
||||
if _, err := c.conn.Write(reqHeaderB); err != nil {
|
||||
|
@ -103,18 +73,42 @@ func (c *Client) Handshake(ctx context.Context) error {
|
|||
return fmt.Errorf("write payload: %w", err)
|
||||
}
|
||||
|
||||
again:
|
||||
responseHeaderB := make([]byte, LevinHeaderSizeBytes)
|
||||
if _, err := io.ReadFull(c.conn, responseHeaderB); err != nil {
|
||||
return fmt.Errorf("read full header: %w", err)
|
||||
}
|
||||
|
||||
respHeader, err := NewHeaderFromResponseBytes(responseHeaderB)
|
||||
respHeader, err := NewHeaderFromBytesBytes(responseHeaderB)
|
||||
if err != nil {
|
||||
return fmt.Errorf("new header from resp bytes: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("%+v\n", respHeader)
|
||||
|
||||
if respHeader.Length != 0 {
|
||||
var dest io.Writer = os.Stderr
|
||||
|
||||
if respHeader.Command == CommandHandshake {
|
||||
f, err := os.Create("resp.bin")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
dest = f
|
||||
}
|
||||
|
||||
if _, err := io.CopyN(dest, c.conn, int64(respHeader.Length)); err != nil {
|
||||
return fmt.Errorf("copy payload to stdout: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if respHeader.Command != CommandHandshake {
|
||||
goto again
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -130,7 +124,7 @@ func (c *Client) Ping(ctx context.Context) error {
|
|||
return fmt.Errorf("read full header: %w", err)
|
||||
}
|
||||
|
||||
respHeader, err := NewHeaderFromResponseBytes(responseHeaderB)
|
||||
respHeader, err := NewHeaderFromBytesBytes(responseHeaderB)
|
||||
if err != nil {
|
||||
return fmt.Errorf("new header from resp bytes: %w", err)
|
||||
}
|
||||
|
|
|
@ -35,7 +35,8 @@ const (
|
|||
)
|
||||
|
||||
func IsValidReturnCode(c int32) bool {
|
||||
return (c >= LevinErrorFormat && c <= LevinOk)
|
||||
// anything >= 0 is good (there are some `1`s in the code :shrug:)
|
||||
return c >= LevinErrorFormat
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -57,7 +58,7 @@ var (
|
|||
0x16, 0xa1, 0xa1, 0x10,
|
||||
}
|
||||
|
||||
MainnetGenesisTx = "013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d1"
|
||||
MainnetGenesisTx = "418015bb9ae982a1975da7d79277c2705727a56894ba0fb246adaabb1f4632e3"
|
||||
)
|
||||
|
||||
func IsValidCommand(c uint32) bool {
|
||||
|
@ -154,7 +155,7 @@ func NewRequestHeader(command uint32, length uint64) *Header {
|
|||
}
|
||||
}
|
||||
|
||||
func NewHeaderFromResponseBytes(bytes []byte) (*Header, error) {
|
||||
func NewHeaderFromBytesBytes(bytes []byte) (*Header, error) {
|
||||
if len(bytes) != LevinHeaderSizeBytes {
|
||||
return nil, fmt.Errorf("invalid header size: expected %d, has %d",
|
||||
LevinHeaderSizeBytes, len(bytes),
|
||||
|
@ -216,11 +217,6 @@ func NewHeaderFromResponseBytes(bytes []byte) (*Header, error) {
|
|||
size = 4
|
||||
header.Flags = binary.LittleEndian.Uint32(bytes[idx : idx+size])
|
||||
idx += size
|
||||
|
||||
if header.Flags != LevinPacketReponse {
|
||||
return nil, fmt.Errorf("response flag not properly set %x",
|
||||
header.Flags)
|
||||
}
|
||||
}
|
||||
|
||||
{ // version
|
||||
|
|
|
@ -12,14 +12,14 @@ import (
|
|||
|
||||
func TestLevin(t *testing.T) {
|
||||
|
||||
spec.Run(t, "NewHeaderFromResponse", func(t *testing.T, when spec.G, it spec.S) {
|
||||
spec.Run(t, "NewHeaderFromBytes", func(t *testing.T, when spec.G, it spec.S) {
|
||||
|
||||
it("fails w/ wrong size", func() {
|
||||
bytes := []byte{
|
||||
0xff,
|
||||
}
|
||||
|
||||
_, err := levin.NewHeaderFromResponseBytes(bytes)
|
||||
_, err := levin.NewHeaderFromBytesBytes(bytes)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
|
@ -36,7 +36,7 @@ func TestLevin(t *testing.T) {
|
|||
0x00, 0x00, 0x00, 0x00, // version
|
||||
}
|
||||
|
||||
_, err := levin.NewHeaderFromResponseBytes(bytes)
|
||||
_, err := levin.NewHeaderFromBytesBytes(bytes)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "signature mismatch")
|
||||
})
|
||||
|
@ -54,7 +54,7 @@ func TestLevin(t *testing.T) {
|
|||
0x00, 0x00, 0x00, 0x00, // version
|
||||
}
|
||||
|
||||
_, err := levin.NewHeaderFromResponseBytes(bytes)
|
||||
_, err := levin.NewHeaderFromBytesBytes(bytes)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "invalid command")
|
||||
})
|
||||
|
@ -66,35 +66,17 @@ func TestLevin(t *testing.T) {
|
|||
0x01, 0x00, 0x00, 0x00, // length
|
||||
0x00, 0x00, 0x00, 0x00, //
|
||||
0x01, // expects response
|
||||
0x03, 0x10, 0x00, 0x00, // command
|
||||
0xe9, 0x03, 0x00, 0x00, // command
|
||||
0xaa, 0xaa, 0xaa, 0xaa, // return code
|
||||
0x00, 0x00, 0x00, 0x00, // flags
|
||||
0x00, 0x00, 0x00, 0x00, // version
|
||||
}
|
||||
|
||||
_, err := levin.NewHeaderFromResponseBytes(bytes)
|
||||
_, err := levin.NewHeaderFromBytesBytes(bytes)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "invalid return code")
|
||||
})
|
||||
|
||||
it("fails w/ response flag not set", func() {
|
||||
bytes := []byte{
|
||||
0x01, 0x21, 0x01, 0x01, // signature
|
||||
0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x00, 0x00, 0x00, // length
|
||||
0x00, 0x00, 0x00, 0x00, //
|
||||
0x01, // expects response
|
||||
0x03, 0x10, 0x00, 0x00, // command
|
||||
0x00, 0x00, 0x00, 0x00, // return code
|
||||
0x00, 0x00, 0x00, 0x00, // flags
|
||||
0x00, 0x00, 0x00, 0x00, // version
|
||||
}
|
||||
|
||||
_, err := levin.NewHeaderFromResponseBytes(bytes)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "response flag not properly set")
|
||||
})
|
||||
|
||||
it("fails w/ invalid version", func() {
|
||||
bytes := []byte{
|
||||
0x01, 0x21, 0x01, 0x01, // signature
|
||||
|
@ -102,13 +84,13 @@ func TestLevin(t *testing.T) {
|
|||
0x01, 0x00, 0x00, 0x00, // length
|
||||
0x00, 0x00, 0x00, 0x00, //
|
||||
0x01, // expects response
|
||||
0x03, 0x10, 0x00, 0x00, // command
|
||||
0xe9, 0x03, 0x00, 0x00, // command
|
||||
0x00, 0x00, 0x00, 0x00, // return code
|
||||
0x02, 0x00, 0x00, 0x00, // flags
|
||||
0x00, 0x00, 0x00, 0x00, // version
|
||||
}
|
||||
|
||||
_, err := levin.NewHeaderFromResponseBytes(bytes)
|
||||
_, err := levin.NewHeaderFromBytesBytes(bytes)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "invalid version")
|
||||
})
|
||||
|
@ -120,13 +102,13 @@ func TestLevin(t *testing.T) {
|
|||
0x01, 0x00, 0x00, 0x00, // length
|
||||
0x00, 0x00, 0x00, 0x00, //
|
||||
0x01, // expects response
|
||||
0x03, 0x10, 0x00, 0x00, // command
|
||||
0xeb, 0x03, 0x00, 0x00, // command
|
||||
0x00, 0x00, 0x00, 0x00, // return code
|
||||
0x02, 0x00, 0x00, 0x00, // flags
|
||||
0x01, 0x00, 0x00, 0x00, // version
|
||||
}
|
||||
|
||||
header, err := levin.NewHeaderFromResponseBytes(bytes)
|
||||
header, err := levin.NewHeaderFromBytesBytes(bytes)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, header.Command, levin.CommandPing)
|
||||
assert.Equal(t, header.ReturnCode, levin.LevinOk)
|
||||
|
@ -147,7 +129,7 @@ func TestLevin(t *testing.T) {
|
|||
0x01, 0x00, 0x00, 0x00, // length -- 0 for a ping msg
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x01, // expects response -- `true` bool
|
||||
0x03, 0x10, 0x00, 0x00, // command -- 1003 for ping
|
||||
0xeb, 0x03, 0x00, 0x00, // command -- 1003 for ping
|
||||
0x00, 0x00, 0x00, 0x00, // return code -- 0 for requests
|
||||
0x01, 0x00, 0x00, 0x00, // flags -- Q(1st lsb) set for req
|
||||
0x01, 0x00, 0x00, 0x00, // version
|
||||
|
@ -162,8 +144,8 @@ func TestLevin(t *testing.T) {
|
|||
0x01, 0x01, 0x01, 0x01,
|
||||
0x04, 0x00, 0x00, 0x00, // length -- 0 for a ping msg
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x01, // expects response -- `true` bool
|
||||
0x01, 0x10, 0x00, 0x00, // command -- 1003 for ping
|
||||
0x01, // expects response -- `true` bool
|
||||
0xe9, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, // return code -- 0 for requests
|
||||
0x01, 0x00, 0x00, 0x00, // flags -- Q(1st lsb) set for req
|
||||
0x01, 0x00, 0x00, 0x00, // version
|
||||
|
|
|
@ -32,6 +32,58 @@ type PortableStorage struct {
|
|||
Entries []Entry
|
||||
}
|
||||
|
||||
func NewPortableStorageFromBytes(bytes []byte) error {
|
||||
|
||||
var (
|
||||
size = 0
|
||||
idx = 0
|
||||
)
|
||||
|
||||
{ // sig-a
|
||||
size = 4
|
||||
sig := binary.LittleEndian.Uint32(bytes[idx : idx+size])
|
||||
idx += size
|
||||
|
||||
if sig != uint32(PortableStorageSignatureA) {
|
||||
return fmt.Errorf("sig-a doesn't match")
|
||||
}
|
||||
}
|
||||
|
||||
{ // sig-b
|
||||
size = 4
|
||||
sig := binary.LittleEndian.Uint32(bytes[idx : idx+size])
|
||||
idx += size
|
||||
|
||||
if sig != uint32(PortableStorageSignatureB) {
|
||||
return fmt.Errorf("sig-b doesn't match")
|
||||
}
|
||||
}
|
||||
|
||||
{ // format ver
|
||||
size = 1
|
||||
version := bytes[idx]
|
||||
idx += size
|
||||
|
||||
if version != PortableStorageFormatVersion {
|
||||
return fmt.Errorf("version doesn't match")
|
||||
}
|
||||
}
|
||||
|
||||
// read section
|
||||
// count = read var int (gives you number of entries)
|
||||
// while count >0:
|
||||
//
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReadVarInt(b []byte) int {
|
||||
// read mask
|
||||
// depending on the mask:
|
||||
// read N next bytes
|
||||
return 0
|
||||
}
|
||||
|
||||
func (s *PortableStorage) Bytes() []byte {
|
||||
var (
|
||||
body = make([]byte, 9) // fit _at least_ signatures + format ver
|
||||
|
|
Reference in a new issue