-
Notifications
You must be signed in to change notification settings - Fork 0
/
transmissionhelpers.go
127 lines (105 loc) · 2.95 KB
/
transmissionhelpers.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 main
import (
"fmt"
"strconv"
)
func IsStreaming() bool {
return isStreamingHeader || isStreamingBody || isStreamingChecksum
}
func GetAvailableID() int {
sendCacheIndex += 1
if sendCacheIndex >= len(sendCache) {
sendCacheIndex = 0
}
// wipe old data
sendCache[sendCacheIndex] = nil
// we always return the next number because we'll never know if the transmission failed (otherwise we'd use the entire bandwidth for acknowledgements of acknowledgements)
return sendCacheIndex
}
func Rebroadcast(id int) error {
if id < 0 || id >= len(sendCache) {
return fmt.Errorf("invalid id")
}
if sendCache[id] == nil {
return fmt.Errorf("no transmission with that id")
}
sendChannel <- *sendCache[id]
return nil
}
func RequestRebroadcast(id int) error {
wt := WireTransmission{
Headers: Headers{
{"type", "requestRebroadcast"},
},
Body: []byte(strconv.Itoa(id)),
}
return SendMessage(wt)
}
func SendMessage(wt WireTransmission) error {
// get ID
id := GetAvailableID()
// if we couldn't get an ID, just ignore it (if we lose this packet it's just never going to be answered)
if id != -1 {
wt.Headers = append(wt.Headers, Header{"id", strconv.Itoa(id)})
}
// check the headers are valid
_, err := wt.Headers.Serialize()
if err != nil {
return err
}
sendChannel <- wt
// add to cache (evicting oldest)
sendCache[id] = &wt
return nil
}
func HandleReceiveByte(data byte) {
if data == StartHeader && !isEscaping {
// set header to streaming and body to not streaming
isStreamingHeader = true
isStreamingBody = false
isStreamingChecksum = false
// reset the current header
currentHeader = []byte{}
} else if data == StartText && !isEscaping {
// set the body to streaming
isStreamingBody = true
isStreamingHeader = false
isStreamingChecksum = false
// reset the current body
currentBody = []byte{}
} else if data == EndText && isStreamingBody && !isEscaping {
isStreamingBody = false
isStreamingHeader = false
isStreamingChecksum = true
// reset the current checksum
currentChecksum = []byte{}
} else if data == EndTransmission && !isEscaping {
// set the body to not streaming
isStreamingBody = false
isStreamingHeader = false
isStreamingChecksum = false
// casting to string should be enough to utf-8 decode the bytes
wt := WireTransmission{}
err := wt.Deserialize(string(currentHeader), currentBody, currentChecksum)
if err != nil {
ErrSerialLog(err)
} else {
receiveChannel <- wt
}
} else if data == EscapeChar && !isEscaping {
isEscaping = true
} else if isStreamingHeader {
// Add the next byte to the current header
currentHeader = append(currentHeader, data)
// reset the escaping flag
isEscaping = false
} else if isStreamingBody {
// Add the next byte to the current body
currentBody = append(currentBody, data)
// reset the escaping flag
isEscaping = false
} else if isStreamingChecksum {
currentChecksum = append(currentChecksum, data)
isEscaping = false
}
}