introduce a logging.CloseReason to log the reason a session was closed

This also allows us to get rid of the ReceivedStatelessReset() method.
This commit is contained in:
Marten Seemann 2020-07-10 14:10:58 +07:00
parent 7d6ce4ea45
commit f93708aca8
8 changed files with 281 additions and 55 deletions

68
logging/close_reason.go Normal file
View file

@ -0,0 +1,68 @@
package logging
// A CloseReason is the reason why a QUIC connection is closed.
// It falls in one of 4 categories:
// 1. The application closed the connection (with an application-specific error code).
// 2. The transport closed the connection with a transport-error code.
// 3. The connection timed out, either during the handshake, or due to an idle timeout.
// 4. A stateless reset was received.
type CloseReason struct {
remote bool
applicationError *ApplicationError
transportError *TransportError
timeout *TimeoutReason
statelessResetToken *[16]byte
}
// NewApplicationCloseReason creates a new CloseReason for an application error.
func NewApplicationCloseReason(errorCode ApplicationError, remote bool) CloseReason {
return CloseReason{remote: remote, applicationError: &errorCode}
}
// NewTransportCloseReason creates a new CloseReason for a transport error.
func NewTransportCloseReason(errorCode TransportError, remote bool) CloseReason {
return CloseReason{remote: remote, transportError: &errorCode}
}
// NewTimeoutCloseReason creates a new CloseReason for a connection timeout.
func NewTimeoutCloseReason(r TimeoutReason) CloseReason {
return CloseReason{timeout: &r}
}
// NewStatelessResetCloseReason creates a new CloseReason for a stateless reset.
func NewStatelessResetCloseReason(token *[16]byte) CloseReason {
return CloseReason{statelessResetToken: token}
}
// ApplicationError gets the application error.
func (r *CloseReason) ApplicationError() (errorCode ApplicationError, remote bool, ok bool) {
if r.applicationError == nil {
return
}
return *r.applicationError, r.remote, true
}
// TransportError gets the transport error.
func (r *CloseReason) TransportError() (errorCode TransportError, remote bool, ok bool) {
if r.transportError == nil {
return
}
return *r.transportError, r.remote, true
}
// Timeout gets the timeout error.
func (r *CloseReason) Timeout() (reason TimeoutReason, ok bool) {
if r.timeout == nil {
return
}
return *r.timeout, true
}
// StatelessReset gets the stateless reset token.
func (r *CloseReason) StatelessReset() (token [16]byte, ok bool) {
if r.statelessResetToken == nil {
return
}
return *r.statelessResetToken, true
}

View file

@ -0,0 +1,70 @@
package logging
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Close Reason", func() {
checkNotApplicationError := func(r CloseReason) {
_, _, ok := r.ApplicationError()
Expect(ok).To(BeFalse())
}
checkNotTransportError := func(r CloseReason) {
_, _, ok := r.TransportError()
Expect(ok).To(BeFalse())
}
checkNotStatelessReset := func(r CloseReason) {
_, ok := r.StatelessReset()
ExpectWithOffset(1, ok).To(BeFalse())
}
checkNotTimeout := func(r CloseReason) {
_, ok := r.Timeout()
ExpectWithOffset(1, ok).To(BeFalse())
}
It("application errors", func() {
r := NewApplicationCloseReason(1337, true)
errorCode, remote, ok := r.ApplicationError()
Expect(ok).To(BeTrue())
Expect(remote).To(BeTrue())
Expect(errorCode).To(Equal(ApplicationError(1337)))
checkNotTransportError(r)
checkNotStatelessReset(r)
checkNotTimeout(r)
})
It("transport errors", func() {
r := NewTransportCloseReason(1337, true)
errorCode, remote, ok := r.TransportError()
Expect(ok).To(BeTrue())
Expect(remote).To(BeTrue())
Expect(errorCode).To(Equal(TransportError(1337)))
checkNotApplicationError(r)
checkNotStatelessReset(r)
checkNotTimeout(r)
})
It("transport errors", func() {
r := NewTimeoutCloseReason(TimeoutReasonIdle)
timeout, ok := r.Timeout()
Expect(ok).To(BeTrue())
Expect(timeout).To(Equal(TimeoutReasonIdle))
checkNotApplicationError(r)
checkNotTransportError(r)
checkNotStatelessReset(r)
})
It("stateless resets", func() {
r := NewStatelessResetCloseReason(&[16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16})
token, ok := r.StatelessReset()
Expect(ok).To(BeTrue())
Expect(token).To(Equal([16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}))
checkNotApplicationError(r)
checkNotTransportError(r)
checkNotTimeout(r)
})
})

View file

@ -84,14 +84,13 @@ type Tracer interface {
// A ConnectionTracer records events.
type ConnectionTracer interface {
StartedConnection(local, remote net.Addr, version VersionNumber, srcConnID, destConnID ConnectionID)
ClosedConnection(TimeoutReason)
ClosedConnection(CloseReason)
SentTransportParameters(*TransportParameters)
ReceivedTransportParameters(*TransportParameters)
SentPacket(hdr *ExtendedHeader, packetSize ByteCount, ack *AckFrame, frames []Frame)
ReceivedVersionNegotiationPacket(*Header, []VersionNumber)
ReceivedRetry(*Header)
ReceivedPacket(hdr *ExtendedHeader, packetSize ByteCount, frames []Frame)
ReceivedStatelessReset(token *[16]byte)
BufferedPacket(PacketType)
DroppedPacket(PacketType, ByteCount, PacketDropReason)
UpdatedMetrics(rttStats *RTTStats, cwnd ByteCount, bytesInFLight ByteCount, packetsInFlight int)