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