228 lines
7.1 KiB
Go
228 lines
7.1 KiB
Go
package qlog
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/lucas-clemente/quic-go/internal/wire"
|
|
"github.com/lucas-clemente/quic-go/logging"
|
|
|
|
"github.com/francoispqt/gojay"
|
|
)
|
|
|
|
type frame struct {
|
|
Frame logging.Frame
|
|
}
|
|
|
|
var _ gojay.MarshalerJSONObject = frame{}
|
|
|
|
var _ gojay.MarshalerJSONArray = frames{}
|
|
|
|
func (f frame) MarshalJSONObject(enc *gojay.Encoder) {
|
|
switch frame := f.Frame.(type) {
|
|
case *logging.PingFrame:
|
|
marshalPingFrame(enc, frame)
|
|
case *logging.AckFrame:
|
|
marshalAckFrame(enc, frame)
|
|
case *logging.ResetStreamFrame:
|
|
marshalResetStreamFrame(enc, frame)
|
|
case *logging.StopSendingFrame:
|
|
marshalStopSendingFrame(enc, frame)
|
|
case *logging.CryptoFrame:
|
|
marshalCryptoFrame(enc, frame)
|
|
case *logging.NewTokenFrame:
|
|
marshalNewTokenFrame(enc, frame)
|
|
case *logging.StreamFrame:
|
|
marshalStreamFrame(enc, frame)
|
|
case *logging.MaxDataFrame:
|
|
marshalMaxDataFrame(enc, frame)
|
|
case *logging.MaxStreamDataFrame:
|
|
marshalMaxStreamDataFrame(enc, frame)
|
|
case *logging.MaxStreamsFrame:
|
|
marshalMaxStreamsFrame(enc, frame)
|
|
case *logging.DataBlockedFrame:
|
|
marshalDataBlockedFrame(enc, frame)
|
|
case *logging.StreamDataBlockedFrame:
|
|
marshalStreamDataBlockedFrame(enc, frame)
|
|
case *logging.StreamsBlockedFrame:
|
|
marshalStreamsBlockedFrame(enc, frame)
|
|
case *logging.NewConnectionIDFrame:
|
|
marshalNewConnectionIDFrame(enc, frame)
|
|
case *logging.RetireConnectionIDFrame:
|
|
marshalRetireConnectionIDFrame(enc, frame)
|
|
case *logging.PathChallengeFrame:
|
|
marshalPathChallengeFrame(enc, frame)
|
|
case *logging.PathResponseFrame:
|
|
marshalPathResponseFrame(enc, frame)
|
|
case *logging.ConnectionCloseFrame:
|
|
marshalConnectionCloseFrame(enc, frame)
|
|
case *logging.HandshakeDoneFrame:
|
|
marshalHandshakeDoneFrame(enc, frame)
|
|
case *logging.DatagramFrame:
|
|
marshalDatagramFrame(enc, frame)
|
|
default:
|
|
panic("unknown frame type")
|
|
}
|
|
}
|
|
|
|
func (f frame) IsNil() bool { return false }
|
|
|
|
type frames []frame
|
|
|
|
func (fs frames) IsNil() bool { return fs == nil }
|
|
func (fs frames) MarshalJSONArray(enc *gojay.Encoder) {
|
|
for _, f := range fs {
|
|
enc.Object(f)
|
|
}
|
|
}
|
|
|
|
func marshalPingFrame(enc *gojay.Encoder, _ *wire.PingFrame) {
|
|
enc.StringKey("frame_type", "ping")
|
|
}
|
|
|
|
type ackRanges []wire.AckRange
|
|
|
|
func (ars ackRanges) MarshalJSONArray(enc *gojay.Encoder) {
|
|
for _, r := range ars {
|
|
enc.Array(ackRange(r))
|
|
}
|
|
}
|
|
|
|
func (ars ackRanges) IsNil() bool { return false }
|
|
|
|
type ackRange wire.AckRange
|
|
|
|
func (ar ackRange) MarshalJSONArray(enc *gojay.Encoder) {
|
|
enc.AddInt64(int64(ar.Smallest))
|
|
if ar.Smallest != ar.Largest {
|
|
enc.AddInt64(int64(ar.Largest))
|
|
}
|
|
}
|
|
|
|
func (ar ackRange) IsNil() bool { return false }
|
|
|
|
func marshalAckFrame(enc *gojay.Encoder, f *logging.AckFrame) {
|
|
enc.StringKey("frame_type", "ack")
|
|
enc.FloatKeyOmitEmpty("ack_delay", milliseconds(f.DelayTime))
|
|
enc.ArrayKey("acked_ranges", ackRanges(f.AckRanges))
|
|
if hasECN := f.ECT0 > 0 || f.ECT1 > 0 || f.ECNCE > 0; hasECN {
|
|
enc.Uint64Key("ect0", f.ECT0)
|
|
enc.Uint64Key("ect1", f.ECT1)
|
|
enc.Uint64Key("ce", f.ECNCE)
|
|
}
|
|
}
|
|
|
|
func marshalResetStreamFrame(enc *gojay.Encoder, f *logging.ResetStreamFrame) {
|
|
enc.StringKey("frame_type", "reset_stream")
|
|
enc.Int64Key("stream_id", int64(f.StreamID))
|
|
enc.Int64Key("error_code", int64(f.ErrorCode))
|
|
enc.Int64Key("final_size", int64(f.FinalSize))
|
|
}
|
|
|
|
func marshalStopSendingFrame(enc *gojay.Encoder, f *logging.StopSendingFrame) {
|
|
enc.StringKey("frame_type", "stop_sending")
|
|
enc.Int64Key("stream_id", int64(f.StreamID))
|
|
enc.Int64Key("error_code", int64(f.ErrorCode))
|
|
}
|
|
|
|
func marshalCryptoFrame(enc *gojay.Encoder, f *logging.CryptoFrame) {
|
|
enc.StringKey("frame_type", "crypto")
|
|
enc.Int64Key("offset", int64(f.Offset))
|
|
enc.Int64Key("length", int64(f.Length))
|
|
}
|
|
|
|
func marshalNewTokenFrame(enc *gojay.Encoder, f *logging.NewTokenFrame) {
|
|
enc.StringKey("frame_type", "new_token")
|
|
enc.ObjectKey("token", &token{Raw: f.Token})
|
|
}
|
|
|
|
func marshalStreamFrame(enc *gojay.Encoder, f *logging.StreamFrame) {
|
|
enc.StringKey("frame_type", "stream")
|
|
enc.Int64Key("stream_id", int64(f.StreamID))
|
|
enc.Int64Key("offset", int64(f.Offset))
|
|
enc.IntKey("length", int(f.Length))
|
|
enc.BoolKeyOmitEmpty("fin", f.Fin)
|
|
}
|
|
|
|
func marshalMaxDataFrame(enc *gojay.Encoder, f *logging.MaxDataFrame) {
|
|
enc.StringKey("frame_type", "max_data")
|
|
enc.Int64Key("maximum", int64(f.MaximumData))
|
|
}
|
|
|
|
func marshalMaxStreamDataFrame(enc *gojay.Encoder, f *logging.MaxStreamDataFrame) {
|
|
enc.StringKey("frame_type", "max_stream_data")
|
|
enc.Int64Key("stream_id", int64(f.StreamID))
|
|
enc.Int64Key("maximum", int64(f.MaximumStreamData))
|
|
}
|
|
|
|
func marshalMaxStreamsFrame(enc *gojay.Encoder, f *logging.MaxStreamsFrame) {
|
|
enc.StringKey("frame_type", "max_streams")
|
|
enc.StringKey("stream_type", streamType(f.Type).String())
|
|
enc.Int64Key("maximum", int64(f.MaxStreamNum))
|
|
}
|
|
|
|
func marshalDataBlockedFrame(enc *gojay.Encoder, f *logging.DataBlockedFrame) {
|
|
enc.StringKey("frame_type", "data_blocked")
|
|
enc.Int64Key("limit", int64(f.MaximumData))
|
|
}
|
|
|
|
func marshalStreamDataBlockedFrame(enc *gojay.Encoder, f *logging.StreamDataBlockedFrame) {
|
|
enc.StringKey("frame_type", "stream_data_blocked")
|
|
enc.Int64Key("stream_id", int64(f.StreamID))
|
|
enc.Int64Key("limit", int64(f.MaximumStreamData))
|
|
}
|
|
|
|
func marshalStreamsBlockedFrame(enc *gojay.Encoder, f *logging.StreamsBlockedFrame) {
|
|
enc.StringKey("frame_type", "streams_blocked")
|
|
enc.StringKey("stream_type", streamType(f.Type).String())
|
|
enc.Int64Key("limit", int64(f.StreamLimit))
|
|
}
|
|
|
|
func marshalNewConnectionIDFrame(enc *gojay.Encoder, f *logging.NewConnectionIDFrame) {
|
|
enc.StringKey("frame_type", "new_connection_id")
|
|
enc.Int64Key("sequence_number", int64(f.SequenceNumber))
|
|
enc.Int64Key("retire_prior_to", int64(f.RetirePriorTo))
|
|
enc.IntKey("length", f.ConnectionID.Len())
|
|
enc.StringKey("connection_id", connectionID(f.ConnectionID).String())
|
|
enc.StringKey("stateless_reset_token", fmt.Sprintf("%x", f.StatelessResetToken))
|
|
}
|
|
|
|
func marshalRetireConnectionIDFrame(enc *gojay.Encoder, f *logging.RetireConnectionIDFrame) {
|
|
enc.StringKey("frame_type", "retire_connection_id")
|
|
enc.Int64Key("sequence_number", int64(f.SequenceNumber))
|
|
}
|
|
|
|
func marshalPathChallengeFrame(enc *gojay.Encoder, f *logging.PathChallengeFrame) {
|
|
enc.StringKey("frame_type", "path_challenge")
|
|
enc.StringKey("data", fmt.Sprintf("%x", f.Data[:]))
|
|
}
|
|
|
|
func marshalPathResponseFrame(enc *gojay.Encoder, f *logging.PathResponseFrame) {
|
|
enc.StringKey("frame_type", "path_response")
|
|
enc.StringKey("data", fmt.Sprintf("%x", f.Data[:]))
|
|
}
|
|
|
|
func marshalConnectionCloseFrame(enc *gojay.Encoder, f *logging.ConnectionCloseFrame) {
|
|
errorSpace := "transport"
|
|
if f.IsApplicationError {
|
|
errorSpace = "application"
|
|
}
|
|
enc.StringKey("frame_type", "connection_close")
|
|
enc.StringKey("error_space", errorSpace)
|
|
if errName := transportError(f.ErrorCode).String(); len(errName) > 0 {
|
|
enc.StringKey("error_code", errName)
|
|
} else {
|
|
enc.Uint64Key("error_code", f.ErrorCode)
|
|
}
|
|
enc.Uint64Key("raw_error_code", f.ErrorCode)
|
|
enc.StringKey("reason", f.ReasonPhrase)
|
|
}
|
|
|
|
func marshalHandshakeDoneFrame(enc *gojay.Encoder, _ *logging.HandshakeDoneFrame) {
|
|
enc.StringKey("frame_type", "handshake_done")
|
|
}
|
|
|
|
func marshalDatagramFrame(enc *gojay.Encoder, f *logging.DatagramFrame) {
|
|
enc.StringKey("frame_type", "datagram")
|
|
enc.Int64Key("length", int64(f.Length))
|
|
}
|