mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-28 04:59:58 +00:00
TUN-5261: Collect QUIC metrics about RTT, packets and bytes transfered and log events at tracing level
This commit is contained in:
529
vendor/github.com/lucas-clemente/quic-go/qlog/event.go
generated
vendored
Normal file
529
vendor/github.com/lucas-clemente/quic-go/qlog/event.go
generated
vendored
Normal file
@@ -0,0 +1,529 @@
|
||||
package qlog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/logging"
|
||||
|
||||
"github.com/francoispqt/gojay"
|
||||
)
|
||||
|
||||
func milliseconds(dur time.Duration) float64 { return float64(dur.Nanoseconds()) / 1e6 }
|
||||
|
||||
type eventDetails interface {
|
||||
Category() category
|
||||
Name() string
|
||||
gojay.MarshalerJSONObject
|
||||
}
|
||||
|
||||
type event struct {
|
||||
RelativeTime time.Duration
|
||||
eventDetails
|
||||
}
|
||||
|
||||
var _ gojay.MarshalerJSONObject = event{}
|
||||
|
||||
func (e event) IsNil() bool { return false }
|
||||
func (e event) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.Float64Key("time", milliseconds(e.RelativeTime))
|
||||
enc.StringKey("name", e.Category().String()+":"+e.Name())
|
||||
enc.ObjectKey("data", e.eventDetails)
|
||||
}
|
||||
|
||||
type versions []versionNumber
|
||||
|
||||
func (v versions) IsNil() bool { return false }
|
||||
func (v versions) MarshalJSONArray(enc *gojay.Encoder) {
|
||||
for _, e := range v {
|
||||
enc.AddString(e.String())
|
||||
}
|
||||
}
|
||||
|
||||
type rawInfo struct {
|
||||
Length logging.ByteCount // full packet length, including header and AEAD authentication tag
|
||||
PayloadLength logging.ByteCount // length of the packet payload, excluding AEAD tag
|
||||
}
|
||||
|
||||
func (i rawInfo) IsNil() bool { return false }
|
||||
func (i rawInfo) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.Uint64Key("length", uint64(i.Length))
|
||||
enc.Uint64KeyOmitEmpty("payload_length", uint64(i.PayloadLength))
|
||||
}
|
||||
|
||||
type eventConnectionStarted struct {
|
||||
SrcAddr *net.UDPAddr
|
||||
DestAddr *net.UDPAddr
|
||||
|
||||
SrcConnectionID protocol.ConnectionID
|
||||
DestConnectionID protocol.ConnectionID
|
||||
}
|
||||
|
||||
var _ eventDetails = &eventConnectionStarted{}
|
||||
|
||||
func (e eventConnectionStarted) Category() category { return categoryTransport }
|
||||
func (e eventConnectionStarted) Name() string { return "connection_started" }
|
||||
func (e eventConnectionStarted) IsNil() bool { return false }
|
||||
|
||||
func (e eventConnectionStarted) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
if utils.IsIPv4(e.SrcAddr.IP) {
|
||||
enc.StringKey("ip_version", "ipv4")
|
||||
} else {
|
||||
enc.StringKey("ip_version", "ipv6")
|
||||
}
|
||||
enc.StringKey("src_ip", e.SrcAddr.IP.String())
|
||||
enc.IntKey("src_port", e.SrcAddr.Port)
|
||||
enc.StringKey("dst_ip", e.DestAddr.IP.String())
|
||||
enc.IntKey("dst_port", e.DestAddr.Port)
|
||||
enc.StringKey("src_cid", connectionID(e.SrcConnectionID).String())
|
||||
enc.StringKey("dst_cid", connectionID(e.DestConnectionID).String())
|
||||
}
|
||||
|
||||
type eventVersionNegotiated struct {
|
||||
clientVersions, serverVersions []versionNumber
|
||||
chosenVersion versionNumber
|
||||
}
|
||||
|
||||
func (e eventVersionNegotiated) Category() category { return categoryTransport }
|
||||
func (e eventVersionNegotiated) Name() string { return "version_information" }
|
||||
func (e eventVersionNegotiated) IsNil() bool { return false }
|
||||
|
||||
func (e eventVersionNegotiated) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
if len(e.clientVersions) > 0 {
|
||||
enc.ArrayKey("client_versions", versions(e.clientVersions))
|
||||
}
|
||||
if len(e.serverVersions) > 0 {
|
||||
enc.ArrayKey("server_versions", versions(e.serverVersions))
|
||||
}
|
||||
enc.StringKey("chosen_version", e.chosenVersion.String())
|
||||
}
|
||||
|
||||
type eventConnectionClosed struct {
|
||||
e error
|
||||
}
|
||||
|
||||
func (e eventConnectionClosed) Category() category { return categoryTransport }
|
||||
func (e eventConnectionClosed) Name() string { return "connection_closed" }
|
||||
func (e eventConnectionClosed) IsNil() bool { return false }
|
||||
|
||||
func (e eventConnectionClosed) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
var (
|
||||
statelessResetErr *quic.StatelessResetError
|
||||
handshakeTimeoutErr *quic.HandshakeTimeoutError
|
||||
idleTimeoutErr *quic.IdleTimeoutError
|
||||
applicationErr *quic.ApplicationError
|
||||
transportErr *quic.TransportError
|
||||
versionNegotiationErr *quic.VersionNegotiationError
|
||||
)
|
||||
switch {
|
||||
case errors.As(e.e, &statelessResetErr):
|
||||
enc.StringKey("owner", ownerRemote.String())
|
||||
enc.StringKey("trigger", "stateless_reset")
|
||||
enc.StringKey("stateless_reset_token", fmt.Sprintf("%x", statelessResetErr.Token))
|
||||
case errors.As(e.e, &handshakeTimeoutErr):
|
||||
enc.StringKey("owner", ownerLocal.String())
|
||||
enc.StringKey("trigger", "handshake_timeout")
|
||||
case errors.As(e.e, &idleTimeoutErr):
|
||||
enc.StringKey("owner", ownerLocal.String())
|
||||
enc.StringKey("trigger", "idle_timeout")
|
||||
case errors.As(e.e, &applicationErr):
|
||||
owner := ownerLocal
|
||||
if applicationErr.Remote {
|
||||
owner = ownerRemote
|
||||
}
|
||||
enc.StringKey("owner", owner.String())
|
||||
enc.Uint64Key("application_code", uint64(applicationErr.ErrorCode))
|
||||
enc.StringKey("reason", applicationErr.ErrorMessage)
|
||||
case errors.As(e.e, &transportErr):
|
||||
owner := ownerLocal
|
||||
if transportErr.Remote {
|
||||
owner = ownerRemote
|
||||
}
|
||||
enc.StringKey("owner", owner.String())
|
||||
enc.StringKey("connection_code", transportError(transportErr.ErrorCode).String())
|
||||
enc.StringKey("reason", transportErr.ErrorMessage)
|
||||
case errors.As(e.e, &versionNegotiationErr):
|
||||
enc.StringKey("owner", ownerRemote.String())
|
||||
enc.StringKey("trigger", "version_negotiation")
|
||||
}
|
||||
}
|
||||
|
||||
type eventPacketSent struct {
|
||||
Header packetHeader
|
||||
Length logging.ByteCount
|
||||
PayloadLength logging.ByteCount
|
||||
Frames frames
|
||||
IsCoalesced bool
|
||||
Trigger string
|
||||
}
|
||||
|
||||
var _ eventDetails = eventPacketSent{}
|
||||
|
||||
func (e eventPacketSent) Category() category { return categoryTransport }
|
||||
func (e eventPacketSent) Name() string { return "packet_sent" }
|
||||
func (e eventPacketSent) IsNil() bool { return false }
|
||||
|
||||
func (e eventPacketSent) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.ObjectKey("header", e.Header)
|
||||
enc.ObjectKey("raw", rawInfo{Length: e.Length, PayloadLength: e.PayloadLength})
|
||||
enc.ArrayKeyOmitEmpty("frames", e.Frames)
|
||||
enc.BoolKeyOmitEmpty("is_coalesced", e.IsCoalesced)
|
||||
enc.StringKeyOmitEmpty("trigger", e.Trigger)
|
||||
}
|
||||
|
||||
type eventPacketReceived struct {
|
||||
Header packetHeader
|
||||
Length logging.ByteCount
|
||||
PayloadLength logging.ByteCount
|
||||
Frames frames
|
||||
IsCoalesced bool
|
||||
Trigger string
|
||||
}
|
||||
|
||||
var _ eventDetails = eventPacketReceived{}
|
||||
|
||||
func (e eventPacketReceived) Category() category { return categoryTransport }
|
||||
func (e eventPacketReceived) Name() string { return "packet_received" }
|
||||
func (e eventPacketReceived) IsNil() bool { return false }
|
||||
|
||||
func (e eventPacketReceived) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.ObjectKey("header", e.Header)
|
||||
enc.ObjectKey("raw", rawInfo{Length: e.Length, PayloadLength: e.PayloadLength})
|
||||
enc.ArrayKeyOmitEmpty("frames", e.Frames)
|
||||
enc.BoolKeyOmitEmpty("is_coalesced", e.IsCoalesced)
|
||||
enc.StringKeyOmitEmpty("trigger", e.Trigger)
|
||||
}
|
||||
|
||||
type eventRetryReceived struct {
|
||||
Header packetHeader
|
||||
}
|
||||
|
||||
func (e eventRetryReceived) Category() category { return categoryTransport }
|
||||
func (e eventRetryReceived) Name() string { return "packet_received" }
|
||||
func (e eventRetryReceived) IsNil() bool { return false }
|
||||
|
||||
func (e eventRetryReceived) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.ObjectKey("header", e.Header)
|
||||
}
|
||||
|
||||
type eventVersionNegotiationReceived struct {
|
||||
Header packetHeader
|
||||
SupportedVersions []versionNumber
|
||||
}
|
||||
|
||||
func (e eventVersionNegotiationReceived) Category() category { return categoryTransport }
|
||||
func (e eventVersionNegotiationReceived) Name() string { return "packet_received" }
|
||||
func (e eventVersionNegotiationReceived) IsNil() bool { return false }
|
||||
|
||||
func (e eventVersionNegotiationReceived) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.ObjectKey("header", e.Header)
|
||||
enc.ArrayKey("supported_versions", versions(e.SupportedVersions))
|
||||
}
|
||||
|
||||
type eventPacketBuffered struct {
|
||||
PacketType logging.PacketType
|
||||
}
|
||||
|
||||
func (e eventPacketBuffered) Category() category { return categoryTransport }
|
||||
func (e eventPacketBuffered) Name() string { return "packet_buffered" }
|
||||
func (e eventPacketBuffered) IsNil() bool { return false }
|
||||
|
||||
func (e eventPacketBuffered) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
//nolint:gosimple
|
||||
enc.ObjectKey("header", packetHeaderWithType{PacketType: e.PacketType})
|
||||
enc.StringKey("trigger", "keys_unavailable")
|
||||
}
|
||||
|
||||
type eventPacketDropped struct {
|
||||
PacketType logging.PacketType
|
||||
PacketSize protocol.ByteCount
|
||||
Trigger packetDropReason
|
||||
}
|
||||
|
||||
func (e eventPacketDropped) Category() category { return categoryTransport }
|
||||
func (e eventPacketDropped) Name() string { return "packet_dropped" }
|
||||
func (e eventPacketDropped) IsNil() bool { return false }
|
||||
|
||||
func (e eventPacketDropped) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.ObjectKey("header", packetHeaderWithType{PacketType: e.PacketType})
|
||||
enc.ObjectKey("raw", rawInfo{Length: e.PacketSize})
|
||||
enc.StringKey("trigger", e.Trigger.String())
|
||||
}
|
||||
|
||||
type metrics struct {
|
||||
MinRTT time.Duration
|
||||
SmoothedRTT time.Duration
|
||||
LatestRTT time.Duration
|
||||
RTTVariance time.Duration
|
||||
|
||||
CongestionWindow protocol.ByteCount
|
||||
BytesInFlight protocol.ByteCount
|
||||
PacketsInFlight int
|
||||
}
|
||||
|
||||
type eventMetricsUpdated struct {
|
||||
Last *metrics
|
||||
Current *metrics
|
||||
}
|
||||
|
||||
func (e eventMetricsUpdated) Category() category { return categoryRecovery }
|
||||
func (e eventMetricsUpdated) Name() string { return "metrics_updated" }
|
||||
func (e eventMetricsUpdated) IsNil() bool { return false }
|
||||
|
||||
func (e eventMetricsUpdated) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
if e.Last == nil || e.Last.MinRTT != e.Current.MinRTT {
|
||||
enc.FloatKey("min_rtt", milliseconds(e.Current.MinRTT))
|
||||
}
|
||||
if e.Last == nil || e.Last.SmoothedRTT != e.Current.SmoothedRTT {
|
||||
enc.FloatKey("smoothed_rtt", milliseconds(e.Current.SmoothedRTT))
|
||||
}
|
||||
if e.Last == nil || e.Last.LatestRTT != e.Current.LatestRTT {
|
||||
enc.FloatKey("latest_rtt", milliseconds(e.Current.LatestRTT))
|
||||
}
|
||||
if e.Last == nil || e.Last.RTTVariance != e.Current.RTTVariance {
|
||||
enc.FloatKey("rtt_variance", milliseconds(e.Current.RTTVariance))
|
||||
}
|
||||
|
||||
if e.Last == nil || e.Last.CongestionWindow != e.Current.CongestionWindow {
|
||||
enc.Uint64Key("congestion_window", uint64(e.Current.CongestionWindow))
|
||||
}
|
||||
if e.Last == nil || e.Last.BytesInFlight != e.Current.BytesInFlight {
|
||||
enc.Uint64Key("bytes_in_flight", uint64(e.Current.BytesInFlight))
|
||||
}
|
||||
if e.Last == nil || e.Last.PacketsInFlight != e.Current.PacketsInFlight {
|
||||
enc.Uint64KeyOmitEmpty("packets_in_flight", uint64(e.Current.PacketsInFlight))
|
||||
}
|
||||
}
|
||||
|
||||
type eventUpdatedPTO struct {
|
||||
Value uint32
|
||||
}
|
||||
|
||||
func (e eventUpdatedPTO) Category() category { return categoryRecovery }
|
||||
func (e eventUpdatedPTO) Name() string { return "metrics_updated" }
|
||||
func (e eventUpdatedPTO) IsNil() bool { return false }
|
||||
|
||||
func (e eventUpdatedPTO) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.Uint32Key("pto_count", e.Value)
|
||||
}
|
||||
|
||||
type eventPacketLost struct {
|
||||
PacketType logging.PacketType
|
||||
PacketNumber protocol.PacketNumber
|
||||
Trigger packetLossReason
|
||||
}
|
||||
|
||||
func (e eventPacketLost) Category() category { return categoryRecovery }
|
||||
func (e eventPacketLost) Name() string { return "packet_lost" }
|
||||
func (e eventPacketLost) IsNil() bool { return false }
|
||||
|
||||
func (e eventPacketLost) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.ObjectKey("header", packetHeaderWithTypeAndPacketNumber{
|
||||
PacketType: e.PacketType,
|
||||
PacketNumber: e.PacketNumber,
|
||||
})
|
||||
enc.StringKey("trigger", e.Trigger.String())
|
||||
}
|
||||
|
||||
type eventKeyUpdated struct {
|
||||
Trigger keyUpdateTrigger
|
||||
KeyType keyType
|
||||
Generation protocol.KeyPhase
|
||||
// we don't log the keys here, so we don't need `old` and `new`.
|
||||
}
|
||||
|
||||
func (e eventKeyUpdated) Category() category { return categorySecurity }
|
||||
func (e eventKeyUpdated) Name() string { return "key_updated" }
|
||||
func (e eventKeyUpdated) IsNil() bool { return false }
|
||||
|
||||
func (e eventKeyUpdated) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("trigger", e.Trigger.String())
|
||||
enc.StringKey("key_type", e.KeyType.String())
|
||||
if e.KeyType == keyTypeClient1RTT || e.KeyType == keyTypeServer1RTT {
|
||||
enc.Uint64Key("generation", uint64(e.Generation))
|
||||
}
|
||||
}
|
||||
|
||||
type eventKeyRetired struct {
|
||||
KeyType keyType
|
||||
Generation protocol.KeyPhase
|
||||
}
|
||||
|
||||
func (e eventKeyRetired) Category() category { return categorySecurity }
|
||||
func (e eventKeyRetired) Name() string { return "key_retired" }
|
||||
func (e eventKeyRetired) IsNil() bool { return false }
|
||||
|
||||
func (e eventKeyRetired) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
if e.KeyType != keyTypeClient1RTT && e.KeyType != keyTypeServer1RTT {
|
||||
enc.StringKey("trigger", "tls")
|
||||
}
|
||||
enc.StringKey("key_type", e.KeyType.String())
|
||||
if e.KeyType == keyTypeClient1RTT || e.KeyType == keyTypeServer1RTT {
|
||||
enc.Uint64Key("generation", uint64(e.Generation))
|
||||
}
|
||||
}
|
||||
|
||||
type eventTransportParameters struct {
|
||||
Restore bool
|
||||
Owner owner
|
||||
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
|
||||
}
|
||||
|
||||
func (e eventTransportParameters) Category() category { return categoryTransport }
|
||||
func (e eventTransportParameters) Name() string {
|
||||
if e.Restore {
|
||||
return "parameters_restored"
|
||||
}
|
||||
return "parameters_set"
|
||||
}
|
||||
func (e eventTransportParameters) IsNil() bool { return false }
|
||||
|
||||
func (e eventTransportParameters) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
if !e.Restore {
|
||||
enc.StringKey("owner", e.Owner.String())
|
||||
if e.SentBy == protocol.PerspectiveServer {
|
||||
enc.StringKey("original_destination_connection_id", connectionID(e.OriginalDestinationConnectionID).String())
|
||||
if e.StatelessResetToken != nil {
|
||||
enc.StringKey("stateless_reset_token", fmt.Sprintf("%x", e.StatelessResetToken[:]))
|
||||
}
|
||||
if e.RetrySourceConnectionID != nil {
|
||||
enc.StringKey("retry_source_connection_id", connectionID(*e.RetrySourceConnectionID).String())
|
||||
}
|
||||
}
|
||||
enc.StringKey("initial_source_connection_id", connectionID(e.InitialSourceConnectionID).String())
|
||||
}
|
||||
enc.BoolKey("disable_active_migration", e.DisableActiveMigration)
|
||||
enc.FloatKeyOmitEmpty("max_idle_timeout", milliseconds(e.MaxIdleTimeout))
|
||||
enc.Int64KeyNullEmpty("max_udp_payload_size", int64(e.MaxUDPPayloadSize))
|
||||
enc.Uint8KeyOmitEmpty("ack_delay_exponent", e.AckDelayExponent)
|
||||
enc.FloatKeyOmitEmpty("max_ack_delay", milliseconds(e.MaxAckDelay))
|
||||
enc.Uint64KeyOmitEmpty("active_connection_id_limit", e.ActiveConnectionIDLimit)
|
||||
|
||||
enc.Int64KeyOmitEmpty("initial_max_data", int64(e.InitialMaxData))
|
||||
enc.Int64KeyOmitEmpty("initial_max_stream_data_bidi_local", int64(e.InitialMaxStreamDataBidiLocal))
|
||||
enc.Int64KeyOmitEmpty("initial_max_stream_data_bidi_remote", int64(e.InitialMaxStreamDataBidiRemote))
|
||||
enc.Int64KeyOmitEmpty("initial_max_stream_data_uni", int64(e.InitialMaxStreamDataUni))
|
||||
enc.Int64KeyOmitEmpty("initial_max_streams_bidi", e.InitialMaxStreamsBidi)
|
||||
enc.Int64KeyOmitEmpty("initial_max_streams_uni", e.InitialMaxStreamsUni)
|
||||
|
||||
if e.PreferredAddress != nil {
|
||||
enc.ObjectKey("preferred_address", e.PreferredAddress)
|
||||
}
|
||||
if e.MaxDatagramFrameSize != protocol.InvalidByteCount {
|
||||
enc.Int64Key("max_datagram_frame_size", int64(e.MaxDatagramFrameSize))
|
||||
}
|
||||
}
|
||||
|
||||
type preferredAddress struct {
|
||||
IPv4, IPv6 net.IP
|
||||
PortV4, PortV6 uint16
|
||||
ConnectionID protocol.ConnectionID
|
||||
StatelessResetToken protocol.StatelessResetToken
|
||||
}
|
||||
|
||||
var _ gojay.MarshalerJSONObject = &preferredAddress{}
|
||||
|
||||
func (a preferredAddress) IsNil() bool { return false }
|
||||
func (a preferredAddress) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("ip_v4", a.IPv4.String())
|
||||
enc.Uint16Key("port_v4", a.PortV4)
|
||||
enc.StringKey("ip_v6", a.IPv6.String())
|
||||
enc.Uint16Key("port_v6", a.PortV6)
|
||||
enc.StringKey("connection_id", connectionID(a.ConnectionID).String())
|
||||
enc.StringKey("stateless_reset_token", fmt.Sprintf("%x", a.StatelessResetToken))
|
||||
}
|
||||
|
||||
type eventLossTimerSet struct {
|
||||
TimerType timerType
|
||||
EncLevel protocol.EncryptionLevel
|
||||
Delta time.Duration
|
||||
}
|
||||
|
||||
func (e eventLossTimerSet) Category() category { return categoryRecovery }
|
||||
func (e eventLossTimerSet) Name() string { return "loss_timer_updated" }
|
||||
func (e eventLossTimerSet) IsNil() bool { return false }
|
||||
|
||||
func (e eventLossTimerSet) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("event_type", "set")
|
||||
enc.StringKey("timer_type", e.TimerType.String())
|
||||
enc.StringKey("packet_number_space", encLevelToPacketNumberSpace(e.EncLevel))
|
||||
enc.Float64Key("delta", milliseconds(e.Delta))
|
||||
}
|
||||
|
||||
type eventLossTimerExpired struct {
|
||||
TimerType timerType
|
||||
EncLevel protocol.EncryptionLevel
|
||||
}
|
||||
|
||||
func (e eventLossTimerExpired) Category() category { return categoryRecovery }
|
||||
func (e eventLossTimerExpired) Name() string { return "loss_timer_updated" }
|
||||
func (e eventLossTimerExpired) IsNil() bool { return false }
|
||||
|
||||
func (e eventLossTimerExpired) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("event_type", "expired")
|
||||
enc.StringKey("timer_type", e.TimerType.String())
|
||||
enc.StringKey("packet_number_space", encLevelToPacketNumberSpace(e.EncLevel))
|
||||
}
|
||||
|
||||
type eventLossTimerCanceled struct{}
|
||||
|
||||
func (e eventLossTimerCanceled) Category() category { return categoryRecovery }
|
||||
func (e eventLossTimerCanceled) Name() string { return "loss_timer_updated" }
|
||||
func (e eventLossTimerCanceled) IsNil() bool { return false }
|
||||
|
||||
func (e eventLossTimerCanceled) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("event_type", "cancelled")
|
||||
}
|
||||
|
||||
type eventCongestionStateUpdated struct {
|
||||
state congestionState
|
||||
}
|
||||
|
||||
func (e eventCongestionStateUpdated) Category() category { return categoryRecovery }
|
||||
func (e eventCongestionStateUpdated) Name() string { return "congestion_state_updated" }
|
||||
func (e eventCongestionStateUpdated) IsNil() bool { return false }
|
||||
|
||||
func (e eventCongestionStateUpdated) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("new", e.state.String())
|
||||
}
|
||||
|
||||
type eventGeneric struct {
|
||||
name string
|
||||
msg string
|
||||
}
|
||||
|
||||
func (e eventGeneric) Category() category { return categoryTransport }
|
||||
func (e eventGeneric) Name() string { return e.name }
|
||||
func (e eventGeneric) IsNil() bool { return false }
|
||||
|
||||
func (e eventGeneric) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("details", e.msg)
|
||||
}
|
227
vendor/github.com/lucas-clemente/quic-go/qlog/frame.go
generated
vendored
Normal file
227
vendor/github.com/lucas-clemente/quic-go/qlog/frame.go
generated
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
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))
|
||||
}
|
119
vendor/github.com/lucas-clemente/quic-go/qlog/packet_header.go
generated
vendored
Normal file
119
vendor/github.com/lucas-clemente/quic-go/qlog/packet_header.go
generated
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
package qlog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/wire"
|
||||
"github.com/lucas-clemente/quic-go/logging"
|
||||
|
||||
"github.com/francoispqt/gojay"
|
||||
)
|
||||
|
||||
func getPacketTypeFromEncryptionLevel(encLevel protocol.EncryptionLevel) logging.PacketType {
|
||||
switch encLevel {
|
||||
case protocol.EncryptionInitial:
|
||||
return logging.PacketTypeInitial
|
||||
case protocol.EncryptionHandshake:
|
||||
return logging.PacketTypeHandshake
|
||||
case protocol.Encryption0RTT:
|
||||
return logging.PacketType0RTT
|
||||
case protocol.Encryption1RTT:
|
||||
return logging.PacketType1RTT
|
||||
default:
|
||||
panic("unknown encryption level")
|
||||
}
|
||||
}
|
||||
|
||||
type token struct {
|
||||
Raw []byte
|
||||
}
|
||||
|
||||
var _ gojay.MarshalerJSONObject = &token{}
|
||||
|
||||
func (t token) IsNil() bool { return false }
|
||||
func (t token) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("data", fmt.Sprintf("%x", t.Raw))
|
||||
}
|
||||
|
||||
// PacketHeader is a QUIC packet header.
|
||||
type packetHeader struct {
|
||||
PacketType logging.PacketType
|
||||
|
||||
KeyPhaseBit logging.KeyPhaseBit
|
||||
PacketNumber logging.PacketNumber
|
||||
|
||||
Version logging.VersionNumber
|
||||
SrcConnectionID logging.ConnectionID
|
||||
DestConnectionID logging.ConnectionID
|
||||
|
||||
Token *token
|
||||
}
|
||||
|
||||
func transformHeader(hdr *wire.Header) *packetHeader {
|
||||
h := &packetHeader{
|
||||
PacketType: logging.PacketTypeFromHeader(hdr),
|
||||
SrcConnectionID: hdr.SrcConnectionID,
|
||||
DestConnectionID: hdr.DestConnectionID,
|
||||
Version: hdr.Version,
|
||||
}
|
||||
if len(hdr.Token) > 0 {
|
||||
h.Token = &token{Raw: hdr.Token}
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
func transformExtendedHeader(hdr *wire.ExtendedHeader) *packetHeader {
|
||||
h := transformHeader(&hdr.Header)
|
||||
h.PacketNumber = hdr.PacketNumber
|
||||
h.KeyPhaseBit = hdr.KeyPhase
|
||||
return h
|
||||
}
|
||||
|
||||
func (h packetHeader) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("packet_type", packetType(h.PacketType).String())
|
||||
if h.PacketType != logging.PacketTypeRetry && h.PacketType != logging.PacketTypeVersionNegotiation {
|
||||
enc.Int64Key("packet_number", int64(h.PacketNumber))
|
||||
}
|
||||
if h.Version != 0 {
|
||||
enc.StringKey("version", versionNumber(h.Version).String())
|
||||
}
|
||||
if h.PacketType != logging.PacketType1RTT {
|
||||
enc.IntKey("scil", h.SrcConnectionID.Len())
|
||||
if h.SrcConnectionID.Len() > 0 {
|
||||
enc.StringKey("scid", connectionID(h.SrcConnectionID).String())
|
||||
}
|
||||
}
|
||||
enc.IntKey("dcil", h.DestConnectionID.Len())
|
||||
if h.DestConnectionID.Len() > 0 {
|
||||
enc.StringKey("dcid", connectionID(h.DestConnectionID).String())
|
||||
}
|
||||
if h.KeyPhaseBit == logging.KeyPhaseZero || h.KeyPhaseBit == logging.KeyPhaseOne {
|
||||
enc.StringKey("key_phase_bit", h.KeyPhaseBit.String())
|
||||
}
|
||||
if h.Token != nil {
|
||||
enc.ObjectKey("token", h.Token)
|
||||
}
|
||||
}
|
||||
|
||||
// a minimal header that only outputs the packet type
|
||||
type packetHeaderWithType struct {
|
||||
PacketType logging.PacketType
|
||||
}
|
||||
|
||||
func (h packetHeaderWithType) IsNil() bool { return false }
|
||||
func (h packetHeaderWithType) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("packet_type", packetType(h.PacketType).String())
|
||||
}
|
||||
|
||||
// a minimal header that only outputs the packet type
|
||||
type packetHeaderWithTypeAndPacketNumber struct {
|
||||
PacketType logging.PacketType
|
||||
PacketNumber logging.PacketNumber
|
||||
}
|
||||
|
||||
func (h packetHeaderWithTypeAndPacketNumber) IsNil() bool { return false }
|
||||
func (h packetHeaderWithTypeAndPacketNumber) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("packet_type", packetType(h.PacketType).String())
|
||||
enc.Int64Key("packet_number", int64(h.PacketNumber))
|
||||
}
|
486
vendor/github.com/lucas-clemente/quic-go/qlog/qlog.go
generated
vendored
Normal file
486
vendor/github.com/lucas-clemente/quic-go/qlog/qlog.go
generated
vendored
Normal file
@@ -0,0 +1,486 @@
|
||||
package qlog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||
"github.com/lucas-clemente/quic-go/internal/wire"
|
||||
"github.com/lucas-clemente/quic-go/logging"
|
||||
|
||||
"github.com/francoispqt/gojay"
|
||||
)
|
||||
|
||||
// Setting of this only works when quic-go is used as a library.
|
||||
// When building a binary from this repository, the version can be set using the following go build flag:
|
||||
// -ldflags="-X github.com/lucas-clemente/quic-go/qlog.quicGoVersion=foobar"
|
||||
var quicGoVersion = "(devel)"
|
||||
|
||||
func init() {
|
||||
if quicGoVersion != "(devel)" { // variable set by ldflags
|
||||
return
|
||||
}
|
||||
info, ok := debug.ReadBuildInfo()
|
||||
if !ok { // no build info available. This happens when quic-go is not used as a library.
|
||||
return
|
||||
}
|
||||
for _, d := range info.Deps {
|
||||
if d.Path == "github.com/lucas-clemente/quic-go" {
|
||||
quicGoVersion = d.Version
|
||||
if d.Replace != nil {
|
||||
if len(d.Replace.Version) > 0 {
|
||||
quicGoVersion = d.Version
|
||||
} else {
|
||||
quicGoVersion += " (replaced)"
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const eventChanSize = 50
|
||||
|
||||
type tracer struct {
|
||||
getLogWriter func(p logging.Perspective, connectionID []byte) io.WriteCloser
|
||||
}
|
||||
|
||||
var _ logging.Tracer = &tracer{}
|
||||
|
||||
// NewTracer creates a new qlog tracer.
|
||||
func NewTracer(getLogWriter func(p logging.Perspective, connectionID []byte) io.WriteCloser) logging.Tracer {
|
||||
return &tracer{getLogWriter: getLogWriter}
|
||||
}
|
||||
|
||||
func (t *tracer) TracerForConnection(_ context.Context, p logging.Perspective, odcid protocol.ConnectionID) logging.ConnectionTracer {
|
||||
if w := t.getLogWriter(p, odcid.Bytes()); w != nil {
|
||||
return NewConnectionTracer(w, p, odcid)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *tracer) SentPacket(net.Addr, *logging.Header, protocol.ByteCount, []logging.Frame) {}
|
||||
func (t *tracer) DroppedPacket(net.Addr, logging.PacketType, protocol.ByteCount, logging.PacketDropReason) {
|
||||
}
|
||||
|
||||
type connectionTracer struct {
|
||||
mutex sync.Mutex
|
||||
|
||||
w io.WriteCloser
|
||||
odcid protocol.ConnectionID
|
||||
perspective protocol.Perspective
|
||||
referenceTime time.Time
|
||||
|
||||
events chan event
|
||||
encodeErr error
|
||||
runStopped chan struct{}
|
||||
|
||||
lastMetrics *metrics
|
||||
}
|
||||
|
||||
var _ logging.ConnectionTracer = &connectionTracer{}
|
||||
|
||||
// NewConnectionTracer creates a new tracer to record a qlog for a connection.
|
||||
func NewConnectionTracer(w io.WriteCloser, p protocol.Perspective, odcid protocol.ConnectionID) logging.ConnectionTracer {
|
||||
t := &connectionTracer{
|
||||
w: w,
|
||||
perspective: p,
|
||||
odcid: odcid,
|
||||
runStopped: make(chan struct{}),
|
||||
events: make(chan event, eventChanSize),
|
||||
referenceTime: time.Now(),
|
||||
}
|
||||
go t.run()
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *connectionTracer) run() {
|
||||
defer close(t.runStopped)
|
||||
buf := &bytes.Buffer{}
|
||||
enc := gojay.NewEncoder(buf)
|
||||
tl := &topLevel{
|
||||
trace: trace{
|
||||
VantagePoint: vantagePoint{Type: t.perspective},
|
||||
CommonFields: commonFields{
|
||||
ODCID: connectionID(t.odcid),
|
||||
GroupID: connectionID(t.odcid),
|
||||
ReferenceTime: t.referenceTime,
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := enc.Encode(tl); err != nil {
|
||||
panic(fmt.Sprintf("qlog encoding into a bytes.Buffer failed: %s", err))
|
||||
}
|
||||
if err := buf.WriteByte('\n'); err != nil {
|
||||
panic(fmt.Sprintf("qlog encoding into a bytes.Buffer failed: %s", err))
|
||||
}
|
||||
if _, err := t.w.Write(buf.Bytes()); err != nil {
|
||||
t.encodeErr = err
|
||||
}
|
||||
enc = gojay.NewEncoder(t.w)
|
||||
for ev := range t.events {
|
||||
if t.encodeErr != nil { // if encoding failed, just continue draining the event channel
|
||||
continue
|
||||
}
|
||||
if err := enc.Encode(ev); err != nil {
|
||||
t.encodeErr = err
|
||||
continue
|
||||
}
|
||||
if _, err := t.w.Write([]byte{'\n'}); err != nil {
|
||||
t.encodeErr = err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *connectionTracer) Close() {
|
||||
if err := t.export(); err != nil {
|
||||
log.Printf("exporting qlog failed: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
// export writes a qlog.
|
||||
func (t *connectionTracer) export() error {
|
||||
close(t.events)
|
||||
<-t.runStopped
|
||||
if t.encodeErr != nil {
|
||||
return t.encodeErr
|
||||
}
|
||||
return t.w.Close()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) recordEvent(eventTime time.Time, details eventDetails) {
|
||||
t.events <- event{
|
||||
RelativeTime: eventTime.Sub(t.referenceTime),
|
||||
eventDetails: details,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *connectionTracer) StartedConnection(local, remote net.Addr, srcConnID, destConnID protocol.ConnectionID) {
|
||||
// ignore this event if we're not dealing with UDP addresses here
|
||||
localAddr, ok := local.(*net.UDPAddr)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
remoteAddr, ok := remote.(*net.UDPAddr)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventConnectionStarted{
|
||||
SrcAddr: localAddr,
|
||||
DestAddr: remoteAddr,
|
||||
SrcConnectionID: srcConnID,
|
||||
DestConnectionID: destConnID,
|
||||
})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) NegotiatedVersion(chosen logging.VersionNumber, client, server []logging.VersionNumber) {
|
||||
var clientVersions, serverVersions []versionNumber
|
||||
if len(client) > 0 {
|
||||
clientVersions = make([]versionNumber, len(client))
|
||||
for i, v := range client {
|
||||
clientVersions[i] = versionNumber(v)
|
||||
}
|
||||
}
|
||||
if len(server) > 0 {
|
||||
serverVersions = make([]versionNumber, len(server))
|
||||
for i, v := range server {
|
||||
serverVersions[i] = versionNumber(v)
|
||||
}
|
||||
}
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventVersionNegotiated{
|
||||
clientVersions: clientVersions,
|
||||
serverVersions: serverVersions,
|
||||
chosenVersion: versionNumber(chosen),
|
||||
})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) ClosedConnection(e error) {
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventConnectionClosed{e: e})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) SentTransportParameters(tp *wire.TransportParameters) {
|
||||
t.recordTransportParameters(t.perspective, tp)
|
||||
}
|
||||
|
||||
func (t *connectionTracer) ReceivedTransportParameters(tp *wire.TransportParameters) {
|
||||
t.recordTransportParameters(t.perspective.Opposite(), tp)
|
||||
}
|
||||
|
||||
func (t *connectionTracer) RestoredTransportParameters(tp *wire.TransportParameters) {
|
||||
ev := t.toTransportParameters(tp)
|
||||
ev.Restore = true
|
||||
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), ev)
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) recordTransportParameters(sentBy protocol.Perspective, tp *wire.TransportParameters) {
|
||||
ev := t.toTransportParameters(tp)
|
||||
ev.Owner = ownerLocal
|
||||
if sentBy != t.perspective {
|
||||
ev.Owner = ownerRemote
|
||||
}
|
||||
ev.SentBy = sentBy
|
||||
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), ev)
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) toTransportParameters(tp *wire.TransportParameters) *eventTransportParameters {
|
||||
var pa *preferredAddress
|
||||
if tp.PreferredAddress != nil {
|
||||
pa = &preferredAddress{
|
||||
IPv4: tp.PreferredAddress.IPv4,
|
||||
PortV4: tp.PreferredAddress.IPv4Port,
|
||||
IPv6: tp.PreferredAddress.IPv6,
|
||||
PortV6: tp.PreferredAddress.IPv6Port,
|
||||
ConnectionID: tp.PreferredAddress.ConnectionID,
|
||||
StatelessResetToken: tp.PreferredAddress.StatelessResetToken,
|
||||
}
|
||||
}
|
||||
return &eventTransportParameters{
|
||||
OriginalDestinationConnectionID: tp.OriginalDestinationConnectionID,
|
||||
InitialSourceConnectionID: tp.InitialSourceConnectionID,
|
||||
RetrySourceConnectionID: tp.RetrySourceConnectionID,
|
||||
StatelessResetToken: tp.StatelessResetToken,
|
||||
DisableActiveMigration: tp.DisableActiveMigration,
|
||||
MaxIdleTimeout: tp.MaxIdleTimeout,
|
||||
MaxUDPPayloadSize: tp.MaxUDPPayloadSize,
|
||||
AckDelayExponent: tp.AckDelayExponent,
|
||||
MaxAckDelay: tp.MaxAckDelay,
|
||||
ActiveConnectionIDLimit: tp.ActiveConnectionIDLimit,
|
||||
InitialMaxData: tp.InitialMaxData,
|
||||
InitialMaxStreamDataBidiLocal: tp.InitialMaxStreamDataBidiLocal,
|
||||
InitialMaxStreamDataBidiRemote: tp.InitialMaxStreamDataBidiRemote,
|
||||
InitialMaxStreamDataUni: tp.InitialMaxStreamDataUni,
|
||||
InitialMaxStreamsBidi: int64(tp.MaxBidiStreamNum),
|
||||
InitialMaxStreamsUni: int64(tp.MaxUniStreamNum),
|
||||
PreferredAddress: pa,
|
||||
MaxDatagramFrameSize: tp.MaxDatagramFrameSize,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *connectionTracer) SentPacket(hdr *wire.ExtendedHeader, packetSize logging.ByteCount, ack *logging.AckFrame, frames []logging.Frame) {
|
||||
numFrames := len(frames)
|
||||
if ack != nil {
|
||||
numFrames++
|
||||
}
|
||||
fs := make([]frame, 0, numFrames)
|
||||
if ack != nil {
|
||||
fs = append(fs, frame{Frame: ack})
|
||||
}
|
||||
for _, f := range frames {
|
||||
fs = append(fs, frame{Frame: f})
|
||||
}
|
||||
header := *transformExtendedHeader(hdr)
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventPacketSent{
|
||||
Header: header,
|
||||
Length: packetSize,
|
||||
PayloadLength: hdr.Length,
|
||||
Frames: fs,
|
||||
})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) ReceivedPacket(hdr *wire.ExtendedHeader, packetSize logging.ByteCount, frames []logging.Frame) {
|
||||
fs := make([]frame, len(frames))
|
||||
for i, f := range frames {
|
||||
fs[i] = frame{Frame: f}
|
||||
}
|
||||
header := *transformExtendedHeader(hdr)
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventPacketReceived{
|
||||
Header: header,
|
||||
Length: packetSize,
|
||||
PayloadLength: hdr.Length,
|
||||
Frames: fs,
|
||||
})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) ReceivedRetry(hdr *wire.Header) {
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventRetryReceived{
|
||||
Header: *transformHeader(hdr),
|
||||
})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) ReceivedVersionNegotiationPacket(hdr *wire.Header, versions []logging.VersionNumber) {
|
||||
ver := make([]versionNumber, len(versions))
|
||||
for i, v := range versions {
|
||||
ver[i] = versionNumber(v)
|
||||
}
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventVersionNegotiationReceived{
|
||||
Header: *transformHeader(hdr),
|
||||
SupportedVersions: ver,
|
||||
})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) BufferedPacket(pt logging.PacketType) {
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventPacketBuffered{PacketType: pt})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) DroppedPacket(pt logging.PacketType, size protocol.ByteCount, reason logging.PacketDropReason) {
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventPacketDropped{
|
||||
PacketType: pt,
|
||||
PacketSize: size,
|
||||
Trigger: packetDropReason(reason),
|
||||
})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) UpdatedMetrics(rttStats *utils.RTTStats, cwnd, bytesInFlight protocol.ByteCount, packetsInFlight int) {
|
||||
m := &metrics{
|
||||
MinRTT: rttStats.MinRTT(),
|
||||
SmoothedRTT: rttStats.SmoothedRTT(),
|
||||
LatestRTT: rttStats.LatestRTT(),
|
||||
RTTVariance: rttStats.MeanDeviation(),
|
||||
CongestionWindow: cwnd,
|
||||
BytesInFlight: bytesInFlight,
|
||||
PacketsInFlight: packetsInFlight,
|
||||
}
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventMetricsUpdated{
|
||||
Last: t.lastMetrics,
|
||||
Current: m,
|
||||
})
|
||||
t.lastMetrics = m
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) AcknowledgedPacket(protocol.EncryptionLevel, protocol.PacketNumber) {}
|
||||
|
||||
func (t *connectionTracer) LostPacket(encLevel protocol.EncryptionLevel, pn protocol.PacketNumber, lossReason logging.PacketLossReason) {
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventPacketLost{
|
||||
PacketType: getPacketTypeFromEncryptionLevel(encLevel),
|
||||
PacketNumber: pn,
|
||||
Trigger: packetLossReason(lossReason),
|
||||
})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) UpdatedCongestionState(state logging.CongestionState) {
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventCongestionStateUpdated{state: congestionState(state)})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) UpdatedPTOCount(value uint32) {
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventUpdatedPTO{Value: value})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) UpdatedKeyFromTLS(encLevel protocol.EncryptionLevel, pers protocol.Perspective) {
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventKeyUpdated{
|
||||
Trigger: keyUpdateTLS,
|
||||
KeyType: encLevelToKeyType(encLevel, pers),
|
||||
})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) UpdatedKey(generation protocol.KeyPhase, remote bool) {
|
||||
trigger := keyUpdateLocal
|
||||
if remote {
|
||||
trigger = keyUpdateRemote
|
||||
}
|
||||
t.mutex.Lock()
|
||||
now := time.Now()
|
||||
t.recordEvent(now, &eventKeyUpdated{
|
||||
Trigger: trigger,
|
||||
KeyType: keyTypeClient1RTT,
|
||||
Generation: generation,
|
||||
})
|
||||
t.recordEvent(now, &eventKeyUpdated{
|
||||
Trigger: trigger,
|
||||
KeyType: keyTypeServer1RTT,
|
||||
Generation: generation,
|
||||
})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) DroppedEncryptionLevel(encLevel protocol.EncryptionLevel) {
|
||||
t.mutex.Lock()
|
||||
now := time.Now()
|
||||
if encLevel == protocol.Encryption0RTT {
|
||||
t.recordEvent(now, &eventKeyRetired{KeyType: encLevelToKeyType(encLevel, t.perspective)})
|
||||
} else {
|
||||
t.recordEvent(now, &eventKeyRetired{KeyType: encLevelToKeyType(encLevel, protocol.PerspectiveServer)})
|
||||
t.recordEvent(now, &eventKeyRetired{KeyType: encLevelToKeyType(encLevel, protocol.PerspectiveClient)})
|
||||
}
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) DroppedKey(generation protocol.KeyPhase) {
|
||||
t.mutex.Lock()
|
||||
now := time.Now()
|
||||
t.recordEvent(now, &eventKeyRetired{
|
||||
KeyType: encLevelToKeyType(protocol.Encryption1RTT, protocol.PerspectiveServer),
|
||||
Generation: generation,
|
||||
})
|
||||
t.recordEvent(now, &eventKeyRetired{
|
||||
KeyType: encLevelToKeyType(protocol.Encryption1RTT, protocol.PerspectiveClient),
|
||||
Generation: generation,
|
||||
})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) SetLossTimer(tt logging.TimerType, encLevel protocol.EncryptionLevel, timeout time.Time) {
|
||||
t.mutex.Lock()
|
||||
now := time.Now()
|
||||
t.recordEvent(now, &eventLossTimerSet{
|
||||
TimerType: timerType(tt),
|
||||
EncLevel: encLevel,
|
||||
Delta: timeout.Sub(now),
|
||||
})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) LossTimerExpired(tt logging.TimerType, encLevel protocol.EncryptionLevel) {
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventLossTimerExpired{
|
||||
TimerType: timerType(tt),
|
||||
EncLevel: encLevel,
|
||||
})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) LossTimerCanceled() {
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventLossTimerCanceled{})
|
||||
t.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (t *connectionTracer) Debug(name, msg string) {
|
||||
t.mutex.Lock()
|
||||
t.recordEvent(time.Now(), &eventGeneric{
|
||||
name: name,
|
||||
msg: msg,
|
||||
})
|
||||
t.mutex.Unlock()
|
||||
}
|
66
vendor/github.com/lucas-clemente/quic-go/qlog/trace.go
generated
vendored
Normal file
66
vendor/github.com/lucas-clemente/quic-go/qlog/trace.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
package qlog
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/francoispqt/gojay"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
)
|
||||
|
||||
type topLevel struct {
|
||||
trace trace
|
||||
}
|
||||
|
||||
func (topLevel) IsNil() bool { return false }
|
||||
func (l topLevel) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("qlog_format", "NDJSON")
|
||||
enc.StringKey("qlog_version", "draft-02")
|
||||
enc.StringKeyOmitEmpty("title", "quic-go qlog")
|
||||
enc.StringKey("code_version", quicGoVersion)
|
||||
enc.ObjectKey("trace", l.trace)
|
||||
}
|
||||
|
||||
type vantagePoint struct {
|
||||
Name string
|
||||
Type protocol.Perspective
|
||||
}
|
||||
|
||||
func (p vantagePoint) IsNil() bool { return false }
|
||||
func (p vantagePoint) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKeyOmitEmpty("name", p.Name)
|
||||
switch p.Type {
|
||||
case protocol.PerspectiveClient:
|
||||
enc.StringKey("type", "client")
|
||||
case protocol.PerspectiveServer:
|
||||
enc.StringKey("type", "server")
|
||||
}
|
||||
}
|
||||
|
||||
type commonFields struct {
|
||||
ODCID connectionID
|
||||
GroupID connectionID
|
||||
ProtocolType string
|
||||
ReferenceTime time.Time
|
||||
}
|
||||
|
||||
func (f commonFields) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.StringKey("ODCID", f.ODCID.String())
|
||||
enc.StringKey("group_id", f.ODCID.String())
|
||||
enc.StringKeyOmitEmpty("protocol_type", f.ProtocolType)
|
||||
enc.Float64Key("reference_time", float64(f.ReferenceTime.UnixNano())/1e6)
|
||||
enc.StringKey("time_format", "relative")
|
||||
}
|
||||
|
||||
func (f commonFields) IsNil() bool { return false }
|
||||
|
||||
type trace struct {
|
||||
VantagePoint vantagePoint
|
||||
CommonFields commonFields
|
||||
}
|
||||
|
||||
func (trace) IsNil() bool { return false }
|
||||
func (t trace) MarshalJSONObject(enc *gojay.Encoder) {
|
||||
enc.ObjectKey("vantage_point", t.VantagePoint)
|
||||
enc.ObjectKey("common_fields", t.CommonFields)
|
||||
}
|
320
vendor/github.com/lucas-clemente/quic-go/qlog/types.go
generated
vendored
Normal file
320
vendor/github.com/lucas-clemente/quic-go/qlog/types.go
generated
vendored
Normal file
@@ -0,0 +1,320 @@
|
||||
package qlog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
"github.com/lucas-clemente/quic-go/internal/qerr"
|
||||
"github.com/lucas-clemente/quic-go/logging"
|
||||
)
|
||||
|
||||
type owner uint8
|
||||
|
||||
const (
|
||||
ownerLocal owner = iota
|
||||
ownerRemote
|
||||
)
|
||||
|
||||
func (o owner) String() string {
|
||||
switch o {
|
||||
case ownerLocal:
|
||||
return "local"
|
||||
case ownerRemote:
|
||||
return "remote"
|
||||
default:
|
||||
return "unknown owner"
|
||||
}
|
||||
}
|
||||
|
||||
type streamType protocol.StreamType
|
||||
|
||||
func (s streamType) String() string {
|
||||
switch protocol.StreamType(s) {
|
||||
case protocol.StreamTypeUni:
|
||||
return "unidirectional"
|
||||
case protocol.StreamTypeBidi:
|
||||
return "bidirectional"
|
||||
default:
|
||||
return "unknown stream type"
|
||||
}
|
||||
}
|
||||
|
||||
type connectionID protocol.ConnectionID
|
||||
|
||||
func (c connectionID) String() string {
|
||||
return fmt.Sprintf("%x", []byte(c))
|
||||
}
|
||||
|
||||
// category is the qlog event category.
|
||||
type category uint8
|
||||
|
||||
const (
|
||||
categoryConnectivity category = iota
|
||||
categoryTransport
|
||||
categorySecurity
|
||||
categoryRecovery
|
||||
)
|
||||
|
||||
func (c category) String() string {
|
||||
switch c {
|
||||
case categoryConnectivity:
|
||||
return "connectivity"
|
||||
case categoryTransport:
|
||||
return "transport"
|
||||
case categorySecurity:
|
||||
return "security"
|
||||
case categoryRecovery:
|
||||
return "recovery"
|
||||
default:
|
||||
return "unknown category"
|
||||
}
|
||||
}
|
||||
|
||||
type versionNumber protocol.VersionNumber
|
||||
|
||||
func (v versionNumber) String() string {
|
||||
return fmt.Sprintf("%x", uint32(v))
|
||||
}
|
||||
|
||||
func (packetHeader) IsNil() bool { return false }
|
||||
|
||||
func encLevelToPacketNumberSpace(encLevel protocol.EncryptionLevel) string {
|
||||
switch encLevel {
|
||||
case protocol.EncryptionInitial:
|
||||
return "initial"
|
||||
case protocol.EncryptionHandshake:
|
||||
return "handshake"
|
||||
case protocol.Encryption0RTT, protocol.Encryption1RTT:
|
||||
return "application_data"
|
||||
default:
|
||||
return "unknown encryption level"
|
||||
}
|
||||
}
|
||||
|
||||
type keyType uint8
|
||||
|
||||
const (
|
||||
keyTypeServerInitial keyType = 1 + iota
|
||||
keyTypeClientInitial
|
||||
keyTypeServerHandshake
|
||||
keyTypeClientHandshake
|
||||
keyTypeServer0RTT
|
||||
keyTypeClient0RTT
|
||||
keyTypeServer1RTT
|
||||
keyTypeClient1RTT
|
||||
)
|
||||
|
||||
func encLevelToKeyType(encLevel protocol.EncryptionLevel, pers protocol.Perspective) keyType {
|
||||
if pers == protocol.PerspectiveServer {
|
||||
switch encLevel {
|
||||
case protocol.EncryptionInitial:
|
||||
return keyTypeServerInitial
|
||||
case protocol.EncryptionHandshake:
|
||||
return keyTypeServerHandshake
|
||||
case protocol.Encryption0RTT:
|
||||
return keyTypeServer0RTT
|
||||
case protocol.Encryption1RTT:
|
||||
return keyTypeServer1RTT
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
switch encLevel {
|
||||
case protocol.EncryptionInitial:
|
||||
return keyTypeClientInitial
|
||||
case protocol.EncryptionHandshake:
|
||||
return keyTypeClientHandshake
|
||||
case protocol.Encryption0RTT:
|
||||
return keyTypeClient0RTT
|
||||
case protocol.Encryption1RTT:
|
||||
return keyTypeClient1RTT
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (t keyType) String() string {
|
||||
switch t {
|
||||
case keyTypeServerInitial:
|
||||
return "server_initial_secret"
|
||||
case keyTypeClientInitial:
|
||||
return "client_initial_secret"
|
||||
case keyTypeServerHandshake:
|
||||
return "server_handshake_secret"
|
||||
case keyTypeClientHandshake:
|
||||
return "client_handshake_secret"
|
||||
case keyTypeServer0RTT:
|
||||
return "server_0rtt_secret"
|
||||
case keyTypeClient0RTT:
|
||||
return "client_0rtt_secret"
|
||||
case keyTypeServer1RTT:
|
||||
return "server_1rtt_secret"
|
||||
case keyTypeClient1RTT:
|
||||
return "client_1rtt_secret"
|
||||
default:
|
||||
return "unknown key type"
|
||||
}
|
||||
}
|
||||
|
||||
type keyUpdateTrigger uint8
|
||||
|
||||
const (
|
||||
keyUpdateTLS keyUpdateTrigger = iota
|
||||
keyUpdateRemote
|
||||
keyUpdateLocal
|
||||
)
|
||||
|
||||
func (t keyUpdateTrigger) String() string {
|
||||
switch t {
|
||||
case keyUpdateTLS:
|
||||
return "tls"
|
||||
case keyUpdateRemote:
|
||||
return "remote_update"
|
||||
case keyUpdateLocal:
|
||||
return "local_update"
|
||||
default:
|
||||
return "unknown key update trigger"
|
||||
}
|
||||
}
|
||||
|
||||
type transportError uint64
|
||||
|
||||
func (e transportError) String() string {
|
||||
switch qerr.TransportErrorCode(e) {
|
||||
case qerr.NoError:
|
||||
return "no_error"
|
||||
case qerr.InternalError:
|
||||
return "internal_error"
|
||||
case qerr.ConnectionRefused:
|
||||
return "connection_refused"
|
||||
case qerr.FlowControlError:
|
||||
return "flow_control_error"
|
||||
case qerr.StreamLimitError:
|
||||
return "stream_limit_error"
|
||||
case qerr.StreamStateError:
|
||||
return "stream_state_error"
|
||||
case qerr.FinalSizeError:
|
||||
return "final_size_error"
|
||||
case qerr.FrameEncodingError:
|
||||
return "frame_encoding_error"
|
||||
case qerr.TransportParameterError:
|
||||
return "transport_parameter_error"
|
||||
case qerr.ConnectionIDLimitError:
|
||||
return "connection_id_limit_error"
|
||||
case qerr.ProtocolViolation:
|
||||
return "protocol_violation"
|
||||
case qerr.InvalidToken:
|
||||
return "invalid_token"
|
||||
case qerr.ApplicationErrorErrorCode:
|
||||
return "application_error"
|
||||
case qerr.CryptoBufferExceeded:
|
||||
return "crypto_buffer_exceeded"
|
||||
case qerr.KeyUpdateError:
|
||||
return "key_update_error"
|
||||
case qerr.AEADLimitReached:
|
||||
return "aead_limit_reached"
|
||||
case qerr.NoViablePathError:
|
||||
return "no_viable_path"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
type packetType logging.PacketType
|
||||
|
||||
func (t packetType) String() string {
|
||||
switch logging.PacketType(t) {
|
||||
case logging.PacketTypeInitial:
|
||||
return "initial"
|
||||
case logging.PacketTypeHandshake:
|
||||
return "handshake"
|
||||
case logging.PacketTypeRetry:
|
||||
return "retry"
|
||||
case logging.PacketType0RTT:
|
||||
return "0RTT"
|
||||
case logging.PacketTypeVersionNegotiation:
|
||||
return "version_negotiation"
|
||||
case logging.PacketTypeStatelessReset:
|
||||
return "stateless_reset"
|
||||
case logging.PacketType1RTT:
|
||||
return "1RTT"
|
||||
case logging.PacketTypeNotDetermined:
|
||||
return ""
|
||||
default:
|
||||
return "unknown packet type"
|
||||
}
|
||||
}
|
||||
|
||||
type packetLossReason logging.PacketLossReason
|
||||
|
||||
func (r packetLossReason) String() string {
|
||||
switch logging.PacketLossReason(r) {
|
||||
case logging.PacketLossReorderingThreshold:
|
||||
return "reordering_threshold"
|
||||
case logging.PacketLossTimeThreshold:
|
||||
return "time_threshold"
|
||||
default:
|
||||
return "unknown loss reason"
|
||||
}
|
||||
}
|
||||
|
||||
type packetDropReason logging.PacketDropReason
|
||||
|
||||
func (r packetDropReason) String() string {
|
||||
switch logging.PacketDropReason(r) {
|
||||
case logging.PacketDropKeyUnavailable:
|
||||
return "key_unavailable"
|
||||
case logging.PacketDropUnknownConnectionID:
|
||||
return "unknown_connection_id"
|
||||
case logging.PacketDropHeaderParseError:
|
||||
return "header_parse_error"
|
||||
case logging.PacketDropPayloadDecryptError:
|
||||
return "payload_decrypt_error"
|
||||
case logging.PacketDropProtocolViolation:
|
||||
return "protocol_violation"
|
||||
case logging.PacketDropDOSPrevention:
|
||||
return "dos_prevention"
|
||||
case logging.PacketDropUnsupportedVersion:
|
||||
return "unsupported_version"
|
||||
case logging.PacketDropUnexpectedPacket:
|
||||
return "unexpected_packet"
|
||||
case logging.PacketDropUnexpectedSourceConnectionID:
|
||||
return "unexpected_source_connection_id"
|
||||
case logging.PacketDropUnexpectedVersion:
|
||||
return "unexpected_version"
|
||||
case logging.PacketDropDuplicate:
|
||||
return "duplicate"
|
||||
default:
|
||||
return "unknown packet drop reason"
|
||||
}
|
||||
}
|
||||
|
||||
type timerType logging.TimerType
|
||||
|
||||
func (t timerType) String() string {
|
||||
switch logging.TimerType(t) {
|
||||
case logging.TimerTypeACK:
|
||||
return "ack"
|
||||
case logging.TimerTypePTO:
|
||||
return "pto"
|
||||
default:
|
||||
return "unknown timer type"
|
||||
}
|
||||
}
|
||||
|
||||
type congestionState logging.CongestionState
|
||||
|
||||
func (s congestionState) String() string {
|
||||
switch logging.CongestionState(s) {
|
||||
case logging.CongestionStateSlowStart:
|
||||
return "slow_start"
|
||||
case logging.CongestionStateCongestionAvoidance:
|
||||
return "congestion_avoidance"
|
||||
case logging.CongestionStateRecovery:
|
||||
return "recovery"
|
||||
case logging.CongestionStateApplicationLimited:
|
||||
return "application_limited"
|
||||
default:
|
||||
return "unknown congestion state"
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user