...

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

Documentation: golang.org/x/net/internal/quic

     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  //go:build go1.21
     6  
     7  package quic
     8  
     9  import (
    10  	"fmt"
    11  	"log/slog"
    12  	"strconv"
    13  	"time"
    14  )
    15  
    16  // A debugFrame is a representation of the contents of a QUIC frame,
    17  // used for debug logs and testing but not the primary serving path.
    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  // debugFramePadding is a sequence of PADDING frames.
    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  // debugFramePing is a PING frame.
   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  // debugFrameAck is an ACK frame.
   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  	// Ranges are parsed high to low; reverse ranges slice to order them low to high.
   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  // debugFrameScaledAck is an ACK frame with scaled ACK Delay.
   171  //
   172  // This type is used in qlog events, which need access to the delay as a duration.
   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  		// Rather than trying to convert the ack ranges into the slog data model,
   186  		// pass a value that can JSON-encode itself.
   187  		slog.Any("acked_ranges", debugAckRanges(f.ranges)),
   188  		ackDelay,
   189  	)
   190  }
   191  
   192  type debugAckRanges []i64range[packetNumber]
   193  
   194  // AppendJSON appends a JSON encoding of the ack ranges to b, and returns it.
   195  // This is different than the standard json.Marshaler, but more efficient.
   196  // Since we only use this in cooperation with the qlog package,
   197  // encoding/json compatibility is irrelevant.
   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 // qlog ranges are closed-closed
   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  // debugFrameResetStream is a RESET_STREAM frame.
   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  // debugFrameStopSending is a STOP_SENDING frame.
   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  // debugFrameCrypto is a CRYPTO frame.
   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  // debugFrameNewToken is a NEW_TOKEN frame.
   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  // debugFrameStream is a STREAM frame.
   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  // debugFrameMaxData is a MAX_DATA frame.
   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  // debugFrameMaxStreamData is a MAX_STREAM_DATA frame.
   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  // debugFrameMaxStreams is a MAX_STREAMS frame.
   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  // debugFrameDataBlocked is a DATA_BLOCKED frame.
   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  // debugFrameStreamDataBlocked is a STREAM_DATA_BLOCKED frame.
   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  // debugFrameStreamsBlocked is a STREAMS_BLOCKED frame.
   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  // debugFrameNewConnectionID is a NEW_CONNECTION_ID frame.
   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  // debugFrameRetireConnectionID is a NEW_CONNECTION_ID frame.
   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  // debugFramePathChallenge is a PATH_CHALLENGE frame.
   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  // debugFramePathResponse is a PATH_RESPONSE frame.
   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  // debugFrameConnectionCloseTransport is a CONNECTION_CLOSE frame carrying a transport error.
   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  // debugFrameConnectionCloseApplication is a CONNECTION_CLOSE frame carrying an application error.
   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  // debugFrameHandshakeDone is a HANDSHAKE_DONE frame.
   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