github.com/tumi8/quic-go@v0.37.4-tum/qlog/frame.go (about) 1 package qlog 2 3 import ( 4 "fmt" 5 6 "github.com/tumi8/quic-go/noninternal/wire" 7 "github.com/tumi8/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 }