...
1
2
3
4
5
6
7 package quic
8
9 import (
10 "encoding/binary"
11 "fmt"
12 )
13
14
15
16 type packetType byte
17
18 const (
19 packetTypeInvalid = packetType(iota)
20 packetTypeInitial
21 packetType0RTT
22 packetTypeHandshake
23 packetTypeRetry
24 packetType1RTT
25 packetTypeVersionNegotiation
26 )
27
28 func (p packetType) String() string {
29 switch p {
30 case packetTypeInitial:
31 return "Initial"
32 case packetType0RTT:
33 return "0-RTT"
34 case packetTypeHandshake:
35 return "Handshake"
36 case packetTypeRetry:
37 return "Retry"
38 case packetType1RTT:
39 return "1-RTT"
40 }
41 return fmt.Sprintf("unknown packet type %v", byte(p))
42 }
43
44 func (p packetType) qlogString() string {
45 switch p {
46 case packetTypeInitial:
47 return "initial"
48 case packetType0RTT:
49 return "0RTT"
50 case packetTypeHandshake:
51 return "handshake"
52 case packetTypeRetry:
53 return "retry"
54 case packetType1RTT:
55 return "1RTT"
56 }
57 return "unknown"
58 }
59
60
61 const (
62 headerFormLong = 0x80
63 headerFormShort = 0x00
64 fixedBit = 0x40
65 reservedLongBits = 0x0c
66 reserved1RTTBits = 0x18
67 keyPhaseBit = 0x04
68 )
69
70
71
72 const (
73 longPacketTypeInitial = 0 << 4
74 longPacketType0RTT = 1 << 4
75 longPacketTypeHandshake = 2 << 4
76 longPacketTypeRetry = 3 << 4
77 )
78
79
80
81 const (
82 frameTypePadding = 0x00
83 frameTypePing = 0x01
84 frameTypeAck = 0x02
85 frameTypeAckECN = 0x03
86 frameTypeResetStream = 0x04
87 frameTypeStopSending = 0x05
88 frameTypeCrypto = 0x06
89 frameTypeNewToken = 0x07
90 frameTypeStreamBase = 0x08
91 frameTypeMaxData = 0x10
92 frameTypeMaxStreamData = 0x11
93 frameTypeMaxStreamsBidi = 0x12
94 frameTypeMaxStreamsUni = 0x13
95 frameTypeDataBlocked = 0x14
96 frameTypeStreamDataBlocked = 0x15
97 frameTypeStreamsBlockedBidi = 0x16
98 frameTypeStreamsBlockedUni = 0x17
99 frameTypeNewConnectionID = 0x18
100 frameTypeRetireConnectionID = 0x19
101 frameTypePathChallenge = 0x1a
102 frameTypePathResponse = 0x1b
103 frameTypeConnectionCloseTransport = 0x1c
104 frameTypeConnectionCloseApplication = 0x1d
105 frameTypeHandshakeDone = 0x1e
106 )
107
108
109
110 const (
111 streamOffBit = 0x04
112 streamLenBit = 0x02
113 streamFinBit = 0x01
114 )
115
116
117 const maxConnIDLen = 20
118
119
120 func isLongHeader(b byte) bool {
121 return b&headerFormLong == headerFormLong
122 }
123
124
125 func getPacketType(b []byte) packetType {
126 if len(b) == 0 {
127 return packetTypeInvalid
128 }
129 if !isLongHeader(b[0]) {
130 if b[0]&fixedBit != fixedBit {
131 return packetTypeInvalid
132 }
133 return packetType1RTT
134 }
135 if len(b) < 5 {
136 return packetTypeInvalid
137 }
138 if b[1] == 0 && b[2] == 0 && b[3] == 0 && b[4] == 0 {
139
140 return packetTypeVersionNegotiation
141 }
142 if b[0]&fixedBit != fixedBit {
143 return packetTypeInvalid
144 }
145 switch b[0] & 0x30 {
146 case longPacketTypeInitial:
147 return packetTypeInitial
148 case longPacketType0RTT:
149 return packetType0RTT
150 case longPacketTypeHandshake:
151 return packetTypeHandshake
152 case longPacketTypeRetry:
153 return packetTypeRetry
154 }
155 return packetTypeInvalid
156 }
157
158
159
160 func dstConnIDForDatagram(pkt []byte) (id []byte, ok bool) {
161 if len(pkt) < 1 {
162 return nil, false
163 }
164 var n int
165 var b []byte
166 if isLongHeader(pkt[0]) {
167 if len(pkt) < 6 {
168 return nil, false
169 }
170 n = int(pkt[5])
171 b = pkt[6:]
172 } else {
173 n = connIDLen
174 b = pkt[1:]
175 }
176 if len(b) < n {
177 return nil, false
178 }
179 return b[:n], true
180 }
181
182
183
184
185 func parseVersionNegotiation(pkt []byte) (dstConnID, srcConnID, versions []byte) {
186 p, ok := parseGenericLongHeaderPacket(pkt)
187 if !ok {
188 return nil, nil, nil
189 }
190 if len(p.data)%4 != 0 {
191 return nil, nil, nil
192 }
193 return p.dstConnID, p.srcConnID, p.data
194 }
195
196
197
198 func appendVersionNegotiation(pkt, dstConnID, srcConnID []byte, versions ...uint32) []byte {
199 pkt = append(pkt, headerFormLong|fixedBit)
200 pkt = append(pkt, 0, 0, 0, 0)
201 pkt = appendUint8Bytes(pkt, dstConnID)
202 pkt = appendUint8Bytes(pkt, srcConnID)
203 for _, v := range versions {
204 pkt = binary.BigEndian.AppendUint32(pkt, v)
205 }
206 return pkt
207 }
208
209
210 type longPacket struct {
211 ptype packetType
212 version uint32
213 num packetNumber
214 dstConnID []byte
215 srcConnID []byte
216 payload []byte
217
218
219
220
221 extra []byte
222 }
223
224
225 type shortPacket struct {
226 num packetNumber
227 payload []byte
228 }
229
230
231
232 type genericLongPacket struct {
233 version uint32
234 dstConnID []byte
235 srcConnID []byte
236 data []byte
237 }
238
239 func parseGenericLongHeaderPacket(b []byte) (p genericLongPacket, ok bool) {
240 if len(b) < 5 || !isLongHeader(b[0]) {
241 return genericLongPacket{}, false
242 }
243 b = b[1:]
244
245 var n int
246 p.version, n = consumeUint32(b)
247 if n < 0 {
248 return genericLongPacket{}, false
249 }
250 b = b[n:]
251
252
253 p.dstConnID, n = consumeUint8Bytes(b)
254 if n < 0 || len(p.dstConnID) > 2048/8 {
255 return genericLongPacket{}, false
256 }
257 b = b[n:]
258
259
260 p.srcConnID, n = consumeUint8Bytes(b)
261 if n < 0 || len(p.dstConnID) > 2048/8 {
262 return genericLongPacket{}, false
263 }
264 b = b[n:]
265 p.data = b
266 return p, true
267 }
268
View as plain text