forked from eoscanada/eos-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
p2p.go
132 lines (106 loc) · 3.01 KB
/
p2p.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package eos
import (
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"io"
"reflect"
)
// Work-in-progress p2p comms implementation
//
// See /home/abourget/build/eos3/plugins/net_plugin/include/eosio/net_plugin/protocol.hpp:219
//
type P2PMessageType byte
const (
HandshakeMessageType P2PMessageType = iota // 0
ChainSizeType
GoAwayMessageType // 2
TimeMessageType
NoticeMessageType // 4
RequestMessageType
SyncRequestMessageType // 6
SignedBlockType // 7
PackedTransactionMessageType // 8
)
type MessageReflectTypes struct {
Name string
ReflectType reflect.Type
}
var messageAttributes = []MessageReflectTypes{
{Name: "Handshake", ReflectType: reflect.TypeOf(HandshakeMessage{})},
{Name: "ChainSize", ReflectType: reflect.TypeOf(ChainSizeMessage{})},
{Name: "GoAway", ReflectType: reflect.TypeOf(GoAwayMessage{})},
{Name: "Time", ReflectType: reflect.TypeOf(TimeMessage{})},
{Name: "Notice", ReflectType: reflect.TypeOf(NoticeMessage{})},
{Name: "Request", ReflectType: reflect.TypeOf(RequestMessage{})},
{Name: "SyncRequest", ReflectType: reflect.TypeOf(SyncRequestMessage{})},
{Name: "SignedBlock", ReflectType: reflect.TypeOf(SignedBlock{})},
{Name: "PackedTransaction", ReflectType: reflect.TypeOf(PackedTransactionMessage{})},
}
var ErrUnknownMessageType = errors.New("unknown type")
func NewMessageType(aType byte) (t P2PMessageType, err error) {
t = P2PMessageType(aType)
if !t.isValid() {
return t, ErrUnknownMessageType
}
return
}
func (t P2PMessageType) isValid() bool {
index := byte(t)
return int(index) < len(messageAttributes) && index >= 0
}
func (t P2PMessageType) Name() (string, bool) {
index := byte(t)
if !t.isValid() {
return "Unknown", false
}
attr := messageAttributes[index]
return attr.Name, true
}
func (t P2PMessageType) reflectTypes() (MessageReflectTypes, bool) {
index := byte(t)
if !t.isValid() {
return MessageReflectTypes{}, false
}
attr := messageAttributes[index]
return attr, true
}
type Packet struct {
Length uint32 `json:"length"`
Type P2PMessageType `json:"type"`
Payload []byte `json:"-"`
P2PMessage P2PMessage `json:"message" eos:"-"`
Raw []byte `json:"-"`
}
func ReadPacket(r io.Reader) (packet *Packet, err error) {
data := make([]byte, 0)
lengthBytes := make([]byte, 4, 4)
//_, err = r.Read(lengthBytes)
_, err = io.ReadFull(r, lengthBytes)
if err != nil {
return
}
data = append(data, lengthBytes...)
size := binary.LittleEndian.Uint32(lengthBytes)
payloadBytes := make([]byte, size, size)
count, err := io.ReadFull(r, payloadBytes)
if count != int(size) {
err = fmt.Errorf("readfull not full read[%d] expected[%d]", count, size)
return
}
if err != nil {
fmt.Println("ReadFull, error: ", err)
return
}
data = append(data, payloadBytes...)
packet = &Packet{}
decoder := NewDecoder(data)
decoder.DecodeActions(false)
err = decoder.Decode(packet)
if err != nil {
fmt.Println("Failing data: ", hex.EncodeToString(data))
}
packet.Raw = data
return
}