diff --git a/go.mod b/go.mod index 57353d8..0afcf26 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/gorilla/websocket v1.5.0 github.com/hexops/gotextdiff v1.0.3 github.com/iancoleman/strcase v0.2.0 - github.com/lucas-clemente/quic-go v0.26.0 + github.com/lucas-clemente/quic-go v0.27.0 github.com/marten-seemann/qtls-go1-17 v0.1.1 github.com/mattn/go-colorable v0.1.12 github.com/miekg/dns v1.1.48 @@ -40,6 +40,7 @@ require ( golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 golang.org/x/net v0.0.0-20220412020605-290c469a71a5 golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 + gopkg.in/yaml.v2 v2.4.0 upper.io/db.v3 v3.8.0+incompatible ) diff --git a/go.sum b/go.sum index 800ca52..409cea1 100644 --- a/go.sum +++ b/go.sum @@ -437,8 +437,8 @@ github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E= github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= -github.com/lucas-clemente/quic-go v0.26.0 h1:ALBQXr9UJ8A1LyzvceX4jd9QFsHvlI0RR6BkV16o00A= -github.com/lucas-clemente/quic-go v0.26.0/go.mod h1:AzgQoPda7N+3IqMMMkywBKggIFo2KT6pfnlrQ2QieeI= +github.com/lucas-clemente/quic-go v0.27.0 h1:v6WY87q9zD4dKASbG8hy/LpzAVNzEQzw8sEIeloJsc4= +github.com/lucas-clemente/quic-go v0.27.0/go.mod h1:AzgQoPda7N+3IqMMMkywBKggIFo2KT6pfnlrQ2QieeI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= diff --git a/internal/archival/quic.go b/internal/archival/quic.go index 7cf3990..5e34c69 100644 --- a/internal/archival/quic.go +++ b/internal/archival/quic.go @@ -59,7 +59,7 @@ func (s *Saver) safeAddrString(addr net.Addr) (out string) { // QUICDialContext dials a QUIC session using the given dialer // and saves the results inside of the saver. func (s *Saver) QUICDialContext(ctx context.Context, dialer model.QUICDialer, - network, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) { + network, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { started := time.Now() var state tls.ConnectionState sess, err := dialer.DialContext(ctx, network, address, tlsConfig, quicConfig) diff --git a/internal/archival/quic_test.go b/internal/archival/quic_test.go index f2237cc..f7a0341 100644 --- a/internal/archival/quic_test.go +++ b/internal/archival/quic_test.go @@ -184,20 +184,20 @@ func TestSaverReadFrom(t *testing.T) { func TestSaverQUICDialContext(t *testing.T) { // newQUICDialer creates a new QUICDialer for testing. - newQUICDialer := func(sess quic.EarlySession, err error) model.QUICDialer { + newQUICDialer := func(qconn quic.EarlyConnection, err error) model.QUICDialer { return &mocks.QUICDialer{ MockDialContext: func( ctx context.Context, network, address string, tlsConfig *tls.Config, - quicConfig *quic.Config) (quic.EarlySession, error) { + quicConfig *quic.Config) (quic.EarlyConnection, error) { time.Sleep(time.Microsecond) - return sess, err + return qconn, err }, } } - // newQUICSession creates a new quic.EarlySession for testing. - newQUICSession := func(handshakeComplete context.Context, state tls.ConnectionState) quic.EarlySession { - return &mocks.QUICEarlySession{ + // newQUICConnection creates a new quic.EarlyConnection for testing. + newQUICConnection := func(handshakeComplete context.Context, state tls.ConnectionState) quic.EarlyConnection { + return &mocks.QUICEarlyConnection{ MockHandshakeComplete: func() context.Context { return handshakeComplete }, @@ -245,18 +245,18 @@ func TestSaverQUICDialContext(t *testing.T) { ExpectedFailure: nil, Saver: saver, } - sess := newQUICSession(handshakeCtx, v.NewTLSConnectionState()) - dialer := newQUICDialer(sess, nil) + qconn := newQUICConnection(handshakeCtx, v.NewTLSConnectionState()) + dialer := newQUICDialer(qconn, nil) ctx := context.Background() - sess, err := saver.QUICDialContext(ctx, dialer, expectedNetwork, + qconn, err := saver.QUICDialContext(ctx, dialer, expectedNetwork, mockedEndpoint, v.NewTLSConfig(), v.QUICConfig) if err != nil { t.Fatal(err) } - if sess == nil { - t.Fatal("expected nil sess") + if qconn == nil { + t.Fatal("expected nil qconn") } - sess.CloseWithError(0, "") + qconn.CloseWithError(0, "") if err := v.Validate(); err != nil { t.Fatal(err) } @@ -287,18 +287,18 @@ func TestSaverQUICDialContext(t *testing.T) { ExpectedFailure: context.DeadlineExceeded, Saver: saver, } - sess := newQUICSession(handshakeCtx, tls.ConnectionState{}) - dialer := newQUICDialer(sess, nil) + qconn := newQUICConnection(handshakeCtx, tls.ConnectionState{}) + dialer := newQUICDialer(qconn, nil) ctx := context.Background() ctx, cancel := context.WithTimeout(ctx, time.Microsecond) defer cancel() - sess, err := saver.QUICDialContext(ctx, dialer, expectedNetwork, + qconn, err := saver.QUICDialContext(ctx, dialer, expectedNetwork, mockedEndpoint, v.NewTLSConfig(), v.QUICConfig) if !errors.Is(err, context.DeadlineExceeded) { t.Fatal("unexpected error") } - if sess != nil { - t.Fatal("expected nil sess") + if qconn != nil { + t.Fatal("expected nil connection") } if err := v.Validate(); err != nil { t.Fatal(err) @@ -330,13 +330,13 @@ func TestSaverQUICDialContext(t *testing.T) { } dialer := newQUICDialer(nil, mockedError) ctx := context.Background() - sess, err := saver.QUICDialContext(ctx, dialer, expectedNetwork, + qconn, err := saver.QUICDialContext(ctx, dialer, expectedNetwork, mockedEndpoint, v.NewTLSConfig(), v.QUICConfig) if !errors.Is(err, mockedError) { t.Fatal("unexpected error") } - if sess != nil { - t.Fatal("expected nil sess") + if qconn != nil { + t.Fatal("expected nil connection") } if err := v.Validate(); err != nil { t.Fatal(err) diff --git a/internal/cmd/oohelperd/internal/websteps/generate_test.go b/internal/cmd/oohelperd/internal/websteps/generate_test.go index 6fb35be..ee504e2 100644 --- a/internal/cmd/oohelperd/internal/websteps/generate_test.go +++ b/internal/cmd/oohelperd/internal/websteps/generate_test.go @@ -32,7 +32,7 @@ type fakeQUICDialer struct { } func (d fakeQUICDialer) DialContext(ctx context.Context, network, address string, - tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) { + tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { return nil, d.err } diff --git a/internal/engine/experiment/websteps/factory.go b/internal/engine/experiment/websteps/factory.go index fb785b8..84e33a9 100644 --- a/internal/engine/experiment/websteps/factory.go +++ b/internal/engine/experiment/websteps/factory.go @@ -59,12 +59,12 @@ func NewQUICDialerResolver(resolver model.Resolver) model.QUICDialer { } // NewSingleH3Transport creates an http3.RoundTripper. -func NewSingleH3Transport(qsess quic.EarlySession, tlscfg *tls.Config, qcfg *quic.Config) http.RoundTripper { +func NewSingleH3Transport(qconn quic.EarlyConnection, tlscfg *tls.Config, qcfg *quic.Config) http.RoundTripper { transport := &http3.RoundTripper{ DisableCompression: true, TLSClientConfig: tlscfg, QuicConfig: qcfg, - Dial: (&SingleDialerH3{qsess: &qsess}).Dial, + Dial: (&SingleDialerH3{qconn: &qconn}).Dial, } return transport } @@ -117,16 +117,16 @@ func (s *SingleDialer) DialContext(ctx context.Context, network string, addr str type SingleDialerH3 struct { sync.Mutex - qsess *quic.EarlySession + qconn *quic.EarlyConnection } -func (s *SingleDialerH3) Dial(network, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error) { +func (s *SingleDialerH3) Dial(ctx context.Context, network, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) { s.Lock() defer s.Unlock() - if s.qsess == nil { + if s.qconn == nil { return nil, ErrNoConnReuse } - qs := s.qsess - s.qsess = nil + qs := s.qconn + s.qconn = nil return *qs, nil } diff --git a/internal/engine/experiment/websteps/quic.go b/internal/engine/experiment/websteps/quic.go index 021217d..ef62dab 100644 --- a/internal/engine/experiment/websteps/quic.go +++ b/internal/engine/experiment/websteps/quic.go @@ -17,7 +17,7 @@ type QUICConfig struct { } // QUICDo performs the QUIC check. -func QUICDo(ctx context.Context, config QUICConfig) (quic.EarlySession, error) { +func QUICDo(ctx context.Context, config QUICConfig) (quic.EarlyConnection, error) { if config.QUICDialer != nil { return config.QUICDialer.DialContext(ctx, "udp", config.Endpoint, config.TLSConf, &quic.Config{}) } diff --git a/internal/engine/netx/httptransport/http3transport_test.go b/internal/engine/netx/httptransport/http3transport_test.go index a0e2418..2e2b9e3 100644 --- a/internal/engine/netx/httptransport/http3transport_test.go +++ b/internal/engine/netx/httptransport/http3transport_test.go @@ -1,12 +1,40 @@ package httptransport_test import ( + "context" + "crypto/tls" + "errors" + "net/http" "testing" + "github.com/lucas-clemente/quic-go" "github.com/ooni/probe-cli/v3/internal/engine/netx/httptransport" + "github.com/ooni/probe-cli/v3/internal/model/mocks" ) func TestNewHTTP3Transport(t *testing.T) { - // mainly to cover a line which otherwise won't be directly covered - httptransport.NewHTTP3Transport(httptransport.Config{}) + // make sure we can create a working transport using this factory. + expected := errors.New("mocked error") + txp := httptransport.NewHTTP3Transport(httptransport.Config{ + QUICDialer: &mocks.QUICDialer{ + MockDialContext: func(ctx context.Context, network, address string, + tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { + return nil, expected + }, + MockCloseIdleConnections: func() { + // nothing + }, + }, + }) + req, err := http.NewRequest("GET", "https://google.com", nil) + if err != nil { + t.Fatal(err) + } + resp, err := txp.RoundTrip(req) + if !errors.Is(err, expected) { + t.Fatal("unexpected err", err) + } + if resp != nil { + t.Fatal("expected nil resp") + } } diff --git a/internal/engine/netx/quicdialer/connectionstate.go b/internal/engine/netx/quicdialer/connectionstate.go index 7cb37c6..847bef4 100644 --- a/internal/engine/netx/quicdialer/connectionstate.go +++ b/internal/engine/netx/quicdialer/connectionstate.go @@ -7,6 +7,6 @@ import ( ) // connectionState returns the ConnectionState of a QUIC Session. -func connectionState(sess quic.EarlySession) tls.ConnectionState { +func connectionState(sess quic.EarlyConnection) tls.ConnectionState { return sess.ConnectionState().TLS.ConnectionState } diff --git a/internal/engine/netx/quicdialer/saver.go b/internal/engine/netx/quicdialer/saver.go index 3018694..b7640d3 100644 --- a/internal/engine/netx/quicdialer/saver.go +++ b/internal/engine/netx/quicdialer/saver.go @@ -19,7 +19,7 @@ type HandshakeSaver struct { // DialContext implements ContextDialer.DialContext func (h HandshakeSaver) DialContext(ctx context.Context, network string, - host string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error) { + host string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) { start := time.Now() // TODO(bassosimone): in the future we probably want to also save // information about what versions we're willing to accept. diff --git a/internal/engine/netx/quicdialer/saver_test.go b/internal/engine/netx/quicdialer/saver_test.go index eb92201..6aa7ace 100644 --- a/internal/engine/netx/quicdialer/saver_test.go +++ b/internal/engine/netx/quicdialer/saver_test.go @@ -18,12 +18,12 @@ import ( type MockDialer struct { Dialer model.QUICDialer - Sess quic.EarlySession + Sess quic.EarlyConnection Err error } func (d MockDialer) DialContext(ctx context.Context, network, host string, - tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error) { + tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) { if d.Dialer != nil { return d.Dialer.DialContext(ctx, network, host, tlsCfg, cfg) } diff --git a/internal/measurex/http.go b/internal/measurex/http.go index 5222533..ef210f3 100644 --- a/internal/measurex/http.go +++ b/internal/measurex/http.go @@ -93,12 +93,12 @@ func (mx *Measurer) NewHTTPTransportWithTLSConn( logger, netxlite.NewNullDialer(), netxlite.NewSingleUseTLSDialer(conn))) } -// NewHTTPTransportWithQUICSess creates and wraps an HTTPTransport that -// does not dial and only uses the given QUIC session. -func (mx *Measurer) NewHTTPTransportWithQUICSess( - logger model.Logger, db WritableDB, sess quic.EarlySession) *HTTPTransportDB { +// NewHTTPTransportWithQUICConn creates and wraps an HTTPTransport that +// does not dial and only uses the given QUIC connection. +func (mx *Measurer) NewHTTPTransportWithQUICConn( + logger model.Logger, db WritableDB, qconn quic.EarlyConnection) *HTTPTransportDB { return mx.WrapHTTPTransport(db, netxlite.NewHTTP3Transport( - logger, netxlite.NewSingleUseQUICDialer(sess), &tls.Config{})) + logger, netxlite.NewSingleUseQUICDialer(qconn), &tls.Config{})) } // HTTPTransportDB is an implementation of HTTPTransport that diff --git a/internal/measurex/measurer.go b/internal/measurex/measurer.go index 071e570..3354a9e 100644 --- a/internal/measurex/measurer.go +++ b/internal/measurex/measurer.go @@ -387,11 +387,11 @@ func (mx *Measurer) TLSConnectAndHandshakeWithDB(ctx context.Context, func (mx *Measurer) QUICHandshake(ctx context.Context, address string, config *tls.Config) *EndpointMeasurement { db := &MeasurementDB{} - sess, _ := mx.QUICHandshakeWithDB(ctx, db, address, config) + qconn, _ := mx.QUICHandshakeWithDB(ctx, db, address, config) measurement := db.AsMeasurement() - if sess != nil { - // TODO(bassosimone): close session with correct message - sess.CloseWithError(0, "") + if qconn != nil { + // TODO(bassosimone): close connection with correct message + qconn.CloseWithError(0, "") } return &EndpointMeasurement{ Network: NetworkQUIC, @@ -413,9 +413,9 @@ func (mx *Measurer) quicHandshakeTimeout() time.Duration { // QUICHandshakeWithDB is like QUICHandshake but uses the given // db to store events rather than creating a temporary one and -// use it to generate a new Measuremet. +// use it to generate a new Measurement. func (mx *Measurer) QUICHandshakeWithDB(ctx context.Context, db WritableDB, - address string, config *tls.Config) (quic.EarlySession, error) { + address string, config *tls.Config) (quic.EarlyConnection, error) { timeout := mx.quicHandshakeTimeout() ol := NewOperationLogger(mx.Logger, "QUICHandshake %s with sni=%s", address, config.ServerName) @@ -423,9 +423,9 @@ func (mx *Measurer) QUICHandshakeWithDB(ctx context.Context, db WritableDB, defer cancel() qd := mx.NewQUICDialerWithoutResolver(db, mx.Logger) defer qd.CloseIdleConnections() - sess, err := qd.DialContext(ctx, "udp", address, config, &quic.Config{}) + qconn, err := qd.DialContext(ctx, "udp", address, config, &quic.Config{}) ol.Stop(err) - return sess, err + return qconn, err } // HTTPEndpointGet performs a GET request for an HTTP endpoint. @@ -575,7 +575,7 @@ func (mx *Measurer) httpEndpointGetHTTPS(ctx context.Context, // httpEndpointGetQUIC specializes httpEndpointGetTCP for QUIC. func (mx *Measurer) httpEndpointGetQUIC(ctx context.Context, db WritableDB, epnt *HTTPEndpoint, jar http.CookieJar) (*http.Response, error) { - sess, err := mx.QUICHandshakeWithDB(ctx, db, epnt.Address, &tls.Config{ + qconn, err := mx.QUICHandshakeWithDB(ctx, db, epnt.Address, &tls.Config{ ServerName: epnt.SNI, NextProtos: epnt.ALPN, RootCAs: netxlite.NewDefaultCertPool(), @@ -583,10 +583,10 @@ func (mx *Measurer) httpEndpointGetQUIC(ctx context.Context, if err != nil { return nil, err } - // TODO(bassosimone): close session with correct message - defer sess.CloseWithError(0, "") // we own it + // TODO(bassosimone): close connection with correct message + defer qconn.CloseWithError(0, "") // we own it clnt := NewHTTPClientWithoutRedirects(db, jar, - mx.NewHTTPTransportWithQUICSess(mx.Logger, db, sess)) + mx.NewHTTPTransportWithQUICConn(mx.Logger, db, qconn)) defer clnt.CloseIdleConnections() return mx.httpClientDo(ctx, clnt, epnt) } diff --git a/internal/measurex/quic.go b/internal/measurex/quic.go index ea48375..f03a887 100644 --- a/internal/measurex/quic.go +++ b/internal/measurex/quic.go @@ -106,7 +106,7 @@ type quicDialerDB struct { } func (qh *quicDialerDB) DialContext(ctx context.Context, network, address string, - tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) { + tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { started := time.Since(qh.begin).Seconds() var state tls.ConnectionState listener := &quicListenerDB{ diff --git a/internal/model/mocks/quic.go b/internal/model/mocks/quic.go index bd87e54..5741437 100644 --- a/internal/model/mocks/quic.go +++ b/internal/model/mocks/quic.go @@ -25,7 +25,7 @@ func (ql *QUICListener) Listen(addr *net.UDPAddr) (model.UDPLikeConn, error) { type QUICDialer struct { // MockDialContext allows mocking DialContext. MockDialContext func(ctx context.Context, network, address string, - tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) + tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) // MockCloseIdleConnections allows mocking CloseIdleConnections. MockCloseIdleConnections func() @@ -33,7 +33,7 @@ type QUICDialer struct { // DialContext calls MockDialContext. func (qcd *QUICDialer) DialContext(ctx context.Context, network, address string, - tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) { + tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { return qcd.MockDialContext(ctx, network, address, tlsConfig, quicConfig) } @@ -42,8 +42,8 @@ func (qcd *QUICDialer) CloseIdleConnections() { qcd.MockCloseIdleConnections() } -// QUICEarlySession is a mockable quic.EarlySession. -type QUICEarlySession struct { +// QUICEarlyConnection is a mockable quic.EarlyConnection. +type QUICEarlyConnection struct { MockAcceptStream func(context.Context) (quic.Stream, error) MockAcceptUniStream func(context.Context) (quic.ReceiveStream, error) MockOpenStream func() (quic.Stream, error) @@ -56,86 +56,86 @@ type QUICEarlySession struct { MockContext func() context.Context MockConnectionState func() quic.ConnectionState MockHandshakeComplete func() context.Context - MockNextSession func() quic.Session + MockNextConnection func() quic.Connection MockSendMessage func(b []byte) error MockReceiveMessage func() ([]byte, error) } -var _ quic.EarlySession = &QUICEarlySession{} +var _ quic.EarlyConnection = &QUICEarlyConnection{} // AcceptStream calls MockAcceptStream. -func (s *QUICEarlySession) AcceptStream(ctx context.Context) (quic.Stream, error) { +func (s *QUICEarlyConnection) AcceptStream(ctx context.Context) (quic.Stream, error) { return s.MockAcceptStream(ctx) } // AcceptUniStream calls MockAcceptUniStream. -func (s *QUICEarlySession) AcceptUniStream(ctx context.Context) (quic.ReceiveStream, error) { +func (s *QUICEarlyConnection) AcceptUniStream(ctx context.Context) (quic.ReceiveStream, error) { return s.MockAcceptUniStream(ctx) } // OpenStream calls MockOpenStream. -func (s *QUICEarlySession) OpenStream() (quic.Stream, error) { +func (s *QUICEarlyConnection) OpenStream() (quic.Stream, error) { return s.MockOpenStream() } // OpenStreamSync calls MockOpenStreamSync. -func (s *QUICEarlySession) OpenStreamSync(ctx context.Context) (quic.Stream, error) { +func (s *QUICEarlyConnection) OpenStreamSync(ctx context.Context) (quic.Stream, error) { return s.MockOpenStreamSync(ctx) } // OpenUniStream calls MockOpenUniStream. -func (s *QUICEarlySession) OpenUniStream() (quic.SendStream, error) { +func (s *QUICEarlyConnection) OpenUniStream() (quic.SendStream, error) { return s.MockOpenUniStream() } // OpenUniStreamSync calls MockOpenUniStreamSync. -func (s *QUICEarlySession) OpenUniStreamSync(ctx context.Context) (quic.SendStream, error) { +func (s *QUICEarlyConnection) OpenUniStreamSync(ctx context.Context) (quic.SendStream, error) { return s.MockOpenUniStreamSync(ctx) } // LocalAddr class MockLocalAddr. -func (c *QUICEarlySession) LocalAddr() net.Addr { +func (c *QUICEarlyConnection) LocalAddr() net.Addr { return c.MockLocalAddr() } // RemoteAddr calls MockRemoteAddr. -func (c *QUICEarlySession) RemoteAddr() net.Addr { +func (c *QUICEarlyConnection) RemoteAddr() net.Addr { return c.MockRemoteAddr() } // CloseWithError calls MockCloseWithError. -func (c *QUICEarlySession) CloseWithError( +func (c *QUICEarlyConnection) CloseWithError( code quic.ApplicationErrorCode, reason string) error { return c.MockCloseWithError(code, reason) } // Context calls MockContext. -func (s *QUICEarlySession) Context() context.Context { +func (s *QUICEarlyConnection) Context() context.Context { return s.MockContext() } // ConnectionState calls MockConnectionState. -func (s *QUICEarlySession) ConnectionState() quic.ConnectionState { +func (s *QUICEarlyConnection) ConnectionState() quic.ConnectionState { return s.MockConnectionState() } // HandshakeComplete calls MockHandshakeComplete. -func (s *QUICEarlySession) HandshakeComplete() context.Context { +func (s *QUICEarlyConnection) HandshakeComplete() context.Context { return s.MockHandshakeComplete() } -// NextSession calls MockNextSession. -func (s *QUICEarlySession) NextSession() quic.Session { - return s.MockNextSession() +// NextConnection calls MockNextConnection. +func (s *QUICEarlyConnection) NextConnection() quic.Connection { + return s.MockNextConnection() } // SendMessage calls MockSendMessage. -func (s *QUICEarlySession) SendMessage(b []byte) error { +func (s *QUICEarlyConnection) SendMessage(b []byte) error { return s.MockSendMessage(b) } // ReceiveMessage calls MockReceiveMessage. -func (s *QUICEarlySession) ReceiveMessage() ([]byte, error) { +func (s *QUICEarlyConnection) ReceiveMessage() ([]byte, error) { return s.MockReceiveMessage() } diff --git a/internal/model/mocks/quic_test.go b/internal/model/mocks/quic_test.go index 687cf12..c6d86f4 100644 --- a/internal/model/mocks/quic_test.go +++ b/internal/model/mocks/quic_test.go @@ -37,19 +37,19 @@ func TestQUICDialer(t *testing.T) { t.Run("DialContext", func(t *testing.T) { expected := errors.New("mocked error") qcd := &QUICDialer{ - MockDialContext: func(ctx context.Context, network string, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) { + MockDialContext: func(ctx context.Context, network string, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { return nil, expected }, } ctx := context.Background() tlsConfig := &tls.Config{} quicConfig := &quic.Config{} - sess, err := qcd.DialContext(ctx, "udp", "dns.google:443", tlsConfig, quicConfig) + qconn, err := qcd.DialContext(ctx, "udp", "dns.google:443", tlsConfig, quicConfig) if !errors.Is(err, expected) { t.Fatal("not the error we expected") } - if sess != nil { - t.Fatal("expected nil session") + if qconn != nil { + t.Fatal("expected nil connection") } }) @@ -67,16 +67,16 @@ func TestQUICDialer(t *testing.T) { }) } -func TestQUICEarlySession(t *testing.T) { +func TestQUICEarlyConnection(t *testing.T) { t.Run("AcceptStream", func(t *testing.T) { expected := errors.New("mocked error") - sess := &QUICEarlySession{ + qconn := &QUICEarlyConnection{ MockAcceptStream: func(ctx context.Context) (quic.Stream, error) { return nil, expected }, } ctx := context.Background() - stream, err := sess.AcceptStream(ctx) + stream, err := qconn.AcceptStream(ctx) if !errors.Is(err, expected) { t.Fatal("not the error we expected", err) } @@ -87,13 +87,13 @@ func TestQUICEarlySession(t *testing.T) { t.Run("AcceptUniStream", func(t *testing.T) { expected := errors.New("mocked error") - sess := &QUICEarlySession{ + qconn := &QUICEarlyConnection{ MockAcceptUniStream: func(ctx context.Context) (quic.ReceiveStream, error) { return nil, expected }, } ctx := context.Background() - stream, err := sess.AcceptUniStream(ctx) + stream, err := qconn.AcceptUniStream(ctx) if !errors.Is(err, expected) { t.Fatal("not the error we expected", err) } @@ -104,12 +104,12 @@ func TestQUICEarlySession(t *testing.T) { t.Run("OpenStream", func(t *testing.T) { expected := errors.New("mocked error") - sess := &QUICEarlySession{ + qconn := &QUICEarlyConnection{ MockOpenStream: func() (quic.Stream, error) { return nil, expected }, } - stream, err := sess.OpenStream() + stream, err := qconn.OpenStream() if !errors.Is(err, expected) { t.Fatal("not the error we expected", err) } @@ -120,13 +120,13 @@ func TestQUICEarlySession(t *testing.T) { t.Run("OpenStreamSync", func(t *testing.T) { expected := errors.New("mocked error") - sess := &QUICEarlySession{ + qconn := &QUICEarlyConnection{ MockOpenStreamSync: func(ctx context.Context) (quic.Stream, error) { return nil, expected }, } ctx := context.Background() - stream, err := sess.OpenStreamSync(ctx) + stream, err := qconn.OpenStreamSync(ctx) if !errors.Is(err, expected) { t.Fatal("not the error we expected", err) } @@ -137,12 +137,12 @@ func TestQUICEarlySession(t *testing.T) { t.Run("OpenUniStream", func(t *testing.T) { expected := errors.New("mocked error") - sess := &QUICEarlySession{ + qconn := &QUICEarlyConnection{ MockOpenUniStream: func() (quic.SendStream, error) { return nil, expected }, } - stream, err := sess.OpenUniStream() + stream, err := qconn.OpenUniStream() if !errors.Is(err, expected) { t.Fatal("not the error we expected", err) } @@ -153,13 +153,13 @@ func TestQUICEarlySession(t *testing.T) { t.Run("OpenUniStreamSync", func(t *testing.T) { expected := errors.New("mocked error") - sess := &QUICEarlySession{ + qconn := &QUICEarlyConnection{ MockOpenUniStreamSync: func(ctx context.Context) (quic.SendStream, error) { return nil, expected }, } ctx := context.Background() - stream, err := sess.OpenUniStreamSync(ctx) + stream, err := qconn.OpenUniStreamSync(ctx) if !errors.Is(err, expected) { t.Fatal("not the error we expected", err) } @@ -169,24 +169,24 @@ func TestQUICEarlySession(t *testing.T) { }) t.Run("LocalAddr", func(t *testing.T) { - sess := &QUICEarlySession{ + qconn := &QUICEarlyConnection{ MockLocalAddr: func() net.Addr { return &net.UDPAddr{} }, } - addr := sess.LocalAddr() + addr := qconn.LocalAddr() if !reflect.ValueOf(addr).Elem().IsZero() { t.Fatal("expected a zero address here") } }) t.Run("RemoteAddr", func(t *testing.T) { - sess := &QUICEarlySession{ + qconn := &QUICEarlyConnection{ MockRemoteAddr: func() net.Addr { return &net.UDPAddr{} }, } - addr := sess.RemoteAddr() + addr := qconn.RemoteAddr() if !reflect.ValueOf(addr).Elem().IsZero() { t.Fatal("expected a zero address here") } @@ -194,13 +194,13 @@ func TestQUICEarlySession(t *testing.T) { t.Run("CloseWithError", func(t *testing.T) { expected := errors.New("mocked error") - sess := &QUICEarlySession{ + qconn := &QUICEarlyConnection{ MockCloseWithError: func( code quic.ApplicationErrorCode, reason string) error { return expected }, } - err := sess.CloseWithError(0, "") + err := qconn.CloseWithError(0, "") if !errors.Is(err, expected) { t.Fatal("not the error we expected", err) } @@ -208,12 +208,12 @@ func TestQUICEarlySession(t *testing.T) { t.Run("Context", func(t *testing.T) { ctx := context.Background() - sess := &QUICEarlySession{ + qconn := &QUICEarlyConnection{ MockContext: func() context.Context { return ctx }, } - out := sess.Context() + out := qconn.Context() if !reflect.DeepEqual(ctx, out) { t.Fatal("not the context we expected") } @@ -221,12 +221,12 @@ func TestQUICEarlySession(t *testing.T) { t.Run("ConnectionState", func(t *testing.T) { state := quic.ConnectionState{SupportsDatagrams: true} - sess := &QUICEarlySession{ + qconn := &QUICEarlyConnection{ MockConnectionState: func() quic.ConnectionState { return state }, } - out := sess.ConnectionState() + out := qconn.ConnectionState() if !reflect.DeepEqual(state, out) { t.Fatal("not the context we expected") } @@ -234,25 +234,25 @@ func TestQUICEarlySession(t *testing.T) { t.Run("HandshakeComplete", func(t *testing.T) { ctx := context.Background() - sess := &QUICEarlySession{ + qconn := &QUICEarlyConnection{ MockHandshakeComplete: func() context.Context { return ctx }, } - out := sess.HandshakeComplete() + out := qconn.HandshakeComplete() if !reflect.DeepEqual(ctx, out) { t.Fatal("not the context we expected") } }) - t.Run("NextSession", func(t *testing.T) { - next := &QUICEarlySession{} - sess := &QUICEarlySession{ - MockNextSession: func() quic.Session { + t.Run("NextConnection", func(t *testing.T) { + next := &QUICEarlyConnection{} + qconn := &QUICEarlyConnection{ + MockNextConnection: func() quic.Connection { return next }, } - out := sess.NextSession() + out := qconn.NextConnection() if !reflect.DeepEqual(next, out) { t.Fatal("not the context we expected") } @@ -260,13 +260,13 @@ func TestQUICEarlySession(t *testing.T) { t.Run("SendMessage", func(t *testing.T) { expected := errors.New("mocked error") - sess := &QUICEarlySession{ + qconn := &QUICEarlyConnection{ MockSendMessage: func(b []byte) error { return expected }, } b := make([]byte, 17) - err := sess.SendMessage(b) + err := qconn.SendMessage(b) if !errors.Is(err, expected) { t.Fatal("not the error we expected", err) } @@ -274,12 +274,12 @@ func TestQUICEarlySession(t *testing.T) { t.Run("ReceiveMessage", func(t *testing.T) { expected := errors.New("mocked error") - sess := &QUICEarlySession{ + qconn := &QUICEarlyConnection{ MockReceiveMessage: func() ([]byte, error) { return nil, expected }, } - b, err := sess.ReceiveMessage() + b, err := qconn.ReceiveMessage() if !errors.Is(err, expected) { t.Fatal("not the error we expected", err) } diff --git a/internal/model/netx.go b/internal/model/netx.go index 9a6a2d2..c99e0da 100644 --- a/internal/model/netx.go +++ b/internal/model/netx.go @@ -152,7 +152,7 @@ type QUICDialer interface { // // Typically, you want to pass `&quic.Config{}` as quicConfig. DialContext(ctx context.Context, network, address string, - tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) + tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) // CloseIdleConnections closes idle connections, if any. CloseIdleConnections() diff --git a/internal/netxlite/http3.go b/internal/netxlite/http3.go index 5f8e807..49cec12 100644 --- a/internal/netxlite/http3.go +++ b/internal/netxlite/http3.go @@ -1,30 +1,14 @@ package netxlite import ( - "context" "crypto/tls" "io" "net/http" - "github.com/lucas-clemente/quic-go" "github.com/lucas-clemente/quic-go/http3" "github.com/ooni/probe-cli/v3/internal/model" ) -// http3Dialer adapts a QUICContextDialer to work with -// an http3.RoundTripper. This is necessary because the -// http3.RoundTripper does not support DialContext. -type http3Dialer struct { - model.QUICDialer -} - -// dial is like QUICContextDialer.DialContext but without context. -func (d *http3Dialer) dial(network, address string, tlsConfig *tls.Config, - quicConfig *quic.Config) (quic.EarlySession, error) { - return d.QUICDialer.DialContext( - context.Background(), network, address, tlsConfig, quicConfig) -} - // http3RoundTripper is the abstract type of quic-go/http3.RoundTripper. type http3RoundTripper interface { http.RoundTripper @@ -63,7 +47,7 @@ func NewHTTP3Transport( return &httpTransportLogger{ HTTPTransport: &http3Transport{ child: &http3.RoundTripper{ - Dial: (&http3Dialer{dialer}).dial, + Dial: dialer.DialContext, // The following (1) reduces the number of headers that Go will // automatically send for us and (2) ensures that we always receive // back the true headers, such as Content-Length. This change is diff --git a/internal/netxlite/http3_test.go b/internal/netxlite/http3_test.go index f063e5d..0291505 100644 --- a/internal/netxlite/http3_test.go +++ b/internal/netxlite/http3_test.go @@ -1,39 +1,17 @@ package netxlite import ( - "context" "crypto/tls" "errors" "net/http" "testing" "github.com/apex/log" - "github.com/lucas-clemente/quic-go" "github.com/lucas-clemente/quic-go/http3" "github.com/ooni/probe-cli/v3/internal/model/mocks" nlmocks "github.com/ooni/probe-cli/v3/internal/netxlite/mocks" ) -func TestHTTP3Dialer(t *testing.T) { - t.Run("Dial", func(t *testing.T) { - expected := errors.New("mocked error") - d := &http3Dialer{ - QUICDialer: &mocks.QUICDialer{ - MockDialContext: func(ctx context.Context, network, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) { - return nil, expected - }, - }, - } - sess, err := d.dial("", "", &tls.Config{}, &quic.Config{}) - if !errors.Is(err, expected) { - t.Fatal("unexpected err", err) - } - if sess != nil { - t.Fatal("unexpected resp") - } - }) -} - func TestHTTP3Transport(t *testing.T) { t.Run("CloseIdleConnections", func(t *testing.T) { var ( diff --git a/internal/netxlite/mocks/legacy.go b/internal/netxlite/mocks/legacy.go index 2f6dceb..4dca3b8 100644 --- a/internal/netxlite/mocks/legacy.go +++ b/internal/netxlite/mocks/legacy.go @@ -12,11 +12,11 @@ import ( // DEPRECATED: please use QUICDialer. type QUICContextDialer struct { MockDialContext func(ctx context.Context, network, address string, - tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) + tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) } // DialContext calls MockDialContext. func (qcd *QUICContextDialer) DialContext(ctx context.Context, network, address string, - tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) { + tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { return qcd.MockDialContext(ctx, network, address, tlsConfig, quicConfig) } diff --git a/internal/netxlite/mocks/legacy_test.go b/internal/netxlite/mocks/legacy_test.go index 9c5f4c1..7dcd3f6 100644 --- a/internal/netxlite/mocks/legacy_test.go +++ b/internal/netxlite/mocks/legacy_test.go @@ -13,7 +13,7 @@ func TestQUICContextDialer(t *testing.T) { t.Run("DialContext", func(t *testing.T) { expected := errors.New("mocked error") qcd := &QUICContextDialer{ - MockDialContext: func(ctx context.Context, network string, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) { + MockDialContext: func(ctx context.Context, network string, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { return nil, expected }, } diff --git a/internal/netxlite/quic.go b/internal/netxlite/quic.go index 066a86d..2913a69 100644 --- a/internal/netxlite/quic.go +++ b/internal/netxlite/quic.go @@ -83,7 +83,7 @@ type quicDialerQUICGo struct { // mockDialEarlyContext allows to mock quic.DialEarlyContext. mockDialEarlyContext func(ctx context.Context, pconn net.PacketConn, remoteAddr net.Addr, host string, tlsConfig *tls.Config, - quicConfig *quic.Config) (quic.EarlySession, error) + quicConfig *quic.Config) (quic.EarlyConnection, error) } var _ model.QUICDialer = &quicDialerQUICGo{} @@ -101,7 +101,7 @@ var errInvalidIP = errors.New("netxlite: invalid IP") // then we configure, respectively, "h3" and "dq". func (d *quicDialerQUICGo) DialContext(ctx context.Context, network string, address string, tlsConfig *tls.Config, quicConfig *quic.Config) ( - quic.EarlySession, error) { + quic.EarlyConnection, error) { onlyhost, onlyport, err := net.SplitHostPort(address) if err != nil { return nil, err @@ -120,18 +120,18 @@ func (d *quicDialerQUICGo) DialContext(ctx context.Context, network string, } udpAddr := &net.UDPAddr{IP: ip, Port: port, Zone: ""} tlsConfig = d.maybeApplyTLSDefaults(tlsConfig, port) - sess, err := d.dialEarlyContext( + qconn, err := d.dialEarlyContext( ctx, pconn, udpAddr, address, tlsConfig, quicConfig) if err != nil { pconn.Close() // we own it on failure return nil, err } - return &quicSessionOwnsConn{EarlySession: sess, conn: pconn}, nil + return &quicConnectionOwnsConn{EarlyConnection: qconn, conn: pconn}, nil } func (d *quicDialerQUICGo) dialEarlyContext(ctx context.Context, pconn net.PacketConn, remoteAddr net.Addr, address string, - tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) { + tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { if d.mockDialEarlyContext != nil { return d.mockDialEarlyContext( ctx, pconn, remoteAddr, address, tlsConfig, quicConfig) @@ -164,20 +164,20 @@ func (d *quicDialerQUICGo) CloseIdleConnections() { // nothing to do } -// quicSessionOwnsConn ensures that we close the UDPLikeConn. -type quicSessionOwnsConn struct { - // EarlySession is the embedded early session - quic.EarlySession +// quicConnectionOwnsConn ensures that we close the UDPLikeConn. +type quicConnectionOwnsConn struct { + // EarlyConnection is the embedded early connection + quic.EarlyConnection // conn is the connection we own conn model.UDPLikeConn } -// CloseWithError implements quic.EarlySession.CloseWithError. -func (sess *quicSessionOwnsConn) CloseWithError( +// CloseWithError implements quic.EarlyConnection.CloseWithError. +func (qconn *quicConnectionOwnsConn) CloseWithError( code quic.ApplicationErrorCode, reason string) error { - err := sess.EarlySession.CloseWithError(code, reason) - sess.conn.Close() + err := qconn.EarlyConnection.CloseWithError(code, reason) + qconn.conn.Close() return err } @@ -200,7 +200,7 @@ var _ model.QUICDialer = &quicDialerResolver{} // contained inside of the `address` endpoint. func (d *quicDialerResolver) DialContext( ctx context.Context, network, address string, - tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) { + tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { onlyhost, onlyport, err := net.SplitHostPort(address) if err != nil { return nil, err @@ -217,10 +217,10 @@ func (d *quicDialerResolver) DialContext( var errorslist []error for _, addr := range addrs { target := net.JoinHostPort(addr, onlyport) - sess, err := d.Dialer.DialContext( + qconn, err := d.Dialer.DialContext( ctx, network, target, tlsConfig, quicConfig) if err == nil { - return sess, nil + return qconn, nil } errorslist = append(errorslist, err) } @@ -272,16 +272,16 @@ var _ model.QUICDialer = &quicDialerLogger{} // DialContext implements QUICContextDialer.DialContext. func (d *quicDialerLogger) DialContext( ctx context.Context, network, address string, - tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) { + tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { d.Logger.Debugf("quic_dial%s %s/%s...", d.operationSuffix, address, network) - sess, err := d.Dialer.DialContext(ctx, network, address, tlsConfig, quicConfig) + qconn, err := d.Dialer.DialContext(ctx, network, address, tlsConfig, quicConfig) if err != nil { d.Logger.Debugf("quic_dial%s %s/%s... %s", d.operationSuffix, address, network, err) return nil, err } d.Logger.Debugf("quic_dial%s %s/%s... ok", d.operationSuffix, address, network) - return sess, nil + return qconn, nil } // CloseIdleConnections implements QUICDialer.CloseIdleConnections. @@ -290,14 +290,14 @@ func (d *quicDialerLogger) CloseIdleConnections() { } // NewSingleUseQUICDialer is like NewSingleUseDialer but for QUIC. -func NewSingleUseQUICDialer(sess quic.EarlySession) model.QUICDialer { - return &quicDialerSingleUse{sess: sess} +func NewSingleUseQUICDialer(qconn quic.EarlyConnection) model.QUICDialer { + return &quicDialerSingleUse{qconn: qconn} } // quicDialerSingleUse is the QUICDialer returned by NewSingleQUICDialer. type quicDialerSingleUse struct { sync.Mutex - sess quic.EarlySession + qconn quic.EarlyConnection } var _ model.QUICDialer = &quicDialerSingleUse{} @@ -305,15 +305,15 @@ var _ model.QUICDialer = &quicDialerSingleUse{} // DialContext implements QUICDialer.DialContext. func (s *quicDialerSingleUse) DialContext( ctx context.Context, network, addr string, tlsCfg *tls.Config, - cfg *quic.Config) (quic.EarlySession, error) { - var sess quic.EarlySession + cfg *quic.Config) (quic.EarlyConnection, error) { + var qconn quic.EarlyConnection defer s.Unlock() s.Lock() - if s.sess == nil { + if s.qconn == nil { return nil, ErrNoConnReuse } - sess, s.sess = s.sess, nil - return sess, nil + qconn, s.qconn = s.qconn, nil + return qconn, nil } // CloseIdleConnections closes idle connections. @@ -381,11 +381,11 @@ type quicDialerErrWrapper struct { // DialContext implements ContextDialer.DialContext func (d *quicDialerErrWrapper) DialContext( ctx context.Context, network string, host string, - tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlySession, error) { - sess, err := d.QUICDialer.DialContext(ctx, network, host, tlsCfg, cfg) + tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) { + qconn, err := d.QUICDialer.DialContext(ctx, network, host, tlsCfg, cfg) if err != nil { return nil, NewErrWrapper( classifyQUICHandshakeError, QUICHandshakeOperation, err) } - return sess, nil + return qconn, nil } diff --git a/internal/netxlite/quic_test.go b/internal/netxlite/quic_test.go index ee1a0c7..d0d02ac 100644 --- a/internal/netxlite/quic_test.go +++ b/internal/netxlite/quic_test.go @@ -55,13 +55,13 @@ func TestQUICDialerQUICGo(t *testing.T) { } defer systemdialer.CloseIdleConnections() // just to see it running ctx := context.Background() - sess, err := systemdialer.DialContext( + qconn, err := systemdialer.DialContext( ctx, "udp", "a.b.c.d", tlsConfig, &quic.Config{}) if err == nil || !strings.HasSuffix(err.Error(), "missing port in address") { t.Fatal("not the error we expected", err) } - if sess != nil { - t.Fatal("expected nil sess here") + if qconn != nil { + t.Fatal("expected nil connection here") } }) @@ -73,13 +73,13 @@ func TestQUICDialerQUICGo(t *testing.T) { QUICListener: &quicListenerStdlib{}, } ctx := context.Background() - sess, err := systemdialer.DialContext( + qconn, err := systemdialer.DialContext( ctx, "udp", "8.8.4.4:xyz", tlsConfig, &quic.Config{}) if err == nil || !strings.HasSuffix(err.Error(), "invalid syntax") { t.Fatal("not the error we expected", err) } - if sess != nil { - t.Fatal("expected nil sess here") + if qconn != nil { + t.Fatal("expected nil connection here") } }) @@ -91,13 +91,13 @@ func TestQUICDialerQUICGo(t *testing.T) { QUICListener: &quicListenerStdlib{}, } ctx := context.Background() - sess, err := systemdialer.DialContext( + qconn, err := systemdialer.DialContext( ctx, "udp", "a.b.c.d:0", tlsConfig, &quic.Config{}) if !errors.Is(err, errInvalidIP) { t.Fatal("not the error we expected", err) } - if sess != nil { - t.Fatal("expected nil sess here") + if qconn != nil { + t.Fatal("expected nil connection here") } }) @@ -114,13 +114,13 @@ func TestQUICDialerQUICGo(t *testing.T) { }, } ctx := context.Background() - sess, err := systemdialer.DialContext( + qconn, err := systemdialer.DialContext( ctx, "udp", "8.8.8.8:443", tlsConfig, &quic.Config{}) if !errors.Is(err, expected) { t.Fatal("not the error we expected", err) } - if sess != nil { - t.Fatal("expected nil sess here") + if qconn != nil { + t.Fatal("expected nil connection here") } }) @@ -133,13 +133,13 @@ func TestQUICDialerQUICGo(t *testing.T) { } ctx, cancel := context.WithCancel(context.Background()) cancel() // fail immediately - sess, err := systemdialer.DialContext( + qconn, err := systemdialer.DialContext( ctx, "udp", "8.8.8.8:443", tlsConfig, &quic.Config{}) if !errors.Is(err, context.Canceled) { t.Fatal("not the error we expected", err) } - if sess != nil { - log.Fatal("expected nil session here") + if qconn != nil { + log.Fatal("expected nil connection here") } }) @@ -153,19 +153,19 @@ func TestQUICDialerQUICGo(t *testing.T) { QUICListener: &quicListenerStdlib{}, mockDialEarlyContext: func(ctx context.Context, pconn net.PacketConn, remoteAddr net.Addr, host string, tlsConfig *tls.Config, - quicConfig *quic.Config) (quic.EarlySession, error) { + quicConfig *quic.Config) (quic.EarlyConnection, error) { gotTLSConfig = tlsConfig return nil, expected }, } ctx := context.Background() - sess, err := systemdialer.DialContext( + qconn, err := systemdialer.DialContext( ctx, "udp", "8.8.8.8:443", tlsConfig, &quic.Config{}) if !errors.Is(err, expected) { t.Fatal("not the error we expected", err) } - if sess != nil { - t.Fatal("expected nil session here") + if qconn != nil { + t.Fatal("expected nil connection here") } if tlsConfig.RootCAs != nil { t.Fatal("tlsConfig.RootCAs should not have been changed") @@ -194,19 +194,19 @@ func TestQUICDialerQUICGo(t *testing.T) { QUICListener: &quicListenerStdlib{}, mockDialEarlyContext: func(ctx context.Context, pconn net.PacketConn, remoteAddr net.Addr, host string, tlsConfig *tls.Config, - quicConfig *quic.Config) (quic.EarlySession, error) { + quicConfig *quic.Config) (quic.EarlyConnection, error) { gotTLSConfig = tlsConfig return nil, expected }, } ctx := context.Background() - sess, err := systemdialer.DialContext( + qconn, err := systemdialer.DialContext( ctx, "udp", "8.8.8.8:8853", tlsConfig, &quic.Config{}) if !errors.Is(err, expected) { t.Fatal("not the error we expected", err) } - if sess != nil { - t.Fatal("expected nil session here") + if qconn != nil { + t.Fatal("expected nil connection here") } if tlsConfig.RootCAs != nil { t.Fatal("tlsConfig.RootCAs should not have been changed") @@ -257,14 +257,14 @@ func TestQUICDialerResolver(t *testing.T) { dialer := &quicDialerResolver{ Resolver: NewResolverStdlib(log.Log), Dialer: &quicDialerQUICGo{}} - sess, err := dialer.DialContext( + qconn, err := dialer.DialContext( context.Background(), "udp", "www.google.com", tlsConfig, &quic.Config{}) if err == nil || !strings.HasSuffix(err.Error(), "missing port in address") { t.Fatal("not the error we expected") } - if sess != nil { - t.Fatal("expected a nil sess here") + if qconn != nil { + t.Fatal("expected a nil connection here") } }) @@ -276,14 +276,14 @@ func TestQUICDialerResolver(t *testing.T) { return nil, expected }, }} - sess, err := dialer.DialContext( + qconn, err := dialer.DialContext( context.Background(), "udp", "dns.google.com:853", tlsConfig, &quic.Config{}) if !errors.Is(err, expected) { t.Fatal("not the error we expected") } - if sess != nil { - t.Fatal("expected nil sess") + if qconn != nil { + t.Fatal("expected nil connection") } }) @@ -296,7 +296,7 @@ func TestQUICDialerResolver(t *testing.T) { Dialer: &quicDialerQUICGo{ QUICListener: &quicListenerStdlib{}, }} - sess, err := dialer.DialContext( + qconn, err := dialer.DialContext( context.Background(), "udp", "8.8.4.4:x", tlsConf, &quic.Config{}) if err == nil { @@ -305,8 +305,8 @@ func TestQUICDialerResolver(t *testing.T) { if !strings.HasSuffix(err.Error(), "invalid syntax") { t.Fatal("not the error we expected", err) } - if sess != nil { - t.Fatal("expected nil sess") + if qconn != nil { + t.Fatal("expected nil connection") } }) @@ -318,19 +318,19 @@ func TestQUICDialerResolver(t *testing.T) { Resolver: NewResolverStdlib(log.Log), Dialer: &mocks.QUICDialer{ MockDialContext: func(ctx context.Context, network, address string, - tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) { + tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { gotTLSConfig = tlsConfig return nil, expected }, }} - sess, err := dialer.DialContext( + qconn, err := dialer.DialContext( context.Background(), "udp", "8.8.4.4:443", tlsConfig, &quic.Config{}) if !errors.Is(err, expected) { t.Fatal("not the error we expected", err) } - if sess != nil { - t.Fatal("expected nil session here") + if qconn != nil { + t.Fatal("expected nil connection here") } if tlsConfig.ServerName != "" { t.Fatal("should not have changed tlsConfig.ServerName") @@ -387,8 +387,8 @@ func TestQUICLoggerDialer(t *testing.T) { Dialer: &mocks.QUICDialer{ MockDialContext: func(ctx context.Context, network string, address string, tlsConfig *tls.Config, - quicConfig *quic.Config) (quic.EarlySession, error) { - return &mocks.QUICEarlySession{ + quicConfig *quic.Config) (quic.EarlyConnection, error) { + return &mocks.QUICEarlyConnection{ MockCloseWithError: func( code quic.ApplicationErrorCode, reason string) error { return nil @@ -401,11 +401,11 @@ func TestQUICLoggerDialer(t *testing.T) { ctx := context.Background() tlsConfig := &tls.Config{} quicConfig := &quic.Config{} - sess, err := d.DialContext(ctx, "udp", "8.8.8.8:443", tlsConfig, quicConfig) + qconn, err := d.DialContext(ctx, "udp", "8.8.8.8:443", tlsConfig, quicConfig) if err != nil { t.Fatal(err) } - if err := sess.CloseWithError(0, ""); err != nil { + if err := qconn.CloseWithError(0, ""); err != nil { t.Fatal(err) } if called != 2 { @@ -425,7 +425,7 @@ func TestQUICLoggerDialer(t *testing.T) { Dialer: &mocks.QUICDialer{ MockDialContext: func(ctx context.Context, network string, address string, tlsConfig *tls.Config, - quicConfig *quic.Config) (quic.EarlySession, error) { + quicConfig *quic.Config) (quic.EarlyConnection, error) { return nil, expected }, }, @@ -434,12 +434,12 @@ func TestQUICLoggerDialer(t *testing.T) { ctx := context.Background() tlsConfig := &tls.Config{} quicConfig := &quic.Config{} - sess, err := d.DialContext(ctx, "udp", "8.8.8.8:443", tlsConfig, quicConfig) + qconn, err := d.DialContext(ctx, "udp", "8.8.8.8:443", tlsConfig, quicConfig) if !errors.Is(err, expected) { t.Fatal("not the error we expected", err) } - if sess != nil { - t.Fatal("expected nil session") + if qconn != nil { + t.Fatal("expected nil connection") } if called != 2 { t.Fatal("invalid number of calls") @@ -449,24 +449,24 @@ func TestQUICLoggerDialer(t *testing.T) { } func TestNewSingleUseQUICDialer(t *testing.T) { - sess := &mocks.QUICEarlySession{} - qd := NewSingleUseQUICDialer(sess) + qconn := &mocks.QUICEarlyConnection{} + qd := NewSingleUseQUICDialer(qconn) defer qd.CloseIdleConnections() - outsess, err := qd.DialContext( + outconn, err := qd.DialContext( context.Background(), "", "", &tls.Config{}, &quic.Config{}) if err != nil { t.Fatal(err) } - if sess != outsess { - t.Fatal("invalid outsess") + if qconn != outconn { + t.Fatal("invalid outconn") } for i := 0; i < 4; i++ { - outsess, err = qd.DialContext( + outconn, err = qd.DialContext( context.Background(), "", "", &tls.Config{}, &quic.Config{}) if !errors.Is(err, ErrNoConnReuse) { t.Fatal("not the error we expected", err) } - if outsess != nil { + if outconn != nil { t.Fatal("expected nil outconn here") } } @@ -649,21 +649,21 @@ func TestQUICDialerErrWrapper(t *testing.T) { t.Run("DialContext", func(t *testing.T) { t.Run("on success", func(t *testing.T) { - expectedSess := &mocks.QUICEarlySession{} + expectedConn := &mocks.QUICEarlyConnection{} d := &quicDialerErrWrapper{ QUICDialer: &mocks.QUICDialer{ - MockDialContext: func(ctx context.Context, network, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) { - return expectedSess, nil + MockDialContext: func(ctx context.Context, network, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { + return expectedConn, nil }, }, } ctx := context.Background() - sess, err := d.DialContext(ctx, "", "", &tls.Config{}, &quic.Config{}) + qconn, err := d.DialContext(ctx, "", "", &tls.Config{}, &quic.Config{}) if err != nil { t.Fatal(err) } - if sess != expectedSess { - t.Fatal("unexpected sess") + if qconn != expectedConn { + t.Fatal("unexpected connection") } }) @@ -671,18 +671,18 @@ func TestQUICDialerErrWrapper(t *testing.T) { expectedErr := io.EOF d := &quicDialerErrWrapper{ QUICDialer: &mocks.QUICDialer{ - MockDialContext: func(ctx context.Context, network, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlySession, error) { + MockDialContext: func(ctx context.Context, network, address string, tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error) { return nil, expectedErr }, }, } ctx := context.Background() - sess, err := d.DialContext(ctx, "", "", &tls.Config{}, &quic.Config{}) + qconn, err := d.DialContext(ctx, "", "", &tls.Config{}, &quic.Config{}) if err == nil || err.Error() != FailureEOFError { t.Fatal("unexpected err", err) } - if sess != nil { - t.Fatal("unexpected sess") + if qconn != nil { + t.Fatal("unexpected connection") } }) }) diff --git a/internal/tutorial/netxlite/chapter04/README.md b/internal/tutorial/netxlite/chapter04/README.md index 53af8f2..d8b888f 100644 --- a/internal/tutorial/netxlite/chapter04/README.md +++ b/internal/tutorial/netxlite/chapter04/README.md @@ -2,7 +2,7 @@ # Chapter I: Using QUIC In this chapter we will write together a `main.go` file that -uses netxlite to establish a new QUIC session with an UDP endpoint. +uses netxlite to establish a new QUIC connection with an UDP endpoint. Conceptually, this program is very similar to the ones presented in chapters 2 and 3, except that here we use QUIC. @@ -58,7 +58,7 @@ Also, where previously we called `dialTLS` now we call a function with a similar API called `dialQUIC`. ``` - sess, state, err := dialQUIC(ctx, *address, config) + qconn, state, err := dialQUIC(ctx, *address, config) ``` The rest of the main function is pretty much the same. @@ -67,11 +67,11 @@ The rest of the main function is pretty much the same. if err != nil { fatal(err) } - log.Infof("Sess type : %T", sess) + log.Infof("Connection type : %T", qconn) log.Infof("Cipher suite : %s", netxlite.TLSCipherSuiteString(state.CipherSuite)) log.Infof("Negotiated protocol: %s", state.NegotiatedProtocol) log.Infof("TLS version : %s", netxlite.TLSVersionString(state.Version)) - sess.CloseWithError(0, "") + qconn.CloseWithError(0, "") } ``` @@ -90,10 +90,10 @@ in the next two chapters.) ```Go func dialQUIC(ctx context.Context, address string, - config *tls.Config) (quic.EarlySession, tls.ConnectionState, error) { + config *tls.Config) (quic.EarlyConnection, tls.ConnectionState, error) { ql := netxlite.NewQUICListener() d := netxlite.NewQUICDialerWithoutResolver(ql, log.Log) - sess, err := d.DialContext(ctx, "udp", address, config, &quic.Config{}) + qconn, err := d.DialContext(ctx, "udp", address, config, &quic.Config{}) if err != nil { return nil, tls.ConnectionState{}, err } @@ -104,7 +104,7 @@ QUIC code to be of the same type of the ConnectionState that we returned in the previous chapters. ```Go - return sess, sess.ConnectionState().TLS.ConnectionState, nil + return qconn, qconn.ConnectionState().TLS.ConnectionState, nil } ``` @@ -157,5 +157,5 @@ should give you a TLS error mentioning that the certificate is invalid. ## Conclusions -We have seen how to use netxlite to establish a QUIC session +We have seen how to use netxlite to establish a QUIC connection with a remote UDP endpoint speaking QUIC. diff --git a/internal/tutorial/netxlite/chapter04/main.go b/internal/tutorial/netxlite/chapter04/main.go index 15b8f84..b59fde5 100644 --- a/internal/tutorial/netxlite/chapter04/main.go +++ b/internal/tutorial/netxlite/chapter04/main.go @@ -3,7 +3,7 @@ // # Chapter I: Using QUIC // // In this chapter we will write together a `main.go` file that -// uses netxlite to establish a new QUIC session with an UDP endpoint. +// uses netxlite to establish a new QUIC connection with an UDP endpoint. // // Conceptually, this program is very similar to the ones presented // in chapters 2 and 3, except that here we use QUIC. @@ -59,7 +59,7 @@ func main() { // a function with a similar API called `dialQUIC`. // // ``` - sess, state, err := dialQUIC(ctx, *address, config) + qconn, state, err := dialQUIC(ctx, *address, config) // ``` // // The rest of the main function is pretty much the same. @@ -68,11 +68,11 @@ func main() { if err != nil { fatal(err) } - log.Infof("Sess type : %T", sess) + log.Infof("Connection type : %T", qconn) log.Infof("Cipher suite : %s", netxlite.TLSCipherSuiteString(state.CipherSuite)) log.Infof("Negotiated protocol: %s", state.NegotiatedProtocol) log.Infof("TLS version : %s", netxlite.TLSVersionString(state.Version)) - sess.CloseWithError(0, "") + qconn.CloseWithError(0, "") } // ``` @@ -91,10 +91,10 @@ func main() { // // ```Go func dialQUIC(ctx context.Context, address string, - config *tls.Config) (quic.EarlySession, tls.ConnectionState, error) { + config *tls.Config) (quic.EarlyConnection, tls.ConnectionState, error) { ql := netxlite.NewQUICListener() d := netxlite.NewQUICDialerWithoutResolver(ql, log.Log) - sess, err := d.DialContext(ctx, "udp", address, config, &quic.Config{}) + qconn, err := d.DialContext(ctx, "udp", address, config, &quic.Config{}) if err != nil { return nil, tls.ConnectionState{}, err } @@ -105,7 +105,7 @@ func dialQUIC(ctx context.Context, address string, // we returned in the previous chapters. // // ```Go - return sess, sess.ConnectionState().TLS.ConnectionState, nil + return qconn, qconn.ConnectionState().TLS.ConnectionState, nil } // ``` @@ -158,5 +158,5 @@ func fatal(err error) { // // ## Conclusions // -// We have seen how to use netxlite to establish a QUIC session +// We have seen how to use netxlite to establish a QUIC connection // with a remote UDP endpoint speaking QUIC. diff --git a/internal/tutorial/netxlite/chapter08/README.md b/internal/tutorial/netxlite/chapter08/README.md index 9d62580..cf6a288 100644 --- a/internal/tutorial/netxlite/chapter08/README.md +++ b/internal/tutorial/netxlite/chapter08/README.md @@ -1,8 +1,8 @@ -# Chapter I: HTTP GET with QUIC sess +# Chapter I: HTTP GET with QUIC conn In this chapter we will write together a `main.go` file that -uses netxlite to establish a QUIC session to a remote endpoint +uses netxlite to establish a QUIC connection to a remote endpoint and then fetches a webpage from it using GET. This file is basically the same as the one used in chapter04 @@ -49,11 +49,11 @@ func main() { NextProtos: []string{"h3"}, RootCAs: netxlite.NewDefaultCertPool(), } - sess, _, err := dialQUIC(ctx, *address, config) + qconn, _, err := dialQUIC(ctx, *address, config) if err != nil { fatal(err) } - log.Infof("Sess type : %T", sess) + log.Infof("Connection type : %T", qconn) ``` This is where things diverge. We create an HTTP client @@ -61,13 +61,13 @@ using a transport created with `netxlite.NewHTTP3Transport`. This transport will use a "single use" QUIC dialer. What does this mean? Well, we create such a QUICDialer -using the session we already established. The first +using the connection we already established. The first time the HTTP code dials for QUIC, the QUICDialer will -return the session we passed to its constructor +return the connection we passed to its constructor immediately. Every subsequent QUIC dial attempt will fail. The result is an HTTPTransport suitable for performing -a single request using the given QUIC sess. +a single request using the given QUIC conn. (A similar construct allows to create an HTTPTransport that uses a cleartext TCP connection. In the previous chapter we've @@ -75,7 +75,7 @@ seen how to do the same using TLS conns.) ```Go clnt := &http.Client{Transport: netxlite.NewHTTP3Transport( - log.Log, netxlite.NewSingleUseQUICDialer(sess), &tls.Config{}, + log.Log, netxlite.NewSingleUseQUICDialer(qconn), &tls.Config{}, )} ``` @@ -103,14 +103,14 @@ exactly like what we've seen in chapter04. ```Go func dialQUIC(ctx context.Context, address string, - config *tls.Config) (quic.EarlySession, tls.ConnectionState, error) { + config *tls.Config) (quic.EarlyConnection, tls.ConnectionState, error) { ql := netxlite.NewQUICListener() d := netxlite.NewQUICDialerWithoutResolver(ql, log.Log) - sess, err := d.DialContext(ctx, "udp", address, config, &quic.Config{}) + qconn, err := d.DialContext(ctx, "udp", address, config, &quic.Config{}) if err != nil { return nil, tls.ConnectionState{}, err } - return sess, sess.ConnectionState().TLS.ConnectionState, nil + return qconn, qconn.ConnectionState().TLS.ConnectionState, nil } func fatal(err error) { @@ -158,5 +158,5 @@ should give you an error mentioning the certificate is invalid. ## Conclusions -We have seen how to establish a QUIC session with a website -and then how to GET a webpage using such a session. +We have seen how to establish a QUIC connection with a website +and then how to GET a webpage using such a connection. diff --git a/internal/tutorial/netxlite/chapter08/main.go b/internal/tutorial/netxlite/chapter08/main.go index 136aaa9..5ab8bd5 100644 --- a/internal/tutorial/netxlite/chapter08/main.go +++ b/internal/tutorial/netxlite/chapter08/main.go @@ -1,9 +1,9 @@ // -=-=- StartHere -=-=- // -// # Chapter I: HTTP GET with QUIC sess +// # Chapter I: HTTP GET with QUIC conn // // In this chapter we will write together a `main.go` file that -// uses netxlite to establish a QUIC session to a remote endpoint +// uses netxlite to establish a QUIC connection to a remote endpoint // and then fetches a webpage from it using GET. // // This file is basically the same as the one used in chapter04 @@ -50,11 +50,11 @@ func main() { NextProtos: []string{"h3"}, RootCAs: netxlite.NewDefaultCertPool(), } - sess, _, err := dialQUIC(ctx, *address, config) + qconn, _, err := dialQUIC(ctx, *address, config) if err != nil { fatal(err) } - log.Infof("Sess type : %T", sess) + log.Infof("Connection type : %T", qconn) // ``` // // This is where things diverge. We create an HTTP client @@ -62,13 +62,13 @@ func main() { // // This transport will use a "single use" QUIC dialer. // What does this mean? Well, we create such a QUICDialer - // using the session we already established. The first + // using the connection we already established. The first // time the HTTP code dials for QUIC, the QUICDialer will - // return the session we passed to its constructor + // return the connection we passed to its constructor // immediately. Every subsequent QUIC dial attempt will fail. // // The result is an HTTPTransport suitable for performing - // a single request using the given QUIC sess. + // a single request using the given QUIC conn. // // (A similar construct allows to create an HTTPTransport that // uses a cleartext TCP connection. In the previous chapter we've @@ -76,7 +76,7 @@ func main() { // // ```Go clnt := &http.Client{Transport: netxlite.NewHTTP3Transport( - log.Log, netxlite.NewSingleUseQUICDialer(sess), &tls.Config{}, + log.Log, netxlite.NewSingleUseQUICDialer(qconn), &tls.Config{}, )} // ``` // @@ -104,14 +104,14 @@ func main() { // ```Go func dialQUIC(ctx context.Context, address string, - config *tls.Config) (quic.EarlySession, tls.ConnectionState, error) { + config *tls.Config) (quic.EarlyConnection, tls.ConnectionState, error) { ql := netxlite.NewQUICListener() d := netxlite.NewQUICDialerWithoutResolver(ql, log.Log) - sess, err := d.DialContext(ctx, "udp", address, config, &quic.Config{}) + qconn, err := d.DialContext(ctx, "udp", address, config, &quic.Config{}) if err != nil { return nil, tls.ConnectionState{}, err } - return sess, sess.ConnectionState().TLS.ConnectionState, nil + return qconn, qconn.ConnectionState().TLS.ConnectionState, nil } func fatal(err error) { @@ -159,5 +159,5 @@ func fatal(err error) { // // ## Conclusions // -// We have seen how to establish a QUIC session with a website -// and then how to GET a webpage using such a session. +// We have seen how to establish a QUIC connection with a website +// and then how to GET a webpage using such a connection.