forked from perlin-network/noise
-
Notifications
You must be signed in to change notification settings - Fork 1
/
msg.go
127 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
127
package noise
import (
"bytes"
"github.com/cynthiatong/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
}