-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprotocol.go
More file actions
146 lines (125 loc) · 4.21 KB
/
Copy pathprotocol.go
File metadata and controls
146 lines (125 loc) · 4.21 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
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// This file contains constants and methods for handling the
// NetworkTables protocol, including encoding and decoding bytes for
// messages.
package networktables
import (
"encoding/binary"
"errors"
"math"
)
// The version of the protocol currently implemented.
const version = 0x0200
// Values used to indicate the various message types used in the
// NetworkTables protocol.
const (
keepAlive = 0x00
hello = 0x01
versionUnsupported = 0x02
helloComplete = 0x03
entryAssignment = 0x10
entryUpdate = 0x11
)
// Types of data that can be sent over NetworkTables.
const (
tBoolean = 0x00
tDouble = 0x01
tString = 0x02
tBooleanArray = 0x10
tDoubleArray = 0x11
tStringArray = 0x12
)
// ClientRequestID is the id clients use when requesting the server
// assign an id to the key.
const clientRequestID = 0xFFFF
// Errors that can occur while handling connections and dealing with
// the protocol.
var (
ErrUnsupportedHelloMsg = errors.New("networktables: server unexpectedly sent hello message")
ErrUnsupportedVersion = errors.New("networktables: unsupported client version tried to connect")
ErrUnsupportedVersionMsg = errors.New("networktables: server shouldn't get unsupported version message")
ErrHelloCompleteMsg = errors.New("networktables: server shouldn't get hello complete message")
ErrMultipleHellosCompleted = errors.New("networktables: server unexpectedly sent hello complete message")
ErrAssertiveClient = errors.New("networktables: assertive client trying to select entry ID")
ErrArraysUnsupported = errors.New("networktables: server currently doesn't support array types")
)
// Errors that can occur while trying to get a value from a client.
var (
ErrNoSuchKey = errors.New("networktables: no such key exists")
ErrWrongType = errors.New("networktables: key exists but contains the wrong type of data")
ErrHelloNotDone = errors.New("networktables: server has not finished sending hello to client")
)
// Other errors that can occur
var (
ErrConnectionNotOpen = errors.New("networktables: cannot close a connection that is not open")
ErrUserClosedConnection = errors.New("networktables: user has closed connection")
)
// helloMessage returns the bytes to send for the hello
// message of the given version.
func helloMessage(version uint16) []byte {
msg := []byte{hello}
msg = append(msg, getUint16Bytes(version)...)
return msg
}
// assignmentMessage returns the bytes to send for the assignment
// message of a given entry.
func assignmentMessage(e entry) []byte {
msg := []byte{entryAssignment}
msg = append(msg, getStringBytes(e.Name())...)
msg = append(msg, e.Type())
msg = append(msg, getUint16Bytes(e.ID())...)
msg = append(msg, getUint16Bytes(uint16(e.SequenceNumber()))...)
msg = append(msg, e.dataToBytes()...)
return msg
}
// updateMessage returns the bytes to send for the update message of a
// given entry.
func updateMessage(e entry) []byte {
msg := []byte{entryUpdate}
msg = append(msg, getUint16Bytes(e.ID())...)
msg = append(msg, getUint16Bytes(uint16(e.SequenceNumber()))...)
msg = append(msg, e.dataToBytes()...)
return msg
}
// Encoding and decoding methods
func getUint16(c <-chan byte) uint16 {
return binary.BigEndian.Uint16([]byte{<-c, <-c})
}
func getBoolean(c <-chan byte) bool {
return (<-c) != 0x00
}
func getDouble(c <-chan byte) float64 {
bits := binary.BigEndian.Uint64([]byte{<-c, <-c, <-c, <-c, <-c, <-c, <-c, <-c})
return math.Float64frombits(bits)
}
func getString(c <-chan byte) string {
length := getUint16(c)
bytes := make([]byte, length, length)
for i := uint16(0); i < length; i++ {
bytes[i] = <-c
}
return string(bytes)
}
func getUint16Bytes(val uint16) []byte {
bytes := make([]byte, 2, 2)
binary.BigEndian.PutUint16(bytes, val)
return bytes
}
func getBooleanByte(val bool) byte {
if val {
return 0x01
} else {
return 0x00
}
}
func getDoubleBytes(val float64) []byte {
bytes := make([]byte, 8, 8)
bits := math.Float64bits(val)
binary.BigEndian.PutUint64(bytes, bits)
return bytes
}
func getStringBytes(val string) []byte {
bytes := make([]byte, 0, 2+len(val))
bytes = append(bytes, getUint16Bytes((uint16)(len(val)))...)
bytes = append(bytes, []byte(val)...)
return bytes
}