-
Notifications
You must be signed in to change notification settings - Fork 19
/
packet.go
193 lines (171 loc) · 3.88 KB
/
packet.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
package udt
// Structure of packets and functions for writing/reading them
import (
"bytes"
"encoding/binary"
"fmt"
"io"
)
const (
flag_bit_32 = 1 << 31 // leading bit for distinguishing control from data packets (32 bit version)
flag_bit_16 = 1 << 15 // leading bit for distinguishing control from data packets (16 bit version)
// Control packet types
handshake = 0x0
keepalive = 0x1
ack = 0x2
nak = 0x3
unused = 0x4
shutdown = 0x5
ack2 = 0x6
msg_drop_req = 0x7
// Socket types
// Note - these are reversed from the spec, as the C++ implementation of UDT
// seems to have them reversed and we want to stay interoperable
STREAM = 1
DGRAM = 0 // not supported!
// No info for info section of header
noinfo = 0
)
var (
endianness = binary.BigEndian
)
type packet interface {
// socketId retrieves the socket id of a packet
socketId() (sockId uint32)
// sendTime retrieves the timesamp of the packet
sendTime() (ts uint32)
writeTo(io.Writer) (err error)
/*
readFrom reads the packet from a Reader
*/
readFrom(r io.Reader) (err error)
}
type dataPacket struct {
seq uint32
ts uint32
dstSockId uint32
data []byte
}
type header struct {
ts uint32
dstSockId uint32
}
func (p *dataPacket) socketId() (sockId uint32) {
return p.dstSockId
}
func (p *dataPacket) sendTime() (ts uint32) {
return p.ts
}
func (dp *dataPacket) writeTo(w io.Writer) (err error) {
if err := writeBinary(w, dp.seq); err != nil {
return err
}
if err := writeBinary(w, dp.ts); err != nil {
return err
}
if err := writeBinary(w, dp.dstSockId); err != nil {
return err
}
if _, err := w.Write(dp.data); err != nil {
return err
}
return
}
func (p *dataPacket) readFrom(r io.Reader) (err error) {
if err = readBinary(r, &p.ts); err != nil {
return
}
if err = readBinary(r, &p.dstSockId); err != nil {
return
}
// The data is whatever is what comes after the 12 bytes of header
var buf *bytes.Buffer
switch b := r.(type) {
case *bytes.Buffer:
buf = b
default:
buf := bytes.NewBuffer([]byte{})
buf.ReadFrom(r)
}
p.data = buf.Bytes()
return
}
func (h *header) writeTo(w io.Writer, msgType uint16, info uint32) (err error) {
// Sets the flag bit to indicate this is a control packet
if err := writeBinary(w, msgType|flag_bit_16); err != nil {
return err
}
// Write 16 bit reserved data
if err := writeBinary(w, uint16(0)); err != nil {
return err
}
if err := writeBinary(w, info); err != nil {
return err
}
if err := writeBinary(w, h.ts); err != nil {
return err
}
if err := writeBinary(w, h.dstSockId); err != nil {
return err
}
return
}
func (p *header) readFrom(r io.Reader) (addtlInfo uint32, err error) {
if err = readBinary(r, &addtlInfo); err != nil {
return
}
if err = readBinary(r, &p.ts); err != nil {
return
}
if err = readBinary(r, &p.dstSockId); err != nil {
return
}
return
}
func readPacketFrom(r io.Reader) (p packet, err error) {
var h uint32
if err = readBinary(r, &h); err != nil {
return
}
if h&flag_bit_32 == flag_bit_32 {
// this is a control packet
// Remove flag bit
h = h &^ flag_bit_32
// Message type is leading 16 bits
msgType := h >> 16
switch msgType {
case handshake:
p = &handshakePacket{}
case keepalive:
p = &keepAlivePacket{}
case ack:
p = &ackPacket{}
case nak:
p = &nakPacket{}
case shutdown:
p = &shutdownPacket{}
case ack2:
p = &ack2Packet{}
case msg_drop_req:
p = &msgDropReqPacket{}
default:
err = fmt.Errorf("Unkown control packet type: %X", msgType)
return nil, err
}
err = p.readFrom(r)
return
} else {
// this is a data packet
p = &dataPacket{
seq: h,
}
err = p.readFrom(r)
}
return
}
func writeBinary(w io.Writer, n interface{}) (err error) {
return binary.Write(w, endianness, n)
}
func readBinary(r io.Reader, n interface{}) (err error) {
return binary.Read(r, endianness, n)
}