github.com/sagernet/quic-go@v0.43.1-beta.1/qlog/frame.go (about)

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