github.com/apernet/quic-go@v0.43.1-0.20240515053213-5e9e635fd9f0/qlog/frame.go (about)

     1  package qlog
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/apernet/quic-go/internal/wire"
     7  	"github.com/apernet/quic-go/logging"
     8  
     9  	"github.com/francoispqt/gojay"
    10  )
    11  
    12  type frame struct {
    13  	Frame logging.Frame
    14  }
    15  
    16  var _ gojay.MarshalerJSONObject = frame{}
    17  
    18  var _ gojay.MarshalerJSONArray = frames{}
    19  
    20  func (f frame) MarshalJSONObject(enc *gojay.Encoder) {
    21  	switch frame := f.Frame.(type) {
    22  	case *logging.PingFrame:
    23  		marshalPingFrame(enc, frame)
    24  	case *logging.AckFrame:
    25  		marshalAckFrame(enc, frame)
    26  	case *logging.ResetStreamFrame:
    27  		marshalResetStreamFrame(enc, frame)
    28  	case *logging.StopSendingFrame:
    29  		marshalStopSendingFrame(enc, frame)
    30  	case *logging.CryptoFrame:
    31  		marshalCryptoFrame(enc, frame)
    32  	case *logging.NewTokenFrame:
    33  		marshalNewTokenFrame(enc, frame)
    34  	case *logging.StreamFrame:
    35  		marshalStreamFrame(enc, frame)
    36  	case *logging.MaxDataFrame:
    37  		marshalMaxDataFrame(enc, frame)
    38  	case *logging.MaxStreamDataFrame:
    39  		marshalMaxStreamDataFrame(enc, frame)
    40  	case *logging.MaxStreamsFrame:
    41  		marshalMaxStreamsFrame(enc, frame)
    42  	case *logging.DataBlockedFrame:
    43  		marshalDataBlockedFrame(enc, frame)
    44  	case *logging.StreamDataBlockedFrame:
    45  		marshalStreamDataBlockedFrame(enc, frame)
    46  	case *logging.StreamsBlockedFrame:
    47  		marshalStreamsBlockedFrame(enc, frame)
    48  	case *logging.NewConnectionIDFrame:
    49  		marshalNewConnectionIDFrame(enc, frame)
    50  	case *logging.RetireConnectionIDFrame:
    51  		marshalRetireConnectionIDFrame(enc, frame)
    52  	case *logging.PathChallengeFrame:
    53  		marshalPathChallengeFrame(enc, frame)
    54  	case *logging.PathResponseFrame:
    55  		marshalPathResponseFrame(enc, frame)
    56  	case *logging.ConnectionCloseFrame:
    57  		marshalConnectionCloseFrame(enc, frame)
    58  	case *logging.HandshakeDoneFrame:
    59  		marshalHandshakeDoneFrame(enc, frame)
    60  	case *logging.DatagramFrame:
    61  		marshalDatagramFrame(enc, frame)
    62  	default:
    63  		panic("unknown frame type")
    64  	}
    65  }
    66  
    67  func (f frame) IsNil() bool { return false }
    68  
    69  type frames []frame
    70  
    71  func (fs frames) IsNil() bool { return fs == nil }
    72  func (fs frames) MarshalJSONArray(enc *gojay.Encoder) {
    73  	for _, f := range fs {
    74  		enc.Object(f)
    75  	}
    76  }
    77  
    78  func marshalPingFrame(enc *gojay.Encoder, _ *wire.PingFrame) {
    79  	enc.StringKey("frame_type", "ping")
    80  }
    81  
    82  type ackRanges []wire.AckRange
    83  
    84  func (ars ackRanges) MarshalJSONArray(enc *gojay.Encoder) {
    85  	for _, r := range ars {
    86  		enc.Array(ackRange(r))
    87  	}
    88  }
    89  
    90  func (ars ackRanges) IsNil() bool { return false }
    91  
    92  type ackRange wire.AckRange
    93  
    94  func (ar ackRange) MarshalJSONArray(enc *gojay.Encoder) {
    95  	enc.AddInt64(int64(ar.Smallest))
    96  	if ar.Smallest != ar.Largest {
    97  		enc.AddInt64(int64(ar.Largest))
    98  	}
    99  }
   100  
   101  func (ar ackRange) IsNil() bool { return false }
   102  
   103  func marshalAckFrame(enc *gojay.Encoder, f *logging.AckFrame) {
   104  	enc.StringKey("frame_type", "ack")
   105  	enc.FloatKeyOmitEmpty("ack_delay", milliseconds(f.DelayTime))
   106  	enc.ArrayKey("acked_ranges", ackRanges(f.AckRanges))
   107  	if hasECN := f.ECT0 > 0 || f.ECT1 > 0 || f.ECNCE > 0; hasECN {
   108  		enc.Uint64Key("ect0", f.ECT0)
   109  		enc.Uint64Key("ect1", f.ECT1)
   110  		enc.Uint64Key("ce", f.ECNCE)
   111  	}
   112  }
   113  
   114  func marshalResetStreamFrame(enc *gojay.Encoder, f *logging.ResetStreamFrame) {
   115  	enc.StringKey("frame_type", "reset_stream")
   116  	enc.Int64Key("stream_id", int64(f.StreamID))
   117  	enc.Int64Key("error_code", int64(f.ErrorCode))
   118  	enc.Int64Key("final_size", int64(f.FinalSize))
   119  }
   120  
   121  func marshalStopSendingFrame(enc *gojay.Encoder, f *logging.StopSendingFrame) {
   122  	enc.StringKey("frame_type", "stop_sending")
   123  	enc.Int64Key("stream_id", int64(f.StreamID))
   124  	enc.Int64Key("error_code", int64(f.ErrorCode))
   125  }
   126  
   127  func marshalCryptoFrame(enc *gojay.Encoder, f *logging.CryptoFrame) {
   128  	enc.StringKey("frame_type", "crypto")
   129  	enc.Int64Key("offset", int64(f.Offset))
   130  	enc.Int64Key("length", int64(f.Length))
   131  }
   132  
   133  func marshalNewTokenFrame(enc *gojay.Encoder, f *logging.NewTokenFrame) {
   134  	enc.StringKey("frame_type", "new_token")
   135  	enc.ObjectKey("token", &token{Raw: f.Token})
   136  }
   137  
   138  func marshalStreamFrame(enc *gojay.Encoder, f *logging.StreamFrame) {
   139  	enc.StringKey("frame_type", "stream")
   140  	enc.Int64Key("stream_id", int64(f.StreamID))
   141  	enc.Int64Key("offset", int64(f.Offset))
   142  	enc.IntKey("length", int(f.Length))
   143  	enc.BoolKeyOmitEmpty("fin", f.Fin)
   144  }
   145  
   146  func marshalMaxDataFrame(enc *gojay.Encoder, f *logging.MaxDataFrame) {
   147  	enc.StringKey("frame_type", "max_data")
   148  	enc.Int64Key("maximum", int64(f.MaximumData))
   149  }
   150  
   151  func marshalMaxStreamDataFrame(enc *gojay.Encoder, f *logging.MaxStreamDataFrame) {
   152  	enc.StringKey("frame_type", "max_stream_data")
   153  	enc.Int64Key("stream_id", int64(f.StreamID))
   154  	enc.Int64Key("maximum", int64(f.MaximumStreamData))
   155  }
   156  
   157  func marshalMaxStreamsFrame(enc *gojay.Encoder, f *logging.MaxStreamsFrame) {
   158  	enc.StringKey("frame_type", "max_streams")
   159  	enc.StringKey("stream_type", streamType(f.Type).String())
   160  	enc.Int64Key("maximum", int64(f.MaxStreamNum))
   161  }
   162  
   163  func marshalDataBlockedFrame(enc *gojay.Encoder, f *logging.DataBlockedFrame) {
   164  	enc.StringKey("frame_type", "data_blocked")
   165  	enc.Int64Key("limit", int64(f.MaximumData))
   166  }
   167  
   168  func marshalStreamDataBlockedFrame(enc *gojay.Encoder, f *logging.StreamDataBlockedFrame) {
   169  	enc.StringKey("frame_type", "stream_data_blocked")
   170  	enc.Int64Key("stream_id", int64(f.StreamID))
   171  	enc.Int64Key("limit", int64(f.MaximumStreamData))
   172  }
   173  
   174  func marshalStreamsBlockedFrame(enc *gojay.Encoder, f *logging.StreamsBlockedFrame) {
   175  	enc.StringKey("frame_type", "streams_blocked")
   176  	enc.StringKey("stream_type", streamType(f.Type).String())
   177  	enc.Int64Key("limit", int64(f.StreamLimit))
   178  }
   179  
   180  func marshalNewConnectionIDFrame(enc *gojay.Encoder, f *logging.NewConnectionIDFrame) {
   181  	enc.StringKey("frame_type", "new_connection_id")
   182  	enc.Int64Key("sequence_number", int64(f.SequenceNumber))
   183  	enc.Int64Key("retire_prior_to", int64(f.RetirePriorTo))
   184  	enc.IntKey("length", f.ConnectionID.Len())
   185  	enc.StringKey("connection_id", f.ConnectionID.String())
   186  	enc.StringKey("stateless_reset_token", fmt.Sprintf("%x", f.StatelessResetToken))
   187  }
   188  
   189  func marshalRetireConnectionIDFrame(enc *gojay.Encoder, f *logging.RetireConnectionIDFrame) {
   190  	enc.StringKey("frame_type", "retire_connection_id")
   191  	enc.Int64Key("sequence_number", int64(f.SequenceNumber))
   192  }
   193  
   194  func marshalPathChallengeFrame(enc *gojay.Encoder, f *logging.PathChallengeFrame) {
   195  	enc.StringKey("frame_type", "path_challenge")
   196  	enc.StringKey("data", fmt.Sprintf("%x", f.Data[:]))
   197  }
   198  
   199  func marshalPathResponseFrame(enc *gojay.Encoder, f *logging.PathResponseFrame) {
   200  	enc.StringKey("frame_type", "path_response")
   201  	enc.StringKey("data", fmt.Sprintf("%x", f.Data[:]))
   202  }
   203  
   204  func marshalConnectionCloseFrame(enc *gojay.Encoder, f *logging.ConnectionCloseFrame) {
   205  	errorSpace := "transport"
   206  	if f.IsApplicationError {
   207  		errorSpace = "application"
   208  	}
   209  	enc.StringKey("frame_type", "connection_close")
   210  	enc.StringKey("error_space", errorSpace)
   211  	if errName := transportError(f.ErrorCode).String(); len(errName) > 0 {
   212  		enc.StringKey("error_code", errName)
   213  	} else {
   214  		enc.Uint64Key("error_code", f.ErrorCode)
   215  	}
   216  	enc.Uint64Key("raw_error_code", f.ErrorCode)
   217  	enc.StringKey("reason", f.ReasonPhrase)
   218  }
   219  
   220  func marshalHandshakeDoneFrame(enc *gojay.Encoder, _ *logging.HandshakeDoneFrame) {
   221  	enc.StringKey("frame_type", "handshake_done")
   222  }
   223  
   224  func marshalDatagramFrame(enc *gojay.Encoder, f *logging.DatagramFrame) {
   225  	enc.StringKey("frame_type", "datagram")
   226  	enc.Int64Key("length", int64(f.Length))
   227  }