1
2
3
4
5
6
7 package quic
8
9 import (
10 "encoding/binary"
11 )
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 type packetWriter struct {
28 dgramLim int
29 pktLim int
30 pktOff int
31 payOff int
32 b []byte
33 sent *sentPacket
34 }
35
36
37 func (w *packetWriter) reset(lim int) {
38 if cap(w.b) < lim {
39 w.b = make([]byte, 0, lim)
40 }
41 w.dgramLim = lim
42 w.b = w.b[:0]
43 }
44
45
46 func (w *packetWriter) datagram() []byte {
47 return w.b
48 }
49
50
51 func (w *packetWriter) packetLen() int {
52 return len(w.b[w.pktOff:]) + aeadOverhead
53 }
54
55
56 func (w *packetWriter) payload() []byte {
57 return w.b[w.payOff:]
58 }
59
60 func (w *packetWriter) abandonPacket() {
61 w.b = w.b[:w.payOff]
62 w.sent.reset()
63 }
64
65
66 func (w *packetWriter) startProtectedLongHeaderPacket(pnumMaxAcked packetNumber, p longPacket) {
67 if w.sent == nil {
68 w.sent = newSentPacket()
69 }
70 w.pktOff = len(w.b)
71 hdrSize := 1
72 hdrSize += 4
73 hdrSize += 1 + len(p.dstConnID)
74 hdrSize += 1 + len(p.srcConnID)
75 switch p.ptype {
76 case packetTypeInitial:
77 hdrSize += sizeVarint(uint64(len(p.extra))) + len(p.extra)
78 }
79 hdrSize += 2
80 pnumOff := len(w.b) + hdrSize
81 hdrSize += packetNumberLength(p.num, pnumMaxAcked)
82 payOff := len(w.b) + hdrSize
83
84
85 if pnumOff+4+headerProtectionSampleSize+aeadOverhead >= w.dgramLim {
86
87
88 w.payOff = len(w.b)
89 w.pktLim = len(w.b)
90 return
91 }
92 w.payOff = payOff
93 w.pktLim = w.dgramLim - aeadOverhead
94
95
96
97
98
99 if lim := pnumOff + 16383 - aeadOverhead; lim < w.pktLim {
100 w.pktLim = lim
101 }
102 w.b = w.b[:payOff]
103 }
104
105
106
107
108 func (w *packetWriter) finishProtectedLongHeaderPacket(pnumMaxAcked packetNumber, k fixedKeys, p longPacket) *sentPacket {
109 if len(w.b) == w.payOff {
110
111 w.b = w.b[:w.pktOff]
112 return nil
113 }
114 pnumLen := packetNumberLength(p.num, pnumMaxAcked)
115 plen := w.padPacketLength(pnumLen)
116 hdr := w.b[:w.pktOff]
117 var typeBits byte
118 switch p.ptype {
119 case packetTypeInitial:
120 typeBits = longPacketTypeInitial
121 case packetType0RTT:
122 typeBits = longPacketType0RTT
123 case packetTypeHandshake:
124 typeBits = longPacketTypeHandshake
125 case packetTypeRetry:
126 typeBits = longPacketTypeRetry
127 }
128 hdr = append(hdr, headerFormLong|fixedBit|typeBits|byte(pnumLen-1))
129 hdr = binary.BigEndian.AppendUint32(hdr, p.version)
130 hdr = appendUint8Bytes(hdr, p.dstConnID)
131 hdr = appendUint8Bytes(hdr, p.srcConnID)
132 switch p.ptype {
133 case packetTypeInitial:
134 hdr = appendVarintBytes(hdr, p.extra)
135 }
136
137
138 hdr = append(hdr, 0x40|byte(plen>>8), byte(plen))
139
140 pnumOff := len(hdr)
141 hdr = appendPacketNumber(hdr, p.num, pnumMaxAcked)
142
143 k.protect(hdr[w.pktOff:], w.b[len(hdr):], pnumOff-w.pktOff, p.num)
144 return w.finish(p.num)
145 }
146
147
148 func (w *packetWriter) start1RTTPacket(pnum, pnumMaxAcked packetNumber, dstConnID []byte) {
149 if w.sent == nil {
150 w.sent = newSentPacket()
151 }
152 w.pktOff = len(w.b)
153 hdrSize := 1
154 hdrSize += len(dstConnID)
155
156
157 if len(w.b)+hdrSize+4+headerProtectionSampleSize+aeadOverhead >= w.dgramLim {
158 w.payOff = len(w.b)
159 w.pktLim = len(w.b)
160 return
161 }
162 hdrSize += packetNumberLength(pnum, pnumMaxAcked)
163 w.payOff = len(w.b) + hdrSize
164 w.pktLim = w.dgramLim - aeadOverhead
165 w.b = w.b[:w.payOff]
166 }
167
168
169
170
171 func (w *packetWriter) finish1RTTPacket(pnum, pnumMaxAcked packetNumber, dstConnID []byte, k *updatingKeyPair) *sentPacket {
172 if len(w.b) == w.payOff {
173
174 w.b = w.b[:w.pktOff]
175 return nil
176 }
177
178 pnumLen := packetNumberLength(pnum, pnumMaxAcked)
179 hdr := w.b[:w.pktOff]
180 hdr = append(hdr, 0x40|byte(pnumLen-1))
181 hdr = append(hdr, dstConnID...)
182 pnumOff := len(hdr)
183 hdr = appendPacketNumber(hdr, pnum, pnumMaxAcked)
184 w.padPacketLength(pnumLen)
185 k.protect(hdr[w.pktOff:], w.b[len(hdr):], pnumOff-w.pktOff, pnum)
186 return w.finish(pnum)
187 }
188
189
190
191
192 func (w *packetWriter) padPacketLength(pnumLen int) int {
193 plen := len(w.b) - w.payOff + pnumLen + aeadOverhead
194
195
196
197
198
199 for plen < 4+headerProtectionSampleSize {
200 w.b = append(w.b, 0)
201 plen++
202 }
203 return plen
204 }
205
206
207 func (w *packetWriter) finish(pnum packetNumber) *sentPacket {
208 w.b = w.b[:len(w.b)+aeadOverhead]
209 w.sent.size = len(w.b) - w.pktOff
210 w.sent.num = pnum
211 sent := w.sent
212 w.sent = nil
213 return sent
214 }
215
216
217 func (w *packetWriter) avail() int {
218 return w.pktLim - len(w.b)
219 }
220
221
222
223 func (w *packetWriter) appendPaddingTo(n int) {
224 n -= aeadOverhead
225 lim := w.pktLim
226 if n < lim {
227 lim = n
228 }
229 if len(w.b) >= lim {
230 return
231 }
232 for len(w.b) < lim {
233 w.b = append(w.b, frameTypePadding)
234 }
235
236
237 w.sent.inFlight = true
238 }
239
240 func (w *packetWriter) appendPingFrame() (added bool) {
241 if len(w.b) >= w.pktLim {
242 return false
243 }
244 w.b = append(w.b, frameTypePing)
245
246
247 w.sent.ackEliciting = true
248 w.sent.inFlight = true
249 return true
250 }
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267 func (w *packetWriter) appendAckFrame(seen rangeset[packetNumber], delay unscaledAckDelay) (added bool) {
268 if len(seen) == 0 {
269 return false
270 }
271 var (
272 largest = uint64(seen.max())
273 firstRange = uint64(seen[len(seen)-1].size() - 1)
274 )
275 if w.avail() < 1+sizeVarint(largest)+sizeVarint(uint64(delay))+1+sizeVarint(firstRange) {
276 return false
277 }
278 w.b = append(w.b, frameTypeAck)
279 w.b = appendVarint(w.b, largest)
280 w.b = appendVarint(w.b, uint64(delay))
281
282
283 rangeCountOff := len(w.b)
284 w.b = append(w.b, 0)
285 w.b = appendVarint(w.b, firstRange)
286 rangeCount := byte(0)
287 for i := len(seen) - 2; i >= 0; i-- {
288 gap := uint64(seen[i+1].start - seen[i].end - 1)
289 size := uint64(seen[i].size() - 1)
290 if w.avail() < sizeVarint(gap)+sizeVarint(size) || rangeCount > 62 {
291 break
292 }
293 w.b = appendVarint(w.b, gap)
294 w.b = appendVarint(w.b, size)
295 rangeCount++
296 }
297 w.b[rangeCountOff] = rangeCount
298 w.sent.appendNonAckElicitingFrame(frameTypeAck)
299 w.sent.appendInt(uint64(seen.max()))
300 return true
301 }
302
303 func (w *packetWriter) appendNewTokenFrame(token []byte) (added bool) {
304 if w.avail() < 1+sizeVarint(uint64(len(token)))+len(token) {
305 return false
306 }
307 w.b = append(w.b, frameTypeNewToken)
308 w.b = appendVarintBytes(w.b, token)
309 return true
310 }
311
312 func (w *packetWriter) appendResetStreamFrame(id streamID, code uint64, finalSize int64) (added bool) {
313 if w.avail() < 1+sizeVarint(uint64(id))+sizeVarint(code)+sizeVarint(uint64(finalSize)) {
314 return false
315 }
316 w.b = append(w.b, frameTypeResetStream)
317 w.b = appendVarint(w.b, uint64(id))
318 w.b = appendVarint(w.b, code)
319 w.b = appendVarint(w.b, uint64(finalSize))
320 w.sent.appendAckElicitingFrame(frameTypeResetStream)
321 w.sent.appendInt(uint64(id))
322 return true
323 }
324
325 func (w *packetWriter) appendStopSendingFrame(id streamID, code uint64) (added bool) {
326 if w.avail() < 1+sizeVarint(uint64(id))+sizeVarint(code) {
327 return false
328 }
329 w.b = append(w.b, frameTypeStopSending)
330 w.b = appendVarint(w.b, uint64(id))
331 w.b = appendVarint(w.b, code)
332 w.sent.appendAckElicitingFrame(frameTypeStopSending)
333 w.sent.appendInt(uint64(id))
334 return true
335 }
336
337
338
339
340 func (w *packetWriter) appendCryptoFrame(off int64, size int) (_ []byte, added bool) {
341 max := w.avail()
342 max -= 1
343 max -= sizeVarint(uint64(off))
344 max -= sizeVarint(uint64(size))
345 if max <= 0 {
346 return nil, false
347 }
348 if max < size {
349 size = max
350 }
351 w.b = append(w.b, frameTypeCrypto)
352 w.b = appendVarint(w.b, uint64(off))
353 w.b = appendVarint(w.b, uint64(size))
354 start := len(w.b)
355 w.b = w.b[:start+size]
356 w.sent.appendAckElicitingFrame(frameTypeCrypto)
357 w.sent.appendOffAndSize(off, size)
358 return w.b[start:][:size], true
359 }
360
361
362
363
364 func (w *packetWriter) appendStreamFrame(id streamID, off int64, size int, fin bool) (_ []byte, added bool) {
365 typ := uint8(frameTypeStreamBase | streamLenBit)
366 max := w.avail()
367 max -= 1
368 max -= sizeVarint(uint64(id))
369 if off != 0 {
370 max -= sizeVarint(uint64(off))
371 typ |= streamOffBit
372 }
373 max -= sizeVarint(uint64(size))
374 if max < 0 || (max == 0 && size > 0) {
375 return nil, false
376 }
377 if max < size {
378 size = max
379 } else if fin {
380 typ |= streamFinBit
381 }
382 w.b = append(w.b, typ)
383 w.b = appendVarint(w.b, uint64(id))
384 if off != 0 {
385 w.b = appendVarint(w.b, uint64(off))
386 }
387 w.b = appendVarint(w.b, uint64(size))
388 start := len(w.b)
389 w.b = w.b[:start+size]
390 if fin {
391 w.sent.appendAckElicitingFrame(frameTypeStreamBase | streamFinBit)
392 } else {
393 w.sent.appendAckElicitingFrame(frameTypeStreamBase)
394 }
395 w.sent.appendInt(uint64(id))
396 w.sent.appendOffAndSize(off, size)
397 return w.b[start:][:size], true
398 }
399
400 func (w *packetWriter) appendMaxDataFrame(max int64) (added bool) {
401 if w.avail() < 1+sizeVarint(uint64(max)) {
402 return false
403 }
404 w.b = append(w.b, frameTypeMaxData)
405 w.b = appendVarint(w.b, uint64(max))
406 w.sent.appendAckElicitingFrame(frameTypeMaxData)
407 return true
408 }
409
410 func (w *packetWriter) appendMaxStreamDataFrame(id streamID, max int64) (added bool) {
411 if w.avail() < 1+sizeVarint(uint64(id))+sizeVarint(uint64(max)) {
412 return false
413 }
414 w.b = append(w.b, frameTypeMaxStreamData)
415 w.b = appendVarint(w.b, uint64(id))
416 w.b = appendVarint(w.b, uint64(max))
417 w.sent.appendAckElicitingFrame(frameTypeMaxStreamData)
418 w.sent.appendInt(uint64(id))
419 return true
420 }
421
422 func (w *packetWriter) appendMaxStreamsFrame(streamType streamType, max int64) (added bool) {
423 if w.avail() < 1+sizeVarint(uint64(max)) {
424 return false
425 }
426 var typ byte
427 if streamType == bidiStream {
428 typ = frameTypeMaxStreamsBidi
429 } else {
430 typ = frameTypeMaxStreamsUni
431 }
432 w.b = append(w.b, typ)
433 w.b = appendVarint(w.b, uint64(max))
434 w.sent.appendAckElicitingFrame(typ)
435 return true
436 }
437
438 func (w *packetWriter) appendDataBlockedFrame(max int64) (added bool) {
439 if w.avail() < 1+sizeVarint(uint64(max)) {
440 return false
441 }
442 w.b = append(w.b, frameTypeDataBlocked)
443 w.b = appendVarint(w.b, uint64(max))
444 w.sent.appendAckElicitingFrame(frameTypeDataBlocked)
445 return true
446 }
447
448 func (w *packetWriter) appendStreamDataBlockedFrame(id streamID, max int64) (added bool) {
449 if w.avail() < 1+sizeVarint(uint64(id))+sizeVarint(uint64(max)) {
450 return false
451 }
452 w.b = append(w.b, frameTypeStreamDataBlocked)
453 w.b = appendVarint(w.b, uint64(id))
454 w.b = appendVarint(w.b, uint64(max))
455 w.sent.appendAckElicitingFrame(frameTypeStreamDataBlocked)
456 w.sent.appendInt(uint64(id))
457 return true
458 }
459
460 func (w *packetWriter) appendStreamsBlockedFrame(typ streamType, max int64) (added bool) {
461 if w.avail() < 1+sizeVarint(uint64(max)) {
462 return false
463 }
464 var ftype byte
465 if typ == bidiStream {
466 ftype = frameTypeStreamsBlockedBidi
467 } else {
468 ftype = frameTypeStreamsBlockedUni
469 }
470 w.b = append(w.b, ftype)
471 w.b = appendVarint(w.b, uint64(max))
472 w.sent.appendAckElicitingFrame(ftype)
473 return true
474 }
475
476 func (w *packetWriter) appendNewConnectionIDFrame(seq, retirePriorTo int64, connID []byte, token [16]byte) (added bool) {
477 if w.avail() < 1+sizeVarint(uint64(seq))+sizeVarint(uint64(retirePriorTo))+1+len(connID)+len(token) {
478 return false
479 }
480 w.b = append(w.b, frameTypeNewConnectionID)
481 w.b = appendVarint(w.b, uint64(seq))
482 w.b = appendVarint(w.b, uint64(retirePriorTo))
483 w.b = appendUint8Bytes(w.b, connID)
484 w.b = append(w.b, token[:]...)
485 w.sent.appendAckElicitingFrame(frameTypeNewConnectionID)
486 w.sent.appendInt(uint64(seq))
487 return true
488 }
489
490 func (w *packetWriter) appendRetireConnectionIDFrame(seq int64) (added bool) {
491 if w.avail() < 1+sizeVarint(uint64(seq)) {
492 return false
493 }
494 w.b = append(w.b, frameTypeRetireConnectionID)
495 w.b = appendVarint(w.b, uint64(seq))
496 w.sent.appendAckElicitingFrame(frameTypeRetireConnectionID)
497 w.sent.appendInt(uint64(seq))
498 return true
499 }
500
501 func (w *packetWriter) appendPathChallengeFrame(data uint64) (added bool) {
502 if w.avail() < 1+8 {
503 return false
504 }
505 w.b = append(w.b, frameTypePathChallenge)
506 w.b = binary.BigEndian.AppendUint64(w.b, data)
507 w.sent.appendAckElicitingFrame(frameTypePathChallenge)
508 return true
509 }
510
511 func (w *packetWriter) appendPathResponseFrame(data uint64) (added bool) {
512 if w.avail() < 1+8 {
513 return false
514 }
515 w.b = append(w.b, frameTypePathResponse)
516 w.b = binary.BigEndian.AppendUint64(w.b, data)
517 w.sent.appendAckElicitingFrame(frameTypePathResponse)
518 return true
519 }
520
521
522
523 func (w *packetWriter) appendConnectionCloseTransportFrame(code transportError, frameType uint64, reason string) (added bool) {
524 if w.avail() < 1+sizeVarint(uint64(code))+sizeVarint(frameType)+sizeVarint(uint64(len(reason)))+len(reason) {
525 return false
526 }
527 w.b = append(w.b, frameTypeConnectionCloseTransport)
528 w.b = appendVarint(w.b, uint64(code))
529 w.b = appendVarint(w.b, frameType)
530 w.b = appendVarintBytes(w.b, []byte(reason))
531
532
533 return true
534 }
535
536
537
538 func (w *packetWriter) appendConnectionCloseApplicationFrame(code uint64, reason string) (added bool) {
539 if w.avail() < 1+sizeVarint(code)+sizeVarint(uint64(len(reason)))+len(reason) {
540 return false
541 }
542 w.b = append(w.b, frameTypeConnectionCloseApplication)
543 w.b = appendVarint(w.b, code)
544 w.b = appendVarintBytes(w.b, []byte(reason))
545
546
547 return true
548 }
549
550 func (w *packetWriter) appendHandshakeDoneFrame() (added bool) {
551 if w.avail() < 1 {
552 return false
553 }
554 w.b = append(w.b, frameTypeHandshakeDone)
555 w.sent.appendAckElicitingFrame(frameTypeHandshakeDone)
556 return true
557 }
558
View as plain text