mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-03 20:27:35 +03:00
Merge branch 'upstream' into sync-upstream
This commit is contained in:
commit
856bc02b8f
130 changed files with 1364 additions and 463 deletions
|
@ -39,8 +39,6 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
|
|||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
|
@ -136,8 +134,8 @@ github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7q
|
|||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.0 h1:NrCXmDl8BddZwO67vlvEpBTwT89bJfKYygxv4HQvuDk=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.0/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
|
||||
|
@ -173,10 +171,11 @@ github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cb
|
|||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
go.uber.org/mock v0.2.0 h1:TaP3xedm7JaAgScZO7tlvlKrqT0p7I6OsdGB5YNSMDU=
|
||||
go.uber.org/mock v0.2.0/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM=
|
||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
|
@ -195,7 +194,7 @@ golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTk
|
|||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
|
@ -217,7 +216,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
|
@ -261,9 +259,7 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -309,7 +305,7 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
|
|||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
|
|
|
@ -201,6 +201,8 @@ var _ = Describe("Handshake tests", func() {
|
|||
Expect(errors.As(err, &transportErr)).To(BeTrue())
|
||||
Expect(transportErr.ErrorCode.IsCryptoError()).To(BeTrue())
|
||||
Expect(transportErr.Error()).To(ContainSubstring("x509: certificate is valid for localhost, not foo.bar"))
|
||||
var certErr *tls.CertificateVerificationError
|
||||
Expect(errors.As(transportErr, &certErr)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("fails the handshake if the client fails to provide the requested client cert", func() {
|
||||
|
@ -452,7 +454,7 @@ var _ = Describe("Handshake tests", func() {
|
|||
|
||||
It("rejects invalid Retry token with the INVALID_TOKEN error", func() {
|
||||
serverConfig.RequireAddressValidation = func(net.Addr) bool { return true }
|
||||
serverConfig.MaxRetryTokenAge = time.Nanosecond
|
||||
serverConfig.MaxRetryTokenAge = -time.Second
|
||||
|
||||
server, err := quic.ListenAddr("localhost:0", getTLSConfig(), serverConfig)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
|
|
@ -42,7 +42,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
rt *http3.RoundTripper
|
||||
server *http3.Server
|
||||
stoppedServing chan struct{}
|
||||
port string
|
||||
port int
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
|
@ -93,7 +93,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
Expect(err).NotTo(HaveOccurred())
|
||||
conn, err := net.ListenUDP("udp", addr)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
port = strconv.Itoa(conn.LocalAddr().(*net.UDPAddr).Port)
|
||||
port = conn.LocalAddr().(*net.UDPAddr).Port
|
||||
|
||||
stoppedServing = make(chan struct{})
|
||||
|
||||
|
@ -120,7 +120,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
})
|
||||
|
||||
It("downloads a hello", func() {
|
||||
resp, err := client.Get("https://localhost:" + port + "/hello")
|
||||
resp, err := client.Get(fmt.Sprintf("https://localhost:%d/hello", port))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(200))
|
||||
body, err := io.ReadAll(gbytes.TimeoutReader(resp.Body, 3*time.Second))
|
||||
|
@ -128,13 +128,25 @@ var _ = Describe("HTTP tests", func() {
|
|||
Expect(string(body)).To(Equal("Hello, World!\n"))
|
||||
})
|
||||
|
||||
It("sets content-length for small response", func() {
|
||||
mux.HandleFunc("/small", func(w http.ResponseWriter, r *http.Request) {
|
||||
defer GinkgoRecover()
|
||||
w.Write([]byte("foobar"))
|
||||
})
|
||||
|
||||
resp, err := client.Get(fmt.Sprintf("https://localhost:%d/small", port))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(200))
|
||||
Expect(resp.Header.Get("Content-Length")).To(Equal(strconv.Itoa(len("foobar"))))
|
||||
})
|
||||
|
||||
It("requests to different servers with the same udpconn", func() {
|
||||
resp, err := client.Get("https://localhost:" + port + "/remoteAddr")
|
||||
resp, err := client.Get(fmt.Sprintf("https://localhost:%d/remoteAddr", port))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(200))
|
||||
addr1 := resp.Header.Get("X-RemoteAddr")
|
||||
Expect(addr1).ToNot(Equal(""))
|
||||
resp, err = client.Get("https://127.0.0.1:" + port + "/remoteAddr")
|
||||
resp, err = client.Get(fmt.Sprintf("https://127.0.0.1:%d/remoteAddr", port))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(200))
|
||||
addr2 := resp.Header.Get("X-RemoteAddr")
|
||||
|
@ -146,7 +158,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
group, ctx := errgroup.WithContext(context.Background())
|
||||
for i := 0; i < 2; i++ {
|
||||
group.Go(func() error {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://localhost:"+port+"/hello", nil)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://localhost:%d/hello", port), nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
resp, err := client.Do(req)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
@ -172,7 +184,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
close(handlerCalled)
|
||||
})
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "https://localhost:"+port+"/headers/request", nil)
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("https://localhost:%d/headers/request", port), nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
req.Header.Set("foo", "bar")
|
||||
req.Header.Set("lorem", "ipsum")
|
||||
|
@ -189,7 +201,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
w.Header().Set("lorem", "ipsum")
|
||||
})
|
||||
|
||||
resp, err := client.Get("https://localhost:" + port + "/headers/response")
|
||||
resp, err := client.Get(fmt.Sprintf("https://localhost:%d/headers/response", port))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(200))
|
||||
Expect(resp.Header.Get("foo")).To(Equal("bar"))
|
||||
|
@ -197,7 +209,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
})
|
||||
|
||||
It("downloads a small file", func() {
|
||||
resp, err := client.Get("https://localhost:" + port + "/prdata")
|
||||
resp, err := client.Get(fmt.Sprintf("https://localhost:%d/prdata", port))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(200))
|
||||
body, err := io.ReadAll(gbytes.TimeoutReader(resp.Body, 5*time.Second))
|
||||
|
@ -206,7 +218,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
})
|
||||
|
||||
It("downloads a large file", func() {
|
||||
resp, err := client.Get("https://localhost:" + port + "/prdatalong")
|
||||
resp, err := client.Get(fmt.Sprintf("https://localhost:%d/prdatalong", port))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(200))
|
||||
body, err := io.ReadAll(gbytes.TimeoutReader(resp.Body, 20*time.Second))
|
||||
|
@ -218,7 +230,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
const num = 150
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
resp, err := client.Get("https://localhost:" + port + "/hello")
|
||||
resp, err := client.Get(fmt.Sprintf("https://localhost:%d/hello", port))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(200))
|
||||
body, err := io.ReadAll(gbytes.TimeoutReader(resp.Body, 3*time.Second))
|
||||
|
@ -231,7 +243,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
const num = 150
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
resp, err := client.Get("https://localhost:" + port + "/prdata")
|
||||
resp, err := client.Get(fmt.Sprintf("https://localhost:%d/prdata", port))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(200))
|
||||
Expect(resp.Body.Close()).To(Succeed())
|
||||
|
@ -240,7 +252,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
|
||||
It("posts a small message", func() {
|
||||
resp, err := client.Post(
|
||||
"https://localhost:"+port+"/echo",
|
||||
fmt.Sprintf("https://localhost:%d/echo", port),
|
||||
"text/plain",
|
||||
bytes.NewReader([]byte("Hello, world!")),
|
||||
)
|
||||
|
@ -253,7 +265,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
|
||||
It("uploads a file", func() {
|
||||
resp, err := client.Post(
|
||||
"https://localhost:"+port+"/echo",
|
||||
fmt.Sprintf("https://localhost:%d/echo", port),
|
||||
"text/plain",
|
||||
bytes.NewReader(PRData),
|
||||
)
|
||||
|
@ -277,7 +289,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
})
|
||||
|
||||
client.Transport.(*http3.RoundTripper).DisableCompression = false
|
||||
resp, err := client.Get("https://localhost:" + port + "/gzipped/hello")
|
||||
resp, err := client.Get(fmt.Sprintf("https://localhost:%d/gzipped/hello", port))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(200))
|
||||
Expect(resp.Uncompressed).To(BeTrue())
|
||||
|
@ -303,7 +315,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
}
|
||||
})
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "https://localhost:"+port+"/cancel", nil)
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("https://localhost:%d/cancel", port), nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
req = req.WithContext(ctx)
|
||||
|
@ -336,7 +348,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
})
|
||||
|
||||
r, w := io.Pipe()
|
||||
req, err := http.NewRequest("PUT", "https://localhost:"+port+"/echoline", r)
|
||||
req, err := http.NewRequest(http.MethodPut, fmt.Sprintf("https://localhost:%d/echoline", port), r)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
rsp, err := client.Do(req)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
@ -373,7 +385,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
}()
|
||||
})
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "https://localhost:"+port+"/httpstreamer", nil)
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("https://localhost:%d/httpstreamer", port), nil)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
rsp, err := client.Transport.(*http3.RoundTripper).RoundTripOpt(req, http3.RoundTripOpt{DontCloseRequestStream: true})
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
@ -431,7 +443,11 @@ var _ = Describe("HTTP tests", func() {
|
|||
})
|
||||
|
||||
expectedEnd := time.Now().Add(deadlineDelay)
|
||||
resp, err := client.Post("https://localhost:"+port+"/read-deadline", "text/plain", neverEnding('a'))
|
||||
resp, err := client.Post(
|
||||
fmt.Sprintf("https://localhost:%d/read-deadline", port),
|
||||
"text/plain",
|
||||
neverEnding('a'),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(200))
|
||||
|
||||
|
@ -453,7 +469,7 @@ var _ = Describe("HTTP tests", func() {
|
|||
|
||||
expectedEnd := time.Now().Add(deadlineDelay)
|
||||
|
||||
resp, err := client.Get("https://localhost:" + port + "/write-deadline")
|
||||
resp, err := client.Get(fmt.Sprintf("https://localhost:%d/write-deadline", port))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(resp.StatusCode).To(Equal(200))
|
||||
|
||||
|
|
|
@ -2,9 +2,11 @@ package self_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"io"
|
||||
"net"
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
@ -209,4 +211,67 @@ var _ = Describe("Multiplexing", func() {
|
|||
})
|
||||
}
|
||||
})
|
||||
|
||||
It("sends and receives non-QUIC packets", func() {
|
||||
addr1, err := net.ResolveUDPAddr("udp", "localhost:0")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
conn1, err := net.ListenUDP("udp", addr1)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer conn1.Close()
|
||||
tr1 := &quic.Transport{Conn: conn1}
|
||||
|
||||
addr2, err := net.ResolveUDPAddr("udp", "localhost:0")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
conn2, err := net.ListenUDP("udp", addr2)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer conn2.Close()
|
||||
tr2 := &quic.Transport{Conn: conn2}
|
||||
|
||||
server, err := tr1.Listen(getTLSConfig(), getQuicConfig(nil))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
runServer(server)
|
||||
defer server.Close()
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
var sentPackets, rcvdPackets atomic.Int64
|
||||
const packetLen = 128
|
||||
// send a non-QUIC packet every 100µs
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
ticker := time.NewTicker(time.Millisecond / 10)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
b := make([]byte, packetLen)
|
||||
rand.Read(b[1:]) // keep the first byte set to 0, so it's not classified as a QUIC packet
|
||||
_, err := tr1.WriteTo(b, tr2.Conn.LocalAddr())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
sentPackets.Add(1)
|
||||
}
|
||||
}()
|
||||
|
||||
// receive and count non-QUIC packets
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
for {
|
||||
b := make([]byte, 1024)
|
||||
n, addr, err := tr2.ReadNonQUICPacket(ctx, b)
|
||||
if err != nil {
|
||||
Expect(err).To(MatchError(context.Canceled))
|
||||
return
|
||||
}
|
||||
Expect(addr).To(Equal(tr1.Conn.LocalAddr()))
|
||||
Expect(n).To(Equal(packetLen))
|
||||
rcvdPackets.Add(1)
|
||||
}
|
||||
}()
|
||||
dial(tr2, server.Addr())
|
||||
Eventually(func() int64 { return sentPackets.Load() }).Should(BeNumerically(">", 10))
|
||||
Eventually(func() int64 { return rcvdPackets.Load() }).Should(BeNumerically(">=", sentPackets.Load()*4/5))
|
||||
})
|
||||
})
|
||||
|
|
|
@ -56,7 +56,7 @@ var _ = Describe("TLS session resumption", func() {
|
|||
context.Background(),
|
||||
fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
|
||||
tlsConf,
|
||||
nil,
|
||||
getQuicConfig(nil),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
var sessionKey string
|
||||
|
@ -71,7 +71,7 @@ var _ = Describe("TLS session resumption", func() {
|
|||
context.Background(),
|
||||
fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
|
||||
tlsConf,
|
||||
nil,
|
||||
getQuicConfig(nil),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(gets).To(Receive(Equal(sessionKey)))
|
||||
|
@ -85,7 +85,7 @@ var _ = Describe("TLS session resumption", func() {
|
|||
It("doesn't use session resumption, if the config disables it", func() {
|
||||
sConf := getTLSConfig()
|
||||
sConf.SessionTicketsDisabled = true
|
||||
server, err := quic.ListenAddr("localhost:0", sConf, nil)
|
||||
server, err := quic.ListenAddr("localhost:0", sConf, getQuicConfig(nil))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer server.Close()
|
||||
|
||||
|
@ -98,7 +98,7 @@ var _ = Describe("TLS session resumption", func() {
|
|||
context.Background(),
|
||||
fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
|
||||
tlsConf,
|
||||
nil,
|
||||
getQuicConfig(nil),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Consistently(puts).ShouldNot(Receive())
|
||||
|
@ -114,7 +114,55 @@ var _ = Describe("TLS session resumption", func() {
|
|||
context.Background(),
|
||||
fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
|
||||
tlsConf,
|
||||
nil,
|
||||
getQuicConfig(nil),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(conn.ConnectionState().TLS.DidResume).To(BeFalse())
|
||||
|
||||
serverConn, err = server.Accept(context.Background())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(serverConn.ConnectionState().TLS.DidResume).To(BeFalse())
|
||||
})
|
||||
|
||||
It("doesn't use session resumption, if the config returned by GetConfigForClient disables it", func() {
|
||||
sConf := &tls.Config{
|
||||
GetConfigForClient: func(*tls.ClientHelloInfo) (*tls.Config, error) {
|
||||
conf := getTLSConfig()
|
||||
conf.SessionTicketsDisabled = true
|
||||
return conf, nil
|
||||
},
|
||||
}
|
||||
|
||||
server, err := quic.ListenAddr("localhost:0", sConf, getQuicConfig(nil))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer server.Close()
|
||||
|
||||
gets := make(chan string, 100)
|
||||
puts := make(chan string, 100)
|
||||
cache := newClientSessionCache(tls.NewLRUClientSessionCache(10), gets, puts)
|
||||
tlsConf := getTLSClientConfig()
|
||||
tlsConf.ClientSessionCache = cache
|
||||
conn, err := quic.DialAddr(
|
||||
context.Background(),
|
||||
fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
|
||||
tlsConf,
|
||||
getQuicConfig(nil),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Consistently(puts).ShouldNot(Receive())
|
||||
Expect(conn.ConnectionState().TLS.DidResume).To(BeFalse())
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
serverConn, err := server.Accept(ctx)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(serverConn.ConnectionState().TLS.DidResume).To(BeFalse())
|
||||
|
||||
conn, err = quic.DialAddr(
|
||||
context.Background(),
|
||||
fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
|
||||
tlsConf,
|
||||
getQuicConfig(nil),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(conn.ConnectionState().TLS.DidResume).To(BeFalse())
|
||||
|
|
|
@ -802,4 +802,116 @@ var _ = Describe("0-RTT", func() {
|
|||
Expect(len(zeroRTTPackets)).To(BeNumerically(">", 10))
|
||||
Expect(zeroRTTPackets[0]).To(Equal(protocol.PacketNumber(0)))
|
||||
})
|
||||
|
||||
It("sends 0-RTT datagrams", func() {
|
||||
tlsConf, clientTLSConf := dialAndReceiveSessionTicket(getQuicConfig(&quic.Config{
|
||||
EnableDatagrams: true,
|
||||
}))
|
||||
|
||||
tracer := newPacketTracer()
|
||||
ln, err := quic.ListenAddrEarly(
|
||||
"localhost:0",
|
||||
tlsConf,
|
||||
getQuicConfig(&quic.Config{
|
||||
Allow0RTT: true,
|
||||
EnableDatagrams: true,
|
||||
Tracer: newTracer(tracer),
|
||||
}),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer ln.Close()
|
||||
|
||||
proxy, num0RTTPackets := runCountingProxy(ln.Addr().(*net.UDPAddr).Port)
|
||||
defer proxy.Close()
|
||||
|
||||
// second connection
|
||||
sentMessage := GeneratePRData(100)
|
||||
var receivedMessage []byte
|
||||
received := make(chan struct{})
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
defer close(received)
|
||||
conn, err := ln.Accept(context.Background())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
receivedMessage, err = conn.ReceiveMessage(context.Background())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(conn.ConnectionState().Used0RTT).To(BeTrue())
|
||||
}()
|
||||
conn, err := quic.DialAddrEarly(
|
||||
context.Background(),
|
||||
fmt.Sprintf("localhost:%d", proxy.LocalPort()),
|
||||
clientTLSConf,
|
||||
getQuicConfig(&quic.Config{
|
||||
EnableDatagrams: true,
|
||||
}),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(conn.ConnectionState().SupportsDatagrams).To(BeTrue())
|
||||
Expect(conn.SendMessage(sentMessage)).To(Succeed())
|
||||
<-conn.HandshakeComplete()
|
||||
<-received
|
||||
|
||||
Expect(conn.ConnectionState().Used0RTT).To(BeTrue())
|
||||
Expect(receivedMessage).To(Equal(sentMessage))
|
||||
num0RTT := atomic.LoadUint32(num0RTTPackets)
|
||||
fmt.Fprintf(GinkgoWriter, "Sent %d 0-RTT packets.", num0RTT)
|
||||
Expect(num0RTT).ToNot(BeZero())
|
||||
zeroRTTPackets := get0RTTPackets(tracer.getRcvdLongHeaderPackets())
|
||||
Expect(zeroRTTPackets).To(HaveLen(1))
|
||||
Expect(conn.CloseWithError(0, "")).To(Succeed())
|
||||
})
|
||||
|
||||
It("rejects 0-RTT datagrams when the server doesn't support datagrams anymore", func() {
|
||||
tlsConf, clientTLSConf := dialAndReceiveSessionTicket(getQuicConfig(&quic.Config{
|
||||
EnableDatagrams: true,
|
||||
}))
|
||||
|
||||
tracer := newPacketTracer()
|
||||
ln, err := quic.ListenAddrEarly(
|
||||
"localhost:0",
|
||||
tlsConf,
|
||||
getQuicConfig(&quic.Config{
|
||||
Allow0RTT: true,
|
||||
EnableDatagrams: false,
|
||||
Tracer: newTracer(tracer),
|
||||
}),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer ln.Close()
|
||||
|
||||
proxy, num0RTTPackets := runCountingProxy(ln.Addr().(*net.UDPAddr).Port)
|
||||
defer proxy.Close()
|
||||
|
||||
// second connection
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
conn, err := ln.Accept(context.Background())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err = conn.ReceiveMessage(context.Background())
|
||||
Expect(err.Error()).To(Equal("datagram support disabled"))
|
||||
<-conn.HandshakeComplete()
|
||||
Expect(conn.ConnectionState().Used0RTT).To(BeFalse())
|
||||
}()
|
||||
conn, err := quic.DialAddrEarly(
|
||||
context.Background(),
|
||||
fmt.Sprintf("localhost:%d", proxy.LocalPort()),
|
||||
clientTLSConf,
|
||||
getQuicConfig(&quic.Config{
|
||||
EnableDatagrams: true,
|
||||
}),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// the client can temporarily send datagrams but the server doesn't process them.
|
||||
Expect(conn.ConnectionState().SupportsDatagrams).To(BeTrue())
|
||||
Expect(conn.SendMessage(make([]byte, 100))).To(Succeed())
|
||||
<-conn.HandshakeComplete()
|
||||
|
||||
Expect(conn.ConnectionState().SupportsDatagrams).To(BeFalse())
|
||||
Expect(conn.ConnectionState().Used0RTT).To(BeFalse())
|
||||
num0RTT := atomic.LoadUint32(num0RTTPackets)
|
||||
fmt.Fprintf(GinkgoWriter, "Sent %d 0-RTT packets.", num0RTT)
|
||||
Expect(num0RTT).ToNot(BeZero())
|
||||
Expect(get0RTTPackets(tracer.getRcvdLongHeaderPackets())).To(BeEmpty())
|
||||
Expect(conn.CloseWithError(0, "")).To(Succeed())
|
||||
})
|
||||
})
|
||||
|
|
|
@ -939,4 +939,119 @@ var _ = Describe("0-RTT", func() {
|
|||
)
|
||||
Expect(restored).To(BeTrue())
|
||||
})
|
||||
|
||||
It("sends 0-RTT datagrams", func() {
|
||||
tlsConf := getTLSConfig()
|
||||
clientTLSConf := getTLSClientConfig()
|
||||
dialAndReceiveSessionTicket(tlsConf, getQuicConfig(&quic.Config{
|
||||
EnableDatagrams: true,
|
||||
}), clientTLSConf)
|
||||
|
||||
tracer := newPacketTracer()
|
||||
ln, err := quic.ListenAddrEarly(
|
||||
"localhost:0",
|
||||
tlsConf,
|
||||
getQuicConfig(&quic.Config{
|
||||
Allow0RTT: true,
|
||||
EnableDatagrams: true,
|
||||
Tracer: newTracer(tracer),
|
||||
}),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer ln.Close()
|
||||
proxy, num0RTTPackets := runCountingProxy(ln.Addr().(*net.UDPAddr).Port)
|
||||
defer proxy.Close()
|
||||
|
||||
// second connection
|
||||
sentMessage := GeneratePRData(100)
|
||||
var receivedMessage []byte
|
||||
received := make(chan struct{})
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
defer close(received)
|
||||
conn, err := ln.Accept(context.Background())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
receivedMessage, err = conn.ReceiveMessage(context.Background())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(conn.ConnectionState().Used0RTT).To(BeTrue())
|
||||
}()
|
||||
conn, err := quic.DialAddrEarly(
|
||||
context.Background(),
|
||||
fmt.Sprintf("localhost:%d", proxy.LocalPort()),
|
||||
clientTLSConf,
|
||||
getQuicConfig(&quic.Config{
|
||||
EnableDatagrams: true,
|
||||
}),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(conn.ConnectionState().SupportsDatagrams).To(BeTrue())
|
||||
Expect(conn.SendMessage(sentMessage)).To(Succeed())
|
||||
<-conn.HandshakeComplete()
|
||||
<-received
|
||||
|
||||
Expect(conn.ConnectionState().Used0RTT).To(BeTrue())
|
||||
Expect(receivedMessage).To(Equal(sentMessage))
|
||||
num0RTT := atomic.LoadUint32(num0RTTPackets)
|
||||
fmt.Fprintf(GinkgoWriter, "Sent %d 0-RTT packets.", num0RTT)
|
||||
Expect(num0RTT).ToNot(BeZero())
|
||||
zeroRTTPackets := get0RTTPackets(tracer.getRcvdLongHeaderPackets())
|
||||
Expect(zeroRTTPackets).To(HaveLen(1))
|
||||
Expect(conn.CloseWithError(0, "")).To(Succeed())
|
||||
})
|
||||
|
||||
It("rejects 0-RTT datagrams when the server doesn't support datagrams anymore", func() {
|
||||
tlsConf := getTLSConfig()
|
||||
clientTLSConf := getTLSClientConfig()
|
||||
dialAndReceiveSessionTicket(tlsConf, getQuicConfig(&quic.Config{
|
||||
EnableDatagrams: true,
|
||||
}), clientTLSConf)
|
||||
|
||||
tracer := newPacketTracer()
|
||||
ln, err := quic.ListenAddrEarly(
|
||||
"localhost:0",
|
||||
tlsConf,
|
||||
getQuicConfig(&quic.Config{
|
||||
Allow0RTT: true,
|
||||
EnableDatagrams: false,
|
||||
Tracer: newTracer(tracer),
|
||||
}),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
defer ln.Close()
|
||||
|
||||
proxy, num0RTTPackets := runCountingProxy(ln.Addr().(*net.UDPAddr).Port)
|
||||
defer proxy.Close()
|
||||
|
||||
// second connection
|
||||
go func() {
|
||||
defer GinkgoRecover()
|
||||
conn, err := ln.Accept(context.Background())
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err = conn.ReceiveMessage(context.Background())
|
||||
Expect(err.Error()).To(Equal("datagram support disabled"))
|
||||
<-conn.HandshakeComplete()
|
||||
Expect(conn.ConnectionState().Used0RTT).To(BeFalse())
|
||||
}()
|
||||
conn, err := quic.DialAddrEarly(
|
||||
context.Background(),
|
||||
fmt.Sprintf("localhost:%d", proxy.LocalPort()),
|
||||
clientTLSConf,
|
||||
getQuicConfig(&quic.Config{
|
||||
EnableDatagrams: true,
|
||||
}),
|
||||
)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// the client can temporarily send datagrams but the server doesn't process them.
|
||||
Expect(conn.ConnectionState().SupportsDatagrams).To(BeTrue())
|
||||
Expect(conn.SendMessage(make([]byte, 100))).To(Succeed())
|
||||
<-conn.HandshakeComplete()
|
||||
|
||||
Expect(conn.ConnectionState().SupportsDatagrams).To(BeFalse())
|
||||
Expect(conn.ConnectionState().Used0RTT).To(BeFalse())
|
||||
num0RTT := atomic.LoadUint32(num0RTTPackets)
|
||||
fmt.Fprintf(GinkgoWriter, "Sent %d 0-RTT packets.", num0RTT)
|
||||
Expect(num0RTT).ToNot(BeZero())
|
||||
Expect(get0RTTPackets(tracer.getRcvdLongHeaderPackets())).To(BeEmpty())
|
||||
Expect(conn.CloseWithError(0, "")).To(Succeed())
|
||||
})
|
||||
})
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -68,7 +69,11 @@ var _ = Describe("QUIC Proxy", func() {
|
|||
addr, err := net.ResolveUDPAddr("udp", "localhost:"+strconv.Itoa(proxy.LocalPort()))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
_, err = net.ListenUDP("udp", addr)
|
||||
Expect(err).To(MatchError(fmt.Sprintf("listen udp 127.0.0.1:%d: bind: address already in use", proxy.LocalPort())))
|
||||
if runtime.GOOS == "windows" {
|
||||
Expect(err).To(MatchError(fmt.Sprintf("listen udp 127.0.0.1:%d: bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.", proxy.LocalPort())))
|
||||
} else {
|
||||
Expect(err).To(MatchError(fmt.Sprintf("listen udp 127.0.0.1:%d: bind: address already in use", proxy.LocalPort())))
|
||||
}
|
||||
Expect(proxy.Close()).To(Succeed()) // stopping is tested in the next test
|
||||
})
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue