-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmessage.go
More file actions
102 lines (85 loc) · 2.18 KB
/
message.go
File metadata and controls
102 lines (85 loc) · 2.18 KB
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
package roc
import (
"encoding/binary"
"errors"
"io"
)
const MaxPayloadSize = 0xffff
type header struct {
Destination Address
Source Address
Opcode byte
DataLength byte
}
func (header *header) read(reader io.Reader) error {
// Read destination address
err := header.Destination.read(reader)
if err != nil {
return err
}
// Read source address
err = header.Source.read(reader)
if err != nil {
return err
}
// read Opcode and DataLength
remainingHeader := make([]byte, 2)
_, err = io.ReadFull(reader, remainingHeader)
header.Opcode, header.DataLength = remainingHeader[0], remainingHeader[1]
return err
}
func (header *header) bytes() []byte {
addresses := append(header.Destination.bytes(), header.Source.bytes()...)
return append(addresses, header.Opcode, header.DataLength)
}
type Message struct {
header
Data []byte
CRC uint16
}
// read reads a message from the provided reader
func (message *Message) read(reader io.Reader) error {
err := message.header.read(reader)
if err != nil {
return err
}
// read data
message.Data = make([]byte, int(message.DataLength))
_, err = io.ReadFull(reader, message.Data)
if err != nil {
return err
}
err = binary.Read(reader, binary.LittleEndian, &message.CRC)
if err != nil {
return err
}
return message.validate()
}
func (message *Message) bytes() []byte {
data := append(message.header.bytes(), message.Data...)
crcBytes := make([]byte, 2)
binary.LittleEndian.PutUint16(crcBytes, message.CRC)
return append(data, crcBytes...)
}
func (message *Message) validate() (err error) {
if len(message.Data) != int(message.DataLength) {
return errors.New("Data Length Mismatch")
}
data := message.bytes()
// Calculate CRC for the entire message minus the crc
crc := calculateCRC(data[:len(data)-2])
if crc != message.CRC {
err = errors.New("CRC Mismatch")
}
return err
}
func (message *Message) updateCalculatedFields() (err error) {
if len(message.Data) > MaxPayloadSize {
return errors.New("Message payload too long")
}
message.DataLength = byte(len(message.Data))
data := message.bytes()
// Calculate CRC for the entire message minus the crc
message.CRC = calculateCRC(data[:len(data)-2])
return
}