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