Source file src/vendor/golang.org/x/net/quic/frame_debug.go

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package quic
     6  
     7  import (
     8  	"fmt"
     9  	"log/slog"
    10  	"strconv"
    11  	"time"
    12  )
    13  
    14  // A debugFrame is a representation of the contents of a QUIC frame,
    15  // used for debug logs and testing but not the primary serving path.
    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  // debugFramePadding is a sequence of PADDING frames.
    76  type debugFramePadding struct {
    77  	size int
    78  	to   int // alternate for writing packets: pad to
    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  // debugFramePing is a PING frame.
   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  // debugFrameAck is an ACK frame.
   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  	// Ranges are parsed high to low; reverse ranges slice to order them low to high.
   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  // debugFrameScaledAck is an ACK frame with scaled ACK Delay.
   179  //
   180  // This type is used in qlog events, which need access to the delay as a duration.
   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  		// Rather than trying to convert the ack ranges into the slog data model,
   194  		// pass a value that can JSON-encode itself.
   195  		slog.Any("acked_ranges", debugAckRanges(f.ranges)),
   196  		ackDelay,
   197  	)
   198  }
   199  
   200  type debugAckRanges []i64range[packetNumber]
   201  
   202  // AppendJSON appends a JSON encoding of the ack ranges to b, and returns it.
   203  // This is different than the standard json.Marshaler, but more efficient.
   204  // Since we only use this in cooperation with the qlog package,
   205  // encoding/json compatibility is irrelevant.
   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 // qlog ranges are closed-closed
   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  // debugFrameResetStream is a RESET_STREAM frame.
   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  // debugFrameStopSending is a STOP_SENDING frame.
   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  // debugFrameCrypto is a CRYPTO frame.
   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  // debugFrameNewToken is a NEW_TOKEN frame.
   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  // debugFrameStream is a STREAM frame.
   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  // debugFrameMaxData is a MAX_DATA frame.
   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  // debugFrameMaxStreamData is a MAX_STREAM_DATA frame.
   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  // debugFrameMaxStreams is a MAX_STREAMS frame.
   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  // debugFrameDataBlocked is a DATA_BLOCKED frame.
   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  // debugFrameStreamDataBlocked is a STREAM_DATA_BLOCKED frame.
   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  // debugFrameStreamsBlocked is a STREAMS_BLOCKED frame.
   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  // debugFrameNewConnectionID is a NEW_CONNECTION_ID frame.
   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  // debugFrameRetireConnectionID is a NEW_CONNECTION_ID frame.
   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  // debugFramePathChallenge is a PATH_CHALLENGE frame.
   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  // debugFramePathResponse is a PATH_RESPONSE frame.
   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  // debugFrameConnectionCloseTransport is a CONNECTION_CLOSE frame carrying a transport error.
   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  // debugFrameConnectionCloseApplication is a CONNECTION_CLOSE frame carrying an application error.
   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  // debugFrameHandshakeDone is a HANDSHAKE_DONE frame.
   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