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