Merge pull request #3789 from quic-go/listener-structs

make Listener and EarlyListener a struct
This commit is contained in:
Marten Seemann
2023-05-01 15:00:37 +02:00
committed by GitHub
26 changed files with 227 additions and 201 deletions

View File

@@ -0,0 +1,80 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/quic-go/quic-go/http3 (interfaces: QUICEarlyListener)
// Package http3 is a generated GoMock package.
package http3
import (
context "context"
net "net"
reflect "reflect"
gomock "github.com/golang/mock/gomock"
quic "github.com/quic-go/quic-go"
)
// MockQUICEarlyListener is a mock of QUICEarlyListener interface.
type MockQUICEarlyListener struct {
ctrl *gomock.Controller
recorder *MockQUICEarlyListenerMockRecorder
}
// MockQUICEarlyListenerMockRecorder is the mock recorder for MockQUICEarlyListener.
type MockQUICEarlyListenerMockRecorder struct {
mock *MockQUICEarlyListener
}
// NewMockQUICEarlyListener creates a new mock instance.
func NewMockQUICEarlyListener(ctrl *gomock.Controller) *MockQUICEarlyListener {
mock := &MockQUICEarlyListener{ctrl: ctrl}
mock.recorder = &MockQUICEarlyListenerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockQUICEarlyListener) EXPECT() *MockQUICEarlyListenerMockRecorder {
return m.recorder
}
// Accept mocks base method.
func (m *MockQUICEarlyListener) Accept(arg0 context.Context) (quic.EarlyConnection, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Accept", arg0)
ret0, _ := ret[0].(quic.EarlyConnection)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Accept indicates an expected call of Accept.
func (mr *MockQUICEarlyListenerMockRecorder) Accept(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Accept", reflect.TypeOf((*MockQUICEarlyListener)(nil).Accept), arg0)
}
// Addr mocks base method.
func (m *MockQUICEarlyListener) Addr() net.Addr {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Addr")
ret0, _ := ret[0].(net.Addr)
return ret0
}
// Addr indicates an expected call of Addr.
func (mr *MockQUICEarlyListenerMockRecorder) Addr() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Addr", reflect.TypeOf((*MockQUICEarlyListener)(nil).Addr))
}
// Close mocks base method.
func (m *MockQUICEarlyListener) Close() error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Close")
ret0, _ := ret[0].(error)
return ret0
}
// Close indicates an expected call of Close.
func (mr *MockQUICEarlyListenerMockRecorder) Close() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockQUICEarlyListener)(nil).Close))
}

View File

@@ -4,3 +4,5 @@ package http3
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package http3 -destination mock_roundtripcloser_test.go github.com/quic-go/quic-go/http3 RoundTripCloser"
type RoundTripCloser = roundTripCloser
//go:generate sh -c "go run github.com/golang/mock/mockgen -package http3 -destination mock_quic_early_listener_test.go github.com/quic-go/quic-go/http3 QUICEarlyListener"

View File

@@ -23,8 +23,12 @@ import (
// allows mocking of quic.Listen and quic.ListenAddr
var (
quicListen = quic.ListenEarly
quicListenAddr = quic.ListenAddrEarly
quicListen = func(conn net.PacketConn, tlsConf *tls.Config, config *quic.Config) (QUICEarlyListener, error) {
return quic.ListenEarly(conn, tlsConf, config)
}
quicListenAddr = func(addr string, tlsConf *tls.Config, config *quic.Config) (QUICEarlyListener, error) {
return quic.ListenAddrEarly(addr, tlsConf, config)
}
)
const (
@@ -44,6 +48,15 @@ const (
streamTypeQPACKDecoderStream = 3
)
// A QUICEarlyListener listens for incoming QUIC connections.
type QUICEarlyListener interface {
Accept(context.Context) (quic.EarlyConnection, error)
Addr() net.Addr
io.Closer
}
var _ QUICEarlyListener = &quic.EarlyListener{}
func versionToALPN(v protocol.VersionNumber) string {
//nolint:exhaustive // These are all the versions we care about.
switch v {
@@ -193,7 +206,7 @@ type Server struct {
UniStreamHijacker func(StreamType, quic.Connection, quic.ReceiveStream, error) (hijacked bool)
mutex sync.RWMutex
listeners map[*quic.EarlyListener]listenerInfo
listeners map[*QUICEarlyListener]listenerInfo
closed bool
@@ -249,7 +262,7 @@ func (s *Server) ServeQUICConn(conn quic.Connection) error {
// Make sure you use http3.ConfigureTLSConfig to configure a tls.Config
// and use it to construct a http3-friendly QUIC listener.
// Closing the server does close the listener.
func (s *Server) ServeListener(ln quic.EarlyListener) error {
func (s *Server) ServeListener(ln QUICEarlyListener) error {
if err := s.addListener(&ln); err != nil {
return err
}
@@ -283,7 +296,7 @@ func (s *Server) serveConn(tlsConf *tls.Config, conn net.PacketConn) error {
quicConf.EnableDatagrams = true
}
var ln quic.EarlyListener
var ln QUICEarlyListener
var err error
if conn == nil {
addr := s.Addr
@@ -305,7 +318,7 @@ func (s *Server) serveConn(tlsConf *tls.Config, conn net.PacketConn) error {
return err
}
func (s *Server) serveListener(ln quic.EarlyListener) error {
func (s *Server) serveListener(ln QUICEarlyListener) error {
for {
conn, err := ln.Accept(context.Background())
if err != nil {
@@ -391,7 +404,7 @@ func (s *Server) generateAltSvcHeader() {
// We store a pointer to interface in the map set. This is safe because we only
// call trackListener via Serve and can track+defer untrack the same pointer to
// local variable there. We never need to compare a Listener from another caller.
func (s *Server) addListener(l *quic.EarlyListener) error {
func (s *Server) addListener(l *QUICEarlyListener) error {
s.mutex.Lock()
defer s.mutex.Unlock()
@@ -402,25 +415,24 @@ func (s *Server) addListener(l *quic.EarlyListener) error {
s.logger = utils.DefaultLogger.WithPrefix("server")
}
if s.listeners == nil {
s.listeners = make(map[*quic.EarlyListener]listenerInfo)
s.listeners = make(map[*QUICEarlyListener]listenerInfo)
}
if port, err := extractPort((*l).Addr().String()); err == nil {
s.listeners[l] = listenerInfo{port}
} else {
s.logger.Errorf(
"Unable to extract port from listener %+v, will not be announced using SetQuicHeaders: %s", err)
s.logger.Errorf("Unable to extract port from listener %+v, will not be announced using SetQuicHeaders: %s", err)
s.listeners[l] = listenerInfo{}
}
s.generateAltSvcHeader()
return nil
}
func (s *Server) removeListener(l *quic.EarlyListener) {
func (s *Server) removeListener(l *QUICEarlyListener) {
s.mutex.Lock()
defer s.mutex.Unlock()
delete(s.listeners, l)
s.generateAltSvcHeader()
s.mutex.Unlock()
}
func (s *Server) handleConn(conn quic.Connection) error {

View File

@@ -28,34 +28,25 @@ import (
gmtypes "github.com/onsi/gomega/types"
)
type mockAddr struct {
addr string
}
type mockAddr struct{ addr string }
func (ma *mockAddr) Network() string {
return "udp"
}
func (ma *mockAddr) String() string {
return ma.addr
}
func (ma *mockAddr) Network() string { return "udp" }
func (ma *mockAddr) String() string { return ma.addr }
type mockAddrListener struct {
*mockquic.MockEarlyListener
*MockQUICEarlyListener
addr *mockAddr
}
func (m *mockAddrListener) Addr() net.Addr {
_ = m.MockEarlyListener.Addr()
_ = m.MockQUICEarlyListener.Addr()
return m.addr
}
func newMockAddrListener(addr string) *mockAddrListener {
return &mockAddrListener{
MockEarlyListener: mockquic.NewMockEarlyListener(mockCtrl),
addr: &mockAddr{
addr: addr,
},
MockQUICEarlyListener: NewMockQUICEarlyListener(mockCtrl),
addr: &mockAddr{addr: addr},
}
}
@@ -791,20 +782,20 @@ var _ = Describe("Server", func() {
s.QuicConfig = &quic.Config{Versions: []protocol.VersionNumber{protocol.VersionDraft29}}
})
var ln1 quic.EarlyListener
var ln2 quic.EarlyListener
var ln1 QUICEarlyListener
var ln2 QUICEarlyListener
expected := http.Header{
"Alt-Svc": {`h3-29=":443"; ma=2592000`},
}
addListener := func(addr string, ln *quic.EarlyListener) {
addListener := func(addr string, ln *QUICEarlyListener) {
mln := newMockAddrListener(addr)
mln.EXPECT().Addr()
*ln = mln
s.addListener(ln)
}
removeListener := func(ln *quic.EarlyListener) {
removeListener := func(ln *QUICEarlyListener) {
s.removeListener(ln)
}
@@ -951,7 +942,7 @@ var _ = Describe("Server", func() {
It("sets the GetConfigForClient callback if no tls.Config is given", func() {
var receivedConf *tls.Config
quicListenAddr = func(addr string, tlsConf *tls.Config, _ *quic.Config) (quic.EarlyListener, error) {
quicListenAddr = func(addr string, tlsConf *tls.Config, _ *quic.Config) (QUICEarlyListener, error) {
receivedConf = tlsConf
return nil, errors.New("listen err")
}
@@ -1021,7 +1012,7 @@ var _ = Describe("Server", func() {
It("serves a packet conn", func() {
ln := newMockAddrListener(":443")
conn := &net.UDPConn{}
quicListen = func(c net.PacketConn, tlsConf *tls.Config, config *quic.Config) (quic.EarlyListener, error) {
quicListen = func(c net.PacketConn, tlsConf *tls.Config, config *quic.Config) (QUICEarlyListener, error) {
Expect(c).To(Equal(conn))
return ln, nil
}
@@ -1052,12 +1043,12 @@ var _ = Describe("Server", func() {
It("serves two packet conns", func() {
ln1 := newMockAddrListener(":443")
ln2 := newMockAddrListener(":8443")
lns := make(chan quic.EarlyListener, 2)
lns := make(chan QUICEarlyListener, 2)
lns <- ln1
lns <- ln2
conn1 := &net.UDPConn{}
conn2 := &net.UDPConn{}
quicListen = func(c net.PacketConn, tlsConf *tls.Config, config *quic.Config) (quic.EarlyListener, error) {
quicListen = func(c net.PacketConn, tlsConf *tls.Config, config *quic.Config) (QUICEarlyListener, error) {
return <-lns, nil
}
@@ -1111,7 +1102,7 @@ var _ = Describe("Server", func() {
It("serves a listener", func() {
var called int32
ln := newMockAddrListener(":443")
quicListen = func(conn net.PacketConn, tlsConf *tls.Config, config *quic.Config) (quic.EarlyListener, error) {
quicListen = func(conn net.PacketConn, tlsConf *tls.Config, config *quic.Config) (QUICEarlyListener, error) {
atomic.StoreInt32(&called, 1)
return ln, nil
}
@@ -1142,10 +1133,10 @@ var _ = Describe("Server", func() {
var called int32
ln1 := newMockAddrListener(":443")
ln2 := newMockAddrListener(":8443")
lns := make(chan quic.EarlyListener, 2)
lns := make(chan QUICEarlyListener, 2)
lns <- ln1
lns <- ln2
quicListen = func(c net.PacketConn, tlsConf *tls.Config, config *quic.Config) (quic.EarlyListener, error) {
quicListen = func(c net.PacketConn, tlsConf *tls.Config, config *quic.Config) (QUICEarlyListener, error) {
atomic.StoreInt32(&called, 1)
return <-lns, nil
}
@@ -1225,7 +1216,7 @@ var _ = Describe("Server", func() {
It("uses the quic.Config to start the QUIC server", func() {
conf := &quic.Config{HandshakeIdleTimeout: time.Nanosecond}
var receivedConf *quic.Config
quicListenAddr = func(addr string, _ *tls.Config, config *quic.Config) (quic.EarlyListener, error) {
quicListenAddr = func(addr string, _ *tls.Config, config *quic.Config) (QUICEarlyListener, error) {
receivedConf = config
return nil, errors.New("listen err")
}
@@ -1241,7 +1232,7 @@ var _ = Describe("Server", func() {
It("errors when listening fails", func() {
testErr := errors.New("listen error")
quicListenAddr = func(addr string, tlsConf *tls.Config, config *quic.Config) (quic.EarlyListener, error) {
quicListenAddr = func(addr string, tlsConf *tls.Config, config *quic.Config) (QUICEarlyListener, error) {
return nil, testErr
}
fullpem, privkey := testdata.GetCertificatePaths()
@@ -1251,7 +1242,7 @@ var _ = Describe("Server", func() {
It("supports H3_DATAGRAM", func() {
s.EnableDatagrams = true
var receivedConf *quic.Config
quicListenAddr = func(addr string, _ *tls.Config, config *quic.Config) (quic.EarlyListener, error) {
quicListenAddr = func(addr string, _ *tls.Config, config *quic.Config) (QUICEarlyListener, error) {
receivedConf = config
return nil, errors.New("listen err")
}

View File

@@ -20,7 +20,7 @@ var _ = Describe("Stream Cancellations", func() {
const numStreams = 80
Context("canceling the read side", func() {
var server quic.Listener
var server *quic.Listener
// The server accepts a single connection, and then opens numStreams unidirectional streams.
// On each of these streams, it (tries to) write PRData.
@@ -222,7 +222,7 @@ var _ = Describe("Stream Cancellations", func() {
})
Context("canceling the write side", func() {
runClient := func(server quic.Listener) int32 /* number of canceled streams */ {
runClient := func(server *quic.Listener) int32 /* number of canceled streams */ {
conn, err := quic.DialAddr(
context.Background(),
fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),

View File

@@ -34,7 +34,7 @@ func (c *connIDGenerator) ConnectionIDLen() int {
var _ = Describe("Connection ID lengths tests", func() {
randomConnIDLen := func() int { return 4 + int(mrand.Int31n(15)) }
runServer := func(conf *quic.Config) quic.Listener {
runServer := func(conf *quic.Config) *quic.Listener {
GinkgoWriter.Write([]byte(fmt.Sprintf("Using %d byte connection ID for the server\n", conf.ConnectionIDLength)))
ln, err := quic.ListenAddr("localhost:0", getTLSConfig(), conf)
Expect(err).ToNot(HaveOccurred())

View File

@@ -14,7 +14,7 @@ import (
)
var _ = Describe("Stream deadline tests", func() {
setup := func() (quic.Listener, quic.Stream, quic.Stream) {
setup := func() (*quic.Listener, quic.Stream, quic.Stream) {
server, err := quic.ListenAddr("localhost:0", getTLSConfig(), getQuicConfig(nil))
Expect(err).ToNot(HaveOccurred())
strChan := make(chan quic.SendStream)

View File

@@ -22,7 +22,7 @@ func randomDuration(min, max time.Duration) time.Duration {
var _ = Describe("Drop Tests", func() {
var (
proxy *quicproxy.QuicProxy
ln quic.Listener
ln *quic.Listener
)
startListenerAndProxy := func(dropCallback quicproxy.DropCallback) {

View File

@@ -32,7 +32,7 @@ type applicationProtocol struct {
var _ = Describe("Handshake drop tests", func() {
var (
proxy *quicproxy.QuicProxy
ln quic.Listener
ln *quic.Listener
)
data := GeneratePRData(5000)

View File

@@ -46,7 +46,7 @@ func (c *tokenStore) Pop(key string) *quic.ClientToken {
var _ = Describe("Handshake tests", func() {
var (
server quic.Listener
server *quic.Listener
serverConfig *quic.Config
acceptStopped chan struct{}
)
@@ -221,7 +221,7 @@ var _ = Describe("Handshake tests", func() {
Context("rate limiting", func() {
var (
server quic.Listener
server *quic.Listener
pconn net.PacketConn
)

View File

@@ -18,14 +18,14 @@ import (
)
type listenerWrapper struct {
quic.EarlyListener
http3.QUICEarlyListener
listenerClosed bool
count int32
}
func (ln *listenerWrapper) Close() error {
ln.listenerClosed = true
return ln.EarlyListener.Close()
return ln.QUICEarlyListener.Close()
}
func (ln *listenerWrapper) Faker() *fakeClosingListener {
@@ -91,7 +91,7 @@ var _ = Describe("HTTP3 Server hotswap test", func() {
tlsConf := http3.ConfigureTLSConfig(getTLSConfig())
quicln, err := quic.ListenAddrEarly("0.0.0.0:0", tlsConf, getQuicConfig(nil))
ln = &listenerWrapper{EarlyListener: quicln}
ln = &listenerWrapper{QUICEarlyListener: quicln}
Expect(err).NotTo(HaveOccurred())
port = strconv.Itoa(ln.Addr().(*net.UDPAddr).Port)
})

View File

@@ -14,7 +14,7 @@ import (
)
var _ = Describe("Multiplexing", func() {
runServer := func(ln quic.Listener) {
runServer := func(ln *quic.Listener) {
go func() {
defer GinkgoRecover()
for {
@@ -52,7 +52,7 @@ var _ = Describe("Multiplexing", func() {
}
Context("multiplexing clients on the same conn", func() {
getListener := func() quic.Listener {
getListener := func() *quic.Listener {
ln, err := quic.ListenAddr(
"localhost:0",
getTLSConfig(),

View File

@@ -15,7 +15,7 @@ import (
)
var _ = Describe("non-zero RTT", func() {
runServer := func() quic.Listener {
runServer := func() *quic.Listener {
ln, err := quic.ListenAddr(
"localhost:0",
getTLSConfig(),

View File

@@ -16,7 +16,7 @@ var _ = Describe("Bidirectional streams", func() {
const numStreams = 300
var (
server quic.Listener
server *quic.Listener
serverAddr string
)

View File

@@ -377,7 +377,7 @@ var _ = Describe("Timeout tests", func() {
Context("faulty packet conns", func() {
const handshakeTimeout = time.Second / 2
runServer := func(ln quic.Listener) error {
runServer := func(ln *quic.Listener) error {
conn, err := ln.Accept(context.Background())
if err != nil {
return err

View File

@@ -61,7 +61,7 @@ var _ = Describe("Handshake tests", func() {
quicClientConf := addTracers(protocol.PerspectiveClient, getQuicConfig(nil))
quicServerConf := addTracers(protocol.PerspectiveServer, getQuicConfig(nil))
serverChan := make(chan quic.Listener)
serverChan := make(chan *quic.Listener)
go func() {
defer GinkgoRecover()
ln, err := quic.ListenAddr("localhost:0", getTLSConfig(), quicServerConf)

View File

@@ -18,7 +18,7 @@ var _ = Describe("Unidirectional Streams", func() {
const numStreams = 500
var (
server quic.Listener
server *quic.Listener
serverAddr string
)

View File

@@ -99,7 +99,7 @@ var _ = Describe("0-RTT", func() {
}
transfer0RTTData := func(
ln quic.EarlyListener,
ln *quic.EarlyListener,
proxyPort int,
clientTLSConf *tls.Config,
clientConf *quic.Config,
@@ -147,7 +147,7 @@ var _ = Describe("0-RTT", func() {
}
check0RTTRejected := func(
ln quic.EarlyListener,
ln *quic.EarlyListener,
proxyPort int,
clientConf *tls.Config,
) {

View File

@@ -45,7 +45,7 @@ func (t *versionNegotiationTracer) ReceivedVersionNegotiationPacket(dest, src lo
}
var _ = Describe("Handshake tests", func() {
startServer := func(tlsConf *tls.Config, conf *quic.Config) (quic.Listener, func()) {
startServer := func(tlsConf *tls.Config, conf *quic.Config) (*quic.Listener, func()) {
server, err := quic.ListenAddr("localhost:0", tlsConf, conf)
Expect(err).ToNot(HaveOccurred())

View File

@@ -345,24 +345,3 @@ type ConnectionState struct {
SupportsDatagrams bool
Version VersionNumber
}
// A Listener for incoming QUIC connections
type Listener interface {
// Close the server. All active connections will be closed.
Close() error
// Addr returns the local network addr that the server is listening on.
Addr() net.Addr
// Accept returns new connections. It should be called in a loop.
Accept(context.Context) (Connection, error)
}
// An EarlyListener listens for incoming QUIC connections,
// and returns them before the handshake completes.
type EarlyListener interface {
// Close the server. All active connections will be closed.
Close() error
// Addr returns the local network addr that the server is listening on.
Addr() net.Addr
// Accept returns new early connections. It should be called in a loop.
Accept(context.Context) (EarlyConnection, error)
}

View File

@@ -2,7 +2,6 @@ package mocks
//go:generate sh -c "go run github.com/golang/mock/mockgen -package mockquic -destination quic/stream.go github.com/quic-go/quic-go Stream"
//go:generate sh -c "go run github.com/golang/mock/mockgen -package mockquic -destination quic/early_conn_tmp.go github.com/quic-go/quic-go EarlyConnection && sed 's/qtls.ConnectionState/quic.ConnectionState/g' quic/early_conn_tmp.go > quic/early_conn.go && rm quic/early_conn_tmp.go && go run golang.org/x/tools/cmd/goimports -w quic/early_conn.go"
//go:generate sh -c "go run github.com/golang/mock/mockgen -package mockquic -destination quic/early_listener.go github.com/quic-go/quic-go EarlyListener"
//go:generate sh -c "go run github.com/golang/mock/mockgen -package mocklogging -destination logging/tracer.go github.com/quic-go/quic-go/logging Tracer"
//go:generate sh -c "go run github.com/golang/mock/mockgen -package mocklogging -destination logging/connection_tracer.go github.com/quic-go/quic-go/logging ConnectionTracer"
//go:generate sh -c "go run github.com/golang/mock/mockgen -package mocks -destination short_header_sealer.go github.com/quic-go/quic-go/internal/handshake ShortHeaderSealer"

View File

@@ -1,80 +0,0 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/quic-go/quic-go (interfaces: EarlyListener)
// Package mockquic is a generated GoMock package.
package mockquic
import (
context "context"
net "net"
reflect "reflect"
gomock "github.com/golang/mock/gomock"
quic "github.com/quic-go/quic-go"
)
// MockEarlyListener is a mock of EarlyListener interface.
type MockEarlyListener struct {
ctrl *gomock.Controller
recorder *MockEarlyListenerMockRecorder
}
// MockEarlyListenerMockRecorder is the mock recorder for MockEarlyListener.
type MockEarlyListenerMockRecorder struct {
mock *MockEarlyListener
}
// NewMockEarlyListener creates a new mock instance.
func NewMockEarlyListener(ctrl *gomock.Controller) *MockEarlyListener {
mock := &MockEarlyListener{ctrl: ctrl}
mock.recorder = &MockEarlyListenerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockEarlyListener) EXPECT() *MockEarlyListenerMockRecorder {
return m.recorder
}
// Accept mocks base method.
func (m *MockEarlyListener) Accept(arg0 context.Context) (quic.EarlyConnection, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Accept", arg0)
ret0, _ := ret[0].(quic.EarlyConnection)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// Accept indicates an expected call of Accept.
func (mr *MockEarlyListenerMockRecorder) Accept(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Accept", reflect.TypeOf((*MockEarlyListener)(nil).Accept), arg0)
}
// Addr mocks base method.
func (m *MockEarlyListener) Addr() net.Addr {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Addr")
ret0, _ := ret[0].(net.Addr)
return ret0
}
// Addr indicates an expected call of Addr.
func (mr *MockEarlyListenerMockRecorder) Addr() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Addr", reflect.TypeOf((*MockEarlyListener)(nil).Addr))
}
// Close mocks base method.
func (m *MockEarlyListener) Close() error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Close")
ret0, _ := ret[0].(error)
return ret0
}
// Close indicates an expected call of Close.
func (mr *MockEarlyListenerMockRecorder) Close() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockEarlyListener)(nil).Close))
}

View File

@@ -36,8 +36,8 @@ var _ = Describe("HTTP 0.9 integration tests", func() {
defer close(done)
_ = server.ListenAndServe()
}()
var ln quic.EarlyListener
Eventually(func() quic.EarlyListener {
var ln *quic.EarlyListener
Eventually(func() *quic.EarlyListener {
server.mutex.Lock()
defer server.mutex.Unlock()
ln = server.listener

View File

@@ -40,7 +40,7 @@ type Server struct {
QuicConfig *quic.Config
mutex sync.Mutex
listener quic.EarlyListener
listener *quic.EarlyListener
}
// Close closes the server.

View File

@@ -114,33 +114,72 @@ type baseServer struct {
logger utils.Logger
}
var (
_ Listener = &baseServer{}
_ unknownPacketHandler = &baseServer{}
)
var _ unknownPacketHandler = &baseServer{}
type earlyServer struct{ *baseServer }
// A Listener listens for incoming QUIC connections.
// It returns connections once the handshake has completed.
type Listener struct {
baseServer *baseServer
}
var _ EarlyListener = &earlyServer{}
// Accept returns new connections. It should be called in a loop.
func (l *Listener) Accept(ctx context.Context) (Connection, error) {
return l.baseServer.Accept(ctx)
}
func (s *earlyServer) Accept(ctx context.Context) (EarlyConnection, error) {
return s.baseServer.accept(ctx)
// Close the server. All active connections will be closed.
func (l *Listener) Close() error {
return l.baseServer.Close()
}
// Addr returns the local network address that the server is listening on.
func (l *Listener) Addr() net.Addr {
return l.baseServer.Addr()
}
// An EarlyListener listens for incoming QUIC connections, and returns them before the handshake completes.
// For connections that don't use 0-RTT, this allows the server to send 0.5-RTT data.
// This data is encrypted with forward-secure keys, however, the client's identity has not yet been verified.
// For connection using 0-RTT, this allows the server to accept and respond to streams that the client opened in the
// 0-RTT data it sent. Note that at this point during the handshake, the live-ness of the
// client has not yet been confirmed, and the 0-RTT data could have been replayed by an attacker.
type EarlyListener struct {
baseServer *baseServer
}
// Accept returns a new connections. It should be called in a loop.
func (l *EarlyListener) Accept(ctx context.Context) (EarlyConnection, error) {
return l.baseServer.accept(ctx)
}
// Close the server. All active connections will be closed.
func (l *EarlyListener) Close() error {
return l.baseServer.Close()
}
// Addr returns the local network addr that the server is listening on.
func (l *EarlyListener) Addr() net.Addr {
return l.baseServer.Addr()
}
// ListenAddr creates a QUIC server listening on a given address.
// The tls.Config must not be nil and must contain a certificate configuration.
// The quic.Config may be nil, in that case the default values will be used.
func ListenAddr(addr string, tlsConf *tls.Config, config *Config) (Listener, error) {
return listenAddr(addr, tlsConf, config, false)
func ListenAddr(addr string, tlsConf *tls.Config, config *Config) (*Listener, error) {
s, err := listenAddr(addr, tlsConf, config, false)
if err != nil {
return nil, err
}
return &Listener{baseServer: s}, nil
}
// ListenAddrEarly works like ListenAddr, but it returns connections before the handshake completes.
func ListenAddrEarly(addr string, tlsConf *tls.Config, config *Config) (EarlyListener, error) {
func ListenAddrEarly(addr string, tlsConf *tls.Config, config *Config) (*EarlyListener, error) {
s, err := listenAddr(addr, tlsConf, config, true)
if err != nil {
return nil, err
}
return &earlyServer{s}, nil
return &EarlyListener{baseServer: s}, nil
}
func listenAddr(addr string, tlsConf *tls.Config, config *Config, acceptEarly bool) (*baseServer, error) {
@@ -170,17 +209,21 @@ func listenAddr(addr string, tlsConf *tls.Config, config *Config, acceptEarly bo
// The tls.Config must not be nil and must contain a certificate configuration.
// Furthermore, it must define an application control (using NextProtos).
// The quic.Config may be nil, in that case the default values will be used.
func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener, error) {
return listen(conn, tlsConf, config, false)
func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (*Listener, error) {
s, err := listen(conn, tlsConf, config, false)
if err != nil {
return nil, err
}
return &Listener{baseServer: s}, nil
}
// ListenEarly works like Listen, but it returns connections before the handshake completes.
func ListenEarly(conn net.PacketConn, tlsConf *tls.Config, config *Config) (EarlyListener, error) {
func ListenEarly(conn net.PacketConn, tlsConf *tls.Config, config *Config) (*EarlyListener, error) {
s, err := listen(conn, tlsConf, config, true)
if err != nil {
return nil, err
}
return &earlyServer{s}, nil
return &EarlyListener{baseServer: s}, nil
}
func listen(conn net.PacketConn, tlsConf *tls.Config, config *Config, acceptEarly bool) (*baseServer, error) {

View File

@@ -120,7 +120,7 @@ var _ = Describe("Server", func() {
It("fills in default values if options are not set in the Config", func() {
ln, err := Listen(conn, tlsConf, &Config{})
Expect(err).ToNot(HaveOccurred())
server := ln.(*baseServer)
server := ln.baseServer
Expect(server.config.Versions).To(Equal(protocol.SupportedVersions))
Expect(server.config.HandshakeIdleTimeout).To(Equal(protocol.DefaultHandshakeIdleTimeout))
Expect(server.config.MaxIdleTimeout).To(Equal(protocol.DefaultIdleTimeout))
@@ -143,7 +143,7 @@ var _ = Describe("Server", func() {
}
ln, err := Listen(conn, tlsConf, &config)
Expect(err).ToNot(HaveOccurred())
server := ln.(*baseServer)
server := ln.baseServer
Expect(server.connHandler).ToNot(BeNil())
Expect(server.config.Versions).To(Equal(supportedVersions))
Expect(server.config.HandshakeIdleTimeout).To(Equal(1337 * time.Hour))
@@ -187,7 +187,7 @@ var _ = Describe("Server", func() {
tracer = mocklogging.NewMockTracer(mockCtrl)
ln, err := Listen(conn, tlsConf, &Config{Tracer: tracer})
Expect(err).ToNot(HaveOccurred())
serv = ln.(*baseServer)
serv = ln.baseServer
phm = NewMockPacketHandlerManager(mockCtrl)
serv.connHandler = phm
})
@@ -1051,16 +1051,16 @@ var _ = Describe("Server", func() {
Context("server accepting connections that haven't completed the handshake", func() {
var (
serv *earlyServer
serv *EarlyListener
phm *MockPacketHandlerManager
)
BeforeEach(func() {
ln, err := ListenEarly(conn, tlsConf, nil)
var err error
serv, err = ListenEarly(conn, tlsConf, nil)
Expect(err).ToNot(HaveOccurred())
serv = ln.(*earlyServer)
phm = NewMockPacketHandlerManager(mockCtrl)
serv.connHandler = phm
serv.baseServer.connHandler = phm
})
AfterEach(func() {
@@ -1081,7 +1081,7 @@ var _ = Describe("Server", func() {
}()
ready := make(chan struct{})
serv.newConn = func(
serv.baseServer.newConn = func(
_ sendConn,
runner connRunner,
_ protocol.ConnectionID,
@@ -1111,7 +1111,7 @@ var _ = Describe("Server", func() {
fn()
return true
})
serv.handleInitialImpl(
serv.baseServer.handleInitialImpl(
&receivedPacket{buffer: getPacketBuffer()},
&wire.Header{DestConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8})},
)
@@ -1123,7 +1123,7 @@ var _ = Describe("Server", func() {
It("rejects new connection attempts if the accept queue is full", func() {
senderAddr := &net.UDPAddr{IP: net.IPv4(1, 2, 3, 4), Port: 42}
serv.newConn = func(
serv.baseServer.newConn = func(
_ sendConn,
runner connRunner,
_ protocol.ConnectionID,
@@ -1158,10 +1158,10 @@ var _ = Describe("Server", func() {
return true
}).Times(protocol.MaxAcceptQueueSize)
for i := 0; i < protocol.MaxAcceptQueueSize; i++ {
serv.handlePacket(getInitialWithRandomDestConnID())
serv.baseServer.handlePacket(getInitialWithRandomDestConnID())
}
Eventually(func() int32 { return atomic.LoadInt32(&serv.connQueueLen) }).Should(BeEquivalentTo(protocol.MaxAcceptQueueSize))
Eventually(func() int32 { return atomic.LoadInt32(&serv.baseServer.connQueueLen) }).Should(BeEquivalentTo(protocol.MaxAcceptQueueSize))
// make sure there are no Write calls on the packet conn
time.Sleep(50 * time.Millisecond)
@@ -1177,7 +1177,7 @@ var _ = Describe("Server", func() {
Expect(rejectHdr.SrcConnectionID).To(Equal(hdr.DestConnectionID))
return len(b), nil
})
serv.handlePacket(p)
serv.baseServer.handlePacket(p)
Eventually(done).Should(BeClosed())
})
@@ -1186,7 +1186,7 @@ var _ = Describe("Server", func() {
ctx, cancel := context.WithCancel(context.Background())
connCreated := make(chan struct{})
conn := NewMockQUICConn(mockCtrl)
serv.newConn = func(
serv.baseServer.newConn = func(
_ sendConn,
runner connRunner,
_ protocol.ConnectionID,
@@ -1218,7 +1218,7 @@ var _ = Describe("Server", func() {
fn()
return true
})
serv.handlePacket(p)
serv.baseServer.handlePacket(p)
// make sure there are no Write calls on the packet conn
time.Sleep(50 * time.Millisecond)
Eventually(connCreated).Should(BeClosed())
@@ -1243,7 +1243,7 @@ var _ = Describe("Server", func() {
Context("0-RTT", func() {
var (
serv *earlyServer
serv *baseServer
phm *MockPacketHandlerManager
tracer *mocklogging.MockTracer
)
@@ -1252,8 +1252,8 @@ var _ = Describe("Server", func() {
tracer = mocklogging.NewMockTracer(mockCtrl)
ln, err := ListenEarly(conn, tlsConf, &Config{Tracer: tracer})
Expect(err).ToNot(HaveOccurred())
serv = ln.(*earlyServer)
phm = NewMockPacketHandlerManager(mockCtrl)
serv = ln.baseServer
serv.connHandler = phm
})