1
2
3
4
5 package quic
6
7 import (
8 "encoding/binary"
9
10 "golang.org/x/net/internal/quic/quicwire"
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 += quicwire.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 = quicwire.AppendUint8Bytes(hdr, p.dstConnID)
131 hdr = quicwire.AppendUint8Bytes(hdr, p.srcConnID)
132 switch p.ptype {
133 case packetTypeInitial:
134 hdr = quicwire.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.ptype, 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(packetType1RTT, 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(ptype packetType, pnum packetNumber) *sentPacket {
208 w.b = w.b[:len(w.b)+aeadOverhead]
209 w.sent.size = len(w.b) - w.pktOff
210 w.sent.ptype = ptype
211 w.sent.num = pnum
212 sent := w.sent
213 w.sent = nil
214 return sent
215 }
216
217
218 func (w *packetWriter) avail() int {
219 return w.pktLim - len(w.b)
220 }
221
222
223
224 func (w *packetWriter) appendPaddingTo(n int) {
225 n -= aeadOverhead
226 lim := min(w.pktLim, n)
227 if len(w.b) >= lim {
228 return
229 }
230 for len(w.b) < lim {
231 w.b = append(w.b, frameTypePadding)
232 }
233
234
235 w.sent.inFlight = true
236 }
237
238 func (w *packetWriter) appendPingFrame() (added bool) {
239 if len(w.b) >= w.pktLim {
240 return false
241 }
242 w.b = append(w.b, frameTypePing)
243 w.sent.markAckEliciting()
244 return true
245 }
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262 func (w *packetWriter) appendAckFrame(seen rangeset[packetNumber], delay unscaledAckDelay, ecn ecnCounts) (added bool) {
263 if len(seen) == 0 {
264 return false
265 }
266 var (
267 largest = uint64(seen.max())
268 firstRange = uint64(seen[len(seen)-1].size() - 1)
269 )
270 var ecnLen int
271 ackType := byte(frameTypeAck)
272 if (ecn != ecnCounts{}) {
273
274
275
276
277 ecnLen = quicwire.SizeVarint(uint64(ecn.ce)) + quicwire.SizeVarint(uint64(ecn.t0)) + quicwire.SizeVarint(uint64(ecn.t1))
278 ackType = frameTypeAckECN
279 }
280 if w.avail() < 1+quicwire.SizeVarint(largest)+quicwire.SizeVarint(uint64(delay))+1+quicwire.SizeVarint(firstRange)+ecnLen {
281 return false
282 }
283 w.b = append(w.b, ackType)
284 w.b = quicwire.AppendVarint(w.b, largest)
285 w.b = quicwire.AppendVarint(w.b, uint64(delay))
286
287
288 rangeCountOff := len(w.b)
289 w.b = append(w.b, 0)
290 w.b = quicwire.AppendVarint(w.b, firstRange)
291 rangeCount := byte(0)
292 for i := len(seen) - 2; i >= 0; i-- {
293 gap := uint64(seen[i+1].start - seen[i].end - 1)
294 size := uint64(seen[i].size() - 1)
295 if w.avail() < quicwire.SizeVarint(gap)+quicwire.SizeVarint(size)+ecnLen || rangeCount > 62 {
296 break
297 }
298 w.b = quicwire.AppendVarint(w.b, gap)
299 w.b = quicwire.AppendVarint(w.b, size)
300 rangeCount++
301 }
302 w.b[rangeCountOff] = rangeCount
303 if ackType == frameTypeAckECN {
304 w.b = quicwire.AppendVarint(w.b, uint64(ecn.t0))
305 w.b = quicwire.AppendVarint(w.b, uint64(ecn.t1))
306 w.b = quicwire.AppendVarint(w.b, uint64(ecn.ce))
307 }
308 w.sent.appendNonAckElicitingFrame(ackType)
309 w.sent.appendInt(uint64(seen.max()))
310 return true
311 }
312
313 func (w *packetWriter) appendNewTokenFrame(token []byte) (added bool) {
314 if w.avail() < 1+quicwire.SizeVarint(uint64(len(token)))+len(token) {
315 return false
316 }
317 w.b = append(w.b, frameTypeNewToken)
318 w.b = quicwire.AppendVarintBytes(w.b, token)
319 return true
320 }
321
322 func (w *packetWriter) appendResetStreamFrame(id streamID, code uint64, finalSize int64) (added bool) {
323 if w.avail() < 1+quicwire.SizeVarint(uint64(id))+quicwire.SizeVarint(code)+quicwire.SizeVarint(uint64(finalSize)) {
324 return false
325 }
326 w.b = append(w.b, frameTypeResetStream)
327 w.b = quicwire.AppendVarint(w.b, uint64(id))
328 w.b = quicwire.AppendVarint(w.b, code)
329 w.b = quicwire.AppendVarint(w.b, uint64(finalSize))
330 w.sent.appendAckElicitingFrame(frameTypeResetStream)
331 w.sent.appendInt(uint64(id))
332 return true
333 }
334
335 func (w *packetWriter) appendStopSendingFrame(id streamID, code uint64) (added bool) {
336 if w.avail() < 1+quicwire.SizeVarint(uint64(id))+quicwire.SizeVarint(code) {
337 return false
338 }
339 w.b = append(w.b, frameTypeStopSending)
340 w.b = quicwire.AppendVarint(w.b, uint64(id))
341 w.b = quicwire.AppendVarint(w.b, code)
342 w.sent.appendAckElicitingFrame(frameTypeStopSending)
343 w.sent.appendInt(uint64(id))
344 return true
345 }
346
347
348
349
350 func (w *packetWriter) appendCryptoFrame(off int64, size int) (_ []byte, added bool) {
351 max := w.avail()
352 max -= 1
353 max -= quicwire.SizeVarint(uint64(off))
354 max -= quicwire.SizeVarint(uint64(size))
355 if max <= 0 {
356 return nil, false
357 }
358 if max < size {
359 size = max
360 }
361 w.b = append(w.b, frameTypeCrypto)
362 w.b = quicwire.AppendVarint(w.b, uint64(off))
363 w.b = quicwire.AppendVarint(w.b, uint64(size))
364 start := len(w.b)
365 w.b = w.b[:start+size]
366 w.sent.appendAckElicitingFrame(frameTypeCrypto)
367 w.sent.appendOffAndSize(off, size)
368 return w.b[start:][:size], true
369 }
370
371
372
373
374 func (w *packetWriter) appendStreamFrame(id streamID, off int64, size int, fin bool) (_ []byte, added bool) {
375 typ := uint8(frameTypeStreamBase | streamLenBit)
376 max := w.avail()
377 max -= 1
378 max -= quicwire.SizeVarint(uint64(id))
379 if off != 0 {
380 max -= quicwire.SizeVarint(uint64(off))
381 typ |= streamOffBit
382 }
383 max -= quicwire.SizeVarint(uint64(size))
384 if max < 0 || (max == 0 && size > 0) {
385 return nil, false
386 }
387 if max < size {
388 size = max
389 } else if fin {
390 typ |= streamFinBit
391 }
392 w.b = append(w.b, typ)
393 w.b = quicwire.AppendVarint(w.b, uint64(id))
394 if off != 0 {
395 w.b = quicwire.AppendVarint(w.b, uint64(off))
396 }
397 w.b = quicwire.AppendVarint(w.b, uint64(size))
398 start := len(w.b)
399 w.b = w.b[:start+size]
400 w.sent.appendAckElicitingFrame(typ & (frameTypeStreamBase | streamFinBit))
401 w.sent.appendInt(uint64(id))
402 w.sent.appendOffAndSize(off, size)
403 return w.b[start:][:size], true
404 }
405
406 func (w *packetWriter) appendMaxDataFrame(max int64) (added bool) {
407 if w.avail() < 1+quicwire.SizeVarint(uint64(max)) {
408 return false
409 }
410 w.b = append(w.b, frameTypeMaxData)
411 w.b = quicwire.AppendVarint(w.b, uint64(max))
412 w.sent.appendAckElicitingFrame(frameTypeMaxData)
413 return true
414 }
415
416 func (w *packetWriter) appendMaxStreamDataFrame(id streamID, max int64) (added bool) {
417 if w.avail() < 1+quicwire.SizeVarint(uint64(id))+quicwire.SizeVarint(uint64(max)) {
418 return false
419 }
420 w.b = append(w.b, frameTypeMaxStreamData)
421 w.b = quicwire.AppendVarint(w.b, uint64(id))
422 w.b = quicwire.AppendVarint(w.b, uint64(max))
423 w.sent.appendAckElicitingFrame(frameTypeMaxStreamData)
424 w.sent.appendInt(uint64(id))
425 return true
426 }
427
428 func (w *packetWriter) appendMaxStreamsFrame(streamType streamType, max int64) (added bool) {
429 if w.avail() < 1+quicwire.SizeVarint(uint64(max)) {
430 return false
431 }
432 var typ byte
433 if streamType == bidiStream {
434 typ = frameTypeMaxStreamsBidi
435 } else {
436 typ = frameTypeMaxStreamsUni
437 }
438 w.b = append(w.b, typ)
439 w.b = quicwire.AppendVarint(w.b, uint64(max))
440 w.sent.appendAckElicitingFrame(typ)
441 return true
442 }
443
444 func (w *packetWriter) appendDataBlockedFrame(max int64) (added bool) {
445 if w.avail() < 1+quicwire.SizeVarint(uint64(max)) {
446 return false
447 }
448 w.b = append(w.b, frameTypeDataBlocked)
449 w.b = quicwire.AppendVarint(w.b, uint64(max))
450 w.sent.appendAckElicitingFrame(frameTypeDataBlocked)
451 return true
452 }
453
454 func (w *packetWriter) appendStreamDataBlockedFrame(id streamID, max int64) (added bool) {
455 if w.avail() < 1+quicwire.SizeVarint(uint64(id))+quicwire.SizeVarint(uint64(max)) {
456 return false
457 }
458 w.b = append(w.b, frameTypeStreamDataBlocked)
459 w.b = quicwire.AppendVarint(w.b, uint64(id))
460 w.b = quicwire.AppendVarint(w.b, uint64(max))
461 w.sent.appendAckElicitingFrame(frameTypeStreamDataBlocked)
462 w.sent.appendInt(uint64(id))
463 return true
464 }
465
466 func (w *packetWriter) appendStreamsBlockedFrame(typ streamType, max int64) (added bool) {
467 if w.avail() < 1+quicwire.SizeVarint(uint64(max)) {
468 return false
469 }
470 var ftype byte
471 if typ == bidiStream {
472 ftype = frameTypeStreamsBlockedBidi
473 } else {
474 ftype = frameTypeStreamsBlockedUni
475 }
476 w.b = append(w.b, ftype)
477 w.b = quicwire.AppendVarint(w.b, uint64(max))
478 w.sent.appendAckElicitingFrame(ftype)
479 return true
480 }
481
482 func (w *packetWriter) appendNewConnectionIDFrame(seq, retirePriorTo int64, connID []byte, token [16]byte) (added bool) {
483 if w.avail() < 1+quicwire.SizeVarint(uint64(seq))+quicwire.SizeVarint(uint64(retirePriorTo))+1+len(connID)+len(token) {
484 return false
485 }
486 w.b = append(w.b, frameTypeNewConnectionID)
487 w.b = quicwire.AppendVarint(w.b, uint64(seq))
488 w.b = quicwire.AppendVarint(w.b, uint64(retirePriorTo))
489 w.b = quicwire.AppendUint8Bytes(w.b, connID)
490 w.b = append(w.b, token[:]...)
491 w.sent.appendAckElicitingFrame(frameTypeNewConnectionID)
492 w.sent.appendInt(uint64(seq))
493 return true
494 }
495
496 func (w *packetWriter) appendRetireConnectionIDFrame(seq int64) (added bool) {
497 if w.avail() < 1+quicwire.SizeVarint(uint64(seq)) {
498 return false
499 }
500 w.b = append(w.b, frameTypeRetireConnectionID)
501 w.b = quicwire.AppendVarint(w.b, uint64(seq))
502 w.sent.appendAckElicitingFrame(frameTypeRetireConnectionID)
503 w.sent.appendInt(uint64(seq))
504 return true
505 }
506
507 func (w *packetWriter) appendPathChallengeFrame(data pathChallengeData) (added bool) {
508 if w.avail() < 1+8 {
509 return false
510 }
511 w.b = append(w.b, frameTypePathChallenge)
512 w.b = append(w.b, data[:]...)
513 w.sent.markAckEliciting()
514 return true
515 }
516
517 func (w *packetWriter) appendPathResponseFrame(data pathChallengeData) (added bool) {
518 if w.avail() < 1+8 {
519 return false
520 }
521 w.b = append(w.b, frameTypePathResponse)
522 w.b = append(w.b, data[:]...)
523 w.sent.markAckEliciting()
524 return true
525 }
526
527
528
529 func (w *packetWriter) appendConnectionCloseTransportFrame(code transportError, frameType uint64, reason string) (added bool) {
530 if w.avail() < 1+quicwire.SizeVarint(uint64(code))+quicwire.SizeVarint(frameType)+quicwire.SizeVarint(uint64(len(reason)))+len(reason) {
531 return false
532 }
533 w.b = append(w.b, frameTypeConnectionCloseTransport)
534 w.b = quicwire.AppendVarint(w.b, uint64(code))
535 w.b = quicwire.AppendVarint(w.b, frameType)
536 w.b = quicwire.AppendVarintBytes(w.b, []byte(reason))
537
538
539 return true
540 }
541
542
543
544 func (w *packetWriter) appendConnectionCloseApplicationFrame(code uint64, reason string) (added bool) {
545 if w.avail() < 1+quicwire.SizeVarint(code)+quicwire.SizeVarint(uint64(len(reason)))+len(reason) {
546 return false
547 }
548 w.b = append(w.b, frameTypeConnectionCloseApplication)
549 w.b = quicwire.AppendVarint(w.b, code)
550 w.b = quicwire.AppendVarintBytes(w.b, []byte(reason))
551
552
553 return true
554 }
555
556 func (w *packetWriter) appendHandshakeDoneFrame() (added bool) {
557 if w.avail() < 1 {
558 return false
559 }
560 w.b = append(w.b, frameTypeHandshakeDone)
561 w.sent.appendAckElicitingFrame(frameTypeHandshakeDone)
562 return true
563 }
564
View as plain text