From 475939a77fbb8132e2f11f1334ad46152404f9f2 Mon Sep 17 00:00:00 2001 From: Nuno Diegues Date: Mon, 6 Jun 2022 14:15:35 +0100 Subject: [PATCH] TUN-6191: Update quic-go to v0.27.1 and with custom patch to allow keep alive period to be configurable The idle period is set to 5sec. We now also ping every second since last activity. This makes the quic.Connection less prone to being closed with no network activity, since we send multiple pings per idle period, and thus a single packet loss cannot cause the problem. --- connection/quic.go | 2 +- connection/quic_test.go | 8 +- go.mod | 10 +- go.sum | 17 +- quic/datagram.go | 4 +- quic/datagram_test.go | 2 +- quic/quic_protocol.go | 3 +- quic/safe_stream_test.go | 3 +- supervisor/tunnel.go | 2 +- .../lucas-clemente/quic-go/.golangci.yml | 1 - .../lucas-clemente/quic-go/README.md | 8 +- .../lucas-clemente/quic-go/client.go | 66 ++--- .../{closed_session.go => closed_conn.go} | 48 +-- .../lucas-clemente/quic-go/config.go | 3 +- .../quic-go/{session.go => connection.go} | 277 +++++++++--------- .../lucas-clemente/quic-go/interface.go | 75 ++--- .../flowcontrol/base_flow_controller.go | 7 +- .../flowcontrol/connection_flow_controller.go | 11 +- .../quic-go/internal/protocol/params.go | 16 +- .../quic-go/internal/qtls/go119.go | 2 +- .../quic-go/internal/qtls/go_oldversion.go | 7 + .../lucas-clemente/quic-go/logging/types.go | 8 +- .../lucas-clemente/quic-go/mockgen.go | 4 +- .../lucas-clemente/quic-go/mtu_discoverer.go | 12 +- .../lucas-clemente/quic-go/multiplexer.go | 2 +- .../quic-go/packet_handler_map.go | 81 +++-- .../lucas-clemente/quic-go/send_conn.go | 8 +- .../lucas-clemente/quic-go/send_queue.go | 8 +- .../lucas-clemente/quic-go/server.go | 136 ++++----- .../quic-go/{conn.go => sys_conn.go} | 33 ++- .../lucas-clemente/quic-go/sys_conn_df.go | 16 + .../quic-go/sys_conn_df_linux.go | 41 +++ .../quic-go/sys_conn_df_windows.go | 46 +++ ...er_darwin.go => sys_conn_helper_darwin.go} | 5 +- ..._freebsd.go => sys_conn_helper_freebsd.go} | 3 +- ...lper_linux.go => sys_conn_helper_linux.go} | 5 +- .../{conn_generic.go => sys_conn_no_oob.go} | 4 +- .../quic-go/{conn_oob.go => sys_conn_oob.go} | 2 +- .../{conn_windows.go => sys_conn_windows.go} | 19 +- .../marten-seemann/qtls-go1-16/common.go | 14 - .../marten-seemann/qtls-go1-16/common_js.go | 12 + .../marten-seemann/qtls-go1-16/common_nojs.go | 20 ++ .../qtls-go1-17/cipher_suites.go | 14 - .../marten-seemann/qtls-go1-17/cpu.go | 22 ++ .../marten-seemann/qtls-go1-17/cpu_other.go | 12 + .../qtls-go1-18/cipher_suites.go | 14 - .../marten-seemann/qtls-go1-18/cpu.go | 22 ++ .../marten-seemann/qtls-go1-18/cpu_other.go | 12 + vendor/modules.txt | 10 +- 49 files changed, 671 insertions(+), 486 deletions(-) rename vendor/github.com/lucas-clemente/quic-go/{closed_session.go => closed_conn.go} (51%) rename vendor/github.com/lucas-clemente/quic-go/{session.go => connection.go} (87%) create mode 100644 vendor/github.com/lucas-clemente/quic-go/internal/qtls/go_oldversion.go rename vendor/github.com/lucas-clemente/quic-go/{conn.go => sys_conn.go} (69%) create mode 100644 vendor/github.com/lucas-clemente/quic-go/sys_conn_df.go create mode 100644 vendor/github.com/lucas-clemente/quic-go/sys_conn_df_linux.go create mode 100644 vendor/github.com/lucas-clemente/quic-go/sys_conn_df_windows.go rename vendor/github.com/lucas-clemente/quic-go/{conn_helper_darwin.go => sys_conn_helper_darwin.go} (81%) rename vendor/github.com/lucas-clemente/quic-go/{conn_helper_freebsd.go => sys_conn_helper_freebsd.go} (75%) rename vendor/github.com/lucas-clemente/quic-go/{conn_helper_linux.go => sys_conn_helper_linux.go} (81%) rename vendor/github.com/lucas-clemente/quic-go/{conn_generic.go => sys_conn_no_oob.go} (75%) rename vendor/github.com/lucas-clemente/quic-go/{conn_oob.go => sys_conn_oob.go} (99%) rename vendor/github.com/lucas-clemente/quic-go/{conn_windows.go => sys_conn_windows.go} (56%) create mode 100644 vendor/github.com/marten-seemann/qtls-go1-16/common_js.go create mode 100644 vendor/github.com/marten-seemann/qtls-go1-16/common_nojs.go create mode 100644 vendor/github.com/marten-seemann/qtls-go1-17/cpu.go create mode 100644 vendor/github.com/marten-seemann/qtls-go1-17/cpu_other.go create mode 100644 vendor/github.com/marten-seemann/qtls-go1-18/cpu.go create mode 100644 vendor/github.com/marten-seemann/qtls-go1-18/cpu_other.go diff --git a/connection/quic.go b/connection/quic.go index 4e2f4681..f1524c67 100644 --- a/connection/quic.go +++ b/connection/quic.go @@ -35,7 +35,7 @@ const ( // QUICConnection represents the type that facilitates Proxying via QUIC streams. type QUICConnection struct { - session quic.Session + session quic.Connection logger *zerolog.Logger orchestrator Orchestrator sessionManager datagramsession.Manager diff --git a/connection/quic_test.go b/connection/quic_test.go index 05fd64e2..cbfaf714 100644 --- a/connection/quic_test.go +++ b/connection/quic_test.go @@ -31,7 +31,7 @@ import ( var ( testTLSServerConfig = quicpogs.GenerateTLSConfig() testQUICConfig = &quic.Config{ - KeepAlive: true, + KeepAlivePeriod: 5 * time.Second, EnableDatagrams: true, } ) @@ -502,7 +502,7 @@ func TestServeUDPSession(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) // Establish QUIC connection with edge - edgeQUICSessionChan := make(chan quic.Session) + edgeQUICSessionChan := make(chan quic.Connection) go func() { earlyListener, err := quic.Listen(udpListener, testTLSServerConfig, testQUICConfig) require.NoError(t, err) @@ -522,7 +522,7 @@ func TestServeUDPSession(t *testing.T) { cancel() } -func serveSession(ctx context.Context, qc *QUICConnection, edgeQUICSession quic.Session, closeType closeReason, expectedReason string, t *testing.T) { +func serveSession(ctx context.Context, qc *QUICConnection, edgeQUICSession quic.Connection, closeType closeReason, expectedReason string, t *testing.T) { var ( payload = []byte(t.Name()) ) @@ -583,7 +583,7 @@ const ( closedByTimeout ) -func runRPCServer(ctx context.Context, session quic.Session, sessionRPCServer tunnelpogs.SessionManager, configRPCServer tunnelpogs.ConfigurationManager, t *testing.T) { +func runRPCServer(ctx context.Context, session quic.Connection, sessionRPCServer tunnelpogs.SessionManager, configRPCServer tunnelpogs.ConfigurationManager, t *testing.T) { stream, err := session.AcceptStream(ctx) require.NoError(t, err) diff --git a/go.mod b/go.mod index 93e4945f..1793f367 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/gorilla/websocket v1.4.2 github.com/json-iterator/go v1.1.12 - github.com/lucas-clemente/quic-go v0.24.0 + github.com/lucas-clemente/quic-go v0.27.1 github.com/mattn/go-colorable v0.1.8 github.com/miekg/dns v1.1.45 github.com/mitchellh/go-homedir v1.1.0 @@ -74,9 +74,9 @@ require ( github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/lucasb-eyer/go-colorful v1.0.3 // indirect - github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect - github.com/marten-seemann/qtls-go1-17 v0.1.0 // indirect - github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 // indirect + github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect + github.com/marten-seemann/qtls-go1-17 v0.1.1 // indirect + github.com/marten-seemann/qtls-go1-18 v0.1.1 // indirect github.com/mattn/go-isatty v0.0.12 // indirect github.com/mattn/go-runewidth v0.0.8 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect @@ -105,7 +105,7 @@ require ( replace github.com/urfave/cli/v2 => github.com/ipostelnik/cli/v2 v2.3.1-0.20210324024421-b6ea8234fe3d -replace github.com/lucas-clemente/quic-go => github.com/chungthuang/quic-go v0.24.1-0.20220110095058-981dc498cb62 +replace github.com/lucas-clemente/quic-go => github.com/chungthuang/quic-go v0.27.1-0.20220607112311-13144fbde8da // Avoid 'CVE-2022-21698' replace github.com/prometheus/golang_client => github.com/prometheus/golang_client v1.12.1 diff --git a/go.sum b/go.sum index c0a1e0d5..f6a15c92 100644 --- a/go.sum +++ b/go.sum @@ -111,8 +111,8 @@ github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cb github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= -github.com/chungthuang/quic-go v0.24.1-0.20220110095058-981dc498cb62 h1:PLTB4iA6sOgAItzQY642tYdcGKfG/7i2gu93JQGgUcM= -github.com/chungthuang/quic-go v0.24.1-0.20220110095058-981dc498cb62/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg= +github.com/chungthuang/quic-go v0.27.1-0.20220607112311-13144fbde8da h1:FmuwbQ8RU/ftTKnfz5diawqvQFH1KDB9wN2Q8S2wqds= +github.com/chungthuang/quic-go v0.27.1-0.20220607112311-13144fbde8da/go.mod h1:AzgQoPda7N+3IqMMMkywBKggIFo2KT6pfnlrQ2QieeI= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -405,13 +405,12 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= -github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= -github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco= -github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= -github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= -github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= -github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaIYMoiBsdwTNmNGkwUUM= -github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI= +github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ= +github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= +github.com/marten-seemann/qtls-go1-17 v0.1.1 h1:DQjHPq+aOzUeh9/lixAGunn6rIOQyWChPSI4+hgW7jc= +github.com/marten-seemann/qtls-go1-17 v0.1.1/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s= +github.com/marten-seemann/qtls-go1-18 v0.1.1 h1:qp7p7XXUFL7fpBvSS1sWD+uSqPvzNQK43DH+/qEkj0Y= +github.com/marten-seemann/qtls-go1-18 v0.1.1/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= diff --git a/quic/datagram.go b/quic/datagram.go index e9b305af..d86d524b 100644 --- a/quic/datagram.go +++ b/quic/datagram.go @@ -14,11 +14,11 @@ const ( ) type DatagramMuxer struct { - session quic.Session + session quic.Connection logger *zerolog.Logger } -func NewDatagramMuxer(quicSession quic.Session, logger *zerolog.Logger) (*DatagramMuxer, error) { +func NewDatagramMuxer(quicSession quic.Connection, logger *zerolog.Logger) (*DatagramMuxer, error) { return &DatagramMuxer{ session: quicSession, logger: logger, diff --git a/quic/datagram_test.go b/quic/datagram_test.go index 3f3eef1a..ac32f410 100644 --- a/quic/datagram_test.go +++ b/quic/datagram_test.go @@ -56,7 +56,7 @@ func TestMaxDatagramPayload(t *testing.T) { payload := make([]byte, maxDatagramPayloadSize) quicConfig := &quic.Config{ - KeepAlive: true, + KeepAlivePeriod: 5 * time.Millisecond, EnableDatagrams: true, MaxDatagramFrameSize: MaxDatagramFrameSize, } diff --git a/quic/quic_protocol.go b/quic/quic_protocol.go index 1e0c6eef..776b2eec 100644 --- a/quic/quic_protocol.go +++ b/quic/quic_protocol.go @@ -37,7 +37,8 @@ const ( protocolVersionLength = 2 HandshakeIdleTimeout = 5 * time.Second - MaxIdleTimeout = 15 * time.Second + MaxIdleTimeout = 5 * time.Second + MaxIdlePingPeriod = 1 * time.Second ) // RequestServerStream is a stream to serve requests diff --git a/quic/safe_stream_test.go b/quic/safe_stream_test.go index 48ffb559..b4c096b2 100644 --- a/quic/safe_stream_test.go +++ b/quic/safe_stream_test.go @@ -7,6 +7,7 @@ import ( "net" "sync" "testing" + "time" "github.com/lucas-clemente/quic-go" "github.com/stretchr/testify/require" @@ -15,7 +16,7 @@ import ( var ( testTLSServerConfig = GenerateTLSConfig() testQUICConfig = &quic.Config{ - KeepAlive: true, + KeepAlivePeriod: 5 * time.Second, EnableDatagrams: true, } exchanges = 1000 diff --git a/supervisor/tunnel.go b/supervisor/tunnel.go index 45a1ffba..a75fe7b7 100644 --- a/supervisor/tunnel.go +++ b/supervisor/tunnel.go @@ -550,9 +550,9 @@ func ServeQUIC( quicConfig := &quic.Config{ HandshakeIdleTimeout: quicpogs.HandshakeIdleTimeout, MaxIdleTimeout: quicpogs.MaxIdleTimeout, + KeepAlivePeriod: quicpogs.MaxIdlePingPeriod, MaxIncomingStreams: connection.MaxConcurrentStreams, MaxIncomingUniStreams: connection.MaxConcurrentStreams, - KeepAlive: true, EnableDatagrams: true, MaxDatagramFrameSize: quicpogs.MaxDatagramFrameSize, Tracer: quicpogs.NewClientTracer(connLogger.Logger(), connIndex), diff --git a/vendor/github.com/lucas-clemente/quic-go/.golangci.yml b/vendor/github.com/lucas-clemente/quic-go/.golangci.yml index 05ddb79a..2589c053 100644 --- a/vendor/github.com/lucas-clemente/quic-go/.golangci.yml +++ b/vendor/github.com/lucas-clemente/quic-go/.golangci.yml @@ -28,7 +28,6 @@ linters: - ineffassign - misspell - prealloc - - scopelint - staticcheck - stylecheck - structcheck diff --git a/vendor/github.com/lucas-clemente/quic-go/README.md b/vendor/github.com/lucas-clemente/quic-go/README.md index f047525e..b28062d5 100644 --- a/vendor/github.com/lucas-clemente/quic-go/README.md +++ b/vendor/github.com/lucas-clemente/quic-go/README.md @@ -3,9 +3,6 @@ [![PkgGoDev](https://pkg.go.dev/badge/github.com/lucas-clemente/quic-go)](https://pkg.go.dev/github.com/lucas-clemente/quic-go) -[![Travis Build Status](https://img.shields.io/travis/lucas-clemente/quic-go/master.svg?style=flat-square&label=Travis+build)](https://travis-ci.org/lucas-clemente/quic-go) -[![CircleCI Build Status](https://img.shields.io/circleci/project/github/lucas-clemente/quic-go.svg?style=flat-square&label=CircleCI+build)](https://circleci.com/gh/lucas-clemente/quic-go) -[![Windows Build Status](https://img.shields.io/appveyor/ci/lucas-clemente/quic-go/master.svg?style=flat-square&label=windows+build)](https://ci.appveyor.com/project/lucas-clemente/quic-go/branch/master) [![Code Coverage](https://img.shields.io/codecov/c/github/lucas-clemente/quic-go/master.svg?style=flat-square)](https://codecov.io/gh/lucas-clemente/quic-go/) quic-go is an implementation of the [QUIC protocol, RFC 9000](https://datatracker.ietf.org/doc/html/rfc9000) protocol in Go. @@ -13,7 +10,7 @@ In addition to RFC 9000, it currently implements the [IETF QUIC draft-29](https: ## Guides -*We currently support Go 1.16.x and Go 1.17.x.* +*We currently support Go 1.16.x, Go 1.17.x, and Go 1.18.x.* Running tests: @@ -51,10 +48,11 @@ http.Client{ | [algernon](https://github.com/xyproto/algernon) | Small self-contained pure-Go web server with Lua, Markdown, HTTP/2, QUIC, Redis and PostgreSQL support | ![GitHub Repo stars](https://img.shields.io/github/stars/xyproto/algernon?style=flat-square) | | [caddy](https://github.com/caddyserver/caddy/) | Fast, multi-platform web server with automatic HTTPS | ![GitHub Repo stars](https://img.shields.io/github/stars/caddyserver/caddy?style=flat-square) | | [go-ipfs](https://github.com/ipfs/go-ipfs) | IPFS implementation in go | ![GitHub Repo stars](https://img.shields.io/github/stars/ipfs/go-ipfs?style=flat-square) | -| [nextdns](https://github.com/nextdns/nextdns) | NextDNS CLI client (DoH Proxy) | ![GitHub Repo stars](https://img.shields.io/github/stars/nextdns/nextdns?style=flat-square) | | [syncthing](https://github.com/syncthing/syncthing/) | Open Source Continuous File Synchronization | ![GitHub Repo stars](https://img.shields.io/github/stars/syncthing/syncthing?style=flat-square) | | [traefik](https://github.com/traefik/traefik) | The Cloud Native Application Proxy | ![GitHub Repo stars](https://img.shields.io/github/stars/traefik/traefik?style=flat-square) | | [v2ray-core](https://github.com/v2fly/v2ray-core) | A platform for building proxies to bypass network restrictions | ![GitHub Repo stars](https://img.shields.io/github/stars/v2fly/v2ray-core?style=flat-square) | +| [cloudflared](https://github.com/cloudflare/cloudflared) | A tunneling daemon that proxies traffic from the Cloudflare network to your origins | ![GitHub Repo stars](https://img.shields.io/github/stars/cloudflare/cloudflared?style=flat-square) | +| [OONI Probe](https://github.com/ooni/probe-cli) | The Open Observatory of Network Interference (OONI) aims to empower decentralized efforts in documenting Internet censorship around the world. | ![GitHub Repo stars](https://img.shields.io/github/stars/ooni/probe-cli?style=flat-square) | ## Contributing diff --git a/vendor/github.com/lucas-clemente/quic-go/client.go b/vendor/github.com/lucas-clemente/quic-go/client.go index 9dbe4ac5..c29a1c29 100644 --- a/vendor/github.com/lucas-clemente/quic-go/client.go +++ b/vendor/github.com/lucas-clemente/quic-go/client.go @@ -14,7 +14,7 @@ import ( ) type client struct { - conn sendConn + sconn sendConn // If the client is created with DialAddr, we create a packet conn. // If it is started with Dial, we take a packet conn as a parameter. createdPacketConn bool @@ -35,7 +35,7 @@ type client struct { handshakeChan chan struct{} - session quicSession + conn quicConn tracer logging.ConnectionTracer tracingID uint64 @@ -49,26 +49,26 @@ var ( ) // DialAddr establishes a new QUIC connection to a server. -// It uses a new UDP connection and closes this connection when the QUIC session is closed. +// It uses a new UDP connection and closes this connection when the QUIC connection is closed. // The hostname for SNI is taken from the given address. // The tls.Config.CipherSuites allows setting of TLS 1.3 cipher suites. func DialAddr( addr string, tlsConf *tls.Config, config *Config, -) (Session, error) { +) (Connection, error) { return DialAddrContext(context.Background(), addr, tlsConf, config) } // DialAddrEarly establishes a new 0-RTT QUIC connection to a server. -// It uses a new UDP connection and closes this connection when the QUIC session is closed. +// It uses a new UDP connection and closes this connection when the QUIC connection is closed. // The hostname for SNI is taken from the given address. // The tls.Config.CipherSuites allows setting of TLS 1.3 cipher suites. func DialAddrEarly( addr string, tlsConf *tls.Config, config *Config, -) (EarlySession, error) { +) (EarlyConnection, error) { return DialAddrEarlyContext(context.Background(), addr, tlsConf, config) } @@ -79,13 +79,13 @@ func DialAddrEarlyContext( addr string, tlsConf *tls.Config, config *Config, -) (EarlySession, error) { - sess, err := dialAddrContext(ctx, addr, tlsConf, config, true) +) (EarlyConnection, error) { + conn, err := dialAddrContext(ctx, addr, tlsConf, config, true) if err != nil { return nil, err } - utils.Logger.WithPrefix(utils.DefaultLogger, "client").Debugf("Returning early session") - return sess, nil + utils.Logger.WithPrefix(utils.DefaultLogger, "client").Debugf("Returning early connection") + return conn, nil } // DialAddrContext establishes a new QUIC connection to a server using the provided context. @@ -95,7 +95,7 @@ func DialAddrContext( addr string, tlsConf *tls.Config, config *Config, -) (Session, error) { +) (Connection, error) { return dialAddrContext(ctx, addr, tlsConf, config, false) } @@ -105,7 +105,7 @@ func dialAddrContext( tlsConf *tls.Config, config *Config, use0RTT bool, -) (quicSession, error) { +) (quicConn, error) { udpAddr, err := net.ResolveUDPAddr("udp", addr) if err != nil { return nil, err @@ -131,7 +131,7 @@ func Dial( host string, tlsConf *tls.Config, config *Config, -) (Session, error) { +) (Connection, error) { return dialContext(context.Background(), pconn, remoteAddr, host, tlsConf, config, false, false) } @@ -146,7 +146,7 @@ func DialEarly( host string, tlsConf *tls.Config, config *Config, -) (EarlySession, error) { +) (EarlyConnection, error) { return DialEarlyContext(context.Background(), pconn, remoteAddr, host, tlsConf, config) } @@ -159,7 +159,7 @@ func DialEarlyContext( host string, tlsConf *tls.Config, config *Config, -) (EarlySession, error) { +) (EarlyConnection, error) { return dialContext(ctx, pconn, remoteAddr, host, tlsConf, config, true, false) } @@ -172,7 +172,7 @@ func DialContext( host string, tlsConf *tls.Config, config *Config, -) (Session, error) { +) (Connection, error) { return dialContext(ctx, pconn, remoteAddr, host, tlsConf, config, false, false) } @@ -185,7 +185,7 @@ func dialContext( config *Config, use0RTT bool, createdPacketConn bool, -) (quicSession, error) { +) (quicConn, error) { if tlsConf == nil { return nil, errors.New("quic: tls.Config not set") } @@ -203,21 +203,21 @@ func dialContext( } c.packetHandlers = packetHandlers - c.tracingID = nextSessionTracingID() + c.tracingID = nextConnTracingID() if c.config.Tracer != nil { c.tracer = c.config.Tracer.TracerForConnection( - context.WithValue(ctx, SessionTracingKey, c.tracingID), + context.WithValue(ctx, ConnectionTracingKey, c.tracingID), protocol.PerspectiveClient, c.destConnID, ) } if c.tracer != nil { - c.tracer.StartedConnection(c.conn.LocalAddr(), c.conn.RemoteAddr(), c.srcConnID, c.destConnID) + c.tracer.StartedConnection(c.sconn.LocalAddr(), c.sconn.RemoteAddr(), c.srcConnID, c.destConnID) } if err := c.dial(ctx); err != nil { return nil, err } - return c.session, nil + return c.conn, nil } func newClient( @@ -265,7 +265,7 @@ func newClient( c := &client{ srcConnID: srcConnID, destConnID: destConnID, - conn: newSendPconn(pconn, remoteAddr), + sconn: newSendPconn(pconn, remoteAddr), createdPacketConn: createdPacketConn, use0RTT: use0RTT, tlsConf: tlsConf, @@ -278,10 +278,10 @@ func newClient( } func (c *client) dial(ctx context.Context) error { - c.logger.Infof("Starting new connection to %s (%s -> %s), source connection ID %s, destination connection ID %s, version %s", c.tlsConf.ServerName, c.conn.LocalAddr(), c.conn.RemoteAddr(), c.srcConnID, c.destConnID, c.version) + c.logger.Infof("Starting new connection to %s (%s -> %s), source connection ID %s, destination connection ID %s, version %s", c.tlsConf.ServerName, c.sconn.LocalAddr(), c.sconn.RemoteAddr(), c.srcConnID, c.destConnID, c.version) - c.session = newClientSession( - c.conn, + c.conn = newClientConnection( + c.sconn, c.packetHandlers, c.destConnID, c.srcConnID, @@ -295,11 +295,11 @@ func (c *client) dial(ctx context.Context) error { c.logger, c.version, ) - c.packetHandlers.Add(c.srcConnID, c.session) + c.packetHandlers.Add(c.srcConnID, c.conn) errorChan := make(chan error, 1) go func() { - err := c.session.run() // returns as soon as the session is closed + err := c.conn.run() // returns as soon as the connection is closed if e := (&errCloseForRecreating{}); !errors.As(err, &e) && c.createdPacketConn { c.packetHandlers.Destroy() @@ -308,15 +308,15 @@ func (c *client) dial(ctx context.Context) error { }() // only set when we're using 0-RTT - // Otherwise, earlySessionChan will be nil. Receiving from a nil chan blocks forever. - var earlySessionChan <-chan struct{} + // Otherwise, earlyConnChan will be nil. Receiving from a nil chan blocks forever. + var earlyConnChan <-chan struct{} if c.use0RTT { - earlySessionChan = c.session.earlySessionReady() + earlyConnChan = c.conn.earlyConnReady() } select { case <-ctx.Done(): - c.session.shutdown() + c.conn.shutdown() return ctx.Err() case err := <-errorChan: var recreateErr *errCloseForRecreating @@ -327,10 +327,10 @@ func (c *client) dial(ctx context.Context) error { return c.dial(ctx) } return err - case <-earlySessionChan: + case <-earlyConnChan: // ready to send 0-RTT data return nil - case <-c.session.HandshakeComplete().Done(): + case <-c.conn.HandshakeComplete().Done(): // handshake successfully completed return nil } diff --git a/vendor/github.com/lucas-clemente/quic-go/closed_session.go b/vendor/github.com/lucas-clemente/quic-go/closed_conn.go similarity index 51% rename from vendor/github.com/lucas-clemente/quic-go/closed_session.go rename to vendor/github.com/lucas-clemente/quic-go/closed_conn.go index 31279020..35c2d739 100644 --- a/vendor/github.com/lucas-clemente/quic-go/closed_session.go +++ b/vendor/github.com/lucas-clemente/quic-go/closed_conn.go @@ -7,15 +7,15 @@ import ( "github.com/lucas-clemente/quic-go/internal/utils" ) -// A closedLocalSession is a session that we closed locally. -// When receiving packets for such a session, we need to retransmit the packet containing the CONNECTION_CLOSE frame, +// A closedLocalConn is a connection that we closed locally. +// When receiving packets for such a connection, we need to retransmit the packet containing the CONNECTION_CLOSE frame, // with an exponential backoff. -type closedLocalSession struct { +type closedLocalConn struct { conn sendConn connClosePacket []byte closeOnce sync.Once - closeChan chan struct{} // is closed when the session is closed or destroyed + closeChan chan struct{} // is closed when the connection is closed or destroyed receivedPackets chan *receivedPacket counter uint64 // number of packets received @@ -25,16 +25,16 @@ type closedLocalSession struct { logger utils.Logger } -var _ packetHandler = &closedLocalSession{} +var _ packetHandler = &closedLocalConn{} -// newClosedLocalSession creates a new closedLocalSession and runs it. -func newClosedLocalSession( +// newClosedLocalConn creates a new closedLocalConn and runs it. +func newClosedLocalConn( conn sendConn, connClosePacket []byte, perspective protocol.Perspective, logger utils.Logger, ) packetHandler { - s := &closedLocalSession{ + s := &closedLocalConn{ conn: conn, connClosePacket: connClosePacket, perspective: perspective, @@ -46,7 +46,7 @@ func newClosedLocalSession( return s } -func (s *closedLocalSession) run() { +func (s *closedLocalConn) run() { for { select { case p := <-s.receivedPackets: @@ -57,14 +57,14 @@ func (s *closedLocalSession) run() { } } -func (s *closedLocalSession) handlePacket(p *receivedPacket) { +func (s *closedLocalConn) handlePacket(p *receivedPacket) { select { case s.receivedPackets <- p: default: } } -func (s *closedLocalSession) handlePacketImpl(_ *receivedPacket) { +func (s *closedLocalConn) handlePacketImpl(_ *receivedPacket) { s.counter++ // exponential backoff // only send a CONNECTION_CLOSE for the 1st, 2nd, 4th, 8th, 16th, ... packet arriving @@ -79,34 +79,34 @@ func (s *closedLocalSession) handlePacketImpl(_ *receivedPacket) { } } -func (s *closedLocalSession) shutdown() { +func (s *closedLocalConn) shutdown() { s.destroy(nil) } -func (s *closedLocalSession) destroy(error) { +func (s *closedLocalConn) destroy(error) { s.closeOnce.Do(func() { close(s.closeChan) }) } -func (s *closedLocalSession) getPerspective() protocol.Perspective { +func (s *closedLocalConn) getPerspective() protocol.Perspective { return s.perspective } -// A closedRemoteSession is a session that was closed remotely. -// For such a session, we might receive reordered packets that were sent before the CONNECTION_CLOSE. +// A closedRemoteConn is a connection that was closed remotely. +// For such a connection, we might receive reordered packets that were sent before the CONNECTION_CLOSE. // We can just ignore those packets. -type closedRemoteSession struct { +type closedRemoteConn struct { perspective protocol.Perspective } -var _ packetHandler = &closedRemoteSession{} +var _ packetHandler = &closedRemoteConn{} -func newClosedRemoteSession(pers protocol.Perspective) packetHandler { - return &closedRemoteSession{perspective: pers} +func newClosedRemoteConn(pers protocol.Perspective) packetHandler { + return &closedRemoteConn{perspective: pers} } -func (s *closedRemoteSession) handlePacket(*receivedPacket) {} -func (s *closedRemoteSession) shutdown() {} -func (s *closedRemoteSession) destroy(error) {} -func (s *closedRemoteSession) getPerspective() protocol.Perspective { return s.perspective } +func (s *closedRemoteConn) handlePacket(*receivedPacket) {} +func (s *closedRemoteConn) shutdown() {} +func (s *closedRemoteConn) destroy(error) {} +func (s *closedRemoteConn) getPerspective() protocol.Perspective { return s.perspective } diff --git a/vendor/github.com/lucas-clemente/quic-go/config.go b/vendor/github.com/lucas-clemente/quic-go/config.go index c5f2389e..ef7a2622 100644 --- a/vendor/github.com/lucas-clemente/quic-go/config.go +++ b/vendor/github.com/lucas-clemente/quic-go/config.go @@ -109,11 +109,12 @@ func populateConfig(config *Config) *Config { HandshakeIdleTimeout: handshakeIdleTimeout, MaxIdleTimeout: idleTimeout, AcceptToken: config.AcceptToken, - KeepAlive: config.KeepAlive, + KeepAlivePeriod: config.KeepAlivePeriod, InitialStreamReceiveWindow: initialStreamReceiveWindow, MaxStreamReceiveWindow: maxStreamReceiveWindow, InitialConnectionReceiveWindow: initialConnectionReceiveWindow, MaxConnectionReceiveWindow: maxConnectionReceiveWindow, + AllowConnectionWindowIncrease: config.AllowConnectionWindowIncrease, MaxIncomingStreams: maxIncomingStreams, MaxIncomingUniStreams: maxIncomingUniStreams, ConnectionIDLength: config.ConnectionIDLength, diff --git a/vendor/github.com/lucas-clemente/quic-go/session.go b/vendor/github.com/lucas-clemente/quic-go/connection.go similarity index 87% rename from vendor/github.com/lucas-clemente/quic-go/session.go rename to vendor/github.com/lucas-clemente/quic-go/connection.go index 6231383b..2f17565a 100644 --- a/vendor/github.com/lucas-clemente/quic-go/session.go +++ b/vendor/github.com/lucas-clemente/quic-go/connection.go @@ -90,7 +90,7 @@ func (p *receivedPacket) Clone() *receivedPacket { } } -type sessionRunner interface { +type connRunner interface { Add(protocol.ConnectionID, packetHandler) bool GetStatelessResetToken(protocol.ConnectionID) protocol.StatelessResetToken Retire(protocol.ConnectionID) @@ -124,18 +124,14 @@ type errCloseForRecreating struct { } func (e *errCloseForRecreating) Error() string { - return "closing session in order to recreate it" + return "closing connection in order to recreate it" } -var sessionTracingID uint64 // to be accessed atomically -func nextSessionTracingID() uint64 { return atomic.AddUint64(&sessionTracingID, 1) } +var connTracingID uint64 // to be accessed atomically +func nextConnTracingID() uint64 { return atomic.AddUint64(&connTracingID, 1) } -func pathMTUDiscoveryEnabled(config *Config) bool { - return !disablePathMTUDiscovery && !config.DisablePathMTUDiscovery -} - -// A Session is a QUIC session -type session struct { +// A Connection is a QUIC connection +type connection struct { // Destination connection ID used during the handshake. // Used to check source connection ID on incoming packets. handshakeDestConnID protocol.ConnectionID @@ -192,7 +188,7 @@ type session struct { undecryptablePacketsToProcess []*receivedPacket clientHelloWritten <-chan *wire.TransportParameters - earlySessionReadyChan chan struct{} + earlyConnReadyChan chan struct{} handshakeCompleteChan chan struct{} // is closed when the handshake completes handshakeComplete bool handshakeConfirmed bool @@ -201,8 +197,8 @@ type session struct { versionNegotiated bool receivedFirstPacket bool - idleTimeout time.Duration - sessionCreationTime time.Time + idleTimeout time.Duration + creationTime time.Time // The idle timeout is set based on the max of the time we received the last packet... lastPacketReceivedTime time.Time // ... and the time we sent a new ack-eliciting packet after receiving a packet. @@ -226,15 +222,15 @@ type session struct { } var ( - _ Session = &session{} - _ EarlySession = &session{} - _ streamSender = &session{} - deadlineSendImmediately = time.Time{}.Add(42 * time.Millisecond) // any value > time.Time{} and before time.Now() is fine + _ Connection = &connection{} + _ EarlyConnection = &connection{} + _ streamSender = &connection{} + deadlineSendImmediately = time.Time{}.Add(42 * time.Millisecond) // any value > time.Time{} and before time.Now() is fine ) -var newSession = func( +var newConnection = func( conn sendConn, - runner sessionRunner, + runner connRunner, origDestConnID protocol.ConnectionID, retrySrcConnID *protocol.ConnectionID, clientDestConnID protocol.ConnectionID, @@ -249,8 +245,8 @@ var newSession = func( tracingID uint64, logger utils.Logger, v protocol.VersionNumber, -) quicSession { - s := &session{ +) quicConn { + s := &connection{ conn: conn, config: conf, handshakeDestConnID: destConnID, @@ -286,7 +282,7 @@ var newSession = func( s.version, ) s.preSetup() - s.ctx, s.ctxCancel = context.WithCancel(context.WithValue(context.Background(), SessionTracingKey, tracingID)) + s.ctx, s.ctxCancel = context.WithCancel(context.WithValue(context.Background(), ConnectionTracingKey, tracingID)) s.sentPacketHandler, s.receivedPacketHandler = ackhandler.NewAckHandler( 0, getMaxPacketSize(s.conn.RemoteAddr()), @@ -369,9 +365,9 @@ var newSession = func( } // declare this as a variable, such that we can it mock it in the tests -var newClientSession = func( +var newClientConnection = func( conn sendConn, - runner sessionRunner, + runner connRunner, destConnID protocol.ConnectionID, srcConnID protocol.ConnectionID, conf *Config, @@ -383,8 +379,8 @@ var newClientSession = func( tracingID uint64, logger utils.Logger, v protocol.VersionNumber, -) quicSession { - s := &session{ +) quicConn { + s := &connection{ conn: conn, config: conf, origDestConnID: destConnID, @@ -416,7 +412,7 @@ var newClientSession = func( s.version, ) s.preSetup() - s.ctx, s.ctxCancel = context.WithCancel(context.WithValue(context.Background(), SessionTracingKey, tracingID)) + s.ctx, s.ctxCancel = context.WithCancel(context.WithValue(context.Background(), ConnectionTracingKey, tracingID)) s.sentPacketHandler, s.receivedPacketHandler = ackhandler.NewAckHandler( initialPacketNumber, getMaxPacketSize(s.conn.RemoteAddr()), @@ -500,7 +496,7 @@ var newClientSession = func( return s } -func (s *session) preSetup() { +func (s *connection) preSetup() { s.sendQueue = newSendQueue(s.conn) s.retransmissionQueue = newRetransmissionQueue(s.version) s.frameParser = wire.NewFrameParser(s.config.EnableDatagrams, s.version) @@ -509,10 +505,16 @@ func (s *session) preSetup() { protocol.ByteCount(s.config.InitialConnectionReceiveWindow), protocol.ByteCount(s.config.MaxConnectionReceiveWindow), s.onHasConnectionWindowUpdate, + func(size protocol.ByteCount) bool { + if s.config.AllowConnectionWindowIncrease == nil { + return true + } + return s.config.AllowConnectionWindowIncrease(s, uint64(size)) + }, s.rttStats, s.logger, ) - s.earlySessionReadyChan = make(chan struct{}) + s.earlyConnReadyChan = make(chan struct{}) s.streamsMap = newStreamsMap( s, s.newFlowController, @@ -522,14 +524,14 @@ func (s *session) preSetup() { s.version, ) s.framer = newFramer(s.streamsMap, s.version) - s.receivedPackets = make(chan *receivedPacket, protocol.MaxSessionUnprocessedPackets) + s.receivedPackets = make(chan *receivedPacket, protocol.MaxConnUnprocessedPackets) s.closeChan = make(chan closeError, 1) s.sendingScheduled = make(chan struct{}, 1) s.handshakeCtx, s.handshakeCtxCancel = context.WithCancel(context.Background()) now := time.Now() s.lastPacketReceivedTime = now - s.sessionCreationTime = now + s.creationTime = now s.windowUpdateQueue = newWindowUpdateQueue(s.streamsMap, s.connFlowController, s.framer.QueueControlFrame) if s.config.EnableDatagrams { @@ -537,8 +539,8 @@ func (s *session) preSetup() { } } -// run the session main loop -func (s *session) run() error { +// run the connection main loop +func (s *connection) run() error { defer s.ctxCancel() s.timer = utils.NewTimer() @@ -556,7 +558,7 @@ func (s *session) run() error { s.scheduleSending() if zeroRTTParams != nil { s.restoreTransportParameters(zeroRTTParams) - close(s.earlySessionReadyChan) + close(s.earlyConnReadyChan) } case closeErr := <-s.closeChan: // put the close error back into the channel, so that the run loop can receive it @@ -590,7 +592,7 @@ runLoop: if processed := s.handlePacketImpl(p); processed { processedUndecryptablePacket = true } - // Don't set timers and send packets if the packet made us close the session. + // Don't set timers and send packets if the packet made us close the connection. select { case closeErr = <-s.closeChan: break runLoop @@ -613,7 +615,7 @@ runLoop: case <-sendQueueAvailable: case firstPacket := <-s.receivedPackets: wasProcessed := s.handlePacketImpl(firstPacket) - // Don't set timers and send packets if the packet made us close the session. + // Don't set timers and send packets if the packet made us close the connection. select { case closeErr = <-s.closeChan: break runLoop @@ -662,11 +664,11 @@ runLoop: } if keepAliveTime := s.nextKeepAliveTime(); !keepAliveTime.IsZero() && !now.Before(keepAliveTime) { - // send a PING frame since there is no activity in the session + // send a PING frame since there is no activity in the connection s.logger.Debugf("Sending a keep-alive PING to keep the connection alive.") s.framer.QueueControlFrame(&wire.PingFrame{}) s.keepAlivePingSent = true - } else if !s.handshakeComplete && now.Sub(s.sessionCreationTime) >= s.config.handshakeTimeout() { + } else if !s.handshakeComplete && now.Sub(s.creationTime) >= s.config.handshakeTimeout() { s.destroyImpl(qerr.ErrHandshakeTimeout) continue } else { @@ -705,24 +707,24 @@ runLoop: return closeErr.err } -// blocks until the early session can be used -func (s *session) earlySessionReady() <-chan struct{} { - return s.earlySessionReadyChan +// blocks until the early connection can be used +func (s *connection) earlyConnReady() <-chan struct{} { + return s.earlyConnReadyChan } -func (s *session) HandshakeComplete() context.Context { +func (s *connection) HandshakeComplete() context.Context { return s.handshakeCtx } -func (s *session) Context() context.Context { +func (s *connection) Context() context.Context { return s.ctx } -func (s *session) supportsDatagrams() bool { +func (s *connection) supportsDatagrams() bool { return s.peerParams.MaxDatagramFrameSize != protocol.InvalidByteCount } -func (s *session) ConnectionState() ConnectionState { +func (s *connection) ConnectionState() ConnectionState { return ConnectionState{ TLS: s.cryptoStreamHandler.ConnectionState(), SupportsDatagrams: s.supportsDatagrams(), @@ -731,18 +733,18 @@ func (s *session) ConnectionState() ConnectionState { // Time when the next keep-alive packet should be sent. // It returns a zero time if no keep-alive should be sent. -func (s *session) nextKeepAliveTime() time.Time { - if !s.config.KeepAlive || s.keepAlivePingSent || !s.firstAckElicitingPacketAfterIdleSentTime.IsZero() { +func (s *connection) nextKeepAliveTime() time.Time { + if s.config.KeepAlivePeriod == 0 || s.keepAlivePingSent || !s.firstAckElicitingPacketAfterIdleSentTime.IsZero() { return time.Time{} } return s.lastPacketReceivedTime.Add(s.keepAliveInterval) } -func (s *session) maybeResetTimer() { +func (s *connection) maybeResetTimer() { var deadline time.Time if !s.handshakeComplete { deadline = utils.MinTime( - s.sessionCreationTime.Add(s.config.handshakeTimeout()), + s.creationTime.Add(s.config.handshakeTimeout()), s.idleTimeoutStartTime().Add(s.config.HandshakeIdleTimeout), ) } else { @@ -752,11 +754,6 @@ func (s *session) maybeResetTimer() { deadline = s.idleTimeoutStartTime().Add(s.idleTimeout) } } - if s.handshakeConfirmed && pathMTUDiscoveryEnabled(s.config) { - if probeTime := s.mtuDiscoverer.NextProbeTime(); !probeTime.IsZero() { - deadline = utils.MinTime(deadline, probeTime) - } - } if ackAlarm := s.receivedPacketHandler.GetAlarmTimeout(); !ackAlarm.IsZero() { deadline = utils.MinTime(deadline, ackAlarm) @@ -771,11 +768,11 @@ func (s *session) maybeResetTimer() { s.timer.Reset(deadline) } -func (s *session) idleTimeoutStartTime() time.Time { +func (s *connection) idleTimeoutStartTime() time.Time { return utils.MaxTime(s.lastPacketReceivedTime, s.firstAckElicitingPacketAfterIdleSentTime) } -func (s *session) handleHandshakeComplete() { +func (s *connection) handleHandshakeComplete() { s.handshakeComplete = true s.handshakeCompleteChan = nil // prevent this case from ever being selected again defer s.handshakeCtxCancel() @@ -811,12 +808,12 @@ func (s *session) handleHandshakeComplete() { s.queueControlFrame(&wire.HandshakeDoneFrame{}) } -func (s *session) handleHandshakeConfirmed() { +func (s *connection) handleHandshakeConfirmed() { s.handshakeConfirmed = true s.sentPacketHandler.SetHandshakeConfirmed() s.cryptoStreamHandler.SetHandshakeConfirmed() - if pathMTUDiscoveryEnabled(s.config) { + if !s.config.DisablePathMTUDiscovery { maxPacketSize := s.peerParams.MaxUDPPayloadSize if maxPacketSize == 0 { maxPacketSize = protocol.MaxByteCount @@ -834,7 +831,7 @@ func (s *session) handleHandshakeConfirmed() { } } -func (s *session) handlePacketImpl(rp *receivedPacket) bool { +func (s *connection) handlePacketImpl(rp *receivedPacket) bool { s.sentPacketHandler.ReceivedBytes(rp.Size()) if wire.IsVersionNegotiationPacket(rp.data) { @@ -902,7 +899,7 @@ func (s *session) handlePacketImpl(rp *receivedPacket) bool { return processed } -func (s *session) handleSinglePacket(p *receivedPacket, hdr *wire.Header) bool /* was the packet successfully processed */ { +func (s *connection) handleSinglePacket(p *receivedPacket, hdr *wire.Header) bool /* was the packet successfully processed */ { var wasQueued bool defer func() { @@ -994,7 +991,7 @@ func (s *session) handleSinglePacket(p *receivedPacket, hdr *wire.Header) bool / return true } -func (s *session) handleRetryPacket(hdr *wire.Header, data []byte) bool /* was this a valid Retry */ { +func (s *connection) handleRetryPacket(hdr *wire.Header, data []byte) bool /* was this a valid Retry */ { if s.perspective == protocol.PerspectiveServer { if s.tracer != nil { s.tracer.DroppedPacket(logging.PacketTypeRetry, protocol.ByteCount(len(data)), logging.PacketDropUnexpectedPacket) @@ -1056,7 +1053,7 @@ func (s *session) handleRetryPacket(hdr *wire.Header, data []byte) bool /* was t return true } -func (s *session) handleVersionNegotiationPacket(p *receivedPacket) { +func (s *connection) handleVersionNegotiationPacket(p *receivedPacket) { if s.perspective == protocol.PerspectiveServer || // servers never receive version negotiation packets s.receivedFirstPacket || s.versionNegotiated { // ignore delayed / duplicated version negotiation packets if s.tracer != nil { @@ -1110,7 +1107,7 @@ func (s *session) handleVersionNegotiationPacket(p *receivedPacket) { }) } -func (s *session) handleUnpackedPacket( +func (s *connection) handleUnpackedPacket( packet *unpackedPacket, ecn protocol.ECN, rcvTime time.Time, @@ -1142,10 +1139,10 @@ func (s *session) handleUnpackedPacket( s.handshakeDestConnID = cid s.connIDManager.ChangeInitialConnID(cid) } - // We create the session as soon as we receive the first packet from the client. + // We create the connection as soon as we receive the first packet from the client. // We do that before authenticating the packet. // That means that if the source connection ID was corrupted, - // we might have create a session with an incorrect source connection ID. + // we might have create a connection with an incorrect source connection ID. // Once we authenticate the first packet, we need to update it. if s.perspective == protocol.PerspectiveServer { if !packet.hdr.SrcConnectionID.Equal(s.handshakeDestConnID) { @@ -1210,7 +1207,7 @@ func (s *session) handleUnpackedPacket( return s.receivedPacketHandler.ReceivedPacket(packet.packetNumber, ecn, packet.encryptionLevel, rcvTime, isAckEliciting) } -func (s *session) handleFrame(f wire.Frame, encLevel protocol.EncryptionLevel, destConnID protocol.ConnectionID) error { +func (s *connection) handleFrame(f wire.Frame, encLevel protocol.EncryptionLevel, destConnID protocol.ConnectionID) error { var err error wire.LogFrame(s.logger, f, false) switch frame := f.(type) { @@ -1258,9 +1255,9 @@ func (s *session) handleFrame(f wire.Frame, encLevel protocol.EncryptionLevel, d } // handlePacket is called by the server with a new packet -func (s *session) handlePacket(p *receivedPacket) { +func (s *connection) handlePacket(p *receivedPacket) { // Discard packets once the amount of queued packets is larger than - // the channel size, protocol.MaxSessionUnprocessedPackets + // the channel size, protocol.MaxConnUnprocessedPackets select { case s.receivedPackets <- p: default: @@ -1270,7 +1267,7 @@ func (s *session) handlePacket(p *receivedPacket) { } } -func (s *session) handleConnectionCloseFrame(frame *wire.ConnectionCloseFrame) { +func (s *connection) handleConnectionCloseFrame(frame *wire.ConnectionCloseFrame) { if frame.IsApplicationError { s.closeRemote(&qerr.ApplicationError{ Remote: true, @@ -1287,7 +1284,7 @@ func (s *session) handleConnectionCloseFrame(frame *wire.ConnectionCloseFrame) { }) } -func (s *session) handleCryptoFrame(frame *wire.CryptoFrame, encLevel protocol.EncryptionLevel) error { +func (s *connection) handleCryptoFrame(frame *wire.CryptoFrame, encLevel protocol.EncryptionLevel) error { encLevelChanged, err := s.cryptoStreamManager.HandleCryptoFrame(frame, encLevel) if err != nil { return err @@ -1300,7 +1297,7 @@ func (s *session) handleCryptoFrame(frame *wire.CryptoFrame, encLevel protocol.E return nil } -func (s *session) handleStreamFrame(frame *wire.StreamFrame) error { +func (s *connection) handleStreamFrame(frame *wire.StreamFrame) error { str, err := s.streamsMap.GetOrOpenReceiveStream(frame.StreamID) if err != nil { return err @@ -1313,11 +1310,11 @@ func (s *session) handleStreamFrame(frame *wire.StreamFrame) error { return str.handleStreamFrame(frame) } -func (s *session) handleMaxDataFrame(frame *wire.MaxDataFrame) { +func (s *connection) handleMaxDataFrame(frame *wire.MaxDataFrame) { s.connFlowController.UpdateSendWindow(frame.MaximumData) } -func (s *session) handleMaxStreamDataFrame(frame *wire.MaxStreamDataFrame) error { +func (s *connection) handleMaxStreamDataFrame(frame *wire.MaxStreamDataFrame) error { str, err := s.streamsMap.GetOrOpenSendStream(frame.StreamID) if err != nil { return err @@ -1330,11 +1327,11 @@ func (s *session) handleMaxStreamDataFrame(frame *wire.MaxStreamDataFrame) error return nil } -func (s *session) handleMaxStreamsFrame(frame *wire.MaxStreamsFrame) { +func (s *connection) handleMaxStreamsFrame(frame *wire.MaxStreamsFrame) { s.streamsMap.HandleMaxStreamsFrame(frame) } -func (s *session) handleResetStreamFrame(frame *wire.ResetStreamFrame) error { +func (s *connection) handleResetStreamFrame(frame *wire.ResetStreamFrame) error { str, err := s.streamsMap.GetOrOpenReceiveStream(frame.StreamID) if err != nil { return err @@ -1346,7 +1343,7 @@ func (s *session) handleResetStreamFrame(frame *wire.ResetStreamFrame) error { return str.handleResetStreamFrame(frame) } -func (s *session) handleStopSendingFrame(frame *wire.StopSendingFrame) error { +func (s *connection) handleStopSendingFrame(frame *wire.StopSendingFrame) error { str, err := s.streamsMap.GetOrOpenSendStream(frame.StreamID) if err != nil { return err @@ -1359,11 +1356,11 @@ func (s *session) handleStopSendingFrame(frame *wire.StopSendingFrame) error { return nil } -func (s *session) handlePathChallengeFrame(frame *wire.PathChallengeFrame) { +func (s *connection) handlePathChallengeFrame(frame *wire.PathChallengeFrame) { s.queueControlFrame(&wire.PathResponseFrame{Data: frame.Data}) } -func (s *session) handleNewTokenFrame(frame *wire.NewTokenFrame) error { +func (s *connection) handleNewTokenFrame(frame *wire.NewTokenFrame) error { if s.perspective == protocol.PerspectiveServer { return &qerr.TransportError{ ErrorCode: qerr.ProtocolViolation, @@ -1376,15 +1373,15 @@ func (s *session) handleNewTokenFrame(frame *wire.NewTokenFrame) error { return nil } -func (s *session) handleNewConnectionIDFrame(f *wire.NewConnectionIDFrame) error { +func (s *connection) handleNewConnectionIDFrame(f *wire.NewConnectionIDFrame) error { return s.connIDManager.Add(f) } -func (s *session) handleRetireConnectionIDFrame(f *wire.RetireConnectionIDFrame, destConnID protocol.ConnectionID) error { +func (s *connection) handleRetireConnectionIDFrame(f *wire.RetireConnectionIDFrame, destConnID protocol.ConnectionID) error { return s.connIDGenerator.Retire(f.SequenceNumber, destConnID) } -func (s *session) handleHandshakeDoneFrame() error { +func (s *connection) handleHandshakeDoneFrame() error { if s.perspective == protocol.PerspectiveServer { return &qerr.TransportError{ ErrorCode: qerr.ProtocolViolation, @@ -1397,7 +1394,7 @@ func (s *session) handleHandshakeDoneFrame() error { return nil } -func (s *session) handleAckFrame(frame *wire.AckFrame, encLevel protocol.EncryptionLevel) error { +func (s *connection) handleAckFrame(frame *wire.AckFrame, encLevel protocol.EncryptionLevel) error { acked1RTTPacket, err := s.sentPacketHandler.ReceivedAck(frame, encLevel, s.lastPacketReceivedTime) if err != nil { return err @@ -1411,7 +1408,7 @@ func (s *session) handleAckFrame(frame *wire.AckFrame, encLevel protocol.Encrypt return s.cryptoStreamHandler.SetLargest1RTTAcked(frame.LargestAcked()) } -func (s *session) handleDatagramFrame(f *wire.DatagramFrame) error { +func (s *connection) handleDatagramFrame(f *wire.DatagramFrame) error { if f.Length(s.version) > protocol.ByteCount(s.config.MaxDatagramFrameSize) { return &qerr.TransportError{ ErrorCode: qerr.ProtocolViolation, @@ -1422,50 +1419,50 @@ func (s *session) handleDatagramFrame(f *wire.DatagramFrame) error { return nil } -// closeLocal closes the session and send a CONNECTION_CLOSE containing the error -func (s *session) closeLocal(e error) { +// closeLocal closes the connection and send a CONNECTION_CLOSE containing the error +func (s *connection) closeLocal(e error) { s.closeOnce.Do(func() { if e == nil { - s.logger.Infof("Closing session.") + s.logger.Infof("Closing connection.") } else { - s.logger.Errorf("Closing session with error: %s", e) + s.logger.Errorf("Closing connection with error: %s", e) } s.closeChan <- closeError{err: e, immediate: false, remote: false} }) } -// destroy closes the session without sending the error on the wire -func (s *session) destroy(e error) { +// destroy closes the connection without sending the error on the wire +func (s *connection) destroy(e error) { s.destroyImpl(e) <-s.ctx.Done() } -func (s *session) destroyImpl(e error) { +func (s *connection) destroyImpl(e error) { s.closeOnce.Do(func() { if nerr, ok := e.(net.Error); ok && nerr.Timeout() { - s.logger.Errorf("Destroying session: %s", e) + s.logger.Errorf("Destroying connection: %s", e) } else { - s.logger.Errorf("Destroying session with error: %s", e) + s.logger.Errorf("Destroying connection with error: %s", e) } s.closeChan <- closeError{err: e, immediate: true, remote: false} }) } -func (s *session) closeRemote(e error) { +func (s *connection) closeRemote(e error) { s.closeOnce.Do(func() { - s.logger.Errorf("Peer closed session with error: %s", e) + s.logger.Errorf("Peer closed connection with error: %s", e) s.closeChan <- closeError{err: e, immediate: true, remote: true} }) } // Close the connection. It sends a NO_ERROR application error. // It waits until the run loop has stopped before returning -func (s *session) shutdown() { +func (s *connection) shutdown() { s.closeLocal(nil) <-s.ctx.Done() } -func (s *session) CloseWithError(code ApplicationErrorCode, desc string) error { +func (s *connection) CloseWithError(code ApplicationErrorCode, desc string) error { s.closeLocal(&qerr.ApplicationError{ ErrorCode: code, ErrorMessage: desc, @@ -1474,7 +1471,7 @@ func (s *session) CloseWithError(code ApplicationErrorCode, desc string) error { return nil } -func (s *session) handleCloseError(closeErr *closeError) { +func (s *connection) handleCloseError(closeErr *closeError) { e := closeErr.err if e == nil { e = &qerr.ApplicationError{} @@ -1518,7 +1515,7 @@ func (s *session) handleCloseError(closeErr *closeError) { // If this is a remote close we're done here if closeErr.remote { - s.connIDGenerator.ReplaceWithClosed(newClosedRemoteSession(s.perspective)) + s.connIDGenerator.ReplaceWithClosed(newClosedRemoteConn(s.perspective)) return } if closeErr.immediate { @@ -1529,11 +1526,11 @@ func (s *session) handleCloseError(closeErr *closeError) { if err != nil { s.logger.Debugf("Error sending CONNECTION_CLOSE: %s", err) } - cs := newClosedLocalSession(s.conn, connClosePacket, s.perspective, s.logger) + cs := newClosedLocalConn(s.conn, connClosePacket, s.perspective, s.logger) s.connIDGenerator.ReplaceWithClosed(cs) } -func (s *session) dropEncryptionLevel(encLevel protocol.EncryptionLevel) { +func (s *connection) dropEncryptionLevel(encLevel protocol.EncryptionLevel) { s.sentPacketHandler.DropPackets(encLevel) s.receivedPacketHandler.DropPackets(encLevel) if s.tracer != nil { @@ -1551,7 +1548,7 @@ func (s *session) dropEncryptionLevel(encLevel protocol.EncryptionLevel) { } // is called for the client, when restoring transport parameters saved for 0-RTT -func (s *session) restoreTransportParameters(params *wire.TransportParameters) { +func (s *connection) restoreTransportParameters(params *wire.TransportParameters) { if s.logger.Debug() { s.logger.Debugf("Restoring Transport Parameters: %s", params) } @@ -1562,7 +1559,7 @@ func (s *session) restoreTransportParameters(params *wire.TransportParameters) { s.streamsMap.UpdateLimits(params) } -func (s *session) handleTransportParameters(params *wire.TransportParameters) { +func (s *connection) handleTransportParameters(params *wire.TransportParameters) { if err := s.checkTransportParameters(params); err != nil { s.closeLocal(&qerr.TransportError{ ErrorCode: qerr.TransportParameterError, @@ -1574,13 +1571,13 @@ func (s *session) handleTransportParameters(params *wire.TransportParameters) { // During a 0-RTT connection, we are only allowed to use the new transport parameters for 1-RTT packets. if s.perspective == protocol.PerspectiveServer { s.applyTransportParameters() - // On the server side, the early session is ready as soon as we processed + // On the server side, the early connection is ready as soon as we processed // the client's transport parameters. - close(s.earlySessionReadyChan) + close(s.earlyConnReadyChan) } } -func (s *session) checkTransportParameters(params *wire.TransportParameters) error { +func (s *connection) checkTransportParameters(params *wire.TransportParameters) error { if s.logger.Debug() { s.logger.Debugf("Processed Transport Parameters: %s", params) } @@ -1613,11 +1610,11 @@ func (s *session) checkTransportParameters(params *wire.TransportParameters) err return nil } -func (s *session) applyTransportParameters() { +func (s *connection) applyTransportParameters() { params := s.peerParams // Our local idle timeout will always be > 0. s.idleTimeout = utils.MinNonZeroDuration(s.config.MaxIdleTimeout, params.MaxIdleTimeout) - s.keepAliveInterval = utils.MinDuration(s.idleTimeout/2, protocol.MaxKeepAliveInterval) + s.keepAliveInterval = utils.MinDuration(s.config.KeepAlivePeriod, utils.MinDuration(s.idleTimeout/2, protocol.MaxKeepAliveInterval)) s.streamsMap.UpdateLimits(params) s.packer.HandleTransportParameters(params) s.frameParser.SetAckDelayExponent(params.AckDelayExponent) @@ -1634,7 +1631,7 @@ func (s *session) applyTransportParameters() { } } -func (s *session) sendPackets() error { +func (s *connection) sendPackets() error { s.pacingDeadline = time.Time{} var sentPacket bool // only used in for packets sent in send mode SendAny @@ -1700,7 +1697,7 @@ func (s *session) sendPackets() error { } } -func (s *session) maybeSendAckOnlyPacket() error { +func (s *connection) maybeSendAckOnlyPacket() error { packet, err := s.packer.MaybePackAckPacket(s.handshakeConfirmed) if err != nil { return err @@ -1712,7 +1709,7 @@ func (s *session) maybeSendAckOnlyPacket() error { return nil } -func (s *session) sendProbePacket(encLevel protocol.EncryptionLevel) error { +func (s *connection) sendProbePacket(encLevel protocol.EncryptionLevel) error { // Queue probe packets until we actually send out a packet, // or until there are no more packets to queue. var packet *packedPacket @@ -1748,13 +1745,13 @@ func (s *session) sendProbePacket(encLevel protocol.EncryptionLevel) error { } } if packet == nil || packet.packetContents == nil { - return fmt.Errorf("session BUG: couldn't pack %s probe packet", encLevel) + return fmt.Errorf("connection BUG: couldn't pack %s probe packet", encLevel) } s.sendPackedPacket(packet, time.Now()) return nil } -func (s *session) sendPacket() (bool, error) { +func (s *connection) sendPacket() (bool, error) { if isBlocked, offset := s.connFlowController.IsNewlyBlocked(); isBlocked { s.framer.QueueControlFrame(&wire.DataBlockedFrame{MaximumData: offset}) } @@ -1777,7 +1774,7 @@ func (s *session) sendPacket() (bool, error) { s.sendQueue.Send(packet.buffer) return true, nil } - if pathMTUDiscoveryEnabled(s.config) && s.mtuDiscoverer.ShouldSendProbe(now) { + if !s.config.DisablePathMTUDiscovery && s.mtuDiscoverer.ShouldSendProbe(now) { packet, err := s.packer.PackMTUProbePacket(s.mtuDiscoverer.GetPing()) if err != nil { return false, err @@ -1793,7 +1790,7 @@ func (s *session) sendPacket() (bool, error) { return true, nil } -func (s *session) sendPackedPacket(packet *packedPacket, now time.Time) { +func (s *connection) sendPackedPacket(packet *packedPacket, now time.Time) { if s.firstAckElicitingPacketAfterIdleSentTime.IsZero() && packet.IsAckEliciting() { s.firstAckElicitingPacketAfterIdleSentTime = now } @@ -1803,7 +1800,7 @@ func (s *session) sendPackedPacket(packet *packedPacket, now time.Time) { s.sendQueue.Send(packet.buffer) } -func (s *session) sendConnectionClose(e error) ([]byte, error) { +func (s *connection) sendConnectionClose(e error) ([]byte, error) { var packet *coalescedPacket var err error var transportErr *qerr.TransportError @@ -1815,7 +1812,7 @@ func (s *session) sendConnectionClose(e error) ([]byte, error) { } else { packet, err = s.packer.PackConnectionClose(&qerr.TransportError{ ErrorCode: qerr.InternalError, - ErrorMessage: fmt.Sprintf("session BUG: unspecified error type (msg: %s)", e.Error()), + ErrorMessage: fmt.Sprintf("connection BUG: unspecified error type (msg: %s)", e.Error()), }) } if err != nil { @@ -1825,7 +1822,7 @@ func (s *session) sendConnectionClose(e error) ([]byte, error) { return packet.buffer.Data, s.conn.Write(packet.buffer.Data) } -func (s *session) logPacketContents(p *packetContents) { +func (s *connection) logPacketContents(p *packetContents) { // tracing if s.tracer != nil { frames := make([]logging.Frame, 0, len(p.frames)) @@ -1848,7 +1845,7 @@ func (s *session) logPacketContents(p *packetContents) { } } -func (s *session) logCoalescedPacket(packet *coalescedPacket) { +func (s *connection) logCoalescedPacket(packet *coalescedPacket) { if s.logger.Debug() { if len(packet.packets) > 1 { s.logger.Debugf("-> Sending coalesced packet (%d parts, %d bytes) for connection %s", len(packet.packets), packet.buffer.Len(), s.logID) @@ -1861,7 +1858,7 @@ func (s *session) logCoalescedPacket(packet *coalescedPacket) { } } -func (s *session) logPacket(packet *packedPacket) { +func (s *connection) logPacket(packet *packedPacket) { if s.logger.Debug() { s.logger.Debugf("-> Sending packet %d (%d bytes) for connection %s, %s", packet.header.PacketNumber, packet.buffer.Len(), s.logID, packet.EncryptionLevel()) } @@ -1869,32 +1866,32 @@ func (s *session) logPacket(packet *packedPacket) { } // AcceptStream returns the next stream openend by the peer -func (s *session) AcceptStream(ctx context.Context) (Stream, error) { +func (s *connection) AcceptStream(ctx context.Context) (Stream, error) { return s.streamsMap.AcceptStream(ctx) } -func (s *session) AcceptUniStream(ctx context.Context) (ReceiveStream, error) { +func (s *connection) AcceptUniStream(ctx context.Context) (ReceiveStream, error) { return s.streamsMap.AcceptUniStream(ctx) } // OpenStream opens a stream -func (s *session) OpenStream() (Stream, error) { +func (s *connection) OpenStream() (Stream, error) { return s.streamsMap.OpenStream() } -func (s *session) OpenStreamSync(ctx context.Context) (Stream, error) { +func (s *connection) OpenStreamSync(ctx context.Context) (Stream, error) { return s.streamsMap.OpenStreamSync(ctx) } -func (s *session) OpenUniStream() (SendStream, error) { +func (s *connection) OpenUniStream() (SendStream, error) { return s.streamsMap.OpenUniStream() } -func (s *session) OpenUniStreamSync(ctx context.Context) (SendStream, error) { +func (s *connection) OpenUniStreamSync(ctx context.Context) (SendStream, error) { return s.streamsMap.OpenUniStreamSync(ctx) } -func (s *session) newFlowController(id protocol.StreamID) flowcontrol.StreamFlowController { +func (s *connection) newFlowController(id protocol.StreamID) flowcontrol.StreamFlowController { initialSendWindow := s.peerParams.InitialMaxStreamDataUni if id.Type() == protocol.StreamTypeBidi { if id.InitiatedBy() == s.perspective { @@ -1916,14 +1913,14 @@ func (s *session) newFlowController(id protocol.StreamID) flowcontrol.StreamFlow } // scheduleSending signals that we have data for sending -func (s *session) scheduleSending() { +func (s *connection) scheduleSending() { select { case s.sendingScheduled <- struct{}{}: default: } } -func (s *session) tryQueueingUndecryptablePacket(p *receivedPacket, hdr *wire.Header) { +func (s *connection) tryQueueingUndecryptablePacket(p *receivedPacket, hdr *wire.Header) { if s.handshakeComplete { panic("shouldn't queue undecryptable packets after handshake completion") } @@ -1941,33 +1938,33 @@ func (s *session) tryQueueingUndecryptablePacket(p *receivedPacket, hdr *wire.He s.undecryptablePackets = append(s.undecryptablePackets, p) } -func (s *session) queueControlFrame(f wire.Frame) { +func (s *connection) queueControlFrame(f wire.Frame) { s.framer.QueueControlFrame(f) s.scheduleSending() } -func (s *session) onHasStreamWindowUpdate(id protocol.StreamID) { +func (s *connection) onHasStreamWindowUpdate(id protocol.StreamID) { s.windowUpdateQueue.AddStream(id) s.scheduleSending() } -func (s *session) onHasConnectionWindowUpdate() { +func (s *connection) onHasConnectionWindowUpdate() { s.windowUpdateQueue.AddConnection() s.scheduleSending() } -func (s *session) onHasStreamData(id protocol.StreamID) { +func (s *connection) onHasStreamData(id protocol.StreamID) { s.framer.AddActiveStream(id) s.scheduleSending() } -func (s *session) onStreamCompleted(id protocol.StreamID) { +func (s *connection) onStreamCompleted(id protocol.StreamID) { if err := s.streamsMap.DeleteStream(id); err != nil { s.closeLocal(err) } } -func (s *session) SendMessage(p []byte) error { +func (s *connection) SendMessage(p []byte) error { f := &wire.DatagramFrame{DataLenPresent: true} if protocol.ByteCount(len(p)) > f.MaxDataLen(s.peerParams.MaxDatagramFrameSize, s.version) { return errors.New("message too large") @@ -1977,27 +1974,27 @@ func (s *session) SendMessage(p []byte) error { return s.datagramQueue.AddAndWait(f) } -func (s *session) ReceiveMessage() ([]byte, error) { +func (s *connection) ReceiveMessage() ([]byte, error) { return s.datagramQueue.Receive() } -func (s *session) LocalAddr() net.Addr { +func (s *connection) LocalAddr() net.Addr { return s.conn.LocalAddr() } -func (s *session) RemoteAddr() net.Addr { +func (s *connection) RemoteAddr() net.Addr { return s.conn.RemoteAddr() } -func (s *session) getPerspective() protocol.Perspective { +func (s *connection) getPerspective() protocol.Perspective { return s.perspective } -func (s *session) GetVersion() protocol.VersionNumber { +func (s *connection) GetVersion() protocol.VersionNumber { return s.version } -func (s *session) NextSession() Session { +func (s *connection) NextConnection() Connection { <-s.HandshakeComplete().Done() s.streamsMap.UseResetMaps() return s diff --git a/vendor/github.com/lucas-clemente/quic-go/interface.go b/vendor/github.com/lucas-clemente/quic-go/interface.go index 5c012256..73154e4a 100644 --- a/vendor/github.com/lucas-clemente/quic-go/interface.go +++ b/vendor/github.com/lucas-clemente/quic-go/interface.go @@ -59,15 +59,15 @@ type TokenStore interface { // when the server rejects a 0-RTT connection attempt. var Err0RTTRejected = errors.New("0-RTT rejected") -// SessionTracingKey can be used to associate a ConnectionTracer with a Session. -// It is set on the Session.Context() context, +// ConnectionTracingKey can be used to associate a ConnectionTracer with a Connection. +// It is set on the Connection.Context() context, // as well as on the context passed to logging.Tracer.NewConnectionTracer. -var SessionTracingKey = sessionTracingCtxKey{} +var ConnectionTracingKey = connTracingCtxKey{} -type sessionTracingCtxKey struct{} +type connTracingCtxKey struct{} // Stream is the interface implemented by QUIC streams -// In addition to the errors listed on the Session, +// In addition to the errors listed on the Connection, // calls to stream functions can return a StreamError if the stream is canceled. type Stream interface { ReceiveStream @@ -87,7 +87,7 @@ type ReceiveStream interface { // after a fixed time limit; see SetDeadline and SetReadDeadline. // If the stream was canceled by the peer, the error implements the StreamError // interface, and Canceled() == true. - // If the session was closed due to a timeout, the error satisfies + // If the connection was closed due to a timeout, the error satisfies // the net.Error interface, and Timeout() will be true. io.Reader // CancelRead aborts receiving on this stream. @@ -111,7 +111,7 @@ type SendStream interface { // after a fixed time limit; see SetDeadline and SetWriteDeadline. // If the stream was canceled by the peer, the error implements the StreamError // interface, and Canceled() == true. - // If the session was closed due to a timeout, the error satisfies + // If the connection was closed due to a timeout, the error satisfies // the net.Error interface, and Timeout() will be true. io.Writer // Close closes the write-direction of the stream. @@ -124,7 +124,7 @@ type SendStream interface { // Write will unblock immediately, and future calls to Write will fail. // When called multiple times or after closing the stream it is a no-op. CancelWrite(StreamErrorCode) - // The context is canceled as soon as the write-side of the stream is closed. + // The Context is canceled as soon as the write-side of the stream is closed. // This happens when Close() or CancelWrite() is called, or when the peer // cancels the read-side of their stream. // Warning: This API should not be considered stable and might change soon. @@ -132,26 +132,26 @@ type SendStream interface { // SetWriteDeadline sets the deadline for future Write calls // and any currently-blocked Write call. // Even if write times out, it may return n > 0, indicating that - // some of the data was successfully written. + // some data was successfully written. // A zero value for t means Write will not time out. SetWriteDeadline(t time.Time) error } -// A Session is a QUIC connection between two peers. -// Calls to the session (and to streams) can return the following types of errors: +// A Connection is a QUIC connection between two peers. +// Calls to the connection (and to streams) can return the following types of errors: // * ApplicationError: for errors triggered by the application running on top of QUIC // * TransportError: for errors triggered by the QUIC transport (in many cases a misbehaving peer) // * IdleTimeoutError: when the peer goes away unexpectedly (this is a net.Error timeout error) // * HandshakeTimeoutError: when the cryptographic handshake takes too long (this is a net.Error timeout error) // * StatelessResetError: when we receive a stateless reset (this is a net.Error temporary error) // * VersionNegotiationError: returned by the client, when there's no version overlap between the peers -type Session interface { +type Connection interface { // AcceptStream returns the next stream opened by the peer, blocking until one is available. - // If the session was closed due to a timeout, the error satisfies + // If the connection was closed due to a timeout, the error satisfies // the net.Error interface, and Timeout() will be true. AcceptStream(context.Context) (Stream, error) // AcceptUniStream returns the next unidirectional stream opened by the peer, blocking until one is available. - // If the session was closed due to a timeout, the error satisfies + // If the connection was closed due to a timeout, the error satisfies // the net.Error interface, and Timeout() will be true. AcceptUniStream(context.Context) (ReceiveStream, error) // OpenStream opens a new bidirectional QUIC stream. @@ -159,22 +159,22 @@ type Session interface { // The peer can only accept the stream after data has been sent on the stream. // If the error is non-nil, it satisfies the net.Error interface. // When reaching the peer's stream limit, err.Temporary() will be true. - // If the session was closed due to a timeout, Timeout() will be true. + // If the connection was closed due to a timeout, Timeout() will be true. OpenStream() (Stream, error) // OpenStreamSync opens a new bidirectional QUIC stream. // It blocks until a new stream can be opened. // If the error is non-nil, it satisfies the net.Error interface. - // If the session was closed due to a timeout, Timeout() will be true. + // If the connection was closed due to a timeout, Timeout() will be true. OpenStreamSync(context.Context) (Stream, error) // OpenUniStream opens a new outgoing unidirectional QUIC stream. // If the error is non-nil, it satisfies the net.Error interface. // When reaching the peer's stream limit, Temporary() will be true. - // If the session was closed due to a timeout, Timeout() will be true. + // If the connection was closed due to a timeout, Timeout() will be true. OpenUniStream() (SendStream, error) // OpenUniStreamSync opens a new outgoing unidirectional QUIC stream. // It blocks until a new stream can be opened. // If the error is non-nil, it satisfies the net.Error interface. - // If the session was closed due to a timeout, Timeout() will be true. + // If the connection was closed due to a timeout, Timeout() will be true. OpenUniStreamSync(context.Context) (SendStream, error) // LocalAddr returns the local address. LocalAddr() net.Addr @@ -183,7 +183,7 @@ type Session interface { // CloseWithError closes the connection with an error. // The error string will be sent to the peer. CloseWithError(ApplicationErrorCode, string) error - // The context is cancelled when the session is closed. + // The context is cancelled when the connection is closed. // Warning: This API should not be considered stable and might change soon. Context() context.Context // ConnectionState returns basic details about the QUIC connection. @@ -199,19 +199,19 @@ type Session interface { ReceiveMessage() ([]byte, error) } -// An EarlySession is a session that is handshaking. +// An EarlyConnection is a connection that is handshaking. // Data sent during the handshake is encrypted using the forward secure keys. // When using client certificates, the client's identity is only verified // after completion of the handshake. -type EarlySession interface { - Session +type EarlyConnection interface { + Connection - // Blocks until the handshake completes (or fails). + // HandshakeComplete blocks until the handshake completes (or fails). // Data sent before completion of the handshake is encrypted with 1-RTT keys. // Note that the client's identity hasn't been verified yet. HandshakeComplete() context.Context - NextSession() Session + NextConnection() Connection } // Config contains all configuration data needed for a QUIC server or client. @@ -266,6 +266,13 @@ type Config struct { // MaxConnectionReceiveWindow is the connection-level flow control window for receiving data. // If this value is zero, it will default to 15 MB. MaxConnectionReceiveWindow uint64 + // AllowConnectionWindowIncrease is called every time the connection flow controller attempts + // to increase the connection flow control window. + // If set, the caller can prevent an increase of the window. Typically, it would do so to + // limit the memory usage. + // To avoid deadlocks, it is not valid to call other functions on the connection or on streams + // in this callback. + AllowConnectionWindowIncrease func(sess Connection, delta uint64) bool // MaxIncomingStreams is the maximum number of concurrent bidirectional streams that a peer is allowed to open. // Values above 2^60 are invalid. // If not set, it will default to 100. @@ -279,11 +286,13 @@ type Config struct { // The StatelessResetKey is used to generate stateless reset tokens. // If no key is configured, sending of stateless resets is disabled. StatelessResetKey []byte - // KeepAlive defines whether this peer will periodically send a packet to keep the connection alive. - KeepAlive bool + // KeepAlivePeriod defines whether this peer will periodically send a packet to keep the connection alive. + // If set to 0, then no keep alive is sent. Otherwise, the keep alive is sent on that period (or at most + // every half of MaxIdleTimeout, whichever is smaller). + KeepAlivePeriod time.Duration // DisablePathMTUDiscovery disables Path MTU Discovery (RFC 8899). // Packets will then be at most 1252 (IPv4) / 1232 (IPv6) bytes in size. - // Note that Path MTU discovery is always disabled on Windows, see https://github.com/lucas-clemente/quic-go/issues/3273. + // Note that if Path MTU discovery is causing issues on your system, please open a new issue DisablePathMTUDiscovery bool // DisableVersionNegotiationPackets disables the sending of Version Negotiation packets. // This can be useful if version information is exchanged out-of-band. @@ -304,21 +313,21 @@ type ConnectionState struct { // A Listener for incoming QUIC connections type Listener interface { - // Close the server. All active sessions will be closed. + // Close the server. All active connections will be closed. Close() error // Addr returns the local network addr that the server is listening on. Addr() net.Addr - // Accept returns new sessions. It should be called in a loop. - Accept(context.Context) (Session, error) + // Accept returns new connections. It should be called in a loop. + Accept(context.Context) (Connection, error) } // An EarlyListener listens for incoming QUIC connections, // and returns them before the handshake completes. type EarlyListener interface { - // Close the server. All active sessions will be closed. + // Close the server. All active connections will be closed. Close() error // Addr returns the local network addr that the server is listening on. Addr() net.Addr - // Accept returns new early sessions. It should be called in a loop. - Accept(context.Context) (EarlySession, error) + // Accept returns new early connections. It should be called in a loop. + Accept(context.Context) (EarlyConnection, error) } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/base_flow_controller.go b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/base_flow_controller.go index da6a7125..2bf14fdc 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/base_flow_controller.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/base_flow_controller.go @@ -23,6 +23,8 @@ type baseFlowController struct { receiveWindowSize protocol.ByteCount maxReceiveWindowSize protocol.ByteCount + allowWindowIncrease func(size protocol.ByteCount) bool + epochStartTime time.Time epochStartOffset protocol.ByteCount rttStats *utils.RTTStats @@ -105,7 +107,10 @@ func (c *baseFlowController) maybeAdjustWindowSize() { now := time.Now() if now.Sub(c.epochStartTime) < time.Duration(4*fraction*float64(rtt)) { // window is consumed too fast, try to increase the window size - c.receiveWindowSize = utils.MinByteCount(2*c.receiveWindowSize, c.maxReceiveWindowSize) + newSize := utils.MinByteCount(2*c.receiveWindowSize, c.maxReceiveWindowSize) + if newSize > c.receiveWindowSize && (c.allowWindowIncrease == nil || c.allowWindowIncrease(newSize-c.receiveWindowSize)) { + c.receiveWindowSize = newSize + } } c.startNewAutoTuningEpoch(now) } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/connection_flow_controller.go b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/connection_flow_controller.go index 90e7ceab..6bf2241b 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/connection_flow_controller.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/connection_flow_controller.go @@ -19,11 +19,12 @@ type connectionFlowController struct { var _ ConnectionFlowController = &connectionFlowController{} // NewConnectionFlowController gets a new flow controller for the connection -// It is created before we receive the peer's transport paramenters, thus it starts with a sendWindow of 0. +// It is created before we receive the peer's transport parameters, thus it starts with a sendWindow of 0. func NewConnectionFlowController( receiveWindow protocol.ByteCount, maxReceiveWindow protocol.ByteCount, queueWindowUpdate func(), + allowWindowIncrease func(size protocol.ByteCount) bool, rttStats *utils.RTTStats, logger utils.Logger, ) ConnectionFlowController { @@ -33,6 +34,7 @@ func NewConnectionFlowController( receiveWindow: receiveWindow, receiveWindowSize: receiveWindow, maxReceiveWindowSize: maxReceiveWindow, + allowWindowIncrease: allowWindowIncrease, logger: logger, }, queueWindowUpdate: queueWindowUpdate, @@ -85,13 +87,16 @@ func (c *connectionFlowController) EnsureMinimumWindowSize(inc protocol.ByteCoun c.mutex.Lock() if inc > c.receiveWindowSize { c.logger.Debugf("Increasing receive flow control window for the connection to %d kB, in response to stream flow control window increase", c.receiveWindowSize/(1<<10)) - c.receiveWindowSize = utils.MinByteCount(inc, c.maxReceiveWindowSize) + newSize := utils.MinByteCount(inc, c.maxReceiveWindowSize) + if delta := newSize - c.receiveWindowSize; delta > 0 && c.allowWindowIncrease(delta) { + c.receiveWindowSize = newSize + } c.startNewAutoTuningEpoch(time.Now()) } c.mutex.Unlock() } -// The flow controller is reset when 0-RTT is rejected. +// Reset rests the flow controller. This happens when 0-RTT is rejected. // All stream data is invalidated, it's if we had never opened a stream and never sent any data. // At that point, we only have sent stream data, but we didn't have the keys to open 1-RTT keys yet. func (c *connectionFlowController) Reset() error { diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/protocol/params.go b/vendor/github.com/lucas-clemente/quic-go/internal/protocol/params.go index 4d3085fb..9c2a5e7f 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/protocol/params.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/protocol/params.go @@ -14,7 +14,7 @@ const InitialPacketSizeIPv6 = 1232 // MaxCongestionWindowPackets is the maximum congestion window in packet. const MaxCongestionWindowPackets = 10000 -// MaxUndecryptablePackets limits the number of undecryptable packets that are queued in the session. +// MaxUndecryptablePackets limits the number of undecryptable packets that are queued in the connection. const MaxUndecryptablePackets = 32 // ConnectionFlowControlMultiplier determines how much larger the connection flow control windows needs to be relative to any stream's flow control window @@ -45,8 +45,8 @@ const DefaultMaxIncomingUniStreams = 100 // MaxServerUnprocessedPackets is the max number of packets stored in the server that are not yet processed. const MaxServerUnprocessedPackets = 1024 -// MaxSessionUnprocessedPackets is the max number of packets stored in each session that are not yet processed. -const MaxSessionUnprocessedPackets = 256 +// MaxConnUnprocessedPackets is the max number of packets stored in each connection that are not yet processed. +const MaxConnUnprocessedPackets = 256 // SkipPacketInitialPeriod is the initial period length used for packet number skipping to prevent an Optimistic ACK attack. // Every time a packet number is skipped, the period is doubled, up to SkipPacketMaxPeriod. @@ -55,7 +55,7 @@ const SkipPacketInitialPeriod PacketNumber = 256 // SkipPacketMaxPeriod is the maximum period length used for packet number skipping. const SkipPacketMaxPeriod PacketNumber = 128 * 1024 -// MaxAcceptQueueSize is the maximum number of sessions that the server queues for accepting. +// MaxAcceptQueueSize is the maximum number of connections that the server queues for accepting. // If the queue is full, new connection attempts will be rejected. const MaxAcceptQueueSize = 32 @@ -112,7 +112,7 @@ const DefaultHandshakeTimeout = 10 * time.Second // It should be shorter than the time that NATs clear their mapping. const MaxKeepAliveInterval = 20 * time.Second -// RetiredConnectionIDDeleteTimeout is the time we keep closed sessions around in order to retransmit the CONNECTION_CLOSE. +// RetiredConnectionIDDeleteTimeout is the time we keep closed connections around in order to retransmit the CONNECTION_CLOSE. // after this time all information about the old connection will be deleted const RetiredConnectionIDDeleteTimeout = 5 * time.Second @@ -189,7 +189,7 @@ const Max0RTTQueueingDuration = 100 * time.Millisecond const Max0RTTQueues = 32 // Max0RTTQueueLen is the maximum number of 0-RTT packets that we buffer for each connection. -// When a new session is created, all buffered packets are passed to the session immediately. -// To avoid blocking, this value has to be smaller than MaxSessionUnprocessedPackets. -// To avoid packets being dropped as undecryptable by the session, this value has to be smaller than MaxUndecryptablePackets. +// When a new connection is created, all buffered packets are passed to the connection immediately. +// To avoid blocking, this value has to be smaller than MaxConnUnprocessedPackets. +// To avoid packets being dropped as undecryptable by the connection, this value has to be smaller than MaxUndecryptablePackets. const Max0RTTQueueLen = 31 diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/qtls/go119.go b/vendor/github.com/lucas-clemente/quic-go/internal/qtls/go119.go index 2c648639..87e7132e 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/qtls/go119.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/qtls/go119.go @@ -3,4 +3,4 @@ package qtls -var _ int = "quic-go doesn't build on Go 1.19 yet." +var _ int = "The version of quic-go you're using can't be built on Go 1.19 yet. For more details, please see https://github.com/lucas-clemente/quic-go/wiki/quic-go-and-Go-versions." diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/qtls/go_oldversion.go b/vendor/github.com/lucas-clemente/quic-go/internal/qtls/go_oldversion.go new file mode 100644 index 00000000..384d719c --- /dev/null +++ b/vendor/github.com/lucas-clemente/quic-go/internal/qtls/go_oldversion.go @@ -0,0 +1,7 @@ +//go:build (go1.9 || go1.10 || go1.11 || go1.12 || go1.13 || go1.14 || go1.15) && !go1.16 +// +build go1.9 go1.10 go1.11 go1.12 go1.13 go1.14 go1.15 +// +build !go1.16 + +package qtls + +var _ int = "The version of quic-go you're using can't be built using outdated Go versions. For more details, please see https://github.com/lucas-clemente/quic-go/wiki/quic-go-and-Go-versions." diff --git a/vendor/github.com/lucas-clemente/quic-go/logging/types.go b/vendor/github.com/lucas-clemente/quic-go/logging/types.go index e1886503..ad800692 100644 --- a/vendor/github.com/lucas-clemente/quic-go/logging/types.go +++ b/vendor/github.com/lucas-clemente/quic-go/logging/types.go @@ -68,14 +68,14 @@ const ( TimerTypePTO ) -// TimeoutReason is the reason why a session is closed +// TimeoutReason is the reason why a connection is closed type TimeoutReason uint8 const ( - // TimeoutReasonHandshake is used when the session is closed due to a handshake timeout + // TimeoutReasonHandshake is used when the connection is closed due to a handshake timeout // This reason is not defined in the qlog draft, but very useful for debugging. TimeoutReasonHandshake TimeoutReason = iota - // TimeoutReasonIdle is used when the session is closed due to an idle timeout + // TimeoutReasonIdle is used when the connection is closed due to an idle timeout // This reason is not defined in the qlog draft, but very useful for debugging. TimeoutReasonIdle ) @@ -87,7 +87,7 @@ const ( CongestionStateSlowStart CongestionState = iota // CongestionStateCongestionAvoidance is the slow start phase of Reno / Cubic CongestionStateCongestionAvoidance - // CongestionStateCongestionAvoidance is the recovery phase of Reno / Cubic + // CongestionStateRecovery is the recovery phase of Reno / Cubic CongestionStateRecovery // CongestionStateApplicationLimited means that the congestion controller is application limited CongestionStateApplicationLimited diff --git a/vendor/github.com/lucas-clemente/quic-go/mockgen.go b/vendor/github.com/lucas-clemente/quic-go/mockgen.go index 053cfa9a..22c2c0e7 100644 --- a/vendor/github.com/lucas-clemente/quic-go/mockgen.go +++ b/vendor/github.com/lucas-clemente/quic-go/mockgen.go @@ -16,8 +16,8 @@ package quic //go:generate sh -c "./mockgen_private.sh quic mock_unpacker_test.go github.com/lucas-clemente/quic-go unpacker" //go:generate sh -c "./mockgen_private.sh quic mock_packer_test.go github.com/lucas-clemente/quic-go packer" //go:generate sh -c "./mockgen_private.sh quic mock_mtu_discoverer_test.go github.com/lucas-clemente/quic-go mtuDiscoverer" -//go:generate sh -c "./mockgen_private.sh quic mock_session_runner_test.go github.com/lucas-clemente/quic-go sessionRunner" -//go:generate sh -c "./mockgen_private.sh quic mock_quic_session_test.go github.com/lucas-clemente/quic-go quicSession" +//go:generate sh -c "./mockgen_private.sh quic mock_conn_runner_test.go github.com/lucas-clemente/quic-go connRunner" +//go:generate sh -c "./mockgen_private.sh quic mock_quic_conn_test.go github.com/lucas-clemente/quic-go quicConn" //go:generate sh -c "./mockgen_private.sh quic mock_packet_handler_test.go github.com/lucas-clemente/quic-go packetHandler" //go:generate sh -c "./mockgen_private.sh quic mock_unknown_packet_handler_test.go github.com/lucas-clemente/quic-go unknownPacketHandler" //go:generate sh -c "./mockgen_private.sh quic mock_packet_handler_manager_test.go github.com/lucas-clemente/quic-go packetHandlerManager" diff --git a/vendor/github.com/lucas-clemente/quic-go/mtu_discoverer.go b/vendor/github.com/lucas-clemente/quic-go/mtu_discoverer.go index a5a83021..bf38eaac 100644 --- a/vendor/github.com/lucas-clemente/quic-go/mtu_discoverer.go +++ b/vendor/github.com/lucas-clemente/quic-go/mtu_discoverer.go @@ -11,7 +11,6 @@ import ( type mtuDiscoverer interface { ShouldSendProbe(now time.Time) bool - NextProbeTime() time.Time GetPing() (ping ackhandler.Frame, datagramSize protocol.ByteCount) } @@ -53,16 +52,7 @@ func (f *mtuFinder) ShouldSendProbe(now time.Time) bool { if f.probeInFlight || f.done() { return false } - return !now.Before(f.NextProbeTime()) -} - -// NextProbeTime returns the time when the next probe packet should be sent. -// It returns the zero value if no probe packet should be sent. -func (f *mtuFinder) NextProbeTime() time.Time { - if f.probeInFlight || f.done() { - return time.Time{} - } - return f.lastProbeTime.Add(mtuProbeDelay * f.rttStats.SmoothedRTT()) + return !now.Before(f.lastProbeTime.Add(mtuProbeDelay * f.rttStats.SmoothedRTT())) } func (f *mtuFinder) GetPing() (ackhandler.Frame, protocol.ByteCount) { diff --git a/vendor/github.com/lucas-clemente/quic-go/multiplexer.go b/vendor/github.com/lucas-clemente/quic-go/multiplexer.go index 006305af..2271b551 100644 --- a/vendor/github.com/lucas-clemente/quic-go/multiplexer.go +++ b/vendor/github.com/lucas-clemente/quic-go/multiplexer.go @@ -32,7 +32,7 @@ type connManager struct { } // The connMultiplexer listens on multiple net.PacketConns and dispatches -// incoming packets to the session handler. +// incoming packets to the connection handler. type connMultiplexer struct { mutex sync.Mutex diff --git a/vendor/github.com/lucas-clemente/quic-go/packet_handler_map.go b/vendor/github.com/lucas-clemente/quic-go/packet_handler_map.go index 5b4659d2..6975d5a2 100644 --- a/vendor/github.com/lucas-clemente/quic-go/packet_handler_map.go +++ b/vendor/github.com/lucas-clemente/quic-go/packet_handler_map.go @@ -7,8 +7,12 @@ import ( "errors" "fmt" "hash" + "io" "log" "net" + "os" + "strconv" + "strings" "sync" "time" @@ -45,6 +49,14 @@ func (h *zeroRTTQueue) Clear() { } } +// rawConn is a connection that allow reading of a receivedPacket. +type rawConn interface { + ReadPacket() (*receivedPacket, error) + WritePacket(b []byte, addr net.Addr, oob []byte) (int, error) + LocalAddr() net.Addr + io.Closer +} + type packetHandlerMapEntry struct { packetHandler packetHandler is0RTTQueue bool @@ -52,12 +64,12 @@ type packetHandlerMapEntry struct { // The packetHandlerMap stores packetHandlers, identified by connection ID. // It is used: -// * by the server to store sessions +// * by the server to store connections // * when multiplexing outgoing connections to store clients type packetHandlerMap struct { mutex sync.Mutex - conn connection + conn rawConn connIDLen int handlers map[string] /* string(ConnectionID)*/ packetHandlerMapEntry @@ -68,8 +80,8 @@ type packetHandlerMap struct { listening chan struct{} // is closed when listen returns closed bool - deleteRetiredSessionsAfter time.Duration - zeroRTTQueueDuration time.Duration + deleteRetiredConnsAfter time.Duration + zeroRTTQueueDuration time.Duration statelessResetEnabled bool statelessResetMutex sync.Mutex @@ -110,7 +122,7 @@ func setReceiveBuffer(c net.PacketConn, logger utils.Logger) error { return nil } -// only print warnings about the UPD receive buffer size once +// only print warnings about the UDP receive buffer size once var receiveBufferWarningOnce sync.Once func newPacketHandlerMap( @@ -121,26 +133,31 @@ func newPacketHandlerMap( logger utils.Logger, ) (packetHandlerManager, error) { if err := setReceiveBuffer(c, logger); err != nil { - receiveBufferWarningOnce.Do(func() { - log.Printf("%s. See https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size for details.", err) - }) + if !strings.Contains(err.Error(), "use of closed network connection") { + receiveBufferWarningOnce.Do(func() { + if disable, _ := strconv.ParseBool(os.Getenv("QUIC_GO_DISABLE_RECEIVE_BUFFER_WARNING")); disable { + return + } + log.Printf("%s. See https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size for details.", err) + }) + } } conn, err := wrapConn(c) if err != nil { return nil, err } m := &packetHandlerMap{ - conn: conn, - connIDLen: connIDLen, - listening: make(chan struct{}), - handlers: make(map[string]packetHandlerMapEntry), - resetTokens: make(map[protocol.StatelessResetToken]packetHandler), - deleteRetiredSessionsAfter: protocol.RetiredConnectionIDDeleteTimeout, - zeroRTTQueueDuration: protocol.Max0RTTQueueingDuration, - statelessResetEnabled: len(statelessResetKey) > 0, - statelessResetHasher: hmac.New(sha256.New, statelessResetKey), - tracer: tracer, - logger: logger, + conn: conn, + connIDLen: connIDLen, + listening: make(chan struct{}), + handlers: make(map[string]packetHandlerMapEntry), + resetTokens: make(map[protocol.StatelessResetToken]packetHandler), + deleteRetiredConnsAfter: protocol.RetiredConnectionIDDeleteTimeout, + zeroRTTQueueDuration: protocol.Max0RTTQueueingDuration, + statelessResetEnabled: len(statelessResetKey) > 0, + statelessResetHasher: hmac.New(sha256.New, statelessResetKey), + tracer: tracer, + logger: logger, } go m.listen() @@ -196,7 +213,7 @@ func (h *packetHandlerMap) AddWithConnID(clientDestConnID, newConnID protocol.Co var q *zeroRTTQueue if entry, ok := h.handlers[string(clientDestConnID)]; ok { if !entry.is0RTTQueue { - h.logger.Debugf("Not adding connection ID %s for a new session, as it already exists.", clientDestConnID) + h.logger.Debugf("Not adding connection ID %s for a new connection, as it already exists.", clientDestConnID) return false } q = entry.packetHandler.(*zeroRTTQueue) @@ -212,7 +229,7 @@ func (h *packetHandlerMap) AddWithConnID(clientDestConnID, newConnID protocol.Co } h.handlers[string(clientDestConnID)] = packetHandlerMapEntry{packetHandler: sess} h.handlers[string(newConnID)] = packetHandlerMapEntry{packetHandler: sess} - h.logger.Debugf("Adding connection IDs %s and %s for a new session.", clientDestConnID, newConnID) + h.logger.Debugf("Adding connection IDs %s and %s for a new connection.", clientDestConnID, newConnID) return true } @@ -224,8 +241,8 @@ func (h *packetHandlerMap) Remove(id protocol.ConnectionID) { } func (h *packetHandlerMap) Retire(id protocol.ConnectionID) { - h.logger.Debugf("Retiring connection ID %s in %s.", id, h.deleteRetiredSessionsAfter) - time.AfterFunc(h.deleteRetiredSessionsAfter, func() { + h.logger.Debugf("Retiring connection ID %s in %s.", id, h.deleteRetiredConnsAfter) + time.AfterFunc(h.deleteRetiredConnsAfter, func() { h.mutex.Lock() delete(h.handlers, string(id)) h.mutex.Unlock() @@ -237,14 +254,14 @@ func (h *packetHandlerMap) ReplaceWithClosed(id protocol.ConnectionID, handler p h.mutex.Lock() h.handlers[string(id)] = packetHandlerMapEntry{packetHandler: handler} h.mutex.Unlock() - h.logger.Debugf("Replacing session for connection ID %s with a closed session.", id) + h.logger.Debugf("Replacing connection for connection ID %s with a closed connection.", id) - time.AfterFunc(h.deleteRetiredSessionsAfter, func() { + time.AfterFunc(h.deleteRetiredConnsAfter, func() { h.mutex.Lock() handler.shutdown() delete(h.handlers, string(id)) h.mutex.Unlock() - h.logger.Debugf("Removing connection ID %s for a closed session after it has been retired.", id) + h.logger.Debugf("Removing connection ID %s for a closed connection after it has been retired.", id) }) } @@ -289,7 +306,7 @@ func (h *packetHandlerMap) CloseServer() { } // Destroy closes the underlying connection and waits until listen() has returned. -// It does not close active sessions. +// It does not close active connections. func (h *packetHandlerMap) Destroy() error { if err := h.conn.Close(); err != nil { return err @@ -327,6 +344,10 @@ func (h *packetHandlerMap) listen() { defer close(h.listening) for { p, err := h.conn.ReadPacket() + //nolint:staticcheck // SA1019 ignore this! + // TODO: This code is used to ignore wsa errors on Windows. + // Since net.Error.Temporary is deprecated as of Go 1.18, we should find a better solution. + // See https://github.com/lucas-clemente/quic-go/issues/1737 for details. if nerr, ok := err.(net.Error); ok && nerr.Temporary() { h.logger.Debugf("Temporary error reading from conn: %w", err) continue @@ -363,7 +384,7 @@ func (h *packetHandlerMap) handlePacket(p *receivedPacket) { entry.packetHandler.handlePacket(p) return } - } else { // existing session + } else { // existing connection entry.packetHandler.handlePacket(p) return } @@ -389,7 +410,7 @@ func (h *packetHandlerMap) handlePacket(p *receivedPacket) { queue.retireTimer = time.AfterFunc(h.zeroRTTQueueDuration, func() { h.mutex.Lock() defer h.mutex.Unlock() - // The entry might have been replaced by an actual session. + // The entry might have been replaced by an actual connection. // Only delete it if it's still a 0-RTT queue. if entry, ok := h.handlers[string(connID)]; ok && entry.is0RTTQueue { delete(h.handlers, string(connID)) @@ -421,7 +442,7 @@ func (h *packetHandlerMap) maybeHandleStatelessReset(data []byte) bool { var token protocol.StatelessResetToken copy(token[:], data[len(data)-16:]) if sess, ok := h.resetTokens[token]; ok { - h.logger.Debugf("Received a stateless reset with token %#x. Closing session.", token) + h.logger.Debugf("Received a stateless reset with token %#x. Closing connection.", token) go sess.destroy(&StatelessResetError{Token: token}) return true } diff --git a/vendor/github.com/lucas-clemente/quic-go/send_conn.go b/vendor/github.com/lucas-clemente/quic-go/send_conn.go index b276af11..c53ebdfa 100644 --- a/vendor/github.com/lucas-clemente/quic-go/send_conn.go +++ b/vendor/github.com/lucas-clemente/quic-go/send_conn.go @@ -13,7 +13,7 @@ type sendConn interface { } type sconn struct { - connection + rawConn remoteAddr net.Addr info *packetInfo @@ -22,9 +22,9 @@ type sconn struct { var _ sendConn = &sconn{} -func newSendConn(c connection, remote net.Addr, info *packetInfo) sendConn { +func newSendConn(c rawConn, remote net.Addr, info *packetInfo) sendConn { return &sconn{ - connection: c, + rawConn: c, remoteAddr: remote, info: info, oob: info.OOB(), @@ -41,7 +41,7 @@ func (c *sconn) RemoteAddr() net.Addr { } func (c *sconn) LocalAddr() net.Addr { - addr := c.connection.LocalAddr() + addr := c.rawConn.LocalAddr() if c.info != nil { if udpAddr, ok := addr.(*net.UDPAddr); ok { addrCopy := *udpAddr diff --git a/vendor/github.com/lucas-clemente/quic-go/send_queue.go b/vendor/github.com/lucas-clemente/quic-go/send_queue.go index bf25dded..1fc8c1bf 100644 --- a/vendor/github.com/lucas-clemente/quic-go/send_queue.go +++ b/vendor/github.com/lucas-clemente/quic-go/send_queue.go @@ -64,7 +64,13 @@ func (h *sendQueue) Run() error { shouldClose = true case p := <-h.queue: if err := h.conn.Write(p.Data); err != nil { - return err + // This additional check enables: + // 1. Checking for "datagram too large" message from the kernel, as such, + // 2. Path MTU discovery,and + // 3. Eventual detection of loss PingFrame. + if !isMsgSizeErr(err) { + return err + } } p.Release() select { diff --git a/vendor/github.com/lucas-clemente/quic-go/server.go b/vendor/github.com/lucas-clemente/quic-go/server.go index 6ab869c0..5bf568a6 100644 --- a/vendor/github.com/lucas-clemente/quic-go/server.go +++ b/vendor/github.com/lucas-clemente/quic-go/server.go @@ -36,14 +36,14 @@ type unknownPacketHandler interface { type packetHandlerManager interface { AddWithConnID(protocol.ConnectionID, protocol.ConnectionID, func() packetHandler) bool Destroy() error - sessionRunner + connRunner SetServer(unknownPacketHandler) CloseServer() } -type quicSession interface { - EarlySession - earlySessionReady() <-chan struct{} +type quicConn interface { + EarlyConnection + earlyConnReady() <-chan struct{} handlePacket(*receivedPacket) GetVersion() protocol.VersionNumber getPerspective() protocol.Perspective @@ -56,26 +56,26 @@ type quicSession interface { type baseServer struct { mutex sync.Mutex - acceptEarlySessions bool + acceptEarlyConns bool tlsConf *tls.Config config *Config - conn connection + conn rawConn // If the server is started with ListenAddr, we create a packet conn. // If it is started with Listen, we take a packet conn as a parameter. createdPacketConn bool tokenGenerator *handshake.TokenGenerator - sessionHandler packetHandlerManager + connHandler packetHandlerManager receivedPackets chan *receivedPacket // set as a member, so they can be set in the tests - newSession func( + newConn func( sendConn, - sessionRunner, + connRunner, protocol.ConnectionID, /* original dest connection ID */ *protocol.ConnectionID, /* retry src connection ID */ protocol.ConnectionID, /* client dest connection ID */ @@ -90,15 +90,15 @@ type baseServer struct { uint64, utils.Logger, protocol.VersionNumber, - ) quicSession + ) quicConn serverError error errorChan chan struct{} closed bool running chan struct{} // closed as soon as run() returns - sessionQueue chan quicSession - sessionQueueLen int32 // to be used as an atomic + connQueue chan quicConn + connQueueLen int32 // to be used as an atomic logger utils.Logger } @@ -112,7 +112,7 @@ type earlyServer struct{ *baseServer } var _ EarlyListener = &earlyServer{} -func (s *earlyServer) Accept(ctx context.Context) (EarlySession, error) { +func (s *earlyServer) Accept(ctx context.Context) (EarlyConnection, error) { return s.baseServer.accept(ctx) } @@ -123,7 +123,7 @@ func ListenAddr(addr string, tlsConf *tls.Config, config *Config) (Listener, err return listenAddr(addr, tlsConf, config, false) } -// ListenAddrEarly works like ListenAddr, but it returns sessions before the handshake completes. +// ListenAddrEarly works like ListenAddr, but it returns connections before the handshake completes. func ListenAddrEarly(addr string, tlsConf *tls.Config, config *Config) (EarlyListener, error) { s, err := listenAddr(addr, tlsConf, config, true) if err != nil { @@ -164,7 +164,7 @@ func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener, return listen(conn, tlsConf, config, false) } -// ListenEarly works like Listen, but it returns sessions before the handshake completes. +// ListenEarly works like Listen, but it returns connections before the handshake completes. func ListenEarly(conn net.PacketConn, tlsConf *tls.Config, config *Config) (EarlyListener, error) { s, err := listen(conn, tlsConf, config, true) if err != nil { @@ -187,7 +187,7 @@ func listen(conn net.PacketConn, tlsConf *tls.Config, config *Config, acceptEarl } } - sessionHandler, err := getMultiplexer().AddConn(conn, config.ConnectionIDLength, config.StatelessResetKey, config.Tracer) + connHandler, err := getMultiplexer().AddConn(conn, config.ConnectionIDLength, config.StatelessResetKey, config.Tracer) if err != nil { return nil, err } @@ -200,21 +200,21 @@ func listen(conn net.PacketConn, tlsConf *tls.Config, config *Config, acceptEarl return nil, err } s := &baseServer{ - conn: c, - tlsConf: tlsConf, - config: config, - tokenGenerator: tokenGenerator, - sessionHandler: sessionHandler, - sessionQueue: make(chan quicSession), - errorChan: make(chan struct{}), - running: make(chan struct{}), - receivedPackets: make(chan *receivedPacket, protocol.MaxServerUnprocessedPackets), - newSession: newSession, - logger: utils.DefaultLogger.WithPrefix("server"), - acceptEarlySessions: acceptEarly, + conn: c, + tlsConf: tlsConf, + config: config, + tokenGenerator: tokenGenerator, + connHandler: connHandler, + connQueue: make(chan quicConn), + errorChan: make(chan struct{}), + running: make(chan struct{}), + receivedPackets: make(chan *receivedPacket, protocol.MaxServerUnprocessedPackets), + newConn: newConnection, + logger: utils.DefaultLogger.WithPrefix("server"), + acceptEarlyConns: acceptEarly, } go s.run() - sessionHandler.SetServer(s) + connHandler.SetServer(s) s.logger.Debugf("Listening for %s connections on %s", conn.LocalAddr().Network(), conn.LocalAddr().String()) return s, nil } @@ -258,19 +258,19 @@ var defaultAcceptToken = func(clientAddr net.Addr, token *Token) bool { return sourceAddr == token.RemoteAddr } -// Accept returns sessions that already completed the handshake. -// It is only valid if acceptEarlySessions is false. -func (s *baseServer) Accept(ctx context.Context) (Session, error) { +// Accept returns connections that already completed the handshake. +// It is only valid if acceptEarlyConns is false. +func (s *baseServer) Accept(ctx context.Context) (Connection, error) { return s.accept(ctx) } -func (s *baseServer) accept(ctx context.Context) (quicSession, error) { +func (s *baseServer) accept(ctx context.Context) (quicConn, error) { select { case <-ctx.Done(): return nil, ctx.Err() - case sess := <-s.sessionQueue: - atomic.AddInt32(&s.sessionQueueLen, -1) - return sess, nil + case conn := <-s.connQueue: + atomic.AddInt32(&s.connQueueLen, -1) + return conn, nil case <-s.errorChan: return nil, s.serverError } @@ -294,9 +294,9 @@ func (s *baseServer) Close() error { s.mutex.Unlock() <-s.running - s.sessionHandler.CloseServer() + s.connHandler.CloseServer() if createdPacketConn { - return s.sessionHandler.Destroy() + return s.connHandler.Destroy() } return nil } @@ -336,7 +336,7 @@ func (s *baseServer) handlePacketImpl(p *receivedPacket) bool /* is the buffer s } return false } - // If we're creating a new session, the packet will be passed to the session. + // If we're creating a new connection, the packet will be passed to the connection. // The header will then be parsed again. hdr, _, _, err := wire.ParsePacket(p.data, s.config.ConnectionIDLength) if err != nil && err != wire.ErrUnsupportedVersion { @@ -436,7 +436,7 @@ func (s *baseServer) handleInitialImpl(p *receivedPacket, hdr *wire.Header) erro return nil } - if queueLen := atomic.LoadInt32(&s.sessionQueueLen); queueLen >= protocol.MaxAcceptQueueSize { + if queueLen := atomic.LoadInt32(&s.connQueueLen); queueLen >= protocol.MaxAcceptQueueSize { s.logger.Debugf("Rejecting new connection. Server currently busy. Accept queue length: %d (max %d)", queueLen, protocol.MaxAcceptQueueSize) go func() { defer p.buffer.Release() @@ -452,9 +452,9 @@ func (s *baseServer) handleInitialImpl(p *receivedPacket, hdr *wire.Header) erro return err } s.logger.Debugf("Changing connection ID to %s.", connID) - var sess quicSession - tracingID := nextSessionTracingID() - if added := s.sessionHandler.AddWithConnID(hdr.DestConnectionID, connID, func() packetHandler { + var conn quicConn + tracingID := nextConnTracingID() + if added := s.connHandler.AddWithConnID(hdr.DestConnectionID, connID, func() packetHandler { var tracer logging.ConnectionTracer if s.config.Tracer != nil { // Use the same connection ID that is passed to the client's GetLogWriter callback. @@ -463,74 +463,74 @@ func (s *baseServer) handleInitialImpl(p *receivedPacket, hdr *wire.Header) erro connID = origDestConnID } tracer = s.config.Tracer.TracerForConnection( - context.WithValue(context.Background(), SessionTracingKey, tracingID), + context.WithValue(context.Background(), ConnectionTracingKey, tracingID), protocol.PerspectiveServer, connID, ) } - sess = s.newSession( + conn = s.newConn( newSendConn(s.conn, p.remoteAddr, p.info), - s.sessionHandler, + s.connHandler, origDestConnID, retrySrcConnID, hdr.DestConnectionID, hdr.SrcConnectionID, connID, - s.sessionHandler.GetStatelessResetToken(connID), + s.connHandler.GetStatelessResetToken(connID), s.config, s.tlsConf, s.tokenGenerator, - s.acceptEarlySessions, + s.acceptEarlyConns, tracer, tracingID, s.logger, hdr.Version, ) - sess.handlePacket(p) - return sess + conn.handlePacket(p) + return conn }); !added { return nil } - go sess.run() - go s.handleNewSession(sess) - if sess == nil { + go conn.run() + go s.handleNewConn(conn) + if conn == nil { p.buffer.Release() return nil } return nil } -func (s *baseServer) handleNewSession(sess quicSession) { - sessCtx := sess.Context() - if s.acceptEarlySessions { - // wait until the early session is ready (or the handshake fails) +func (s *baseServer) handleNewConn(conn quicConn) { + connCtx := conn.Context() + if s.acceptEarlyConns { + // wait until the early connection is ready (or the handshake fails) select { - case <-sess.earlySessionReady(): - case <-sessCtx.Done(): + case <-conn.earlyConnReady(): + case <-connCtx.Done(): return } } else { // wait until the handshake is complete (or fails) select { - case <-sess.HandshakeComplete().Done(): - case <-sessCtx.Done(): + case <-conn.HandshakeComplete().Done(): + case <-connCtx.Done(): return } } - atomic.AddInt32(&s.sessionQueueLen, 1) + atomic.AddInt32(&s.connQueueLen, 1) select { - case s.sessionQueue <- sess: - // blocks until the session is accepted - case <-sessCtx.Done(): - atomic.AddInt32(&s.sessionQueueLen, -1) - // don't pass sessions that were already closed to Accept() + case s.connQueue <- conn: + // blocks until the connection is accepted + case <-connCtx.Done(): + atomic.AddInt32(&s.connQueueLen, -1) + // don't pass connections that were already closed to Accept() } } func (s *baseServer) sendRetry(remoteAddr net.Addr, hdr *wire.Header, info *packetInfo) error { // Log the Initial packet now. - // If no Retry is sent, the packet will be logged by the session. + // If no Retry is sent, the packet will be logged by the connection. (&wire.ExtendedHeader{Header: *hdr}).Log(s.logger) srcConnID, err := protocol.GenerateConnectionID(s.config.ConnectionIDLength) if err != nil { diff --git a/vendor/github.com/lucas-clemente/quic-go/conn.go b/vendor/github.com/lucas-clemente/quic-go/sys_conn.go similarity index 69% rename from vendor/github.com/lucas-clemente/quic-go/conn.go rename to vendor/github.com/lucas-clemente/quic-go/sys_conn.go index 2f4e3a23..d73b01d2 100644 --- a/vendor/github.com/lucas-clemente/quic-go/conn.go +++ b/vendor/github.com/lucas-clemente/quic-go/sys_conn.go @@ -1,7 +1,6 @@ package quic import ( - "io" "net" "syscall" "time" @@ -10,14 +9,8 @@ import ( "github.com/lucas-clemente/quic-go/internal/utils" ) -type connection interface { - ReadPacket() (*receivedPacket, error) - WritePacket(b []byte, addr net.Addr, oob []byte) (int, error) - LocalAddr() net.Addr - io.Closer -} - -// If the PacketConn passed to Dial or Listen satisfies this interface, quic-go will read the ECN bits from the IP header. +// OOBCapablePacketConn is a connection that allows the reading of ECN bits from the IP header. +// If the PacketConn passed to Dial or Listen satisfies this interface, quic-go will use it. // In this case, ReadMsgUDP() will be used instead of ReadFrom() to read packets. type OOBCapablePacketConn interface { net.PacketConn @@ -28,7 +21,20 @@ type OOBCapablePacketConn interface { var _ OOBCapablePacketConn = &net.UDPConn{} -func wrapConn(pc net.PacketConn) (connection, error) { +func wrapConn(pc net.PacketConn) (rawConn, error) { + conn, ok := pc.(interface { + SyscallConn() (syscall.RawConn, error) + }) + if ok { + rawConn, err := conn.SyscallConn() + if err != nil { + return nil, err + } + err = setDF(rawConn) + if err != nil { + return nil, err + } + } c, ok := pc.(OOBCapablePacketConn) if !ok { utils.DefaultLogger.Infof("PacketConn is not a net.UDPConn. Disabling optimizations possible on UDP connections.") @@ -37,11 +43,16 @@ func wrapConn(pc net.PacketConn) (connection, error) { return newConn(c) } +// The basicConn is the most trivial implementation of a connection. +// It reads a single packet from the underlying net.PacketConn. +// It is used when +// * the net.PacketConn is not a OOBCapablePacketConn, and +// * when the OS doesn't support OOB. type basicConn struct { net.PacketConn } -var _ connection = &basicConn{} +var _ rawConn = &basicConn{} func (c *basicConn) ReadPacket() (*receivedPacket, error) { buffer := getPacketBuffer() diff --git a/vendor/github.com/lucas-clemente/quic-go/sys_conn_df.go b/vendor/github.com/lucas-clemente/quic-go/sys_conn_df.go new file mode 100644 index 00000000..ae9274d9 --- /dev/null +++ b/vendor/github.com/lucas-clemente/quic-go/sys_conn_df.go @@ -0,0 +1,16 @@ +//go:build !linux && !windows +// +build !linux,!windows + +package quic + +import "syscall" + +func setDF(rawConn syscall.RawConn) error { + // no-op on unsupported platforms + return nil +} + +func isMsgSizeErr(err error) bool { + // to be implemented for more specific platforms + return false +} diff --git a/vendor/github.com/lucas-clemente/quic-go/sys_conn_df_linux.go b/vendor/github.com/lucas-clemente/quic-go/sys_conn_df_linux.go new file mode 100644 index 00000000..69f8fc93 --- /dev/null +++ b/vendor/github.com/lucas-clemente/quic-go/sys_conn_df_linux.go @@ -0,0 +1,41 @@ +//go:build linux +// +build linux + +package quic + +import ( + "errors" + "syscall" + + "golang.org/x/sys/unix" + + "github.com/lucas-clemente/quic-go/internal/utils" +) + +func setDF(rawConn syscall.RawConn) error { + // Enabling IP_MTU_DISCOVER will force the kernel to return "sendto: message too long" + // and the datagram will not be fragmented + var errDFIPv4, errDFIPv6 error + if err := rawConn.Control(func(fd uintptr) { + errDFIPv4 = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_MTU_DISCOVER, unix.IP_PMTUDISC_DO) + errDFIPv6 = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_MTU_DISCOVER, unix.IPV6_PMTUDISC_DO) + }); err != nil { + return err + } + switch { + case errDFIPv4 == nil && errDFIPv6 == nil: + utils.DefaultLogger.Debugf("Setting DF for IPv4 and IPv6.") + case errDFIPv4 == nil && errDFIPv6 != nil: + utils.DefaultLogger.Debugf("Setting DF for IPv4.") + case errDFIPv4 != nil && errDFIPv6 == nil: + utils.DefaultLogger.Debugf("Setting DF for IPv6.") + case errDFIPv4 != nil && errDFIPv6 != nil: + utils.DefaultLogger.Errorf("setting DF failed for both IPv4 and IPv6") + } + return nil +} + +func isMsgSizeErr(err error) bool { + // https://man7.org/linux/man-pages/man7/udp.7.html + return errors.Is(err, unix.EMSGSIZE) +} diff --git a/vendor/github.com/lucas-clemente/quic-go/sys_conn_df_windows.go b/vendor/github.com/lucas-clemente/quic-go/sys_conn_df_windows.go new file mode 100644 index 00000000..4649f646 --- /dev/null +++ b/vendor/github.com/lucas-clemente/quic-go/sys_conn_df_windows.go @@ -0,0 +1,46 @@ +//go:build windows +// +build windows + +package quic + +import ( + "errors" + "syscall" + + "github.com/lucas-clemente/quic-go/internal/utils" + "golang.org/x/sys/windows" +) + +const ( + // same for both IPv4 and IPv6 on Windows + // https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/constant.IP_DONTFRAG.html + // https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/constant.IPV6_DONTFRAG.html + IP_DONTFRAGMENT = 14 + IPV6_DONTFRAG = 14 +) + +func setDF(rawConn syscall.RawConn) error { + var errDFIPv4, errDFIPv6 error + if err := rawConn.Control(func(fd uintptr) { + errDFIPv4 = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, IP_DONTFRAGMENT, 1) + errDFIPv6 = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IPV6, IPV6_DONTFRAG, 1) + }); err != nil { + return err + } + switch { + case errDFIPv4 == nil && errDFIPv6 == nil: + utils.DefaultLogger.Debugf("Setting DF for IPv4 and IPv6.") + case errDFIPv4 == nil && errDFIPv6 != nil: + utils.DefaultLogger.Debugf("Setting DF for IPv4.") + case errDFIPv4 != nil && errDFIPv6 == nil: + utils.DefaultLogger.Debugf("Setting DF for IPv6.") + case errDFIPv4 != nil && errDFIPv6 != nil: + return errors.New("setting DF failed for both IPv4 and IPv6") + } + return nil +} + +func isMsgSizeErr(err error) bool { + // https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2 + return errors.Is(err, windows.WSAEMSGSIZE) +} diff --git a/vendor/github.com/lucas-clemente/quic-go/conn_helper_darwin.go b/vendor/github.com/lucas-clemente/quic-go/sys_conn_helper_darwin.go similarity index 81% rename from vendor/github.com/lucas-clemente/quic-go/conn_helper_darwin.go rename to vendor/github.com/lucas-clemente/quic-go/sys_conn_helper_darwin.go index fdab73b6..eabf489f 100644 --- a/vendor/github.com/lucas-clemente/quic-go/conn_helper_darwin.go +++ b/vendor/github.com/lucas-clemente/quic-go/sys_conn_helper_darwin.go @@ -5,10 +5,7 @@ package quic import "golang.org/x/sys/unix" -const ( - msgTypeIPTOS = unix.IP_RECVTOS - disablePathMTUDiscovery = false -) +const msgTypeIPTOS = unix.IP_RECVTOS const ( ipv4RECVPKTINFO = unix.IP_RECVPKTINFO diff --git a/vendor/github.com/lucas-clemente/quic-go/conn_helper_freebsd.go b/vendor/github.com/lucas-clemente/quic-go/sys_conn_helper_freebsd.go similarity index 75% rename from vendor/github.com/lucas-clemente/quic-go/conn_helper_freebsd.go rename to vendor/github.com/lucas-clemente/quic-go/sys_conn_helper_freebsd.go index e22f9861..0b3e8434 100644 --- a/vendor/github.com/lucas-clemente/quic-go/conn_helper_freebsd.go +++ b/vendor/github.com/lucas-clemente/quic-go/sys_conn_helper_freebsd.go @@ -6,8 +6,7 @@ package quic import "golang.org/x/sys/unix" const ( - msgTypeIPTOS = unix.IP_RECVTOS - disablePathMTUDiscovery = false + msgTypeIPTOS = unix.IP_RECVTOS ) const ( diff --git a/vendor/github.com/lucas-clemente/quic-go/conn_helper_linux.go b/vendor/github.com/lucas-clemente/quic-go/sys_conn_helper_linux.go similarity index 81% rename from vendor/github.com/lucas-clemente/quic-go/conn_helper_linux.go rename to vendor/github.com/lucas-clemente/quic-go/sys_conn_helper_linux.go index 4aa04dc9..51bec900 100644 --- a/vendor/github.com/lucas-clemente/quic-go/conn_helper_linux.go +++ b/vendor/github.com/lucas-clemente/quic-go/sys_conn_helper_linux.go @@ -5,10 +5,7 @@ package quic import "golang.org/x/sys/unix" -const ( - msgTypeIPTOS = unix.IP_TOS - disablePathMTUDiscovery = false -) +const msgTypeIPTOS = unix.IP_TOS const ( ipv4RECVPKTINFO = unix.IP_PKTINFO diff --git a/vendor/github.com/lucas-clemente/quic-go/conn_generic.go b/vendor/github.com/lucas-clemente/quic-go/sys_conn_no_oob.go similarity index 75% rename from vendor/github.com/lucas-clemente/quic-go/conn_generic.go rename to vendor/github.com/lucas-clemente/quic-go/sys_conn_no_oob.go index 526778c1..e3b0d11f 100644 --- a/vendor/github.com/lucas-clemente/quic-go/conn_generic.go +++ b/vendor/github.com/lucas-clemente/quic-go/sys_conn_no_oob.go @@ -5,9 +5,7 @@ package quic import "net" -const disablePathMTUDiscovery = false - -func newConn(c net.PacketConn) (connection, error) { +func newConn(c net.PacketConn) (rawConn, error) { return &basicConn{PacketConn: c}, nil } diff --git a/vendor/github.com/lucas-clemente/quic-go/conn_oob.go b/vendor/github.com/lucas-clemente/quic-go/sys_conn_oob.go similarity index 99% rename from vendor/github.com/lucas-clemente/quic-go/conn_oob.go rename to vendor/github.com/lucas-clemente/quic-go/sys_conn_oob.go index b4678137..acd74d02 100644 --- a/vendor/github.com/lucas-clemente/quic-go/conn_oob.go +++ b/vendor/github.com/lucas-clemente/quic-go/sys_conn_oob.go @@ -64,7 +64,7 @@ type oobConn struct { buffers [batchSize]*packetBuffer } -var _ connection = &oobConn{} +var _ rawConn = &oobConn{} func newConn(c OOBCapablePacketConn) (*oobConn, error) { rawConn, err := c.SyscallConn() diff --git a/vendor/github.com/lucas-clemente/quic-go/conn_windows.go b/vendor/github.com/lucas-clemente/quic-go/sys_conn_windows.go similarity index 56% rename from vendor/github.com/lucas-clemente/quic-go/conn_windows.go rename to vendor/github.com/lucas-clemente/quic-go/sys_conn_windows.go index a6e591b6..f2cc22ab 100644 --- a/vendor/github.com/lucas-clemente/quic-go/conn_windows.go +++ b/vendor/github.com/lucas-clemente/quic-go/sys_conn_windows.go @@ -12,24 +12,7 @@ import ( "golang.org/x/sys/windows" ) -const ( - disablePathMTUDiscovery = true - IP_DONTFRAGMENT = 14 -) - -func newConn(c OOBCapablePacketConn) (connection, error) { - rawConn, err := c.SyscallConn() - if err != nil { - return nil, fmt.Errorf("couldn't get syscall.RawConn: %w", err) - } - if err := rawConn.Control(func(fd uintptr) { - // This should succeed if the connection is a IPv4 or a dual-stack connection. - // It will fail for IPv6 connections. - // TODO: properly handle error. - _ = windows.SetsockoptInt(windows.Handle(fd), windows.IPPROTO_IP, IP_DONTFRAGMENT, 1) - }); err != nil { - return nil, err - } +func newConn(c OOBCapablePacketConn) (rawConn, error) { return &basicConn{PacketConn: c}, nil } diff --git a/vendor/github.com/marten-seemann/qtls-go1-16/common.go b/vendor/github.com/marten-seemann/qtls-go1-16/common.go index 9d07e175..266f93fe 100644 --- a/vendor/github.com/marten-seemann/qtls-go1-16/common.go +++ b/vendor/github.com/marten-seemann/qtls-go1-16/common.go @@ -20,13 +20,10 @@ import ( "fmt" "io" "net" - "runtime" "sort" "strings" "sync" "time" - - "golang.org/x/sys/cpu" ) const ( @@ -1463,17 +1460,6 @@ func defaultCipherSuitesTLS13() []uint16 { return varDefaultCipherSuitesTLS13 } -var ( - hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ - hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL - // Keep in sync with crypto/aes/cipher_s390x.go. - hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM) - - hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 || - runtime.GOARCH == "arm64" && hasGCMAsmARM64 || - runtime.GOARCH == "s390x" && hasGCMAsmS390X -) - func initDefaultCipherSuites() { var topCipherSuites []uint16 diff --git a/vendor/github.com/marten-seemann/qtls-go1-16/common_js.go b/vendor/github.com/marten-seemann/qtls-go1-16/common_js.go new file mode 100644 index 00000000..97e6ecef --- /dev/null +++ b/vendor/github.com/marten-seemann/qtls-go1-16/common_js.go @@ -0,0 +1,12 @@ +// +build js + +package qtls + +var ( + hasGCMAsmAMD64 = false + hasGCMAsmARM64 = false + // Keep in sync with crypto/aes/cipher_s390x.go. + hasGCMAsmS390X = false + + hasAESGCMHardwareSupport = false +) diff --git a/vendor/github.com/marten-seemann/qtls-go1-16/common_nojs.go b/vendor/github.com/marten-seemann/qtls-go1-16/common_nojs.go new file mode 100644 index 00000000..5e56e0fb --- /dev/null +++ b/vendor/github.com/marten-seemann/qtls-go1-16/common_nojs.go @@ -0,0 +1,20 @@ +// +build !js + +package qtls + +import ( + "runtime" + + "golang.org/x/sys/cpu" +) + +var ( + hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ + hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL + // Keep in sync with crypto/aes/cipher_s390x.go. + hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM) + + hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 || + runtime.GOARCH == "arm64" && hasGCMAsmARM64 || + runtime.GOARCH == "s390x" && hasGCMAsmS390X +) diff --git a/vendor/github.com/marten-seemann/qtls-go1-17/cipher_suites.go b/vendor/github.com/marten-seemann/qtls-go1-17/cipher_suites.go index f2846642..53a3956a 100644 --- a/vendor/github.com/marten-seemann/qtls-go1-17/cipher_suites.go +++ b/vendor/github.com/marten-seemann/qtls-go1-17/cipher_suites.go @@ -15,10 +15,8 @@ import ( "crypto/sha256" "fmt" "hash" - "runtime" "golang.org/x/crypto/chacha20poly1305" - "golang.org/x/sys/cpu" ) // CipherSuite is a TLS cipher suite. Note that most functions in this package @@ -365,18 +363,6 @@ var defaultCipherSuitesTLS13NoAES = []uint16{ TLS_AES_256_GCM_SHA384, } -var ( - hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ - hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL - // Keep in sync with crypto/aes/cipher_s390x.go. - hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && - (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM) - - hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 || - runtime.GOARCH == "arm64" && hasGCMAsmARM64 || - runtime.GOARCH == "s390x" && hasGCMAsmS390X -) - var aesgcmCiphers = map[uint16]bool{ // TLS 1.2 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: true, diff --git a/vendor/github.com/marten-seemann/qtls-go1-17/cpu.go b/vendor/github.com/marten-seemann/qtls-go1-17/cpu.go new file mode 100644 index 00000000..12194508 --- /dev/null +++ b/vendor/github.com/marten-seemann/qtls-go1-17/cpu.go @@ -0,0 +1,22 @@ +//go:build !js +// +build !js + +package qtls + +import ( + "runtime" + + "golang.org/x/sys/cpu" +) + +var ( + hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ + hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL + // Keep in sync with crypto/aes/cipher_s390x.go. + hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && + (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM) + + hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 || + runtime.GOARCH == "arm64" && hasGCMAsmARM64 || + runtime.GOARCH == "s390x" && hasGCMAsmS390X +) diff --git a/vendor/github.com/marten-seemann/qtls-go1-17/cpu_other.go b/vendor/github.com/marten-seemann/qtls-go1-17/cpu_other.go new file mode 100644 index 00000000..33f7d219 --- /dev/null +++ b/vendor/github.com/marten-seemann/qtls-go1-17/cpu_other.go @@ -0,0 +1,12 @@ +//go:build js +// +build js + +package qtls + +var ( + hasGCMAsmAMD64 = false + hasGCMAsmARM64 = false + hasGCMAsmS390X = false + + hasAESGCMHardwareSupport = false +) diff --git a/vendor/github.com/marten-seemann/qtls-go1-18/cipher_suites.go b/vendor/github.com/marten-seemann/qtls-go1-18/cipher_suites.go index 2071cebf..e0be5147 100644 --- a/vendor/github.com/marten-seemann/qtls-go1-18/cipher_suites.go +++ b/vendor/github.com/marten-seemann/qtls-go1-18/cipher_suites.go @@ -15,10 +15,8 @@ import ( "crypto/sha256" "fmt" "hash" - "runtime" "golang.org/x/crypto/chacha20poly1305" - "golang.org/x/sys/cpu" ) // CipherSuite is a TLS cipher suite. Note that most functions in this package @@ -365,18 +363,6 @@ var defaultCipherSuitesTLS13NoAES = []uint16{ TLS_AES_256_GCM_SHA384, } -var ( - hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ - hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL - // Keep in sync with crypto/aes/cipher_s390x.go. - hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && - (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM) - - hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 || - runtime.GOARCH == "arm64" && hasGCMAsmARM64 || - runtime.GOARCH == "s390x" && hasGCMAsmS390X -) - var aesgcmCiphers = map[uint16]bool{ // TLS 1.2 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: true, diff --git a/vendor/github.com/marten-seemann/qtls-go1-18/cpu.go b/vendor/github.com/marten-seemann/qtls-go1-18/cpu.go new file mode 100644 index 00000000..12194508 --- /dev/null +++ b/vendor/github.com/marten-seemann/qtls-go1-18/cpu.go @@ -0,0 +1,22 @@ +//go:build !js +// +build !js + +package qtls + +import ( + "runtime" + + "golang.org/x/sys/cpu" +) + +var ( + hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ + hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL + // Keep in sync with crypto/aes/cipher_s390x.go. + hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && + (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM) + + hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 || + runtime.GOARCH == "arm64" && hasGCMAsmARM64 || + runtime.GOARCH == "s390x" && hasGCMAsmS390X +) diff --git a/vendor/github.com/marten-seemann/qtls-go1-18/cpu_other.go b/vendor/github.com/marten-seemann/qtls-go1-18/cpu_other.go new file mode 100644 index 00000000..33f7d219 --- /dev/null +++ b/vendor/github.com/marten-seemann/qtls-go1-18/cpu_other.go @@ -0,0 +1,12 @@ +//go:build js +// +build js + +package qtls + +var ( + hasGCMAsmAMD64 = false + hasGCMAsmARM64 = false + hasGCMAsmS390X = false + + hasAESGCMHardwareSupport = false +) diff --git a/vendor/modules.txt b/vendor/modules.txt index cc9abba7..d18395cb 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -201,7 +201,7 @@ github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc github.com/json-iterator/go # github.com/kylelemons/godebug v1.1.0 ## explicit; go 1.11 -# github.com/lucas-clemente/quic-go v0.24.0 => github.com/chungthuang/quic-go v0.24.1-0.20220110095058-981dc498cb62 +# github.com/lucas-clemente/quic-go v0.27.1 => github.com/chungthuang/quic-go v0.27.1-0.20220607112311-13144fbde8da ## explicit; go 1.16 github.com/lucas-clemente/quic-go github.com/lucas-clemente/quic-go/internal/ackhandler @@ -219,13 +219,13 @@ github.com/lucas-clemente/quic-go/quicvarint # github.com/lucasb-eyer/go-colorful v1.0.3 ## explicit; go 1.12 github.com/lucasb-eyer/go-colorful -# github.com/marten-seemann/qtls-go1-16 v0.1.4 +# github.com/marten-seemann/qtls-go1-16 v0.1.5 ## explicit; go 1.16 github.com/marten-seemann/qtls-go1-16 -# github.com/marten-seemann/qtls-go1-17 v0.1.0 +# github.com/marten-seemann/qtls-go1-17 v0.1.1 ## explicit; go 1.17 github.com/marten-seemann/qtls-go1-17 -# github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 +# github.com/marten-seemann/qtls-go1-18 v0.1.1 ## explicit; go 1.18 github.com/marten-seemann/qtls-go1-18 # github.com/mattn/go-colorable v0.1.8 @@ -612,5 +612,5 @@ zombiezen.com/go/capnproto2/schemas zombiezen.com/go/capnproto2/server zombiezen.com/go/capnproto2/std/capnp/rpc # github.com/urfave/cli/v2 => github.com/ipostelnik/cli/v2 v2.3.1-0.20210324024421-b6ea8234fe3d -# github.com/lucas-clemente/quic-go => github.com/chungthuang/quic-go v0.24.1-0.20220110095058-981dc498cb62 +# github.com/lucas-clemente/quic-go => github.com/chungthuang/quic-go v0.27.1-0.20220607112311-13144fbde8da # github.com/prometheus/golang_client => github.com/prometheus/golang_client v1.12.1