Files
quic-go/qlog/event.go
2025-11-14 04:04:40 +03:00

808 lines
24 KiB
Go

package qlog
import (
"fmt"
"net/netip"
"time"
"git.geeks-team.ru/gr1ffon/quic-go/internal/protocol"
"git.geeks-team.ru/gr1ffon/quic-go/internal/qerr"
"git.geeks-team.ru/gr1ffon/quic-go/qlogwriter/jsontext"
)
func milliseconds(dur time.Duration) float64 { return float64(dur.Nanoseconds()) / 1e6 }
type encoderHelper struct {
enc *jsontext.Encoder
err error
}
func (h *encoderHelper) WriteToken(t jsontext.Token) {
if h.err != nil {
return
}
h.err = h.enc.WriteToken(t)
}
type versions []Version
func (v versions) encode(enc *jsontext.Encoder) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginArray)
for _, e := range v {
h.WriteToken(jsontext.String(fmt.Sprintf("%x", uint32(e))))
}
h.WriteToken(jsontext.EndArray)
return h.err
}
type RawInfo struct {
Length int // full packet length, including header and AEAD authentication tag
PayloadLength int // length of the packet payload, excluding AEAD tag
}
func (i RawInfo) encode(enc *jsontext.Encoder) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("length"))
h.WriteToken(jsontext.Uint(uint64(i.Length)))
if i.PayloadLength != 0 {
h.WriteToken(jsontext.String("payload_length"))
h.WriteToken(jsontext.Uint(uint64(i.PayloadLength)))
}
h.WriteToken(jsontext.EndObject)
return h.err
}
type PathEndpointInfo struct {
IPv4 netip.AddrPort
IPv6 netip.AddrPort
}
func (p PathEndpointInfo) encode(enc *jsontext.Encoder) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
if p.IPv4.IsValid() {
h.WriteToken(jsontext.String("ip_v4"))
h.WriteToken(jsontext.String(p.IPv4.Addr().String()))
h.WriteToken(jsontext.String("port_v4"))
h.WriteToken(jsontext.Int(int64(p.IPv4.Port())))
}
if p.IPv6.IsValid() {
h.WriteToken(jsontext.String("ip_v6"))
h.WriteToken(jsontext.String(p.IPv6.Addr().String()))
h.WriteToken(jsontext.String("port_v6"))
h.WriteToken(jsontext.Int(int64(p.IPv6.Port())))
}
h.WriteToken(jsontext.EndObject)
return h.err
}
type StartedConnection struct {
Local PathEndpointInfo
Remote PathEndpointInfo
}
func (e StartedConnection) Name() string { return "transport:connection_started" }
func (e StartedConnection) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("local"))
if err := e.Local.encode(enc); err != nil {
return err
}
h.WriteToken(jsontext.String("remote"))
if err := e.Remote.encode(enc); err != nil {
return err
}
h.WriteToken(jsontext.EndObject)
return h.err
}
type VersionInformation struct {
ClientVersions, ServerVersions []Version
ChosenVersion Version
}
func (e VersionInformation) Name() string { return "transport:version_information" }
func (e VersionInformation) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
if len(e.ClientVersions) > 0 {
h.WriteToken(jsontext.String("client_versions"))
if err := versions(e.ClientVersions).encode(enc); err != nil {
return err
}
}
if len(e.ServerVersions) > 0 {
h.WriteToken(jsontext.String("server_versions"))
if err := versions(e.ServerVersions).encode(enc); err != nil {
return err
}
}
h.WriteToken(jsontext.String("chosen_version"))
h.WriteToken(jsontext.String(fmt.Sprintf("%x", uint32(e.ChosenVersion))))
h.WriteToken(jsontext.EndObject)
return h.err
}
type ConnectionClosed struct {
Initiator Initiator
ConnectionError *TransportErrorCode
ApplicationError *ApplicationErrorCode
Reason string
Trigger ConnectionCloseTrigger
}
func (e ConnectionClosed) Name() string { return "transport:connection_closed" }
func (e ConnectionClosed) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("initiator"))
h.WriteToken(jsontext.String(string(e.Initiator)))
if e.ConnectionError != nil {
h.WriteToken(jsontext.String("connection_error"))
if e.ConnectionError.IsCryptoError() {
h.WriteToken(jsontext.String(fmt.Sprintf("crypto_error_%#x", uint16(*e.ConnectionError))))
} else {
switch *e.ConnectionError {
case qerr.NoError:
h.WriteToken(jsontext.String("no_error"))
case qerr.InternalError:
h.WriteToken(jsontext.String("internal_error"))
case qerr.ConnectionRefused:
h.WriteToken(jsontext.String("connection_refused"))
case qerr.FlowControlError:
h.WriteToken(jsontext.String("flow_control_error"))
case qerr.StreamLimitError:
h.WriteToken(jsontext.String("stream_limit_error"))
case qerr.StreamStateError:
h.WriteToken(jsontext.String("stream_state_error"))
case qerr.FinalSizeError:
h.WriteToken(jsontext.String("final_size_error"))
case qerr.FrameEncodingError:
h.WriteToken(jsontext.String("frame_encoding_error"))
case qerr.TransportParameterError:
h.WriteToken(jsontext.String("transport_parameter_error"))
case qerr.ConnectionIDLimitError:
h.WriteToken(jsontext.String("connection_id_limit_error"))
case qerr.ProtocolViolation:
h.WriteToken(jsontext.String("protocol_violation"))
case qerr.InvalidToken:
h.WriteToken(jsontext.String("invalid_token"))
case qerr.ApplicationErrorErrorCode:
h.WriteToken(jsontext.String("application_error"))
case qerr.CryptoBufferExceeded:
h.WriteToken(jsontext.String("crypto_buffer_exceeded"))
case qerr.KeyUpdateError:
h.WriteToken(jsontext.String("key_update_error"))
case qerr.AEADLimitReached:
h.WriteToken(jsontext.String("aead_limit_reached"))
case qerr.NoViablePathError:
h.WriteToken(jsontext.String("no_viable_path"))
default:
h.WriteToken(jsontext.String("unknown"))
h.WriteToken(jsontext.String("error_code"))
h.WriteToken(jsontext.Uint(uint64(*e.ConnectionError)))
}
}
}
if e.ApplicationError != nil {
h.WriteToken(jsontext.String("application_error"))
h.WriteToken(jsontext.String("unknown"))
h.WriteToken(jsontext.String("error_code"))
h.WriteToken(jsontext.Uint(uint64(*e.ApplicationError)))
}
if e.ConnectionError != nil || e.ApplicationError != nil {
h.WriteToken(jsontext.String("reason"))
h.WriteToken(jsontext.String(e.Reason))
}
if e.Trigger != "" {
h.WriteToken(jsontext.String("trigger"))
h.WriteToken(jsontext.String(string(e.Trigger)))
}
h.WriteToken(jsontext.EndObject)
return h.err
}
type PacketSent struct {
Header PacketHeader
Raw RawInfo
Frames []Frame
ECN ECN
IsCoalesced bool
Trigger string
SupportedVersions []Version
}
func (e PacketSent) Name() string { return "transport:packet_sent" }
func (e PacketSent) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("header"))
if err := e.Header.encode(enc); err != nil {
return err
}
h.WriteToken(jsontext.String("raw"))
if err := e.Raw.encode(enc); err != nil {
return err
}
if len(e.Frames) > 0 {
h.WriteToken(jsontext.String("frames"))
if err := frames(e.Frames).encode(enc); err != nil {
return err
}
}
if e.IsCoalesced {
h.WriteToken(jsontext.String("is_coalesced"))
h.WriteToken(jsontext.True)
}
if e.ECN != ECNUnsupported {
h.WriteToken(jsontext.String("ecn"))
h.WriteToken(jsontext.String(string(e.ECN)))
}
if e.Trigger != "" {
h.WriteToken(jsontext.String("trigger"))
h.WriteToken(jsontext.String(e.Trigger))
}
h.WriteToken(jsontext.EndObject)
return h.err
}
type PacketReceived struct {
Header PacketHeader
Raw RawInfo
Frames []Frame
ECN ECN
IsCoalesced bool
Trigger string
}
func (e PacketReceived) Name() string { return "transport:packet_received" }
func (e PacketReceived) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("header"))
if err := e.Header.encode(enc); err != nil {
return err
}
h.WriteToken(jsontext.String("raw"))
if err := e.Raw.encode(enc); err != nil {
return err
}
if len(e.Frames) > 0 {
h.WriteToken(jsontext.String("frames"))
if err := frames(e.Frames).encode(enc); err != nil {
return err
}
}
if e.IsCoalesced {
h.WriteToken(jsontext.String("is_coalesced"))
h.WriteToken(jsontext.True)
}
if e.ECN != ECNUnsupported {
h.WriteToken(jsontext.String("ecn"))
h.WriteToken(jsontext.String(string(e.ECN)))
}
if e.Trigger != "" {
h.WriteToken(jsontext.String("trigger"))
h.WriteToken(jsontext.String(e.Trigger))
}
h.WriteToken(jsontext.EndObject)
return h.err
}
type VersionNegotiationReceived struct {
Header PacketHeaderVersionNegotiation
SupportedVersions []Version
}
func (e VersionNegotiationReceived) Name() string { return "transport:packet_received" }
func (e VersionNegotiationReceived) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("header"))
if err := e.Header.encode(enc); err != nil {
return err
}
h.WriteToken(jsontext.String("supported_versions"))
if err := versions(e.SupportedVersions).encode(enc); err != nil {
return err
}
h.WriteToken(jsontext.EndObject)
return h.err
}
type VersionNegotiationSent struct {
Header PacketHeaderVersionNegotiation
SupportedVersions []Version
}
func (e VersionNegotiationSent) Name() string { return "transport:packet_sent" }
func (e VersionNegotiationSent) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("header"))
if err := e.Header.encode(enc); err != nil {
return err
}
h.WriteToken(jsontext.String("supported_versions"))
if err := versions(e.SupportedVersions).encode(enc); err != nil {
return err
}
h.WriteToken(jsontext.EndObject)
return h.err
}
type PacketBuffered struct {
Header PacketHeader
Raw RawInfo
}
func (e PacketBuffered) Name() string { return "transport:packet_buffered" }
func (e PacketBuffered) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("header"))
if err := e.Header.encode(enc); err != nil {
return err
}
h.WriteToken(jsontext.String("raw"))
if err := e.Raw.encode(enc); err != nil {
return err
}
h.WriteToken(jsontext.String("trigger"))
h.WriteToken(jsontext.String("keys_unavailable"))
h.WriteToken(jsontext.EndObject)
return h.err
}
// PacketDropped is the transport:packet_dropped event.
type PacketDropped struct {
Header PacketHeader
Raw RawInfo
Trigger PacketDropReason
}
func (e PacketDropped) Name() string { return "transport:packet_dropped" }
func (e PacketDropped) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("header"))
if err := e.Header.encode(enc); err != nil {
return err
}
h.WriteToken(jsontext.String("raw"))
if err := e.Raw.encode(enc); err != nil {
return err
}
h.WriteToken(jsontext.String("trigger"))
h.WriteToken(jsontext.String(string(e.Trigger)))
h.WriteToken(jsontext.EndObject)
return h.err
}
type MTUUpdated struct {
Value int
Done bool
}
func (e MTUUpdated) Name() string { return "recovery:mtu_updated" }
func (e MTUUpdated) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("mtu"))
h.WriteToken(jsontext.Uint(uint64(e.Value)))
h.WriteToken(jsontext.String("done"))
h.WriteToken(jsontext.Bool(e.Done))
h.WriteToken(jsontext.EndObject)
return h.err
}
// MetricsUpdated logs RTT and congestion metrics as defined in the
// recovery:metrics_updated event.
// The PTO count is logged via PTOCountUpdated.
type MetricsUpdated struct {
MinRTT time.Duration
SmoothedRTT time.Duration
LatestRTT time.Duration
RTTVariance time.Duration
CongestionWindow int
BytesInFlight int
PacketsInFlight int
}
func (e MetricsUpdated) Name() string { return "recovery:metrics_updated" }
func (e MetricsUpdated) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
if e.MinRTT != 0 {
h.WriteToken(jsontext.String("min_rtt"))
h.WriteToken(jsontext.Float(milliseconds(e.MinRTT)))
}
if e.SmoothedRTT != 0 {
h.WriteToken(jsontext.String("smoothed_rtt"))
h.WriteToken(jsontext.Float(milliseconds(e.SmoothedRTT)))
}
if e.LatestRTT != 0 {
h.WriteToken(jsontext.String("latest_rtt"))
h.WriteToken(jsontext.Float(milliseconds(e.LatestRTT)))
}
if e.RTTVariance != 0 {
h.WriteToken(jsontext.String("rtt_variance"))
h.WriteToken(jsontext.Float(milliseconds(e.RTTVariance)))
}
if e.CongestionWindow != 0 {
h.WriteToken(jsontext.String("congestion_window"))
h.WriteToken(jsontext.Uint(uint64(e.CongestionWindow)))
}
if e.BytesInFlight != 0 {
h.WriteToken(jsontext.String("bytes_in_flight"))
h.WriteToken(jsontext.Uint(uint64(e.BytesInFlight)))
}
if e.PacketsInFlight != 0 {
h.WriteToken(jsontext.String("packets_in_flight"))
h.WriteToken(jsontext.Uint(uint64(e.PacketsInFlight)))
}
h.WriteToken(jsontext.EndObject)
return h.err
}
// PTOCountUpdated logs the pto_count value of the
// recovery:metrics_updated event.
type PTOCountUpdated struct {
PTOCount uint32
}
func (e PTOCountUpdated) Name() string { return "recovery:metrics_updated" }
func (e PTOCountUpdated) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("pto_count"))
h.WriteToken(jsontext.Uint(uint64(e.PTOCount)))
h.WriteToken(jsontext.EndObject)
return h.err
}
type PacketLost struct {
Header PacketHeader
Trigger PacketLossReason
}
func (e PacketLost) Name() string { return "recovery:packet_lost" }
func (e PacketLost) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("header"))
if err := e.Header.encode(enc); err != nil {
return err
}
h.WriteToken(jsontext.String("trigger"))
h.WriteToken(jsontext.String(string(e.Trigger)))
h.WriteToken(jsontext.EndObject)
return h.err
}
type SpuriousLoss struct {
EncryptionLevel protocol.EncryptionLevel
PacketNumber protocol.PacketNumber
PacketReordering uint64
TimeReordering time.Duration
}
func (e SpuriousLoss) Name() string { return "recovery:spurious_loss" }
func (e SpuriousLoss) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("packet_number_space"))
h.WriteToken(jsontext.String(encLevelToPacketNumberSpace(e.EncryptionLevel)))
h.WriteToken(jsontext.String("packet_number"))
h.WriteToken(jsontext.Uint(uint64(e.PacketNumber)))
h.WriteToken(jsontext.String("reordering_packets"))
h.WriteToken(jsontext.Uint(e.PacketReordering))
h.WriteToken(jsontext.String("reordering_time"))
h.WriteToken(jsontext.Float(milliseconds(e.TimeReordering)))
h.WriteToken(jsontext.EndObject)
return h.err
}
type KeyUpdated struct {
Trigger KeyUpdateTrigger
KeyType KeyType
KeyPhase KeyPhase // only set for 1-RTT keys
// we don't log the keys here, so we don't need `old` and `new`.
}
func (e KeyUpdated) Name() string { return "security:key_updated" }
func (e KeyUpdated) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("trigger"))
h.WriteToken(jsontext.String(string(e.Trigger)))
h.WriteToken(jsontext.String("key_type"))
h.WriteToken(jsontext.String(string(e.KeyType)))
if e.KeyType == KeyTypeClient1RTT || e.KeyType == KeyTypeServer1RTT {
h.WriteToken(jsontext.String("key_phase"))
h.WriteToken(jsontext.Uint(uint64(e.KeyPhase)))
}
h.WriteToken(jsontext.EndObject)
return h.err
}
type KeyDiscarded struct {
KeyType KeyType
KeyPhase KeyPhase // only set for 1-RTT keys
}
func (e KeyDiscarded) Name() string { return "security:key_discarded" }
func (e KeyDiscarded) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
if e.KeyType != KeyTypeClient1RTT && e.KeyType != KeyTypeServer1RTT {
h.WriteToken(jsontext.String("trigger"))
h.WriteToken(jsontext.String("tls"))
}
h.WriteToken(jsontext.String("key_type"))
h.WriteToken(jsontext.String(string(e.KeyType)))
if e.KeyType == KeyTypeClient1RTT || e.KeyType == KeyTypeServer1RTT {
h.WriteToken(jsontext.String("key_phase"))
h.WriteToken(jsontext.Uint(uint64(e.KeyPhase)))
}
h.WriteToken(jsontext.EndObject)
return h.err
}
type ParametersSet struct {
Restore bool
Initiator Initiator
SentBy protocol.Perspective
OriginalDestinationConnectionID protocol.ConnectionID
InitialSourceConnectionID protocol.ConnectionID
RetrySourceConnectionID *protocol.ConnectionID
StatelessResetToken *protocol.StatelessResetToken
DisableActiveMigration bool
MaxIdleTimeout time.Duration
MaxUDPPayloadSize protocol.ByteCount
AckDelayExponent uint8
MaxAckDelay time.Duration
ActiveConnectionIDLimit uint64
InitialMaxData protocol.ByteCount
InitialMaxStreamDataBidiLocal protocol.ByteCount
InitialMaxStreamDataBidiRemote protocol.ByteCount
InitialMaxStreamDataUni protocol.ByteCount
InitialMaxStreamsBidi int64
InitialMaxStreamsUni int64
PreferredAddress *PreferredAddress
MaxDatagramFrameSize protocol.ByteCount
EnableResetStreamAt bool
}
func (e ParametersSet) Name() string {
if e.Restore {
return "transport:parameters_restored"
}
return "transport:parameters_set"
}
func (e ParametersSet) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
if !e.Restore {
h.WriteToken(jsontext.String("initiator"))
h.WriteToken(jsontext.String(string(e.Initiator)))
if e.SentBy == protocol.PerspectiveServer {
h.WriteToken(jsontext.String("original_destination_connection_id"))
h.WriteToken(jsontext.String(e.OriginalDestinationConnectionID.String()))
if e.StatelessResetToken != nil {
h.WriteToken(jsontext.String("stateless_reset_token"))
h.WriteToken(jsontext.String(fmt.Sprintf("%x", e.StatelessResetToken[:])))
}
if e.RetrySourceConnectionID != nil {
h.WriteToken(jsontext.String("retry_source_connection_id"))
h.WriteToken(jsontext.String((*e.RetrySourceConnectionID).String()))
}
}
h.WriteToken(jsontext.String("initial_source_connection_id"))
h.WriteToken(jsontext.String(e.InitialSourceConnectionID.String()))
}
h.WriteToken(jsontext.String("disable_active_migration"))
h.WriteToken(jsontext.Bool(e.DisableActiveMigration))
if e.MaxIdleTimeout != 0 {
h.WriteToken(jsontext.String("max_idle_timeout"))
h.WriteToken(jsontext.Float(milliseconds(e.MaxIdleTimeout)))
}
if e.MaxUDPPayloadSize != 0 {
h.WriteToken(jsontext.String("max_udp_payload_size"))
h.WriteToken(jsontext.Int(int64(e.MaxUDPPayloadSize)))
}
if e.AckDelayExponent != 0 {
h.WriteToken(jsontext.String("ack_delay_exponent"))
h.WriteToken(jsontext.Uint(uint64(e.AckDelayExponent)))
}
if e.MaxAckDelay != 0 {
h.WriteToken(jsontext.String("max_ack_delay"))
h.WriteToken(jsontext.Float(milliseconds(e.MaxAckDelay)))
}
if e.ActiveConnectionIDLimit != 0 {
h.WriteToken(jsontext.String("active_connection_id_limit"))
h.WriteToken(jsontext.Uint(e.ActiveConnectionIDLimit))
}
if e.InitialMaxData != 0 {
h.WriteToken(jsontext.String("initial_max_data"))
h.WriteToken(jsontext.Int(int64(e.InitialMaxData)))
}
if e.InitialMaxStreamDataBidiLocal != 0 {
h.WriteToken(jsontext.String("initial_max_stream_data_bidi_local"))
h.WriteToken(jsontext.Int(int64(e.InitialMaxStreamDataBidiLocal)))
}
if e.InitialMaxStreamDataBidiRemote != 0 {
h.WriteToken(jsontext.String("initial_max_stream_data_bidi_remote"))
h.WriteToken(jsontext.Int(int64(e.InitialMaxStreamDataBidiRemote)))
}
if e.InitialMaxStreamDataUni != 0 {
h.WriteToken(jsontext.String("initial_max_stream_data_uni"))
h.WriteToken(jsontext.Int(int64(e.InitialMaxStreamDataUni)))
}
if e.InitialMaxStreamsBidi != 0 {
h.WriteToken(jsontext.String("initial_max_streams_bidi"))
h.WriteToken(jsontext.Int(e.InitialMaxStreamsBidi))
}
if e.InitialMaxStreamsUni != 0 {
h.WriteToken(jsontext.String("initial_max_streams_uni"))
h.WriteToken(jsontext.Int(e.InitialMaxStreamsUni))
}
if e.PreferredAddress != nil {
h.WriteToken(jsontext.String("preferred_address"))
if err := e.PreferredAddress.encode(enc); err != nil {
return err
}
}
if e.MaxDatagramFrameSize != protocol.InvalidByteCount {
h.WriteToken(jsontext.String("max_datagram_frame_size"))
h.WriteToken(jsontext.Int(int64(e.MaxDatagramFrameSize)))
}
if e.EnableResetStreamAt {
h.WriteToken(jsontext.String("reset_stream_at"))
h.WriteToken(jsontext.True)
}
h.WriteToken(jsontext.EndObject)
return h.err
}
type PreferredAddress struct {
IPv4, IPv6 netip.AddrPort
ConnectionID protocol.ConnectionID
StatelessResetToken protocol.StatelessResetToken
}
func (a PreferredAddress) encode(enc *jsontext.Encoder) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
if a.IPv4.IsValid() {
h.WriteToken(jsontext.String("ip_v4"))
h.WriteToken(jsontext.String(a.IPv4.Addr().String()))
h.WriteToken(jsontext.String("port_v4"))
h.WriteToken(jsontext.Uint(uint64(a.IPv4.Port())))
}
if a.IPv6.IsValid() {
h.WriteToken(jsontext.String("ip_v6"))
h.WriteToken(jsontext.String(a.IPv6.Addr().String()))
h.WriteToken(jsontext.String("port_v6"))
h.WriteToken(jsontext.Uint(uint64(a.IPv6.Port())))
}
h.WriteToken(jsontext.String("connection_id"))
h.WriteToken(jsontext.String(a.ConnectionID.String()))
h.WriteToken(jsontext.String("stateless_reset_token"))
h.WriteToken(jsontext.String(fmt.Sprintf("%x", a.StatelessResetToken)))
h.WriteToken(jsontext.EndObject)
return h.err
}
type LossTimerUpdated struct {
Type LossTimerUpdateType
TimerType TimerType
EncLevel EncryptionLevel
Time time.Time
}
func (e LossTimerUpdated) Name() string { return "recovery:loss_timer_updated" }
func (e LossTimerUpdated) Encode(enc *jsontext.Encoder, t time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("event_type"))
h.WriteToken(jsontext.String(string(e.Type)))
h.WriteToken(jsontext.String("timer_type"))
h.WriteToken(jsontext.String(string(e.TimerType)))
h.WriteToken(jsontext.String("packet_number_space"))
h.WriteToken(jsontext.String(encLevelToPacketNumberSpace(e.EncLevel)))
if e.Type == LossTimerUpdateTypeSet {
h.WriteToken(jsontext.String("delta"))
h.WriteToken(jsontext.Float(milliseconds(e.Time.Sub(t))))
}
h.WriteToken(jsontext.EndObject)
return h.err
}
type eventLossTimerCanceled struct{}
func (e eventLossTimerCanceled) Name() string { return "recovery:loss_timer_updated" }
func (e eventLossTimerCanceled) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("event_type"))
h.WriteToken(jsontext.String("cancelled"))
h.WriteToken(jsontext.EndObject)
return h.err
}
type CongestionStateUpdated struct {
State CongestionState
}
func (e CongestionStateUpdated) Name() string { return "recovery:congestion_state_updated" }
func (e CongestionStateUpdated) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("new"))
h.WriteToken(jsontext.String(e.State.String()))
h.WriteToken(jsontext.EndObject)
return h.err
}
type ECNStateUpdated struct {
State ECNState
Trigger string
}
func (e ECNStateUpdated) Name() string { return "recovery:ecn_state_updated" }
func (e ECNStateUpdated) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("new"))
h.WriteToken(jsontext.String(string(e.State)))
if e.Trigger != "" {
h.WriteToken(jsontext.String("trigger"))
h.WriteToken(jsontext.String(e.Trigger))
}
h.WriteToken(jsontext.EndObject)
return h.err
}
type ALPNInformation struct {
ChosenALPN string
}
func (e ALPNInformation) Name() string { return "transport:alpn_information" }
func (e ALPNInformation) Encode(enc *jsontext.Encoder, _ time.Time) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("chosen_alpn"))
h.WriteToken(jsontext.String(e.ChosenALPN))
h.WriteToken(jsontext.EndObject)
return h.err
}