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