1
2
3
4
5 package quic
6
7 import (
8 "fmt"
9 "log/slog"
10 "strconv"
11 "time"
12 )
13
14
15
16 type debugFrame interface {
17 String() string
18 write(w *packetWriter) bool
19 LogValue() slog.Value
20 }
21
22 func parseDebugFrame(b []byte) (f debugFrame, n int) {
23 if len(b) == 0 {
24 return nil, -1
25 }
26 switch b[0] {
27 case frameTypePadding:
28 f, n = parseDebugFramePadding(b)
29 case frameTypePing:
30 f, n = parseDebugFramePing(b)
31 case frameTypeAck, frameTypeAckECN:
32 f, n = parseDebugFrameAck(b)
33 case frameTypeResetStream:
34 f, n = parseDebugFrameResetStream(b)
35 case frameTypeStopSending:
36 f, n = parseDebugFrameStopSending(b)
37 case frameTypeCrypto:
38 f, n = parseDebugFrameCrypto(b)
39 case frameTypeNewToken:
40 f, n = parseDebugFrameNewToken(b)
41 case frameTypeStreamBase, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f:
42 f, n = parseDebugFrameStream(b)
43 case frameTypeMaxData:
44 f, n = parseDebugFrameMaxData(b)
45 case frameTypeMaxStreamData:
46 f, n = parseDebugFrameMaxStreamData(b)
47 case frameTypeMaxStreamsBidi, frameTypeMaxStreamsUni:
48 f, n = parseDebugFrameMaxStreams(b)
49 case frameTypeDataBlocked:
50 f, n = parseDebugFrameDataBlocked(b)
51 case frameTypeStreamDataBlocked:
52 f, n = parseDebugFrameStreamDataBlocked(b)
53 case frameTypeStreamsBlockedBidi, frameTypeStreamsBlockedUni:
54 f, n = parseDebugFrameStreamsBlocked(b)
55 case frameTypeNewConnectionID:
56 f, n = parseDebugFrameNewConnectionID(b)
57 case frameTypeRetireConnectionID:
58 f, n = parseDebugFrameRetireConnectionID(b)
59 case frameTypePathChallenge:
60 f, n = parseDebugFramePathChallenge(b)
61 case frameTypePathResponse:
62 f, n = parseDebugFramePathResponse(b)
63 case frameTypeConnectionCloseTransport:
64 f, n = parseDebugFrameConnectionCloseTransport(b)
65 case frameTypeConnectionCloseApplication:
66 f, n = parseDebugFrameConnectionCloseApplication(b)
67 case frameTypeHandshakeDone:
68 f, n = parseDebugFrameHandshakeDone(b)
69 default:
70 return nil, -1
71 }
72 return f, n
73 }
74
75
76 type debugFramePadding struct {
77 size int
78 to int
79 }
80
81 func parseDebugFramePadding(b []byte) (f debugFramePadding, n int) {
82 for n < len(b) && b[n] == frameTypePadding {
83 n++
84 }
85 f.size = n
86 return f, n
87 }
88
89 func (f debugFramePadding) String() string {
90 return fmt.Sprintf("PADDING*%v", f.size)
91 }
92
93 func (f debugFramePadding) write(w *packetWriter) bool {
94 if w.avail() == 0 {
95 return false
96 }
97 if f.to > 0 {
98 w.appendPaddingTo(f.to)
99 return true
100 }
101 for i := 0; i < f.size && w.avail() > 0; i++ {
102 w.b = append(w.b, frameTypePadding)
103 }
104 return true
105 }
106
107 func (f debugFramePadding) LogValue() slog.Value {
108 return slog.GroupValue(
109 slog.String("frame_type", "padding"),
110 slog.Int("length", f.size),
111 )
112 }
113
114
115 type debugFramePing struct{}
116
117 func parseDebugFramePing(b []byte) (f debugFramePing, n int) {
118 return f, 1
119 }
120
121 func (f debugFramePing) String() string {
122 return "PING"
123 }
124
125 func (f debugFramePing) write(w *packetWriter) bool {
126 return w.appendPingFrame()
127 }
128
129 func (f debugFramePing) LogValue() slog.Value {
130 return slog.GroupValue(
131 slog.String("frame_type", "ping"),
132 )
133 }
134
135
136 type debugFrameAck struct {
137 ackDelay unscaledAckDelay
138 ranges []i64range[packetNumber]
139 ecn ecnCounts
140 }
141
142 func parseDebugFrameAck(b []byte) (f debugFrameAck, n int) {
143 f.ranges = nil
144 _, f.ackDelay, f.ecn, n = consumeAckFrame(b, func(_ int, start, end packetNumber) {
145 f.ranges = append(f.ranges, i64range[packetNumber]{
146 start: start,
147 end: end,
148 })
149 })
150
151 for i := 0; i < len(f.ranges)/2; i++ {
152 j := len(f.ranges) - 1
153 f.ranges[i], f.ranges[j] = f.ranges[j], f.ranges[i]
154 }
155 return f, n
156 }
157
158 func (f debugFrameAck) String() string {
159 s := fmt.Sprintf("ACK Delay=%v", f.ackDelay)
160 for _, r := range f.ranges {
161 s += fmt.Sprintf(" [%v,%v)", r.start, r.end)
162 }
163
164 if (f.ecn != ecnCounts{}) {
165 s += fmt.Sprintf(" ECN=[%d,%d,%d]", f.ecn.t0, f.ecn.t1, f.ecn.ce)
166 }
167 return s
168 }
169
170 func (f debugFrameAck) write(w *packetWriter) bool {
171 return w.appendAckFrame(rangeset[packetNumber](f.ranges), f.ackDelay, f.ecn)
172 }
173
174 func (f debugFrameAck) LogValue() slog.Value {
175 return slog.StringValue("error: debugFrameAck should not appear as a slog Value")
176 }
177
178
179
180
181 type debugFrameScaledAck struct {
182 ackDelay time.Duration
183 ranges []i64range[packetNumber]
184 }
185
186 func (f debugFrameScaledAck) LogValue() slog.Value {
187 var ackDelay slog.Attr
188 if f.ackDelay >= 0 {
189 ackDelay = slog.Duration("ack_delay", f.ackDelay)
190 }
191 return slog.GroupValue(
192 slog.String("frame_type", "ack"),
193
194
195 slog.Any("acked_ranges", debugAckRanges(f.ranges)),
196 ackDelay,
197 )
198 }
199
200 type debugAckRanges []i64range[packetNumber]
201
202
203
204
205
206 func (r debugAckRanges) AppendJSON(b []byte) []byte {
207 b = append(b, '[')
208 for i, ar := range r {
209 start, end := ar.start, ar.end-1
210 if i != 0 {
211 b = append(b, ',')
212 }
213 b = append(b, '[')
214 b = strconv.AppendInt(b, int64(start), 10)
215 if start != end {
216 b = append(b, ',')
217 b = strconv.AppendInt(b, int64(end), 10)
218 }
219 b = append(b, ']')
220 }
221 b = append(b, ']')
222 return b
223 }
224
225 func (r debugAckRanges) String() string {
226 return string(r.AppendJSON(nil))
227 }
228
229
230 type debugFrameResetStream struct {
231 id streamID
232 code uint64
233 finalSize int64
234 }
235
236 func parseDebugFrameResetStream(b []byte) (f debugFrameResetStream, n int) {
237 f.id, f.code, f.finalSize, n = consumeResetStreamFrame(b)
238 return f, n
239 }
240
241 func (f debugFrameResetStream) String() string {
242 return fmt.Sprintf("RESET_STREAM ID=%v Code=%v FinalSize=%v", f.id, f.code, f.finalSize)
243 }
244
245 func (f debugFrameResetStream) write(w *packetWriter) bool {
246 return w.appendResetStreamFrame(f.id, f.code, f.finalSize)
247 }
248
249 func (f debugFrameResetStream) LogValue() slog.Value {
250 return slog.GroupValue(
251 slog.String("frame_type", "reset_stream"),
252 slog.Uint64("stream_id", uint64(f.id)),
253 slog.Uint64("final_size", uint64(f.finalSize)),
254 )
255 }
256
257
258 type debugFrameStopSending struct {
259 id streamID
260 code uint64
261 }
262
263 func parseDebugFrameStopSending(b []byte) (f debugFrameStopSending, n int) {
264 f.id, f.code, n = consumeStopSendingFrame(b)
265 return f, n
266 }
267
268 func (f debugFrameStopSending) String() string {
269 return fmt.Sprintf("STOP_SENDING ID=%v Code=%v", f.id, f.code)
270 }
271
272 func (f debugFrameStopSending) write(w *packetWriter) bool {
273 return w.appendStopSendingFrame(f.id, f.code)
274 }
275
276 func (f debugFrameStopSending) LogValue() slog.Value {
277 return slog.GroupValue(
278 slog.String("frame_type", "stop_sending"),
279 slog.Uint64("stream_id", uint64(f.id)),
280 slog.Uint64("error_code", uint64(f.code)),
281 )
282 }
283
284
285 type debugFrameCrypto struct {
286 off int64
287 data []byte
288 }
289
290 func parseDebugFrameCrypto(b []byte) (f debugFrameCrypto, n int) {
291 f.off, f.data, n = consumeCryptoFrame(b)
292 return f, n
293 }
294
295 func (f debugFrameCrypto) String() string {
296 return fmt.Sprintf("CRYPTO Offset=%v Length=%v", f.off, len(f.data))
297 }
298
299 func (f debugFrameCrypto) write(w *packetWriter) bool {
300 b, added := w.appendCryptoFrame(f.off, len(f.data))
301 copy(b, f.data)
302 return added
303 }
304
305 func (f debugFrameCrypto) LogValue() slog.Value {
306 return slog.GroupValue(
307 slog.String("frame_type", "crypto"),
308 slog.Int64("offset", f.off),
309 slog.Int("length", len(f.data)),
310 )
311 }
312
313
314 type debugFrameNewToken struct {
315 token []byte
316 }
317
318 func parseDebugFrameNewToken(b []byte) (f debugFrameNewToken, n int) {
319 f.token, n = consumeNewTokenFrame(b)
320 return f, n
321 }
322
323 func (f debugFrameNewToken) String() string {
324 return fmt.Sprintf("NEW_TOKEN Token=%x", f.token)
325 }
326
327 func (f debugFrameNewToken) write(w *packetWriter) bool {
328 return w.appendNewTokenFrame(f.token)
329 }
330
331 func (f debugFrameNewToken) LogValue() slog.Value {
332 return slog.GroupValue(
333 slog.String("frame_type", "new_token"),
334 slogHexstring("token", f.token),
335 )
336 }
337
338
339 type debugFrameStream struct {
340 id streamID
341 fin bool
342 off int64
343 data []byte
344 }
345
346 func parseDebugFrameStream(b []byte) (f debugFrameStream, n int) {
347 f.id, f.off, f.fin, f.data, n = consumeStreamFrame(b)
348 return f, n
349 }
350
351 func (f debugFrameStream) String() string {
352 fin := ""
353 if f.fin {
354 fin = " FIN"
355 }
356 return fmt.Sprintf("STREAM ID=%v%v Offset=%v Length=%v", f.id, fin, f.off, len(f.data))
357 }
358
359 func (f debugFrameStream) write(w *packetWriter) bool {
360 b, added := w.appendStreamFrame(f.id, f.off, len(f.data), f.fin)
361 copy(b, f.data)
362 return added
363 }
364
365 func (f debugFrameStream) LogValue() slog.Value {
366 var fin slog.Attr
367 if f.fin {
368 fin = slog.Bool("fin", true)
369 }
370 return slog.GroupValue(
371 slog.String("frame_type", "stream"),
372 slog.Uint64("stream_id", uint64(f.id)),
373 slog.Int64("offset", f.off),
374 slog.Int("length", len(f.data)),
375 fin,
376 )
377 }
378
379
380 type debugFrameMaxData struct {
381 max int64
382 }
383
384 func parseDebugFrameMaxData(b []byte) (f debugFrameMaxData, n int) {
385 f.max, n = consumeMaxDataFrame(b)
386 return f, n
387 }
388
389 func (f debugFrameMaxData) String() string {
390 return fmt.Sprintf("MAX_DATA Max=%v", f.max)
391 }
392
393 func (f debugFrameMaxData) write(w *packetWriter) bool {
394 return w.appendMaxDataFrame(f.max)
395 }
396
397 func (f debugFrameMaxData) LogValue() slog.Value {
398 return slog.GroupValue(
399 slog.String("frame_type", "max_data"),
400 slog.Int64("maximum", f.max),
401 )
402 }
403
404
405 type debugFrameMaxStreamData struct {
406 id streamID
407 max int64
408 }
409
410 func parseDebugFrameMaxStreamData(b []byte) (f debugFrameMaxStreamData, n int) {
411 f.id, f.max, n = consumeMaxStreamDataFrame(b)
412 return f, n
413 }
414
415 func (f debugFrameMaxStreamData) String() string {
416 return fmt.Sprintf("MAX_STREAM_DATA ID=%v Max=%v", f.id, f.max)
417 }
418
419 func (f debugFrameMaxStreamData) write(w *packetWriter) bool {
420 return w.appendMaxStreamDataFrame(f.id, f.max)
421 }
422
423 func (f debugFrameMaxStreamData) LogValue() slog.Value {
424 return slog.GroupValue(
425 slog.String("frame_type", "max_stream_data"),
426 slog.Uint64("stream_id", uint64(f.id)),
427 slog.Int64("maximum", f.max),
428 )
429 }
430
431
432 type debugFrameMaxStreams struct {
433 streamType streamType
434 max int64
435 }
436
437 func parseDebugFrameMaxStreams(b []byte) (f debugFrameMaxStreams, n int) {
438 f.streamType, f.max, n = consumeMaxStreamsFrame(b)
439 return f, n
440 }
441
442 func (f debugFrameMaxStreams) String() string {
443 return fmt.Sprintf("MAX_STREAMS Type=%v Max=%v", f.streamType, f.max)
444 }
445
446 func (f debugFrameMaxStreams) write(w *packetWriter) bool {
447 return w.appendMaxStreamsFrame(f.streamType, f.max)
448 }
449
450 func (f debugFrameMaxStreams) LogValue() slog.Value {
451 return slog.GroupValue(
452 slog.String("frame_type", "max_streams"),
453 slog.String("stream_type", f.streamType.qlogString()),
454 slog.Int64("maximum", f.max),
455 )
456 }
457
458
459 type debugFrameDataBlocked struct {
460 max int64
461 }
462
463 func parseDebugFrameDataBlocked(b []byte) (f debugFrameDataBlocked, n int) {
464 f.max, n = consumeDataBlockedFrame(b)
465 return f, n
466 }
467
468 func (f debugFrameDataBlocked) String() string {
469 return fmt.Sprintf("DATA_BLOCKED Max=%v", f.max)
470 }
471
472 func (f debugFrameDataBlocked) write(w *packetWriter) bool {
473 return w.appendDataBlockedFrame(f.max)
474 }
475
476 func (f debugFrameDataBlocked) LogValue() slog.Value {
477 return slog.GroupValue(
478 slog.String("frame_type", "data_blocked"),
479 slog.Int64("limit", f.max),
480 )
481 }
482
483
484 type debugFrameStreamDataBlocked struct {
485 id streamID
486 max int64
487 }
488
489 func parseDebugFrameStreamDataBlocked(b []byte) (f debugFrameStreamDataBlocked, n int) {
490 f.id, f.max, n = consumeStreamDataBlockedFrame(b)
491 return f, n
492 }
493
494 func (f debugFrameStreamDataBlocked) String() string {
495 return fmt.Sprintf("STREAM_DATA_BLOCKED ID=%v Max=%v", f.id, f.max)
496 }
497
498 func (f debugFrameStreamDataBlocked) write(w *packetWriter) bool {
499 return w.appendStreamDataBlockedFrame(f.id, f.max)
500 }
501
502 func (f debugFrameStreamDataBlocked) LogValue() slog.Value {
503 return slog.GroupValue(
504 slog.String("frame_type", "stream_data_blocked"),
505 slog.Uint64("stream_id", uint64(f.id)),
506 slog.Int64("limit", f.max),
507 )
508 }
509
510
511 type debugFrameStreamsBlocked struct {
512 streamType streamType
513 max int64
514 }
515
516 func parseDebugFrameStreamsBlocked(b []byte) (f debugFrameStreamsBlocked, n int) {
517 f.streamType, f.max, n = consumeStreamsBlockedFrame(b)
518 return f, n
519 }
520
521 func (f debugFrameStreamsBlocked) String() string {
522 return fmt.Sprintf("STREAMS_BLOCKED Type=%v Max=%v", f.streamType, f.max)
523 }
524
525 func (f debugFrameStreamsBlocked) write(w *packetWriter) bool {
526 return w.appendStreamsBlockedFrame(f.streamType, f.max)
527 }
528
529 func (f debugFrameStreamsBlocked) LogValue() slog.Value {
530 return slog.GroupValue(
531 slog.String("frame_type", "streams_blocked"),
532 slog.String("stream_type", f.streamType.qlogString()),
533 slog.Int64("limit", f.max),
534 )
535 }
536
537
538 type debugFrameNewConnectionID struct {
539 seq int64
540 retirePriorTo int64
541 connID []byte
542 token statelessResetToken
543 }
544
545 func parseDebugFrameNewConnectionID(b []byte) (f debugFrameNewConnectionID, n int) {
546 f.seq, f.retirePriorTo, f.connID, f.token, n = consumeNewConnectionIDFrame(b)
547 return f, n
548 }
549
550 func (f debugFrameNewConnectionID) String() string {
551 return fmt.Sprintf("NEW_CONNECTION_ID Seq=%v Retire=%v ID=%x Token=%x", f.seq, f.retirePriorTo, f.connID, f.token[:])
552 }
553
554 func (f debugFrameNewConnectionID) write(w *packetWriter) bool {
555 return w.appendNewConnectionIDFrame(f.seq, f.retirePriorTo, f.connID, f.token)
556 }
557
558 func (f debugFrameNewConnectionID) LogValue() slog.Value {
559 return slog.GroupValue(
560 slog.String("frame_type", "new_connection_id"),
561 slog.Int64("sequence_number", f.seq),
562 slog.Int64("retire_prior_to", f.retirePriorTo),
563 slogHexstring("connection_id", f.connID),
564 slogHexstring("stateless_reset_token", f.token[:]),
565 )
566 }
567
568
569 type debugFrameRetireConnectionID struct {
570 seq int64
571 }
572
573 func parseDebugFrameRetireConnectionID(b []byte) (f debugFrameRetireConnectionID, n int) {
574 f.seq, n = consumeRetireConnectionIDFrame(b)
575 return f, n
576 }
577
578 func (f debugFrameRetireConnectionID) String() string {
579 return fmt.Sprintf("RETIRE_CONNECTION_ID Seq=%v", f.seq)
580 }
581
582 func (f debugFrameRetireConnectionID) write(w *packetWriter) bool {
583 return w.appendRetireConnectionIDFrame(f.seq)
584 }
585
586 func (f debugFrameRetireConnectionID) LogValue() slog.Value {
587 return slog.GroupValue(
588 slog.String("frame_type", "retire_connection_id"),
589 slog.Int64("sequence_number", f.seq),
590 )
591 }
592
593
594 type debugFramePathChallenge struct {
595 data pathChallengeData
596 }
597
598 func parseDebugFramePathChallenge(b []byte) (f debugFramePathChallenge, n int) {
599 f.data, n = consumePathChallengeFrame(b)
600 return f, n
601 }
602
603 func (f debugFramePathChallenge) String() string {
604 return fmt.Sprintf("PATH_CHALLENGE Data=%x", f.data)
605 }
606
607 func (f debugFramePathChallenge) write(w *packetWriter) bool {
608 return w.appendPathChallengeFrame(f.data)
609 }
610
611 func (f debugFramePathChallenge) LogValue() slog.Value {
612 return slog.GroupValue(
613 slog.String("frame_type", "path_challenge"),
614 slog.String("data", fmt.Sprintf("%x", f.data)),
615 )
616 }
617
618
619 type debugFramePathResponse struct {
620 data pathChallengeData
621 }
622
623 func parseDebugFramePathResponse(b []byte) (f debugFramePathResponse, n int) {
624 f.data, n = consumePathResponseFrame(b)
625 return f, n
626 }
627
628 func (f debugFramePathResponse) String() string {
629 return fmt.Sprintf("PATH_RESPONSE Data=%x", f.data)
630 }
631
632 func (f debugFramePathResponse) write(w *packetWriter) bool {
633 return w.appendPathResponseFrame(f.data)
634 }
635
636 func (f debugFramePathResponse) LogValue() slog.Value {
637 return slog.GroupValue(
638 slog.String("frame_type", "path_response"),
639 slog.String("data", fmt.Sprintf("%x", f.data)),
640 )
641 }
642
643
644 type debugFrameConnectionCloseTransport struct {
645 code transportError
646 frameType uint64
647 reason string
648 }
649
650 func parseDebugFrameConnectionCloseTransport(b []byte) (f debugFrameConnectionCloseTransport, n int) {
651 f.code, f.frameType, f.reason, n = consumeConnectionCloseTransportFrame(b)
652 return f, n
653 }
654
655 func (f debugFrameConnectionCloseTransport) String() string {
656 s := fmt.Sprintf("CONNECTION_CLOSE Code=%v", f.code)
657 if f.frameType != 0 {
658 s += fmt.Sprintf(" FrameType=%v", f.frameType)
659 }
660 if f.reason != "" {
661 s += fmt.Sprintf(" Reason=%q", f.reason)
662 }
663 return s
664 }
665
666 func (f debugFrameConnectionCloseTransport) write(w *packetWriter) bool {
667 return w.appendConnectionCloseTransportFrame(f.code, f.frameType, f.reason)
668 }
669
670 func (f debugFrameConnectionCloseTransport) LogValue() slog.Value {
671 return slog.GroupValue(
672 slog.String("frame_type", "connection_close"),
673 slog.String("error_space", "transport"),
674 slog.Uint64("error_code_value", uint64(f.code)),
675 slog.String("reason", f.reason),
676 )
677 }
678
679
680 type debugFrameConnectionCloseApplication struct {
681 code uint64
682 reason string
683 }
684
685 func parseDebugFrameConnectionCloseApplication(b []byte) (f debugFrameConnectionCloseApplication, n int) {
686 f.code, f.reason, n = consumeConnectionCloseApplicationFrame(b)
687 return f, n
688 }
689
690 func (f debugFrameConnectionCloseApplication) String() string {
691 s := fmt.Sprintf("CONNECTION_CLOSE AppCode=%v", f.code)
692 if f.reason != "" {
693 s += fmt.Sprintf(" Reason=%q", f.reason)
694 }
695 return s
696 }
697
698 func (f debugFrameConnectionCloseApplication) write(w *packetWriter) bool {
699 return w.appendConnectionCloseApplicationFrame(f.code, f.reason)
700 }
701
702 func (f debugFrameConnectionCloseApplication) LogValue() slog.Value {
703 return slog.GroupValue(
704 slog.String("frame_type", "connection_close"),
705 slog.String("error_space", "application"),
706 slog.Uint64("error_code_value", uint64(f.code)),
707 slog.String("reason", f.reason),
708 )
709 }
710
711
712 type debugFrameHandshakeDone struct{}
713
714 func parseDebugFrameHandshakeDone(b []byte) (f debugFrameHandshakeDone, n int) {
715 return f, 1
716 }
717
718 func (f debugFrameHandshakeDone) String() string {
719 return "HANDSHAKE_DONE"
720 }
721
722 func (f debugFrameHandshakeDone) write(w *packetWriter) bool {
723 return w.appendHandshakeDoneFrame()
724 }
725
726 func (f debugFrameHandshakeDone) LogValue() slog.Value {
727 return slog.GroupValue(
728 slog.String("frame_type", "handshake_done"),
729 )
730 }
731
View as plain text