forked from perlin-network/noise
-
Notifications
You must be signed in to change notification settings - Fork 0
/
msg.go
126 lines (96 loc) · 3.55 KB
/
msg.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
package noise
import (
"bytes"
"github.com/perlin-network/noise/payload"
"github.com/pkg/errors"
)
// To have Noise send/receive messages of a given type, said type must implement the
// following Message interface.
//
// Noise by default encodes messages as bytes in little-endian order, and provides
// utility classes to assist with serializing/deserializing arbitrary Go types into
// bytes efficiently.
//
// By exposing raw network packets as bytes to users, any additional form of serialization
// or message packing or compression scheme or cipher scheme may be bootstrapped on top of
// any particular message type registered to Noise.
type Message interface {
Read(reader payload.Reader) (Message, error)
Write() []byte
}
// EncodeMessage serializes a message body into its byte representation, and prefixes
// said byte representation with the messages opcode for the purpose of sending said
// bytes over the wire.
//
// Additional header/footer bytes is prepended/appended accordingly.
//
// Refer to the functions `OnEncodeHeader` and `OnEncodeFooter` available in `noise.Peer`
// to prepend/append additional information on every single message sent over the wire.
func (p *Peer) EncodeMessage(message Message) ([]byte, error) {
opcode, err := OpcodeFromMessage(message)
if err != nil {
return nil, errors.Wrap(err, "could not find opcode registered for message")
}
var buf bytes.Buffer
_, err = buf.Write(payload.NewWriter(nil).WriteByte(byte(opcode)).Bytes())
if err != nil {
return nil, errors.Wrap(err, "failed to serialize message opcode")
}
_, err = buf.Write(message.Write())
if err != nil {
return nil, errors.Wrap(err, "failed to serialize and write message contents")
}
header, errs := p.onEncodeHeaderCallbacks.RunCallbacks([]byte{}, p.node, buf.Bytes())
if len(errs) > 0 {
err := errs[0]
for _, e := range errs[1:] {
err = errors.Wrap(e, e.Error())
}
return nil, errors.Wrap(err, "failed to serialize custom footer")
}
footer, errs := p.onEncodeFooterCallbacks.RunCallbacks([]byte{}, p.node, buf.Bytes())
if len(errs) > 0 {
err := errs[0]
for _, e := range errs[1:] {
err = errors.Wrap(e, e.Error())
}
return nil, errors.Wrap(err, "failed to serialize custom footer")
}
return append(header.([]byte), append(buf.Bytes(), footer.([]byte)...)...), nil
}
func (p *Peer) DecodeMessage(buf []byte) (Opcode, Message, error) {
reader := payload.NewReader(buf)
// Read custom header from network packet.
errs := p.onDecodeHeaderCallbacks.RunCallbacks(p.node, reader)
if len(errs) > 0 {
err := errs[0]
for _, e := range errs[1:] {
err = errors.Wrap(e, e.Error())
}
return OpcodeNil, nil, errors.Wrap(err, "failed to decode custom headers")
}
afterHeaderSize := len(buf) - reader.Len()
opcode, err := reader.ReadByte()
if err != nil {
return OpcodeNil, nil, errors.Wrap(err, "failed to read opcode")
}
message, err := MessageFromOpcode(Opcode(opcode))
if err != nil {
return Opcode(opcode), nil, errors.Wrap(err, "opcode<->message pairing not registered")
}
message, err = message.Read(reader)
if err != nil {
return Opcode(opcode), nil, errors.Wrap(err, "failed to read message contents")
}
afterMessageSize := len(buf) - reader.Len()
// Read custom footer from network packet.
errs = p.onDecodeFooterCallbacks.RunCallbacks(p.node, buf[afterHeaderSize:afterMessageSize], reader)
if len(errs) > 0 {
err := errs[0]
for _, e := range errs[1:] {
err = errors.Wrap(e, e.Error())
}
return OpcodeNil, nil, errors.Wrap(err, "failed to decode custom footer")
}
return Opcode(opcode), message, nil
}