forked from quic-go/quic-go
Merge pull request #2329 from lucas-clemente/interop-0rtt
add support for the upcoming 0-RTT interop test case
This commit is contained in:
@@ -74,14 +74,16 @@ func runTestcase(testcase string) error {
|
|||||||
QuicConfig: quicConf,
|
QuicConfig: quicConf,
|
||||||
}
|
}
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
return downloadFiles(r, urls)
|
return downloadFiles(r, urls, false)
|
||||||
case "handshake", "transfer", "retry":
|
case "handshake", "transfer", "retry":
|
||||||
case "multiconnect":
|
case "multiconnect":
|
||||||
return runMultiConnectTest(urls)
|
return runMultiConnectTest(urls)
|
||||||
case "versionnegotiation":
|
case "versionnegotiation":
|
||||||
return runVersionNegotiationTest(urls)
|
return runVersionNegotiationTest(urls)
|
||||||
case "resumption":
|
case "resumption":
|
||||||
return runResumptionTest(urls)
|
return runResumptionTest(urls, false)
|
||||||
|
case "zerortt":
|
||||||
|
return runResumptionTest(urls, true)
|
||||||
default:
|
default:
|
||||||
return errUnsupported
|
return errUnsupported
|
||||||
}
|
}
|
||||||
@@ -91,7 +93,7 @@ func runTestcase(testcase string) error {
|
|||||||
QuicConfig: quicConf,
|
QuicConfig: quicConf,
|
||||||
}
|
}
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
return downloadFiles(r, urls)
|
return downloadFiles(r, urls, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runVersionNegotiationTest(urls []string) error {
|
func runVersionNegotiationTest(urls []string) error {
|
||||||
@@ -99,7 +101,7 @@ func runVersionNegotiationTest(urls []string) error {
|
|||||||
return errors.New("expected at least 2 URLs")
|
return errors.New("expected at least 2 URLs")
|
||||||
}
|
}
|
||||||
protocol.SupportedVersions = []protocol.VersionNumber{0x1a2a3a4a}
|
protocol.SupportedVersions = []protocol.VersionNumber{0x1a2a3a4a}
|
||||||
err := downloadFile(&http09.RoundTripper{}, urls[0])
|
err := downloadFile(&http09.RoundTripper{}, urls[0], false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return errors.New("expected version negotiation to fail")
|
return errors.New("expected version negotiation to fail")
|
||||||
}
|
}
|
||||||
@@ -112,7 +114,7 @@ func runVersionNegotiationTest(urls []string) error {
|
|||||||
func runMultiConnectTest(urls []string) error {
|
func runMultiConnectTest(urls []string) error {
|
||||||
for _, url := range urls {
|
for _, url := range urls {
|
||||||
r := &http09.RoundTripper{TLSClientConfig: tlsConf}
|
r := &http09.RoundTripper{TLSClientConfig: tlsConf}
|
||||||
if err := downloadFile(r, url); err != nil {
|
if err := downloadFile(r, url, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := r.Close(); err != nil {
|
if err := r.Close(); err != nil {
|
||||||
@@ -122,7 +124,7 @@ func runMultiConnectTest(urls []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runResumptionTest(urls []string) error {
|
func runResumptionTest(urls []string, use0RTT bool) error {
|
||||||
if len(urls) < 2 {
|
if len(urls) < 2 {
|
||||||
return errors.New("expected at least 2 URLs")
|
return errors.New("expected at least 2 URLs")
|
||||||
}
|
}
|
||||||
@@ -131,7 +133,7 @@ func runResumptionTest(urls []string) error {
|
|||||||
|
|
||||||
// do the first transfer
|
// do the first transfer
|
||||||
r := &http09.RoundTripper{TLSClientConfig: tlsConf}
|
r := &http09.RoundTripper{TLSClientConfig: tlsConf}
|
||||||
if err := downloadFiles(r, urls[:1]); err != nil {
|
if err := downloadFiles(r, urls[:1], false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r.Close()
|
r.Close()
|
||||||
@@ -139,22 +141,26 @@ func runResumptionTest(urls []string) error {
|
|||||||
// reestablish the connection, using the session ticket that the server (hopefully provided)
|
// reestablish the connection, using the session ticket that the server (hopefully provided)
|
||||||
r = &http09.RoundTripper{TLSClientConfig: tlsConf}
|
r = &http09.RoundTripper{TLSClientConfig: tlsConf}
|
||||||
defer r.Close()
|
defer r.Close()
|
||||||
return downloadFiles(r, urls[1:])
|
return downloadFiles(r, urls[1:], use0RTT)
|
||||||
}
|
}
|
||||||
|
|
||||||
func downloadFiles(cl http.RoundTripper, urls []string) error {
|
func downloadFiles(cl http.RoundTripper, urls []string, use0RTT bool) error {
|
||||||
var g errgroup.Group
|
var g errgroup.Group
|
||||||
for _, u := range urls {
|
for _, u := range urls {
|
||||||
url := u
|
url := u
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
return downloadFile(cl, url)
|
return downloadFile(cl, url, use0RTT)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return g.Wait()
|
return g.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func downloadFile(cl http.RoundTripper, url string) error {
|
func downloadFile(cl http.RoundTripper, url string, use0RTT bool) error {
|
||||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
method := http.MethodGet
|
||||||
|
if use0RTT {
|
||||||
|
method = http09.MethodGet0RTT
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest(method, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ import (
|
|||||||
"github.com/lucas-clemente/quic-go"
|
"github.com/lucas-clemente/quic-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MethodGet0RTT allows a GET request to be sent using 0-RTT.
|
||||||
|
// Note that 0-RTT data doesn't provide replay protection.
|
||||||
|
const MethodGet0RTT = "GET_0RTT"
|
||||||
|
|
||||||
// RoundTripper performs HTTP/0.9 roundtrips over QUIC.
|
// RoundTripper performs HTTP/0.9 roundtrips over QUIC.
|
||||||
type RoundTripper struct {
|
type RoundTripper struct {
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
@@ -30,7 +34,7 @@ var _ http.RoundTripper = &RoundTripper{}
|
|||||||
// RoundTrip performs a HTTP/0.9 request.
|
// RoundTrip performs a HTTP/0.9 request.
|
||||||
// It only supports GET requests.
|
// It only supports GET requests.
|
||||||
func (r *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
func (r *RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
if req.Method != http.MethodGet {
|
if req.Method != http.MethodGet && req.Method != MethodGet0RTT {
|
||||||
return nil, errors.New("only GET requests supported")
|
return nil, errors.New("only GET requests supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,17 +80,20 @@ type client struct {
|
|||||||
quicConf *quic.Config
|
quicConf *quic.Config
|
||||||
|
|
||||||
once sync.Once
|
once sync.Once
|
||||||
sess quic.Session
|
sess quic.EarlySession
|
||||||
dialErr error
|
dialErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *client) RoundTrip(req *http.Request) (*http.Response, error) {
|
func (c *client) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
c.once.Do(func() {
|
c.once.Do(func() {
|
||||||
c.sess, c.dialErr = quic.DialAddr(c.hostname, c.tlsConf, c.quicConf)
|
c.sess, c.dialErr = quic.DialAddrEarly(c.hostname, c.tlsConf, c.quicConf)
|
||||||
})
|
})
|
||||||
if c.dialErr != nil {
|
if c.dialErr != nil {
|
||||||
return nil, c.dialErr
|
return nil, c.dialErr
|
||||||
}
|
}
|
||||||
|
if req.Method != MethodGet0RTT {
|
||||||
|
<-c.sess.HandshakeComplete().Done()
|
||||||
|
}
|
||||||
return c.doRequest(req)
|
return c.doRequest(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ var _ = Describe("HTTP 0.9 integration tests", func() {
|
|||||||
defer close(done)
|
defer close(done)
|
||||||
_ = server.ListenAndServe()
|
_ = server.ListenAndServe()
|
||||||
}()
|
}()
|
||||||
var ln quic.Listener
|
var ln quic.EarlyListener
|
||||||
Eventually(func() quic.Listener {
|
Eventually(func() quic.EarlyListener {
|
||||||
server.mutex.Lock()
|
server.mutex.Lock()
|
||||||
defer server.mutex.Unlock()
|
defer server.mutex.Unlock()
|
||||||
ln = server.listener
|
ln = server.listener
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ type Server struct {
|
|||||||
QuicConfig *quic.Config
|
QuicConfig *quic.Config
|
||||||
|
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
listener quic.Listener
|
listener quic.EarlyListener
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the server.
|
// Close closes the server.
|
||||||
@@ -69,7 +69,7 @@ func (s *Server) ListenAndServe() error {
|
|||||||
|
|
||||||
tlsConf := s.TLSConfig.Clone()
|
tlsConf := s.TLSConfig.Clone()
|
||||||
tlsConf.NextProtos = []string{h09alpn}
|
tlsConf.NextProtos = []string{h09alpn}
|
||||||
ln, err := quic.Listen(conn, tlsConf, s.QuicConfig)
|
ln, err := quic.ListenEarly(conn, tlsConf, s.QuicConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ func main() {
|
|||||||
tlsConf.KeyLogWriter = keyLog
|
tlsConf.KeyLogWriter = keyLog
|
||||||
|
|
||||||
switch testcase {
|
switch testcase {
|
||||||
case "versionnegotiation", "handshake", "transfer", "resumption", "multiconnect":
|
case "versionnegotiation", "handshake", "transfer", "resumption", "zerortt", "multiconnect":
|
||||||
err = runHTTP09Server(quicConf)
|
err = runHTTP09Server(quicConf)
|
||||||
case "retry":
|
case "retry":
|
||||||
// By default, quic-go performs a Retry on every incoming connection.
|
// By default, quic-go performs a Retry on every incoming connection.
|
||||||
|
|||||||
Reference in New Issue
Block a user