upstream: sync to 0.39.1

This commit is contained in:
Gaukas Wang 2023-10-26 22:45:37 -06:00
commit 7c77243b04
No known key found for this signature in database
GPG key ID: 9E2F8986D76F8B5D
147 changed files with 3740 additions and 2211 deletions

View file

@ -2,8 +2,10 @@ package versionnegotiation
import (
"context"
"errors"
"fmt"
"net"
"time"
tls "github.com/refraction-networking/utls"
@ -20,29 +22,29 @@ type versioner interface {
GetVersion() protocol.VersionNumber
}
type versionNegotiationTracer struct {
logging.NullConnectionTracer
type result struct {
loggedVersions bool
receivedVersionNegotiation bool
chosen logging.VersionNumber
clientVersions, serverVersions []logging.VersionNumber
}
var _ logging.ConnectionTracer = &versionNegotiationTracer{}
func (t *versionNegotiationTracer) NegotiatedVersion(chosen logging.VersionNumber, clientVersions, serverVersions []logging.VersionNumber) {
if t.loggedVersions {
Fail("only expected one call to NegotiatedVersions")
func newVersionNegotiationTracer() (*result, *logging.ConnectionTracer) {
r := &result{}
return r, &logging.ConnectionTracer{
NegotiatedVersion: func(chosen logging.VersionNumber, clientVersions, serverVersions []logging.VersionNumber) {
if r.loggedVersions {
Fail("only expected one call to NegotiatedVersions")
}
r.loggedVersions = true
r.chosen = chosen
r.clientVersions = clientVersions
r.serverVersions = serverVersions
},
ReceivedVersionNegotiationPacket: func(dest, src logging.ArbitraryLenConnectionID, _ []logging.VersionNumber) {
r.receivedVersionNegotiation = true
},
}
t.loggedVersions = true
t.chosen = chosen
t.clientVersions = clientVersions
t.serverVersions = serverVersions
}
func (t *versionNegotiationTracer) ReceivedVersionNegotiationPacket(dest, src logging.ArbitraryLenConnectionID, _ []logging.VersionNumber) {
t.receivedVersionNegotiation = true
}
var _ = Describe("Handshake tests", func() {
@ -85,54 +87,54 @@ var _ = Describe("Handshake tests", func() {
// but it supports a bunch of versions that the client doesn't speak
serverConfig := &quic.Config{}
serverConfig.Versions = []protocol.VersionNumber{7, 8, protocol.SupportedVersions[0], 9}
serverTracer := &versionNegotiationTracer{}
serverConfig.Tracer = func(context.Context, logging.Perspective, quic.ConnectionID) logging.ConnectionTracer {
serverResult, serverTracer := newVersionNegotiationTracer()
serverConfig.Tracer = func(context.Context, logging.Perspective, quic.ConnectionID) *logging.ConnectionTracer {
return serverTracer
}
server, cl := startServer(getTLSConfig(), serverConfig)
defer cl()
clientTracer := &versionNegotiationTracer{}
clientResult, clientTracer := newVersionNegotiationTracer()
conn, err := quic.DialAddr(
context.Background(),
fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
getTLSClientConfig(),
maybeAddQLOGTracer(&quic.Config{Tracer: func(ctx context.Context, perspective logging.Perspective, id quic.ConnectionID) logging.ConnectionTracer {
maybeAddQLOGTracer(&quic.Config{Tracer: func(ctx context.Context, perspective logging.Perspective, id quic.ConnectionID) *logging.ConnectionTracer {
return clientTracer
}}),
)
Expect(err).ToNot(HaveOccurred())
Expect(conn.(versioner).GetVersion()).To(Equal(expectedVersion))
Expect(conn.CloseWithError(0, "")).To(Succeed())
Expect(clientTracer.chosen).To(Equal(expectedVersion))
Expect(clientTracer.receivedVersionNegotiation).To(BeFalse())
Expect(clientTracer.clientVersions).To(Equal(protocol.SupportedVersions))
Expect(clientTracer.serverVersions).To(BeEmpty())
Expect(serverTracer.chosen).To(Equal(expectedVersion))
Expect(serverTracer.serverVersions).To(Equal(serverConfig.Versions))
Expect(serverTracer.clientVersions).To(BeEmpty())
Expect(clientResult.chosen).To(Equal(expectedVersion))
Expect(clientResult.receivedVersionNegotiation).To(BeFalse())
Expect(clientResult.clientVersions).To(Equal(protocol.SupportedVersions))
Expect(clientResult.serverVersions).To(BeEmpty())
Expect(serverResult.chosen).To(Equal(expectedVersion))
Expect(serverResult.serverVersions).To(Equal(serverConfig.Versions))
Expect(serverResult.clientVersions).To(BeEmpty())
})
It("when the client supports more versions than the server supports", func() {
expectedVersion := protocol.SupportedVersions[0]
// the server doesn't support the highest supported version, which is the first one the client will try
// The server doesn't support the highest supported version, which is the first one the client will try,
// but it supports a bunch of versions that the client doesn't speak
serverTracer := &versionNegotiationTracer{}
serverResult, serverTracer := newVersionNegotiationTracer()
serverConfig := &quic.Config{}
serverConfig.Versions = supportedVersions
serverConfig.Tracer = func(context.Context, logging.Perspective, quic.ConnectionID) logging.ConnectionTracer {
serverConfig.Tracer = func(context.Context, logging.Perspective, quic.ConnectionID) *logging.ConnectionTracer {
return serverTracer
}
server, cl := startServer(getTLSConfig(), serverConfig)
defer cl()
clientVersions := []protocol.VersionNumber{7, 8, 9, protocol.SupportedVersions[0], 10}
clientTracer := &versionNegotiationTracer{}
clientResult, clientTracer := newVersionNegotiationTracer()
conn, err := quic.DialAddr(
context.Background(),
fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
getTLSClientConfig(),
maybeAddQLOGTracer(&quic.Config{
Versions: clientVersions,
Tracer: func(context.Context, logging.Perspective, quic.ConnectionID) logging.ConnectionTracer {
Tracer: func(context.Context, logging.Perspective, quic.ConnectionID) *logging.ConnectionTracer {
return clientTracer
},
}),
@ -140,13 +142,53 @@ var _ = Describe("Handshake tests", func() {
Expect(err).ToNot(HaveOccurred())
Expect(conn.(versioner).GetVersion()).To(Equal(protocol.SupportedVersions[0]))
Expect(conn.CloseWithError(0, "")).To(Succeed())
Expect(clientTracer.chosen).To(Equal(expectedVersion))
Expect(clientTracer.receivedVersionNegotiation).To(BeTrue())
Expect(clientTracer.clientVersions).To(Equal(clientVersions))
Expect(clientTracer.serverVersions).To(ContainElements(supportedVersions)) // may contain greased versions
Expect(serverTracer.chosen).To(Equal(expectedVersion))
Expect(serverTracer.serverVersions).To(Equal(serverConfig.Versions))
Expect(serverTracer.clientVersions).To(BeEmpty())
Expect(clientResult.chosen).To(Equal(expectedVersion))
Expect(clientResult.receivedVersionNegotiation).To(BeTrue())
Expect(clientResult.clientVersions).To(Equal(clientVersions))
Expect(clientResult.serverVersions).To(ContainElements(supportedVersions)) // may contain greased versions
Expect(serverResult.chosen).To(Equal(expectedVersion))
Expect(serverResult.serverVersions).To(Equal(serverConfig.Versions))
Expect(serverResult.clientVersions).To(BeEmpty())
})
It("fails if the server disables version negotiation", func() {
// The server doesn't support the highest supported version, which is the first one the client will try,
// but it supports a bunch of versions that the client doesn't speak
_, serverTracer := newVersionNegotiationTracer()
serverConfig := &quic.Config{}
serverConfig.Versions = supportedVersions
serverConfig.Tracer = func(context.Context, logging.Perspective, quic.ConnectionID) *logging.ConnectionTracer {
return serverTracer
}
conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)})
Expect(err).ToNot(HaveOccurred())
tr := &quic.Transport{
Conn: conn,
DisableVersionNegotiationPackets: true,
}
ln, err := tr.Listen(getTLSConfig(), serverConfig)
Expect(err).ToNot(HaveOccurred())
defer ln.Close()
clientVersions := []protocol.VersionNumber{7, 8, 9, protocol.SupportedVersions[0], 10}
clientResult, clientTracer := newVersionNegotiationTracer()
_, err = quic.DialAddr(
context.Background(),
fmt.Sprintf("localhost:%d", conn.LocalAddr().(*net.UDPAddr).Port),
getTLSClientConfig(),
maybeAddQLOGTracer(&quic.Config{
Versions: clientVersions,
Tracer: func(context.Context, logging.Perspective, quic.ConnectionID) *logging.ConnectionTracer {
return clientTracer
},
HandshakeIdleTimeout: 100 * time.Millisecond,
}),
)
Expect(err).To(HaveOccurred())
var nerr net.Error
Expect(errors.As(err, &nerr)).To(BeTrue())
Expect(nerr.Timeout()).To(BeTrue())
Expect(clientResult.receivedVersionNegotiation).To(BeFalse())
})
}
})