diff --git a/caddytls/client.go b/caddytls/client.go
index b67a2928d..7c747194e 100644
--- a/caddytls/client.go
+++ b/caddytls/client.go
@@ -240,26 +240,30 @@ func (c *ACMEClient) Obtain(name string) error {
 	for attempts := 0; attempts < 2; attempts++ {
 		namesObtaining.Add([]string{name})
 		acmeMu.Lock()
-		certificate, failures := c.acmeClient.ObtainCertificate([]string{name}, true, nil, c.config.MustStaple)
+		certificate, err := c.acmeClient.ObtainCertificate([]string{name}, true, nil, c.config.MustStaple)
 		acmeMu.Unlock()
 		namesObtaining.Remove([]string{name})
-		if len(failures) > 0 {
+		if err != nil {
 			// Error - try to fix it or report it to the user and abort
 
-			var errMsg string // combine all the failures into a single error message
-			for errDomain, obtainErr := range failures {
-				if obtainErr == nil {
-					continue
+			if failures, ok := err.(acme.ObtainError); ok && len(failures) > 0 {
+				// in this case, we can enumerate the error per-domain
+				var errMsg string // combine all the failures into a single error message
+				for errDomain, obtainErr := range failures {
+					if obtainErr == nil {
+						continue
+					}
+					errMsg += fmt.Sprintf("[%s] failed to get certificate: %v\n", errDomain, obtainErr)
 				}
-				errMsg += fmt.Sprintf("[%s] failed to get certificate: %v\n", errDomain, obtainErr)
+				return errors.New(errMsg)
 			}
 
-			return errors.New(errMsg)
+			return fmt.Errorf("[%s] failed to obtain certificate: %v", name, err)
 		}
 
 		// double-check that we actually got a certificate; check a couple fields
 		// TODO: This is a temporary workaround for what I think is a bug in the acmev2 package (March 2018)
-		// but it might not hurt to keep this extra check in place
+		// but it might not hurt to keep this extra check in place (April 18, 2018: might be fixed now.)
 		if certificate.Domain == "" || certificate.Certificate == nil {
 			return errors.New("returned certificate was empty; probably an unchecked error obtaining it")
 		}
diff --git a/vendor/github.com/lucas-clemente/aes12/cipher_generic.go b/vendor/github.com/lucas-clemente/aes12/cipher_generic.go
index a9a6abd55..6861677f8 100644
--- a/vendor/github.com/lucas-clemente/aes12/cipher_generic.go
+++ b/vendor/github.com/lucas-clemente/aes12/cipher_generic.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !amd64,!s390x
+// +build !amd64
 
 package aes12
 
diff --git a/vendor/github.com/lucas-clemente/quic-go/client.go b/vendor/github.com/lucas-clemente/quic-go/client.go
index 02deb6804..1906abdf9 100644
--- a/vendor/github.com/lucas-clemente/quic-go/client.go
+++ b/vendor/github.com/lucas-clemente/quic-go/client.go
@@ -38,6 +38,8 @@ type client struct {
 	version        protocol.VersionNumber
 
 	session packetHandler
+
+	logger utils.Logger
 }
 
 var (
@@ -102,9 +104,10 @@ func Dial(
 		config:                 clientConfig,
 		version:                clientConfig.Versions[0],
 		versionNegotiationChan: make(chan struct{}),
+		logger:                 utils.DefaultLogger,
 	}
 
-	utils.Infof("Starting new connection to %s (%s -> %s), connectionID %x, version %s", hostname, c.conn.LocalAddr().String(), c.conn.RemoteAddr().String(), c.connectionID, c.version)
+	c.logger.Infof("Starting new connection to %s (%s -> %s), connectionID %x, version %s", hostname, c.conn.LocalAddr().String(), c.conn.RemoteAddr().String(), c.connectionID, c.version)
 
 	if err := c.dial(); err != nil {
 		return nil, err
@@ -197,7 +200,7 @@ func (c *client) dialTLS() error {
 		MaxUniStreams:               uint16(c.config.MaxIncomingUniStreams),
 	}
 	csc := handshake.NewCryptoStreamConn(nil)
-	extHandler := handshake.NewExtensionHandlerClient(params, c.initialVersion, c.config.Versions, c.version)
+	extHandler := handshake.NewExtensionHandlerClient(params, c.initialVersion, c.config.Versions, c.version, c.logger)
 	mintConf, err := tlsToMintConfig(c.tlsConf, protocol.PerspectiveClient)
 	if err != nil {
 		return err
@@ -214,7 +217,7 @@ func (c *client) dialTLS() error {
 		if err != handshake.ErrCloseSessionForRetry {
 			return err
 		}
-		utils.Infof("Received a Retry packet. Recreating session.")
+		c.logger.Infof("Received a Retry packet. Recreating session.")
 		if err := c.createNewTLSSession(extHandler.GetPeerParams(), c.version); err != nil {
 			return err
 		}
@@ -237,7 +240,7 @@ func (c *client) establishSecureConnection() error {
 	go func() {
 		runErr = c.session.run() // returns as soon as the session is closed
 		close(errorChan)
-		utils.Infof("Connection %x closed.", c.connectionID)
+		c.logger.Infof("Connection %x closed.", c.connectionID)
 		if runErr != handshake.ErrCloseSessionForRetry && runErr != errCloseSessionForNewVersion {
 			c.conn.Close()
 		}
@@ -291,7 +294,7 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) {
 	r := bytes.NewReader(packet)
 	hdr, err := wire.ParseHeaderSentByServer(r, c.version)
 	if err != nil {
-		utils.Errorf("error parsing packet from %s: %s", remoteAddr.String(), err.Error())
+		c.logger.Errorf("error parsing packet from %s: %s", remoteAddr.String(), err.Error())
 		// drop this packet if we can't parse the header
 		return
 	}
@@ -314,15 +317,15 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) {
 		// check if the remote address and the connection ID match
 		// otherwise this might be an attacker trying to inject a PUBLIC_RESET to kill the connection
 		if cr.Network() != remoteAddr.Network() || cr.String() != remoteAddr.String() || hdr.ConnectionID != c.connectionID {
-			utils.Infof("Received a spoofed Public Reset. Ignoring.")
+			c.logger.Infof("Received a spoofed Public Reset. Ignoring.")
 			return
 		}
 		pr, err := wire.ParsePublicReset(r)
 		if err != nil {
-			utils.Infof("Received a Public Reset. An error occurred parsing the packet: %s", err)
+			c.logger.Infof("Received a Public Reset. An error occurred parsing the packet: %s", err)
 			return
 		}
-		utils.Infof("Received Public Reset, rejected packet number: %#x.", pr.RejectedPacketNumber)
+		c.logger.Infof("Received Public Reset, rejected packet number: %#x.", pr.RejectedPacketNumber)
 		c.session.closeRemote(qerr.Error(qerr.PublicReset, fmt.Sprintf("Received a Public Reset for packet number %#x", pr.RejectedPacketNumber)))
 		return
 	}
@@ -368,7 +371,7 @@ func (c *client) handleVersionNegotiationPacket(hdr *wire.Header) error {
 		}
 	}
 
-	utils.Infof("Received a Version Negotiation Packet. Supported Versions: %s", hdr.SupportedVersions)
+	c.logger.Infof("Received a Version Negotiation Packet. Supported Versions: %s", hdr.SupportedVersions)
 
 	newVersion, ok := protocol.ChooseSupportedVersion(c.config.Versions, hdr.SupportedVersions)
 	if !ok {
@@ -385,7 +388,7 @@ func (c *client) handleVersionNegotiationPacket(hdr *wire.Header) error {
 	if err != nil {
 		return err
 	}
-	utils.Infof("Switching to QUIC version %s. New connection ID: %x", newVersion, c.connectionID)
+	c.logger.Infof("Switching to QUIC version %s. New connection ID: %x", newVersion, c.connectionID)
 	c.session.Close(errCloseSessionForNewVersion)
 	return nil
 }
@@ -402,6 +405,7 @@ func (c *client) createNewGQUICSession() (err error) {
 		c.config,
 		c.initialVersion,
 		c.negotiatedVersions,
+		c.logger,
 	)
 	return err
 }
@@ -421,6 +425,7 @@ func (c *client) createNewTLSSession(
 		c.tls,
 		paramsChan,
 		1,
+		c.logger,
 	)
 	return err
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/example/client/main.go b/vendor/github.com/lucas-clemente/quic-go/example/client/main.go
index 2a28c1612..23f045c84 100644
--- a/vendor/github.com/lucas-clemente/quic-go/example/client/main.go
+++ b/vendor/github.com/lucas-clemente/quic-go/example/client/main.go
@@ -19,12 +19,14 @@ func main() {
 	flag.Parse()
 	urls := flag.Args()
 
+	logger := utils.DefaultLogger
+
 	if *verbose {
-		utils.SetLogLevel(utils.LogLevelDebug)
+		logger.SetLogLevel(utils.LogLevelDebug)
 	} else {
-		utils.SetLogLevel(utils.LogLevelInfo)
+		logger.SetLogLevel(utils.LogLevelInfo)
 	}
-	utils.SetLogTimeFormat("")
+	logger.SetLogTimeFormat("")
 
 	versions := protocol.SupportedVersions
 	if *tls {
@@ -42,21 +44,21 @@ func main() {
 	var wg sync.WaitGroup
 	wg.Add(len(urls))
 	for _, addr := range urls {
-		utils.Infof("GET %s", addr)
+		logger.Infof("GET %s", addr)
 		go func(addr string) {
 			rsp, err := hclient.Get(addr)
 			if err != nil {
 				panic(err)
 			}
-			utils.Infof("Got response for %s: %#v", addr, rsp)
+			logger.Infof("Got response for %s: %#v", addr, rsp)
 
 			body := &bytes.Buffer{}
 			_, err = io.Copy(body, rsp.Body)
 			if err != nil {
 				panic(err)
 			}
-			utils.Infof("Request Body:")
-			utils.Infof("%s", body.Bytes())
+			logger.Infof("Request Body:")
+			logger.Infof("%s", body.Bytes())
 			wg.Done()
 		}(addr)
 	}
diff --git a/vendor/github.com/lucas-clemente/quic-go/example/main.go b/vendor/github.com/lucas-clemente/quic-go/example/main.go
index 35aaa85c6..e83fb8703 100644
--- a/vendor/github.com/lucas-clemente/quic-go/example/main.go
+++ b/vendor/github.com/lucas-clemente/quic-go/example/main.go
@@ -91,7 +91,7 @@ func init() {
 				}
 			}
 			if err != nil {
-				utils.Infof("Error receiving upload: %#v", err)
+				utils.DefaultLogger.Infof("Error receiving upload: %#v", err)
 			}
 		}
 		io.WriteString(w, `<html><body><form action="/demo/upload" method="post" enctype="multipart/form-data">
@@ -126,12 +126,14 @@ func main() {
 	tls := flag.Bool("tls", false, "activate support for IETF QUIC (work in progress)")
 	flag.Parse()
 
+	logger := utils.DefaultLogger
+
 	if *verbose {
-		utils.SetLogLevel(utils.LogLevelDebug)
+		logger.SetLogLevel(utils.LogLevelDebug)
 	} else {
-		utils.SetLogLevel(utils.LogLevelInfo)
+		logger.SetLogLevel(utils.LogLevelInfo)
 	}
-	utils.SetLogTimeFormat("")
+	logger.SetLogTimeFormat("")
 
 	versions := protocol.SupportedVersions
 	if *tls {
diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/client.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/client.go
index 53e667cd1..409808827 100644
--- a/vendor/github.com/lucas-clemente/quic-go/h2quic/client.go
+++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/client.go
@@ -46,6 +46,8 @@ type client struct {
 	requestWriter *requestWriter
 
 	responses map[protocol.StreamID]chan *http.Response
+
+	logger utils.Logger
 }
 
 var _ http.RoundTripper = &client{}
@@ -75,6 +77,7 @@ func newClient(
 		opts:          opts,
 		headerErrored: make(chan struct{}),
 		dialer:        dialer,
+		logger:        utils.DefaultLogger,
 	}
 }
 
@@ -95,7 +98,7 @@ func (c *client) dial() error {
 	if err != nil {
 		return err
 	}
-	c.requestWriter = newRequestWriter(c.headerStream)
+	c.requestWriter = newRequestWriter(c.headerStream, c.logger)
 	go c.handleHeaderStream()
 	return nil
 }
@@ -109,7 +112,7 @@ func (c *client) handleHeaderStream() {
 		err = c.readResponse(h2framer, decoder)
 	}
 	if quicErr, ok := err.(*qerr.QuicError); !ok || quicErr.ErrorCode != qerr.PeerGoingAway {
-		utils.Debugf("Error handling header stream: %s", err)
+		c.logger.Debugf("Error handling header stream: %s", err)
 	}
 	c.headerErr = qerr.Error(qerr.InvalidHeadersStreamData, err.Error())
 	// stop all running request
diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/request_writer.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/request_writer.go
index fdd7ad20a..ddaaa741d 100644
--- a/vendor/github.com/lucas-clemente/quic-go/h2quic/request_writer.go
+++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/request_writer.go
@@ -23,13 +23,16 @@ type requestWriter struct {
 
 	henc *hpack.Encoder
 	hbuf bytes.Buffer // HPACK encoder writes into this
+
+	logger utils.Logger
 }
 
 const defaultUserAgent = "quic-go"
 
-func newRequestWriter(headerStream quic.Stream) *requestWriter {
+func newRequestWriter(headerStream quic.Stream, logger utils.Logger) *requestWriter {
 	rw := &requestWriter{
 		headerStream: headerStream,
+		logger:       logger,
 	}
 	rw.henc = hpack.NewEncoder(&rw.hbuf)
 	return rw
@@ -156,7 +159,7 @@ func (w *requestWriter) encodeHeaders(req *http.Request, addGzipHeader bool, tra
 }
 
 func (w *requestWriter) writeHeader(name, value string) {
-	utils.Debugf("http2: Transport encoding header %q = %q", name, value)
+	w.logger.Debugf("http2: Transport encoding header %q = %q", name, value)
 	w.henc.WriteField(hpack.HeaderField{Name: name, Value: value})
 }
 
diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go
index 1dd4e928a..25b77a54c 100644
--- a/vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go
+++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/response_writer.go
@@ -24,15 +24,24 @@ type responseWriter struct {
 	header        http.Header
 	status        int // status code passed to WriteHeader
 	headerWritten bool
+
+	logger utils.Logger
 }
 
-func newResponseWriter(headerStream quic.Stream, headerStreamMutex *sync.Mutex, dataStream quic.Stream, dataStreamID protocol.StreamID) *responseWriter {
+func newResponseWriter(
+	headerStream quic.Stream,
+	headerStreamMutex *sync.Mutex,
+	dataStream quic.Stream,
+	dataStreamID protocol.StreamID,
+	logger utils.Logger,
+) *responseWriter {
 	return &responseWriter{
 		header:            http.Header{},
 		headerStream:      headerStream,
 		headerStreamMutex: headerStreamMutex,
 		dataStream:        dataStream,
 		dataStreamID:      dataStreamID,
+		logger:            logger,
 	}
 }
 
@@ -57,7 +66,7 @@ func (w *responseWriter) WriteHeader(status int) {
 		}
 	}
 
-	utils.Infof("Responding with %d", status)
+	w.logger.Infof("Responding with %d", status)
 	w.headerStreamMutex.Lock()
 	defer w.headerStreamMutex.Unlock()
 	h2framer := http2.NewFramer(w.headerStream, nil)
@@ -67,7 +76,7 @@ func (w *responseWriter) WriteHeader(status int) {
 		BlockFragment: headers.Bytes(),
 	})
 	if err != nil {
-		utils.Errorf("could not write h2 header: %s", err.Error())
+		w.logger.Errorf("could not write h2 header: %s", err.Error())
 	}
 }
 
diff --git a/vendor/github.com/lucas-clemente/quic-go/h2quic/server.go b/vendor/github.com/lucas-clemente/quic-go/h2quic/server.go
index 329edfd0d..a2412bd16 100644
--- a/vendor/github.com/lucas-clemente/quic-go/h2quic/server.go
+++ b/vendor/github.com/lucas-clemente/quic-go/h2quic/server.go
@@ -53,6 +53,8 @@ type Server struct {
 	closed        bool
 
 	supportedVersionsAsString string
+
+	logger utils.Logger // will be set by Server.serveImpl()
 }
 
 // ListenAndServe listens on the UDP address s.Addr and calls s.Handler to handle HTTP/2 requests on incoming connections.
@@ -88,6 +90,7 @@ func (s *Server) serveImpl(tlsConfig *tls.Config, conn net.PacketConn) error {
 	if s.Server == nil {
 		return errors.New("use of h2quic.Server without http.Server")
 	}
+	s.logger = utils.DefaultLogger
 	s.listenerMutex.Lock()
 	if s.closed {
 		s.listenerMutex.Unlock()
@@ -138,7 +141,7 @@ func (s *Server) handleHeaderStream(session streamCreator) {
 			// In this case, the session has already logged the error, so we don't
 			// need to log it again.
 			if _, ok := err.(*qerr.QuicError); !ok {
-				utils.Errorf("error handling h2 request: %s", err.Error())
+				s.logger.Errorf("error handling h2 request: %s", err.Error())
 			}
 			session.Close(err)
 			return
@@ -160,7 +163,7 @@ func (s *Server) handleRequest(session streamCreator, headerStream quic.Stream,
 	}
 	headers, err := hpackDecoder.DecodeFull(h2headersFrame.HeaderBlockFragment())
 	if err != nil {
-		utils.Errorf("invalid http2 headers encoding: %s", err.Error())
+		s.logger.Errorf("invalid http2 headers encoding: %s", err.Error())
 		return err
 	}
 
@@ -169,10 +172,10 @@ func (s *Server) handleRequest(session streamCreator, headerStream quic.Stream,
 		return err
 	}
 
-	if utils.Debug() {
-		utils.Infof("%s %s%s, on data stream %d", req.Method, req.Host, req.RequestURI, h2headersFrame.StreamID)
+	if s.logger.Debug() {
+		s.logger.Infof("%s %s%s, on data stream %d", req.Method, req.Host, req.RequestURI, h2headersFrame.StreamID)
 	} else {
-		utils.Infof("%s %s%s", req.Method, req.Host, req.RequestURI)
+		s.logger.Infof("%s %s%s", req.Method, req.Host, req.RequestURI)
 	}
 
 	dataStream, err := session.GetOrOpenStream(protocol.StreamID(h2headersFrame.StreamID))
@@ -201,7 +204,7 @@ func (s *Server) handleRequest(session streamCreator, headerStream quic.Stream,
 
 		req.RemoteAddr = session.RemoteAddr().String()
 
-		responseWriter := newResponseWriter(headerStream, headerStreamMutex, dataStream, protocol.StreamID(h2headersFrame.StreamID))
+		responseWriter := newResponseWriter(headerStream, headerStreamMutex, dataStream, protocol.StreamID(h2headersFrame.StreamID), s.logger)
 
 		handler := s.Handler
 		if handler == nil {
@@ -215,7 +218,7 @@ func (s *Server) handleRequest(session streamCreator, headerStream quic.Stream,
 					const size = 64 << 10
 					buf := make([]byte, size)
 					buf = buf[:runtime.Stack(buf, false)]
-					utils.Errorf("http: panic serving: %v\n%s", p, buf)
+					s.logger.Errorf("http: panic serving: %v\n%s", p, buf)
 					panicked = true
 				}
 			}()
diff --git a/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/proxy/proxy.go b/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/proxy/proxy.go
index 423aec019..d12a3baea 100644
--- a/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/proxy/proxy.go
+++ b/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/proxy/proxy.go
@@ -95,6 +95,8 @@ type QuicProxy struct {
 
 	// Mapping from client addresses (as host:port) to connection
 	clientDict map[string]*connection
+
+	logger utils.Logger
 }
 
 // NewQuicProxy creates a new UDP proxy
@@ -132,9 +134,10 @@ func NewQuicProxy(local string, version protocol.VersionNumber, opts *Opts) (*Qu
 		dropPacket:  packetDropper,
 		delayPacket: packetDelayer,
 		version:     version,
+		logger:      utils.DefaultLogger,
 	}
 
-	utils.Debugf("Starting UDP Proxy %s <-> %s", conn.LocalAddr(), raddr)
+	p.logger.Debugf("Starting UDP Proxy %s <-> %s", conn.LocalAddr(), raddr)
 	go p.runProxy()
 	return &p, nil
 }
@@ -200,8 +203,8 @@ func (p *QuicProxy) runProxy() error {
 		packetCount := atomic.AddUint64(&conn.incomingPacketCounter, 1)
 
 		if p.dropPacket(DirectionIncoming, packetCount) {
-			if utils.Debug() {
-				utils.Debugf("dropping incoming packet %d (%d bytes)", packetCount, n)
+			if p.logger.Debug() {
+				p.logger.Debugf("dropping incoming packet %d (%d bytes)", packetCount, n)
 			}
 			continue
 		}
@@ -209,16 +212,16 @@ func (p *QuicProxy) runProxy() error {
 		// Send the packet to the server
 		delay := p.delayPacket(DirectionIncoming, packetCount)
 		if delay != 0 {
-			if utils.Debug() {
-				utils.Debugf("delaying incoming packet %d (%d bytes) to %s by %s", packetCount, n, conn.ServerConn.RemoteAddr(), delay)
+			if p.logger.Debug() {
+				p.logger.Debugf("delaying incoming packet %d (%d bytes) to %s by %s", packetCount, n, conn.ServerConn.RemoteAddr(), delay)
 			}
 			time.AfterFunc(delay, func() {
 				// TODO: handle error
 				_, _ = conn.ServerConn.Write(raw)
 			})
 		} else {
-			if utils.Debug() {
-				utils.Debugf("forwarding incoming packet %d (%d bytes) to %s", packetCount, n, conn.ServerConn.RemoteAddr())
+			if p.logger.Debug() {
+				p.logger.Debugf("forwarding incoming packet %d (%d bytes) to %s", packetCount, n, conn.ServerConn.RemoteAddr())
 			}
 			if _, err := conn.ServerConn.Write(raw); err != nil {
 				return err
@@ -240,24 +243,24 @@ func (p *QuicProxy) runConnection(conn *connection) error {
 		packetCount := atomic.AddUint64(&conn.outgoingPacketCounter, 1)
 
 		if p.dropPacket(DirectionOutgoing, packetCount) {
-			if utils.Debug() {
-				utils.Debugf("dropping outgoing packet %d (%d bytes)", packetCount, n)
+			if p.logger.Debug() {
+				p.logger.Debugf("dropping outgoing packet %d (%d bytes)", packetCount, n)
 			}
 			continue
 		}
 
 		delay := p.delayPacket(DirectionOutgoing, packetCount)
 		if delay != 0 {
-			if utils.Debug() {
-				utils.Debugf("delaying outgoing packet %d (%d bytes) to %s by %s", packetCount, n, conn.ClientAddr, delay)
+			if p.logger.Debug() {
+				p.logger.Debugf("delaying outgoing packet %d (%d bytes) to %s by %s", packetCount, n, conn.ClientAddr, delay)
 			}
 			time.AfterFunc(delay, func() {
 				// TODO: handle error
 				_, _ = p.conn.WriteToUDP(raw, conn.ClientAddr)
 			})
 		} else {
-			if utils.Debug() {
-				utils.Debugf("forwarding outgoing packet %d (%d bytes) to %s", packetCount, n, conn.ClientAddr)
+			if p.logger.Debug() {
+				p.logger.Debugf("forwarding outgoing packet %d (%d bytes) to %s", packetCount, n, conn.ClientAddr)
 			}
 			if _, err := p.conn.WriteToUDP(raw, conn.ClientAddr); err != nil {
 				return err
diff --git a/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/testlog/testlog.go b/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/testlog/testlog.go
index 783531627..c987ddb73 100644
--- a/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/testlog/testlog.go
+++ b/vendor/github.com/lucas-clemente/quic-go/integrationtests/tools/testlog/testlog.go
@@ -30,7 +30,7 @@ var _ = BeforeEach(func() {
 		logFile, err = os.Create(logFileName)
 		Expect(err).ToNot(HaveOccurred())
 		log.SetOutput(logFile)
-		utils.SetLogLevel(utils.LogLevelDebug)
+		utils.DefaultLogger.SetLogLevel(utils.LogLevelDebug)
 	}
 })
 
diff --git a/vendor/github.com/lucas-clemente/quic-go/interface.go b/vendor/github.com/lucas-clemente/quic-go/interface.go
index bcbea1703..3ab64afdc 100644
--- a/vendor/github.com/lucas-clemente/quic-go/interface.go
+++ b/vendor/github.com/lucas-clemente/quic-go/interface.go
@@ -16,6 +16,9 @@ type StreamID = protocol.StreamID
 // A VersionNumber is a QUIC version number.
 type VersionNumber = protocol.VersionNumber
 
+// VersionGQUIC39 is gQUIC version 39.
+const VersionGQUIC39 = protocol.Version39
+
 // A Cookie can be used to verify the ownership of the client address.
 type Cookie = handshake.Cookie
 
@@ -118,6 +121,8 @@ type Session interface {
 	AcceptUniStream() (ReceiveStream, error)
 	// OpenStream opens a new bidirectional QUIC stream.
 	// It returns a special error when the peer's concurrent stream limit is reached.
+	// There is no signaling to the peer about new streams:
+	// The peer can only accept the stream after data has been sent on the stream.
 	// TODO(#1152): Enable testing for the special error
 	OpenStream() (Stream, error)
 	// OpenStreamSync opens a new bidirectional QUIC stream.
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/gen.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/gen.go
new file mode 100644
index 000000000..32235f81a
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/gen.go
@@ -0,0 +1,3 @@
+package ackhandler
+
+//go:generate genny -pkg ackhandler -in ../utils/linkedlist/linkedlist.go -out packet_linkedlist.go gen Item=Packet
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet.go
index 3638b193e..9673a85c7 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet.go
@@ -8,35 +8,22 @@ import (
 )
 
 // A Packet is a packet
-// +gen linkedlist
 type Packet struct {
 	PacketNumber    protocol.PacketNumber
 	PacketType      protocol.PacketType
 	Frames          []wire.Frame
 	Length          protocol.ByteCount
 	EncryptionLevel protocol.EncryptionLevel
+	SendTime        time.Time
 
 	largestAcked protocol.PacketNumber // if the packet contains an ACK, the LargestAcked value of that ACK
-	sendTime     time.Time
 
-	queuedForRetransmission bool
+	// There are two reasons why a packet cannot be retransmitted:
+	// * it was already retransmitted
+	// * this packet is a retransmission, and we already received an ACK for the original packet
+	canBeRetransmitted      bool
 	includedInBytesInFlight bool
 	retransmittedAs         []protocol.PacketNumber
 	isRetransmission        bool // we need a separate bool here because 0 is a valid packet number
 	retransmissionOf        protocol.PacketNumber
 }
-
-// GetFramesForRetransmission gets all the frames for retransmission
-func (p *Packet) GetFramesForRetransmission() []wire.Frame {
-	var fs []wire.Frame
-	for _, frame := range p.Frames {
-		switch frame.(type) {
-		case *wire.AckFrame:
-			continue
-		case *wire.StopWaitingFrame:
-			continue
-		}
-		fs = append(fs, frame)
-	}
-	return fs
-}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet_linkedlist.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet_linkedlist.go
index a827b214e..bb74f4ef9 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet_linkedlist.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/packet_linkedlist.go
@@ -1,13 +1,10 @@
-// Generated by: main
-// TypeWriter: linkedlist
-// Directive: +gen on Packet
+// This file was automatically generated by genny.
+// Any changes will be lost if this file is regenerated.
+// see https://github.com/cheekybits/genny
 
 package ackhandler
 
-// List is a modification of http://golang.org/pkg/container/list/
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
+// Linked list implementation from the Go standard library.
 
 // PacketElement is an element of a linked list.
 type PacketElement struct {
@@ -41,8 +38,7 @@ func (e *PacketElement) Prev() *PacketElement {
 	return nil
 }
 
-// PacketList represents a doubly linked list.
-// The zero value for PacketList is an empty list ready to use.
+// PacketList is a linked list of Packets.
 type PacketList struct {
 	root PacketElement // sentinel list element, only &root, root.prev, and root.next are used
 	len  int           // current list length excluding (this) sentinel element
@@ -63,7 +59,7 @@ func NewPacketList() *PacketList { return new(PacketList).Init() }
 // The complexity is O(1).
 func (l *PacketList) Len() int { return l.len }
 
-// Front returns the first element of list l or nil.
+// Front returns the first element of list l or nil if the list is empty.
 func (l *PacketList) Front() *PacketElement {
 	if l.len == 0 {
 		return nil
@@ -71,7 +67,7 @@ func (l *PacketList) Front() *PacketElement {
 	return l.root.next
 }
 
-// Back returns the last element of list l or nil.
+// Back returns the last element of list l or nil if the list is empty.
 func (l *PacketList) Back() *PacketElement {
 	if l.len == 0 {
 		return nil
@@ -79,7 +75,7 @@ func (l *PacketList) Back() *PacketElement {
 	return l.root.prev
 }
 
-// lazyInit lazily initializes a zero PacketList value.
+// lazyInit lazily initializes a zero List value.
 func (l *PacketList) lazyInit() {
 	if l.root.next == nil {
 		l.Init()
@@ -98,7 +94,7 @@ func (l *PacketList) insert(e, at *PacketElement) *PacketElement {
 	return e
 }
 
-// insertValue is a convenience wrapper for insert(&PacketElement{Value: v}, at).
+// insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
 func (l *PacketList) insertValue(v Packet, at *PacketElement) *PacketElement {
 	return l.insert(&PacketElement{Value: v}, at)
 }
@@ -116,10 +112,11 @@ func (l *PacketList) remove(e *PacketElement) *PacketElement {
 
 // Remove removes e from l if e is an element of list l.
 // It returns the element value e.Value.
+// The element must not be nil.
 func (l *PacketList) Remove(e *PacketElement) Packet {
 	if e.list == l {
 		// if e.list == l, l must have been initialized when e was inserted
-		// in l or l == nil (e is a zero PacketElement) and l.remove will crash
+		// in l or l == nil (e is a zero Element) and l.remove will crash
 		l.remove(e)
 	}
 	return e.Value
@@ -139,46 +136,51 @@ func (l *PacketList) PushBack(v Packet) *PacketElement {
 
 // InsertBefore inserts a new element e with value v immediately before mark and returns e.
 // If mark is not an element of l, the list is not modified.
+// The mark must not be nil.
 func (l *PacketList) InsertBefore(v Packet, mark *PacketElement) *PacketElement {
 	if mark.list != l {
 		return nil
 	}
-	// see comment in PacketList.Remove about initialization of l
+	// see comment in List.Remove about initialization of l
 	return l.insertValue(v, mark.prev)
 }
 
 // InsertAfter inserts a new element e with value v immediately after mark and returns e.
 // If mark is not an element of l, the list is not modified.
+// The mark must not be nil.
 func (l *PacketList) InsertAfter(v Packet, mark *PacketElement) *PacketElement {
 	if mark.list != l {
 		return nil
 	}
-	// see comment in PacketList.Remove about initialization of l
+	// see comment in List.Remove about initialization of l
 	return l.insertValue(v, mark)
 }
 
 // MoveToFront moves element e to the front of list l.
 // If e is not an element of l, the list is not modified.
+// The element must not be nil.
 func (l *PacketList) MoveToFront(e *PacketElement) {
 	if e.list != l || l.root.next == e {
 		return
 	}
-	// see comment in PacketList.Remove about initialization of l
+	// see comment in List.Remove about initialization of l
 	l.insert(l.remove(e), &l.root)
 }
 
 // MoveToBack moves element e to the back of list l.
 // If e is not an element of l, the list is not modified.
+// The element must not be nil.
 func (l *PacketList) MoveToBack(e *PacketElement) {
 	if e.list != l || l.root.prev == e {
 		return
 	}
-	// see comment in PacketList.Remove about initialization of l
+	// see comment in List.Remove about initialization of l
 	l.insert(l.remove(e), l.root.prev)
 }
 
 // MoveBefore moves element e to its new position before mark.
 // If e or mark is not an element of l, or e == mark, the list is not modified.
+// The element and mark must not be nil.
 func (l *PacketList) MoveBefore(e, mark *PacketElement) {
 	if e.list != l || e == mark || mark.list != l {
 		return
@@ -187,7 +189,8 @@ func (l *PacketList) MoveBefore(e, mark *PacketElement) {
 }
 
 // MoveAfter moves element e to its new position after mark.
-// If e is not an element of l, or e == mark, the list is not modified.
+// If e or mark is not an element of l, or e == mark, the list is not modified.
+// The element and mark must not be nil.
 func (l *PacketList) MoveAfter(e, mark *PacketElement) {
 	if e.list != l || e == mark || mark.list != l {
 		return
@@ -196,7 +199,7 @@ func (l *PacketList) MoveAfter(e, mark *PacketElement) {
 }
 
 // PushBackList inserts a copy of an other list at the back of list l.
-// The lists l and other may be the same.
+// The lists l and other may be the same. They must not be nil.
 func (l *PacketList) PushBackList(other *PacketList) {
 	l.lazyInit()
 	for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
@@ -205,7 +208,7 @@ func (l *PacketList) PushBackList(other *PacketList) {
 }
 
 // PushFrontList inserts a copy of an other list at the front of list l.
-// The lists l and other may be the same.
+// The lists l and other may be the same. They must not be nil.
 func (l *PacketList) PushFrontList(other *PacketList) {
 	l.lazyInit()
 	for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/send_mode.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/send_mode.go
index 3ece73522..61573a478 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/send_mode.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/send_mode.go
@@ -12,6 +12,8 @@ const (
 	SendAck
 	// SendRetransmission means that retransmissions should be sent
 	SendRetransmission
+	// SendRTO means that an RTO probe packet should be sent
+	SendRTO
 	// SendAny packet should be sent
 	SendAny
 )
@@ -24,6 +26,8 @@ func (s SendMode) String() string {
 		return "ack"
 	case SendRetransmission:
 		return "retransmission"
+	case SendRTO:
+		return "rto"
 	case SendAny:
 		return "any"
 	default:
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go
index bee194774..72ab4df8f 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go
@@ -32,6 +32,7 @@ const (
 type sentPacketHandler struct {
 	lastSentPacketNumber              protocol.PacketNumber
 	lastSentRetransmittablePacketTime time.Time
+	lastSentHandshakePacketTime       time.Time
 
 	nextPacketSendTime time.Time
 	skippedPackets     []protocol.PacketNumber
@@ -42,6 +43,7 @@ type sentPacketHandler struct {
 	// example: we send an ACK for packets 90-100 with packet number 20
 	// once we receive an ACK from the peer for packet 20, the lowestPacketNotConfirmedAcked is 101
 	lowestPacketNotConfirmedAcked protocol.PacketNumber
+	largestSentBeforeRTO          protocol.PacketNumber
 
 	packetHistory      *sentPacketHistory
 	stopWaitingManager stopWaitingManager
@@ -59,16 +61,20 @@ type sentPacketHandler struct {
 
 	// The number of times an RTO has been sent without receiving an ack.
 	rtoCount uint32
+	// The number of RTO probe packets that should be sent.
+	numRTOs int
 
 	// The time at which the next packet will be considered lost based on early transmit or exceeding the reordering window in time.
 	lossTime time.Time
 
 	// The alarm timeout
 	alarm time.Time
+
+	logger utils.Logger
 }
 
 // NewSentPacketHandler creates a new sentPacketHandler
-func NewSentPacketHandler(rttStats *congestion.RTTStats) SentPacketHandler {
+func NewSentPacketHandler(rttStats *congestion.RTTStats, logger utils.Logger) SentPacketHandler {
 	congestion := congestion.NewCubicSender(
 		congestion.DefaultClock{},
 		rttStats,
@@ -82,6 +88,7 @@ func NewSentPacketHandler(rttStats *congestion.RTTStats) SentPacketHandler {
 		stopWaitingManager: stopWaitingManager{},
 		rttStats:           rttStats,
 		congestion:         congestion,
+		logger:             logger,
 	}
 }
 
@@ -114,7 +121,6 @@ func (h *sentPacketHandler) SetHandshakeComplete() {
 }
 
 func (h *sentPacketHandler) SentPacket(packet *Packet) {
-	packet.sendTime = time.Now()
 	if isRetransmittable := h.sentPacketImpl(packet); isRetransmittable {
 		h.packetHistory.SentPacket(packet)
 		h.updateLossDetectionAlarm()
@@ -122,10 +128,8 @@ func (h *sentPacketHandler) SentPacket(packet *Packet) {
 }
 
 func (h *sentPacketHandler) SentPacketsAsRetransmission(packets []*Packet, retransmissionOf protocol.PacketNumber) {
-	now := time.Now()
 	var p []*Packet
 	for _, packet := range packets {
-		packet.sendTime = now
 		if isRetransmittable := h.sentPacketImpl(packet); isRetransmittable {
 			p = append(p, packet)
 		}
@@ -144,10 +148,9 @@ func (h *sentPacketHandler) sentPacketImpl(packet *Packet) bool /* isRetransmitt
 
 	h.lastSentPacketNumber = packet.PacketNumber
 
-	var largestAcked protocol.PacketNumber
 	if len(packet.Frames) > 0 {
 		if ackFrame, ok := packet.Frames[0].(*wire.AckFrame); ok {
-			largestAcked = ackFrame.LargestAcked
+			packet.largestAcked = ackFrame.LargestAcked
 		}
 	}
 
@@ -155,14 +158,20 @@ func (h *sentPacketHandler) sentPacketImpl(packet *Packet) bool /* isRetransmitt
 	isRetransmittable := len(packet.Frames) != 0
 
 	if isRetransmittable {
-		packet.largestAcked = largestAcked
-		h.lastSentRetransmittablePacketTime = packet.sendTime
+		if packet.EncryptionLevel < protocol.EncryptionForwardSecure {
+			h.lastSentHandshakePacketTime = packet.SendTime
+		}
+		h.lastSentRetransmittablePacketTime = packet.SendTime
 		packet.includedInBytesInFlight = true
 		h.bytesInFlight += packet.Length
+		packet.canBeRetransmitted = true
+		if h.numRTOs > 0 {
+			h.numRTOs--
+		}
 	}
-	h.congestion.OnPacketSent(packet.sendTime, h.bytesInFlight, packet.PacketNumber, packet.Length, isRetransmittable)
+	h.congestion.OnPacketSent(packet.SendTime, h.bytesInFlight, packet.PacketNumber, packet.Length, isRetransmittable)
 
-	h.nextPacketSendTime = utils.MaxTime(h.nextPacketSendTime, packet.sendTime).Add(h.congestion.TimeUntilSend(h.bytesInFlight))
+	h.nextPacketSendTime = utils.MaxTime(h.nextPacketSendTime, packet.SendTime).Add(h.congestion.TimeUntilSend(h.bytesInFlight))
 	return isRetransmittable
 }
 
@@ -173,7 +182,7 @@ func (h *sentPacketHandler) ReceivedAck(ackFrame *wire.AckFrame, withPacketNumbe
 
 	// duplicate or out of order ACK
 	if withPacketNumber != 0 && withPacketNumber <= h.largestReceivedPacketWithAck {
-		utils.Debugf("Ignoring ACK frame (duplicate or out of order).")
+		h.logger.Debugf("Ignoring ACK frame (duplicate or out of order).")
 		return nil
 	}
 	h.largestReceivedPacketWithAck = withPacketNumber
@@ -192,6 +201,7 @@ func (h *sentPacketHandler) ReceivedAck(ackFrame *wire.AckFrame, withPacketNumbe
 		return err
 	}
 
+	priorInFlight := h.bytesInFlight
 	for _, p := range ackedPackets {
 		if encLevel < p.EncryptionLevel {
 			return fmt.Errorf("Received ACK with encryption level %s that acks a packet %d (encryption level %s)", encLevel, p.PacketNumber, p.EncryptionLevel)
@@ -205,12 +215,12 @@ func (h *sentPacketHandler) ReceivedAck(ackFrame *wire.AckFrame, withPacketNumbe
 		if err := h.onPacketAcked(p); err != nil {
 			return err
 		}
-		if len(p.retransmittedAs) == 0 {
-			h.congestion.OnPacketAcked(p.PacketNumber, p.Length, h.bytesInFlight)
+		if p.includedInBytesInFlight {
+			h.congestion.OnPacketAcked(p.PacketNumber, p.Length, priorInFlight)
 		}
 	}
 
-	if err := h.detectLostPackets(rcvTime); err != nil {
+	if err := h.detectLostPackets(rcvTime, priorInFlight); err != nil {
 		return err
 	}
 	h.updateLossDetectionAlarm()
@@ -262,7 +272,7 @@ func (h *sentPacketHandler) determineNewlyAckedPackets(ackFrame *wire.AckFrame)
 
 func (h *sentPacketHandler) maybeUpdateRTT(largestAcked protocol.PacketNumber, ackDelay time.Duration, rcvTime time.Time) bool {
 	if p := h.packetHistory.GetPacket(largestAcked); p != nil {
-		h.rttStats.UpdateRTT(rcvTime.Sub(p.sendTime), ackDelay, rcvTime)
+		h.rttStats.UpdateRTT(rcvTime.Sub(p.SendTime), ackDelay, rcvTime)
 		return true
 	}
 	return false
@@ -277,7 +287,7 @@ func (h *sentPacketHandler) updateLossDetectionAlarm() {
 
 	// TODO(#497): TLP
 	if !h.handshakeComplete {
-		h.alarm = h.lastSentRetransmittablePacketTime.Add(h.computeHandshakeTimeout())
+		h.alarm = h.lastSentHandshakePacketTime.Add(h.computeHandshakeTimeout())
 	} else if !h.lossTime.IsZero() {
 		// Early retransmit timer or time loss detection.
 		h.alarm = h.lossTime
@@ -287,7 +297,7 @@ func (h *sentPacketHandler) updateLossDetectionAlarm() {
 	}
 }
 
-func (h *sentPacketHandler) detectLostPackets(now time.Time) error {
+func (h *sentPacketHandler) detectLostPackets(now time.Time, priorInFlight protocol.ByteCount) error {
 	h.lossTime = time.Time{}
 
 	maxRTT := float64(utils.MaxDuration(h.rttStats.LatestRTT(), h.rttStats.SmoothedRTT()))
@@ -298,11 +308,8 @@ func (h *sentPacketHandler) detectLostPackets(now time.Time) error {
 		if packet.PacketNumber > h.largestAcked {
 			return false, nil
 		}
-		if packet.queuedForRetransmission { // don't retransmit packets twice
-			return true, nil
-		}
 
-		timeSinceSent := now.Sub(packet.sendTime)
+		timeSinceSent := now.Sub(packet.SendTime)
 		if timeSinceSent > delayUntilLost {
 			lostPackets = append(lostPackets, packet)
 		} else if h.lossTime.IsZero() {
@@ -313,12 +320,19 @@ func (h *sentPacketHandler) detectLostPackets(now time.Time) error {
 	})
 
 	for _, p := range lostPackets {
-		if err := h.queuePacketForRetransmission(p); err != nil {
-			return err
+		// the bytes in flight need to be reduced no matter if this packet will be retransmitted
+		if p.includedInBytesInFlight {
+			h.bytesInFlight -= p.Length
+			h.congestion.OnPacketLost(p.PacketNumber, p.Length, priorInFlight)
 		}
-		h.bytesInFlight -= p.Length
-		p.includedInBytesInFlight = false
-		h.congestion.OnPacketLost(p.PacketNumber, p.Length, h.bytesInFlight)
+		if p.canBeRetransmitted {
+			// queue the packet for retransmission, and report the loss to the congestion controller
+			h.logger.Debugf("\tQueueing packet %#x because it was detected lost", p.PacketNumber)
+			if err := h.queuePacketForRetransmission(p); err != nil {
+				return err
+			}
+		}
+		h.packetHistory.Remove(p.PacketNumber)
 	}
 	return nil
 }
@@ -333,10 +347,11 @@ func (h *sentPacketHandler) OnAlarm() error {
 		err = h.queueHandshakePacketsForRetransmission()
 	} else if !h.lossTime.IsZero() {
 		// Early retransmit or time loss detection
-		err = h.detectLostPackets(now)
+		err = h.detectLostPackets(now, h.bytesInFlight)
 	} else {
 		// RTO
 		h.rtoCount++
+		h.numRTOs += 2
 		err = h.queueRTOs()
 	}
 	if err != nil {
@@ -357,57 +372,67 @@ func (h *sentPacketHandler) onPacketAcked(p *Packet) error {
 	if packet := h.packetHistory.GetPacket(p.PacketNumber); packet == nil {
 		return nil
 	}
+
+	// only report the acking of this packet to the congestion controller if:
+	// * it is a retransmittable packet
+	// * this packet wasn't retransmitted yet
+	if p.isRetransmission {
+		// that the parent doesn't exist is expected to happen every time the original packet was already acked
+		if parent := h.packetHistory.GetPacket(p.retransmissionOf); parent != nil {
+			if len(parent.retransmittedAs) == 1 {
+				parent.retransmittedAs = nil
+			} else {
+				// remove this packet from the slice of retransmission
+				retransmittedAs := make([]protocol.PacketNumber, 0, len(parent.retransmittedAs)-1)
+				for _, pn := range parent.retransmittedAs {
+					if pn != p.PacketNumber {
+						retransmittedAs = append(retransmittedAs, pn)
+					}
+				}
+				parent.retransmittedAs = retransmittedAs
+			}
+		}
+	}
+	// this also applies to packets that have been retransmitted as probe packets
+	if p.includedInBytesInFlight {
+		h.bytesInFlight -= p.Length
+	}
+	if h.rtoCount > 0 {
+		h.verifyRTO(p.PacketNumber)
+	}
+	if err := h.stopRetransmissionsFor(p); err != nil {
+		return err
+	}
 	h.rtoCount = 0
 	h.handshakeCount = 0
 	// TODO(#497): h.tlpCount = 0
-
-	// find the first packet, from which on we can delete all retransmissions
-	// example: packet 10 was retransmitted as packet 11 and 12, and
-	// packet 12 was then retransmitted as 13.
-	// When receiving an ACK for packet 13, we can remove packets 12 and 13,
-	// but still need to keep 10 and 11.
-	first := p
-	for first.isRetransmission {
-		previous := h.packetHistory.GetPacket(first.retransmissionOf)
-		if previous == nil {
-			return fmt.Errorf("sent packet handler BUG: retransmitted packet for %d not found (should have been %d)", first.PacketNumber, first.retransmissionOf)
-		}
-		// if the retransmission of a packet was split, we can't remove it yet
-		if len(previous.retransmittedAs) > 1 {
-			break
-		}
-		first = previous
-	}
-	if first.isRetransmission {
-		root := h.packetHistory.GetPacket(first.retransmissionOf)
-		retransmittedAs := make([]protocol.PacketNumber, 0, len(root.retransmittedAs)-1)
-		for _, pn := range root.retransmittedAs {
-			if pn != first.PacketNumber {
-				retransmittedAs = append(retransmittedAs, pn)
-			}
-		}
-		root.retransmittedAs = retransmittedAs
-	}
-	return h.removeAllRetransmissions(first)
+	return h.packetHistory.Remove(p.PacketNumber)
 }
 
-func (h *sentPacketHandler) removeAllRetransmissions(p *Packet) error {
-	if p.includedInBytesInFlight {
-		h.bytesInFlight -= p.Length
-		p.includedInBytesInFlight = false
+func (h *sentPacketHandler) stopRetransmissionsFor(p *Packet) error {
+	if err := h.packetHistory.MarkCannotBeRetransmitted(p.PacketNumber); err != nil {
+		return err
 	}
-	if p.queuedForRetransmission {
-		for _, r := range p.retransmittedAs {
-			packet := h.packetHistory.GetPacket(r)
-			if packet == nil {
-				return fmt.Errorf("sent packet handler BUG: removing packet %d (retransmission of %d) not found in history", r, p.PacketNumber)
-			}
-			if err := h.removeAllRetransmissions(packet); err != nil {
-				return err
-			}
+	for _, r := range p.retransmittedAs {
+		packet := h.packetHistory.GetPacket(r)
+		if packet == nil {
+			return fmt.Errorf("sent packet handler BUG: marking packet as not retransmittable %d (retransmission of %d) not found in history", r, p.PacketNumber)
 		}
+		h.stopRetransmissionsFor(packet)
 	}
-	return h.packetHistory.Remove(p.PacketNumber)
+	return nil
+}
+
+func (h *sentPacketHandler) verifyRTO(pn protocol.PacketNumber) {
+	if pn <= h.largestSentBeforeRTO {
+		h.logger.Debugf("Spurious RTO detected. Received an ACK for %#x (largest sent before RTO: %#x)", pn, h.largestSentBeforeRTO)
+		// Replace SRTT with latest_rtt and increase the variance to prevent
+		// a spurious RTO from happening again.
+		h.rttStats.ExpireSmoothedMetrics()
+		return
+	}
+	h.logger.Debugf("RTO verified. Received an ACK for %#x (largest sent before RTO: %#x", pn, h.largestSentBeforeRTO)
+	h.congestion.OnRetransmissionTimeout(true)
 }
 
 func (h *sentPacketHandler) DequeuePacketForRetransmission() *Packet {
@@ -438,20 +463,23 @@ func (h *sentPacketHandler) SendMode() SendMode {
 	// we will stop sending out new data when reaching MaxOutstandingSentPackets,
 	// but still allow sending of retransmissions and ACKs.
 	if numTrackedPackets >= protocol.MaxTrackedSentPackets {
-		utils.Debugf("Limited by the number of tracked packets: tracking %d packets, maximum %d", numTrackedPackets, protocol.MaxTrackedSentPackets)
+		h.logger.Debugf("Limited by the number of tracked packets: tracking %d packets, maximum %d", numTrackedPackets, protocol.MaxTrackedSentPackets)
 		return SendNone
 	}
+	if h.numRTOs > 0 {
+		return SendRTO
+	}
+	// Only send ACKs if we're congestion limited.
+	if cwnd := h.congestion.GetCongestionWindow(); h.bytesInFlight > cwnd {
+		h.logger.Debugf("Congestion limited: bytes in flight %d, window %d", h.bytesInFlight, cwnd)
+		return SendAck
+	}
 	// Send retransmissions first, if there are any.
 	if len(h.retransmissionQueue) > 0 {
 		return SendRetransmission
 	}
-	// Only send ACKs if we're congestion limited.
-	if cwnd := h.congestion.GetCongestionWindow(); h.bytesInFlight > cwnd {
-		utils.Debugf("Congestion limited: bytes in flight %d, window %d", h.bytesInFlight, cwnd)
-		return SendAck
-	}
 	if numTrackedPackets >= protocol.MaxOutstandingSentPackets {
-		utils.Debugf("Max outstanding limited: tracking %d packets, maximum: %d", numTrackedPackets, protocol.MaxOutstandingSentPackets)
+		h.logger.Debugf("Max outstanding limited: tracking %d packets, maximum: %d", numTrackedPackets, protocol.MaxOutstandingSentPackets)
 		return SendAck
 	}
 	return SendAny
@@ -462,6 +490,10 @@ func (h *sentPacketHandler) TimeUntilSend() time.Time {
 }
 
 func (h *sentPacketHandler) ShouldSendNumPackets() int {
+	if h.numRTOs > 0 {
+		// RTO probes should not be paced, but must be sent immediately.
+		return h.numRTOs
+	}
 	delay := h.congestion.TimeUntilSend(h.bytesInFlight)
 	if delay == 0 || delay > protocol.MinPacingDelay {
 		return 1
@@ -471,14 +503,16 @@ func (h *sentPacketHandler) ShouldSendNumPackets() int {
 
 // retransmit the oldest two packets
 func (h *sentPacketHandler) queueRTOs() error {
+	h.largestSentBeforeRTO = h.lastSentPacketNumber
+	// Queue the first two outstanding packets for retransmission.
+	// This does NOT declare this packets as lost:
+	// They are still tracked in the packet history and count towards the bytes in flight.
 	for i := 0; i < 2; i++ {
 		if p := h.packetHistory.FirstOutstanding(); p != nil {
-			utils.Debugf("\tQueueing packet %#x for retransmission (RTO), %d outstanding", p.PacketNumber, h.packetHistory.Len())
+			h.logger.Debugf("\tQueueing packet %#x for retransmission (RTO)", p.PacketNumber)
 			if err := h.queuePacketForRetransmission(p); err != nil {
 				return err
 			}
-			h.congestion.OnPacketLost(p.PacketNumber, p.Length, h.bytesInFlight)
-			h.congestion.OnRetransmissionTimeout(true)
 		}
 	}
 	return nil
@@ -487,12 +521,13 @@ func (h *sentPacketHandler) queueRTOs() error {
 func (h *sentPacketHandler) queueHandshakePacketsForRetransmission() error {
 	var handshakePackets []*Packet
 	h.packetHistory.Iterate(func(p *Packet) (bool, error) {
-		if !p.queuedForRetransmission && p.EncryptionLevel < protocol.EncryptionForwardSecure {
+		if p.canBeRetransmitted && p.EncryptionLevel < protocol.EncryptionForwardSecure {
 			handshakePackets = append(handshakePackets, p)
 		}
 		return true, nil
 	})
 	for _, p := range handshakePackets {
+		h.logger.Debugf("\tQueueing packet %#x as a handshake retransmission", p.PacketNumber)
 		if err := h.queuePacketForRetransmission(p); err != nil {
 			return err
 		}
@@ -501,7 +536,10 @@ func (h *sentPacketHandler) queueHandshakePacketsForRetransmission() error {
 }
 
 func (h *sentPacketHandler) queuePacketForRetransmission(p *Packet) error {
-	if _, err := h.packetHistory.QueuePacketForRetransmission(p.PacketNumber); err != nil {
+	if !p.canBeRetransmitted {
+		return fmt.Errorf("sent packet handler BUG: packet %d already queued for retransmission", p.PacketNumber)
+	}
+	if err := h.packetHistory.MarkCannotBeRetransmitted(p.PacketNumber); err != nil {
 		return err
 	}
 	h.retransmissionQueue = append(h.retransmissionQueue, p)
@@ -521,9 +559,12 @@ func (h *sentPacketHandler) computeHandshakeTimeout() time.Duration {
 }
 
 func (h *sentPacketHandler) computeRTOTimeout() time.Duration {
-	rto := h.congestion.RetransmissionDelay()
-	if rto == 0 {
+	var rto time.Duration
+	rtt := h.rttStats.SmoothedRTT()
+	if rtt == 0 {
 		rto = defaultRTOTimeout
+	} else {
+		rto = rtt + 4*h.rttStats.MeanDeviation()
 	}
 	rto = utils.MaxDuration(rto, minRTOTimeout)
 	// Exponential backoff
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_history.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_history.go
index f815b8542..38a2a0e50 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_history.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_history.go
@@ -87,26 +87,23 @@ func (h *sentPacketHistory) FirstOutstanding() *Packet {
 
 // QueuePacketForRetransmission marks a packet for retransmission.
 // A packet can only be queued once.
-func (h *sentPacketHistory) QueuePacketForRetransmission(pn protocol.PacketNumber) (*Packet, error) {
+func (h *sentPacketHistory) MarkCannotBeRetransmitted(pn protocol.PacketNumber) error {
 	el, ok := h.packetMap[pn]
 	if !ok {
-		return nil, fmt.Errorf("sent packet history: packet %d not found", pn)
+		return fmt.Errorf("sent packet history: packet %d not found", pn)
 	}
-	if el.Value.queuedForRetransmission {
-		return nil, fmt.Errorf("sent packet history BUG: packet %d already queued for retransmission", pn)
-	}
-	el.Value.queuedForRetransmission = true
+	el.Value.canBeRetransmitted = false
 	if el == h.firstOutstanding {
 		h.readjustFirstOutstanding()
 	}
-	return &el.Value, nil
+	return nil
 }
 
 // readjustFirstOutstanding readjusts the pointer to the first outstanding packet.
 // This is necessary every time the first outstanding packet is deleted or retransmitted.
 func (h *sentPacketHistory) readjustFirstOutstanding() {
 	el := h.firstOutstanding.Next()
-	for el != nil && el.Value.queuedForRetransmission {
+	for el != nil && !el.Value.canBeRetransmitted {
 		el = el.Next()
 	}
 	h.firstOutstanding = el
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/congestion/cubic_sender.go b/vendor/github.com/lucas-clemente/quic-go/internal/congestion/cubic_sender.go
index 1ab59535f..21f019424 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/congestion/cubic_sender.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/congestion/cubic_sender.go
@@ -292,11 +292,3 @@ func (c *cubicSender) OnConnectionMigration() {
 func (c *cubicSender) SetSlowStartLargeReduction(enabled bool) {
 	c.slowStartLargeReduction = enabled
 }
-
-// RetransmissionDelay gives the time to retransmission
-func (c *cubicSender) RetransmissionDelay() time.Duration {
-	if c.rttStats.SmoothedRTT() == 0 {
-		return 0
-	}
-	return c.rttStats.SmoothedRTT() + c.rttStats.MeanDeviation()*4
-}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/congestion/interface.go b/vendor/github.com/lucas-clemente/quic-go/internal/congestion/interface.go
index 3c09428fd..28950dd0c 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/congestion/interface.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/congestion/interface.go
@@ -17,7 +17,6 @@ type SendAlgorithm interface {
 	SetNumEmulatedConnections(n int)
 	OnRetransmissionTimeout(packetsRetransmitted bool)
 	OnConnectionMigration()
-	RetransmissionDelay() time.Duration
 
 	// Experiments
 	SetSlowStartLargeReduction(enabled bool)
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/congestion/rtt_stats.go b/vendor/github.com/lucas-clemente/quic-go/internal/congestion/rtt_stats.go
index 9e5e4541a..599e350fb 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/congestion/rtt_stats.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/congestion/rtt_stats.go
@@ -84,7 +84,6 @@ func (r *RTTStats) SetRecentMinRTTwindow(recentMinRTTwindow time.Duration) {
 // UpdateRTT updates the RTT based on a new sample.
 func (r *RTTStats) UpdateRTT(sendDelta, ackDelay time.Duration, now time.Time) {
 	if sendDelta == utils.InfDuration || sendDelta <= 0 {
-		utils.Debugf("Ignoring measured sendDelta, because it's is either infinite, zero, or negative: %d", sendDelta/time.Microsecond)
 		return
 	}
 
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/curve_25519.go b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/curve_25519.go
index a570d6b31..fd25b00fc 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/curve_25519.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/curve_25519.go
@@ -21,10 +21,6 @@ func NewCurve25519KEX() (KeyExchange, error) {
 	if _, err := rand.Read(c.secret[:]); err != nil {
 		return nil, errors.New("Curve25519: could not create private key")
 	}
-	// See https://cr.yp.to/ecdh.html
-	c.secret[0] &= 248
-	c.secret[31] &= 127
-	c.secret[31] |= 64
 	curve25519.ScalarBaseMult(&c.public, &c.secret)
 	return c, nil
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/key_derivation.go b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/key_derivation.go
index 5cffba590..89b9e1f12 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/key_derivation.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/key_derivation.go
@@ -20,9 +20,7 @@ type TLSExporter interface {
 }
 
 func qhkdfExpand(secret []byte, label string, length int) []byte {
-	// The last byte should be 0x0.
-	// Since Go initializes the slice to 0, we don't need to set it explicitly.
-	qlabel := make([]byte, 2+1+5+len(label)+1)
+	qlabel := make([]byte, 2+1+5+len(label))
 	binary.BigEndian.PutUint16(qlabel[0:2], uint16(length))
 	qlabel[2] = uint8(5 + len(label))
 	copy(qlabel[3:], []byte("QUIC "+label))
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_aesgcm.go b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_aesgcm.go
index 0b192b52b..92c6362f4 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_aesgcm.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_aesgcm.go
@@ -8,7 +8,7 @@ import (
 	"github.com/lucas-clemente/quic-go/internal/protocol"
 )
 
-var quicVersion1Salt = []byte{0xaf, 0xc8, 0x24, 0xec, 0x5f, 0xc7, 0x7e, 0xca, 0x1e, 0x9d, 0x36, 0xf3, 0x7f, 0xb2, 0xd4, 0x65, 0x18, 0xc3, 0x66, 0x39}
+var quicVersion1Salt = []byte{0x9c, 0x10, 0x8f, 0x98, 0x52, 0x0a, 0x5c, 0x5c, 0x32, 0x96, 0x8e, 0x95, 0x0e, 0x8a, 0x2c, 0x5f, 0xe0, 0x6d, 0x6c, 0x38}
 
 func newNullAEADAESGCM(connectionID protocol.ConnectionID, pers protocol.Perspective) (AEAD, error) {
 	clientSecret, serverSecret := computeSecrets(connectionID)
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_fnv128a.go b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_fnv128a.go
index ecc4010bd..6c50ab908 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_fnv128a.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_fnv128a.go
@@ -1,10 +1,11 @@
 package crypto
 
 import (
-	"encoding/binary"
+	"bytes"
 	"errors"
+	"fmt"
+	"hash/fnv"
 
-	"github.com/lucas-clemente/fnv128a"
 	"github.com/lucas-clemente/quic-go/internal/protocol"
 )
 
@@ -21,7 +22,7 @@ func (n *nullAEADFNV128a) Open(dst, src []byte, packetNumber protocol.PacketNumb
 		return nil, errors.New("NullAEAD: ciphertext cannot be less than 12 bytes long")
 	}
 
-	hash := fnv128a.New()
+	hash := fnv.New128a()
 	hash.Write(associatedData)
 	hash.Write(src[12:])
 	if n.perspective == protocol.PerspectiveServer {
@@ -29,13 +30,13 @@ func (n *nullAEADFNV128a) Open(dst, src []byte, packetNumber protocol.PacketNumb
 	} else {
 		hash.Write([]byte("Server"))
 	}
-	testHigh, testLow := hash.Sum128()
+	sum := make([]byte, 0, 16)
+	sum = hash.Sum(sum)
+	// The tag is written in little endian, so we need to reverse the slice.
+	reverse(sum)
 
-	low := binary.LittleEndian.Uint64(src)
-	high := binary.LittleEndian.Uint32(src[8:])
-
-	if uint32(testHigh&0xffffffff) != high || testLow != low {
-		return nil, errors.New("NullAEAD: failed to authenticate received data")
+	if !bytes.Equal(sum[:12], src[:12]) {
+		return nil, fmt.Errorf("NullAEAD: failed to authenticate received data (%#v vs %#v)", sum[:12], src[:12])
 	}
 	return src[12:], nil
 }
@@ -48,7 +49,7 @@ func (n *nullAEADFNV128a) Seal(dst, src []byte, packetNumber protocol.PacketNumb
 		dst = dst[:12+len(src)]
 	}
 
-	hash := fnv128a.New()
+	hash := fnv.New128a()
 	hash.Write(associatedData)
 	hash.Write(src)
 
@@ -57,15 +58,22 @@ func (n *nullAEADFNV128a) Seal(dst, src []byte, packetNumber protocol.PacketNumb
 	} else {
 		hash.Write([]byte("Client"))
 	}
-
-	high, low := hash.Sum128()
+	sum := make([]byte, 0, 16)
+	sum = hash.Sum(sum)
+	// The tag is written in little endian, so we need to reverse the slice.
+	reverse(sum)
 
 	copy(dst[12:], src)
-	binary.LittleEndian.PutUint64(dst, low)
-	binary.LittleEndian.PutUint32(dst[8:], uint32(high))
+	copy(dst, sum[:12])
 	return dst
 }
 
 func (n *nullAEADFNV128a) Overhead() int {
 	return 12
 }
+
+func reverse(a []byte) {
+	for left, right := 0, len(a)-1; left < right; left, right = left+1, right-1 {
+		a[left], a[right] = a[right], a[left]
+	}
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/base_flow_controller.go b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/base_flow_controller.go
index 3a5c01615..fb92f0842 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/base_flow_controller.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/base_flow_controller.go
@@ -25,6 +25,8 @@ type baseFlowController struct {
 	epochStartTime   time.Time
 	epochStartOffset protocol.ByteCount
 	rttStats         *congestion.RTTStats
+
+	logger utils.Logger
 }
 
 func (c *baseFlowController) AddBytesSent(n protocol.ByteCount) {
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/connection_flow_controller.go b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/connection_flow_controller.go
index 975cc5836..c4f6e125e 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/connection_flow_controller.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/connection_flow_controller.go
@@ -22,6 +22,7 @@ func NewConnectionFlowController(
 	receiveWindow protocol.ByteCount,
 	maxReceiveWindow protocol.ByteCount,
 	rttStats *congestion.RTTStats,
+	logger utils.Logger,
 ) ConnectionFlowController {
 	return &connectionFlowController{
 		baseFlowController: baseFlowController{
@@ -29,6 +30,7 @@ func NewConnectionFlowController(
 			receiveWindow:        receiveWindow,
 			receiveWindowSize:    receiveWindow,
 			maxReceiveWindowSize: maxReceiveWindow,
+			logger:               logger,
 		},
 	}
 }
@@ -65,7 +67,7 @@ func (c *connectionFlowController) GetWindowUpdate() protocol.ByteCount {
 	oldWindowSize := c.receiveWindowSize
 	offset := c.baseFlowController.getWindowUpdate()
 	if oldWindowSize < c.receiveWindowSize {
-		utils.Debugf("Increasing receive flow control window for the connection to %d kB", c.receiveWindowSize/(1<<10))
+		c.logger.Debugf("Increasing receive flow control window for the connection to %d kB", c.receiveWindowSize/(1<<10))
 	}
 	c.mutex.Unlock()
 	return offset
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/stream_flow_controller.go b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/stream_flow_controller.go
index 51ecfe7f0..16bef2613 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/stream_flow_controller.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/flowcontrol/stream_flow_controller.go
@@ -31,6 +31,7 @@ func NewStreamFlowController(
 	maxReceiveWindow protocol.ByteCount,
 	initialSendWindow protocol.ByteCount,
 	rttStats *congestion.RTTStats,
+	logger utils.Logger,
 ) StreamFlowController {
 	return &streamFlowController{
 		streamID:                streamID,
@@ -42,6 +43,7 @@ func NewStreamFlowController(
 			receiveWindowSize:    receiveWindow,
 			maxReceiveWindowSize: maxReceiveWindow,
 			sendWindow:           initialSendWindow,
+			logger:               logger,
 		},
 	}
 }
@@ -137,7 +139,7 @@ func (c *streamFlowController) GetWindowUpdate() protocol.ByteCount {
 	oldWindowSize := c.receiveWindowSize
 	offset := c.baseFlowController.getWindowUpdate()
 	if c.receiveWindowSize > oldWindowSize { // auto-tuning enlarged the window size
-		utils.Debugf("Increasing receive flow control window for the connection to %d kB", c.receiveWindowSize/(1<<10))
+		c.logger.Debugf("Increasing receive flow control window for the connection to %d kB", c.receiveWindowSize/(1<<10))
 		if c.contributesToConnection {
 			c.connection.EnsureMinimumWindowSize(protocol.ByteCount(float64(c.receiveWindowSize) * protocol.ConnectionFlowControlMultiplier))
 		}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/cookie_handler.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/cookie_handler.go
index 4257745c0..bc2bd8e57 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/cookie_handler.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/cookie_handler.go
@@ -11,15 +11,16 @@ import (
 // The cookie is sent in the TLS Retry.
 // By including the cookie in its ClientHello, a client can proof ownership of its source address.
 type CookieHandler struct {
-	callback func(net.Addr, *Cookie) bool
-
+	callback        func(net.Addr, *Cookie) bool
 	cookieGenerator *CookieGenerator
+
+	logger utils.Logger
 }
 
 var _ mint.CookieHandler = &CookieHandler{}
 
 // NewCookieHandler creates a new CookieHandler.
-func NewCookieHandler(callback func(net.Addr, *Cookie) bool) (*CookieHandler, error) {
+func NewCookieHandler(callback func(net.Addr, *Cookie) bool, logger utils.Logger) (*CookieHandler, error) {
 	cookieGenerator, err := NewCookieGenerator()
 	if err != nil {
 		return nil, err
@@ -27,6 +28,7 @@ func NewCookieHandler(callback func(net.Addr, *Cookie) bool) (*CookieHandler, er
 	return &CookieHandler{
 		callback:        callback,
 		cookieGenerator: cookieGenerator,
+		logger:          logger,
 	}, nil
 }
 
@@ -42,7 +44,7 @@ func (h *CookieHandler) Generate(conn *mint.Conn) ([]byte, error) {
 func (h *CookieHandler) Validate(conn *mint.Conn, token []byte) bool {
 	data, err := h.cookieGenerator.DecodeToken(token)
 	if err != nil {
-		utils.Debugf("Couldn't decode cookie from %s: %s", conn.RemoteAddr(), err.Error())
+		h.logger.Debugf("Couldn't decode cookie from %s: %s", conn.RemoteAddr(), err.Error())
 		return false
 	}
 	return h.callback(conn.RemoteAddr(), data)
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_client.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_client.go
index cb500b583..0700399a8 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_client.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_client.go
@@ -38,13 +38,12 @@ type cryptoSetupClient struct {
 	lastSentCHLO     []byte
 	certManager      crypto.CertManager
 
-	divNonceChan         chan []byte
+	divNonceChan         <-chan []byte
 	diversificationNonce []byte
 
 	clientHelloCounter int
 	serverVerified     bool // has the certificate chain and the proof already been verified
 	keyDerivation      QuicCryptoKeyDerivationFunction
-	keyExchange        KeyExchangeFunction
 
 	receivedSecurePacket bool
 	nullAEAD             crypto.AEAD
@@ -55,6 +54,8 @@ type cryptoSetupClient struct {
 	handshakeEvent chan<- struct{}
 
 	params *TransportParameters
+
+	logger utils.Logger
 }
 
 var _ CryptoSetup = &cryptoSetupClient{}
@@ -77,12 +78,14 @@ func NewCryptoSetupClient(
 	handshakeEvent chan<- struct{},
 	initialVersion protocol.VersionNumber,
 	negotiatedVersions []protocol.VersionNumber,
-) (CryptoSetup, error) {
+	logger utils.Logger,
+) (CryptoSetup, chan<- []byte, error) {
 	nullAEAD, err := crypto.NewNullAEAD(protocol.PerspectiveClient, connID, version)
 	if err != nil {
-		return nil, err
+		return nil, nil, err
 	}
-	return &cryptoSetupClient{
+	divNonceChan := make(chan []byte)
+	cs := &cryptoSetupClient{
 		cryptoStream:       cryptoStream,
 		hostname:           hostname,
 		connID:             connID,
@@ -90,14 +93,15 @@ func NewCryptoSetupClient(
 		certManager:        crypto.NewCertManager(tlsConfig),
 		params:             params,
 		keyDerivation:      crypto.DeriveQuicCryptoAESKeys,
-		keyExchange:        getEphermalKEX,
 		nullAEAD:           nullAEAD,
 		paramsChan:         paramsChan,
 		handshakeEvent:     handshakeEvent,
 		initialVersion:     initialVersion,
 		negotiatedVersions: negotiatedVersions,
-		divNonceChan:       make(chan []byte),
-	}, nil
+		divNonceChan:       divNonceChan,
+		logger:             logger,
+	}
+	return cs, divNonceChan, nil
 }
 
 func (h *cryptoSetupClient) HandleCryptoStream() error {
@@ -146,7 +150,7 @@ func (h *cryptoSetupClient) HandleCryptoStream() error {
 			return err
 		}
 
-		utils.Debugf("Got %s", message)
+		h.logger.Debugf("Got %s", message)
 		switch message.Tag {
 		case TagREJ:
 			if err := h.handleREJMessage(message.Data); err != nil {
@@ -211,7 +215,7 @@ func (h *cryptoSetupClient) handleREJMessage(cryptoData map[Tag][]byte) error {
 
 		err = h.certManager.Verify(h.hostname)
 		if err != nil {
-			utils.Infof("Certificate validation failed: %s", err.Error())
+			h.logger.Infof("Certificate validation failed: %s", err.Error())
 			return qerr.ProofInvalid
 		}
 	}
@@ -219,7 +223,7 @@ func (h *cryptoSetupClient) handleREJMessage(cryptoData map[Tag][]byte) error {
 	if h.serverConfig != nil && len(h.proof) != 0 && h.certManager.GetLeafCert() != nil {
 		validProof := h.certManager.VerifyServerProof(h.proof, h.chloForSignature, h.serverConfig.Get())
 		if !validProof {
-			utils.Infof("Server proof verification failed")
+			h.logger.Infof("Server proof verification failed")
 			return qerr.ProofInvalid
 		}
 
@@ -373,14 +377,6 @@ func (h *cryptoSetupClient) GetSealerWithEncryptionLevel(encLevel protocol.Encry
 	return nil, errors.New("CryptoSetupClient: no encryption level specified")
 }
 
-func (h *cryptoSetupClient) DiversificationNonce() []byte {
-	panic("not needed for cryptoSetupClient")
-}
-
-func (h *cryptoSetupClient) SetDiversificationNonce(data []byte) {
-	h.divNonceChan <- data
-}
-
 func (h *cryptoSetupClient) ConnectionState() ConnectionState {
 	h.mutex.Lock()
 	defer h.mutex.Unlock()
@@ -408,7 +404,7 @@ func (h *cryptoSetupClient) sendCHLO() error {
 		Data: tags,
 	}
 
-	utils.Debugf("Sending %s", message)
+	h.logger.Debugf("Sending %s", message)
 	message.Write(b)
 
 	_, err = h.cryptoStream.Write(b.Bytes())
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_server.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_server.go
index 54c2b9bd4..d977f6553 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_server.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_server.go
@@ -19,7 +19,7 @@ import (
 type QuicCryptoKeyDerivationFunction func(forwardSecure bool, sharedSecret, nonces []byte, connID protocol.ConnectionID, chlo []byte, scfg []byte, cert []byte, divNonce []byte, pers protocol.Perspective) (crypto.AEAD, error)
 
 // KeyExchangeFunction is used to make a new KEX
-type KeyExchangeFunction func() crypto.KeyExchange
+type KeyExchangeFunction func() (crypto.KeyExchange, error)
 
 // The CryptoSetupServer handles all things crypto for the Session
 type cryptoSetupServer struct {
@@ -54,6 +54,8 @@ type cryptoSetupServer struct {
 	params *TransportParameters
 
 	sni string // need to fill out the ConnectionState
+
+	logger utils.Logger
 }
 
 var _ CryptoSetup = &cryptoSetupServer{}
@@ -73,32 +75,36 @@ func NewCryptoSetup(
 	connID protocol.ConnectionID,
 	remoteAddr net.Addr,
 	version protocol.VersionNumber,
+	divNonce []byte,
 	scfg *ServerConfig,
 	params *TransportParameters,
 	supportedVersions []protocol.VersionNumber,
 	acceptSTK func(net.Addr, *Cookie) bool,
 	paramsChan chan<- TransportParameters,
 	handshakeEvent chan<- struct{},
+	logger utils.Logger,
 ) (CryptoSetup, error) {
 	nullAEAD, err := crypto.NewNullAEAD(protocol.PerspectiveServer, connID, version)
 	if err != nil {
 		return nil, err
 	}
 	return &cryptoSetupServer{
-		cryptoStream:      cryptoStream,
-		connID:            connID,
-		remoteAddr:        remoteAddr,
-		version:           version,
-		supportedVersions: supportedVersions,
-		scfg:              scfg,
-		keyDerivation:     crypto.DeriveQuicCryptoAESKeys,
-		keyExchange:       getEphermalKEX,
-		nullAEAD:          nullAEAD,
-		params:            params,
-		acceptSTKCallback: acceptSTK,
-		sentSHLO:          make(chan struct{}),
-		paramsChan:        paramsChan,
-		handshakeEvent:    handshakeEvent,
+		cryptoStream:         cryptoStream,
+		connID:               connID,
+		remoteAddr:           remoteAddr,
+		version:              version,
+		supportedVersions:    supportedVersions,
+		diversificationNonce: divNonce,
+		scfg:                 scfg,
+		keyDerivation:        crypto.DeriveQuicCryptoAESKeys,
+		keyExchange:          getEphermalKEX,
+		nullAEAD:             nullAEAD,
+		params:               params,
+		acceptSTKCallback:    acceptSTK,
+		sentSHLO:             make(chan struct{}),
+		paramsChan:           paramsChan,
+		handshakeEvent:       handshakeEvent,
+		logger:               logger,
 	}, nil
 }
 
@@ -114,7 +120,7 @@ func (h *cryptoSetupServer) HandleCryptoStream() error {
 			return qerr.InvalidCryptoMessageType
 		}
 
-		utils.Debugf("Got %s", message)
+		h.logger.Debugf("Got %s", message)
 		done, err := h.handleMessage(chloData.Bytes(), message.Data)
 		if err != nil {
 			return err
@@ -297,7 +303,7 @@ func (h *cryptoSetupServer) isInchoateCHLO(cryptoData map[Tag][]byte, cert []byt
 func (h *cryptoSetupServer) acceptSTK(token []byte) bool {
 	stk, err := h.scfg.cookieGenerator.DecodeToken(token)
 	if err != nil {
-		utils.Debugf("STK invalid: %s", err.Error())
+		h.logger.Debugf("STK invalid: %s", err.Error())
 		return false
 	}
 	return h.acceptSTKCallback(h.remoteAddr, stk)
@@ -340,7 +346,7 @@ func (h *cryptoSetupServer) handleInchoateCHLO(sni string, chlo []byte, cryptoDa
 
 	var serverReply bytes.Buffer
 	message.Write(&serverReply)
-	utils.Debugf("Sending %s", message)
+	h.logger.Debugf("Sending %s", message)
 	return serverReply.Bytes(), nil
 }
 
@@ -364,11 +370,6 @@ func (h *cryptoSetupServer) handleCHLO(sni string, data []byte, cryptoData map[T
 		return nil, err
 	}
 
-	h.diversificationNonce = make([]byte, 32)
-	if _, err = rand.Read(h.diversificationNonce); err != nil {
-		return nil, err
-	}
-
 	clientNonce := cryptoData[TagNONC]
 	err = h.validateClientNonce(clientNonce)
 	if err != nil {
@@ -405,7 +406,10 @@ func (h *cryptoSetupServer) handleCHLO(sni string, data []byte, cryptoData map[T
 	var fsNonce bytes.Buffer
 	fsNonce.Write(clientNonce)
 	fsNonce.Write(serverNonce)
-	ephermalKex := h.keyExchange()
+	ephermalKex, err := h.keyExchange()
+	if err != nil {
+		return nil, err
+	}
 	ephermalSharedSecret, err := ephermalKex.CalculateSharedKey(cryptoData[TagPUBS])
 	if err != nil {
 		return nil, err
@@ -443,19 +447,10 @@ func (h *cryptoSetupServer) handleCHLO(sni string, data []byte, cryptoData map[T
 	}
 	var reply bytes.Buffer
 	message.Write(&reply)
-	utils.Debugf("Sending %s", message)
+	h.logger.Debugf("Sending %s", message)
 	return reply.Bytes(), nil
 }
 
-// DiversificationNonce returns the diversification nonce
-func (h *cryptoSetupServer) DiversificationNonce() []byte {
-	return h.diversificationNonce
-}
-
-func (h *cryptoSetupServer) SetDiversificationNonce(data []byte) {
-	panic("not needed for cryptoSetupServer")
-}
-
 func (h *cryptoSetupServer) ConnectionState() ConnectionState {
 	h.mutex.Lock()
 	defer h.mutex.Unlock()
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_tls.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_tls.go
index 54dfe1c03..43f854068 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_tls.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_tls.go
@@ -31,6 +31,8 @@ type cryptoSetupTLS struct {
 	handshakeEvent chan<- struct{}
 }
 
+var _ CryptoSetupTLS = &cryptoSetupTLS{}
+
 // NewCryptoSetupTLSServer creates a new TLS CryptoSetup instance for a server
 func NewCryptoSetupTLSServer(
 	tls MintTLS,
@@ -38,7 +40,7 @@ func NewCryptoSetupTLSServer(
 	nullAEAD crypto.AEAD,
 	handshakeEvent chan<- struct{},
 	version protocol.VersionNumber,
-) CryptoSetup {
+) CryptoSetupTLS {
 	return &cryptoSetupTLS{
 		tls:            tls,
 		cryptoStream:   cryptoStream,
@@ -57,7 +59,7 @@ func NewCryptoSetupTLSClient(
 	handshakeEvent chan<- struct{},
 	tls MintTLS,
 	version protocol.VersionNumber,
-) (CryptoSetup, error) {
+) (CryptoSetupTLS, error) {
 	nullAEAD, err := crypto.NewNullAEAD(protocol.PerspectiveClient, connID, version)
 	if err != nil {
 		return nil, err
@@ -107,22 +109,18 @@ handshakeLoop:
 	return nil
 }
 
-func (h *cryptoSetupTLS) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error) {
+func (h *cryptoSetupTLS) OpenHandshake(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) {
+	return h.nullAEAD.Open(dst, src, packetNumber, associatedData)
+}
+
+func (h *cryptoSetupTLS) Open1RTT(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) {
 	h.mutex.RLock()
 	defer h.mutex.RUnlock()
 
-	if h.aead != nil {
-		data, err := h.aead.Open(dst, src, packetNumber, associatedData)
-		if err != nil {
-			return nil, protocol.EncryptionUnspecified, err
-		}
-		return data, protocol.EncryptionForwardSecure, nil
+	if h.aead == nil {
+		return nil, errors.New("no 1-RTT sealer")
 	}
-	data, err := h.nullAEAD.Open(dst, src, packetNumber, associatedData)
-	if err != nil {
-		return nil, protocol.EncryptionUnspecified, err
-	}
-	return data, protocol.EncryptionUnencrypted, nil
+	return h.aead.Open(dst, src, packetNumber, associatedData)
 }
 
 func (h *cryptoSetupTLS) GetSealer() (protocol.EncryptionLevel, Sealer) {
@@ -157,14 +155,6 @@ func (h *cryptoSetupTLS) GetSealerForCryptoStream() (protocol.EncryptionLevel, S
 	return protocol.EncryptionUnencrypted, h.nullAEAD
 }
 
-func (h *cryptoSetupTLS) DiversificationNonce() []byte {
-	panic("diversification nonce not needed for TLS")
-}
-
-func (h *cryptoSetupTLS) SetDiversificationNonce([]byte) {
-	panic("diversification nonce not needed for TLS")
-}
-
 func (h *cryptoSetupTLS) ConnectionState() ConnectionState {
 	h.mutex.Lock()
 	defer h.mutex.Unlock()
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/ephermal_cache.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/ephermal_cache.go
index 3bccbef06..728715835 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/ephermal_cache.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/ephermal_cache.go
@@ -6,7 +6,6 @@ import (
 
 	"github.com/lucas-clemente/quic-go/internal/crypto"
 	"github.com/lucas-clemente/quic-go/internal/protocol"
-	"github.com/lucas-clemente/quic-go/internal/utils"
 )
 
 var (
@@ -24,13 +23,13 @@ var (
 // used for all connections for 60 seconds is negligible. Thus we can amortise
 // the Diffie-Hellman key generation at the server over all the connections in a
 // small time span.
-func getEphermalKEX() (res crypto.KeyExchange) {
+func getEphermalKEX() (crypto.KeyExchange, error) {
 	kexMutex.RLock()
-	res = kexCurrent
+	res := kexCurrent
 	t := kexCurrentTime
 	kexMutex.RUnlock()
 	if res != nil && time.Since(t) < kexLifetime {
-		return res
+		return res, nil
 	}
 
 	kexMutex.Lock()
@@ -39,12 +38,11 @@ func getEphermalKEX() (res crypto.KeyExchange) {
 	if kexCurrent == nil || time.Since(kexCurrentTime) > kexLifetime {
 		kex, err := crypto.NewCurve25519KEX()
 		if err != nil {
-			utils.Errorf("could not set KEX: %s", err.Error())
-			return kexCurrent
+			return nil, err
 		}
 		kexCurrent = kex
 		kexCurrentTime = time.Now()
-		return kexCurrent
+		return kexCurrent, nil
 	}
-	return kexCurrent
+	return kexCurrent, nil
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/interface.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/interface.go
index 0fd673313..8d8fd5455 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/interface.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/interface.go
@@ -35,13 +35,8 @@ type MintTLS interface {
 	SetCryptoStream(io.ReadWriter)
 }
 
-// CryptoSetup is a crypto setup
-type CryptoSetup interface {
-	Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error)
+type baseCryptoSetup interface {
 	HandleCryptoStream() error
-	// TODO: clean up this interface
-	DiversificationNonce() []byte   // only needed for cryptoSetupServer
-	SetDiversificationNonce([]byte) // only needed for cryptoSetupClient
 	ConnectionState() ConnectionState
 
 	GetSealer() (protocol.EncryptionLevel, Sealer)
@@ -49,6 +44,21 @@ type CryptoSetup interface {
 	GetSealerForCryptoStream() (protocol.EncryptionLevel, Sealer)
 }
 
+// CryptoSetup is the crypto setup used by gQUIC
+type CryptoSetup interface {
+	baseCryptoSetup
+
+	Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error)
+}
+
+// CryptoSetupTLS is the crypto setup used by IETF QUIC
+type CryptoSetupTLS interface {
+	baseCryptoSetup
+
+	OpenHandshake(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error)
+	Open1RTT(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error)
+}
+
 // ConnectionState records basic details about the QUIC connection.
 // Warning: This API should not be considered stable and might change soon.
 type ConnectionState struct {
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_client.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_client.go
index 765cf79fc..8e711be58 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_client.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_client.go
@@ -19,6 +19,8 @@ type extensionHandlerClient struct {
 	initialVersion    protocol.VersionNumber
 	supportedVersions []protocol.VersionNumber
 	version           protocol.VersionNumber
+
+	logger utils.Logger
 }
 
 var _ mint.AppExtensionHandler = &extensionHandlerClient{}
@@ -30,6 +32,7 @@ func NewExtensionHandlerClient(
 	initialVersion protocol.VersionNumber,
 	supportedVersions []protocol.VersionNumber,
 	version protocol.VersionNumber,
+	logger utils.Logger,
 ) TLSExtensionHandler {
 	// The client reads the transport parameters from the Encrypted Extensions message.
 	// The paramsChan is used in the session's run loop's select statement.
@@ -41,6 +44,7 @@ func NewExtensionHandlerClient(
 		initialVersion:    initialVersion,
 		supportedVersions: supportedVersions,
 		version:           version,
+		logger:            logger,
 	}
 }
 
@@ -49,7 +53,7 @@ func (h *extensionHandlerClient) Send(hType mint.HandshakeType, el *mint.Extensi
 		return nil
 	}
 
-	utils.Debugf("Sending Transport Parameters: %s", h.ourParams)
+	h.logger.Debugf("Sending Transport Parameters: %s", h.ourParams)
 	data, err := syntax.Marshal(clientHelloTransportParameters{
 		InitialVersion: uint32(h.initialVersion),
 		Parameters:     h.ourParams.getTransportParameters(),
@@ -122,7 +126,7 @@ func (h *extensionHandlerClient) Receive(hType mint.HandshakeType, el *mint.Exte
 	if err != nil {
 		return err
 	}
-	utils.Debugf("Received Transport Parameters: %s", params)
+	h.logger.Debugf("Received Transport Parameters: %s", params)
 	h.paramsChan <- *params
 	return nil
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_server.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_server.go
index ec73585c8..138fc21bd 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_server.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension_handler_server.go
@@ -19,6 +19,8 @@ type extensionHandlerServer struct {
 
 	version           protocol.VersionNumber
 	supportedVersions []protocol.VersionNumber
+
+	logger utils.Logger
 }
 
 var _ mint.AppExtensionHandler = &extensionHandlerServer{}
@@ -29,6 +31,7 @@ func NewExtensionHandlerServer(
 	params *TransportParameters,
 	supportedVersions []protocol.VersionNumber,
 	version protocol.VersionNumber,
+	logger utils.Logger,
 ) TLSExtensionHandler {
 	// Processing the ClientHello is performed statelessly (and from a single go-routine).
 	// Therefore, we have to use a buffered chan to pass the transport parameters to that go routine.
@@ -38,6 +41,7 @@ func NewExtensionHandlerServer(
 		paramsChan:        paramsChan,
 		supportedVersions: supportedVersions,
 		version:           version,
+		logger:            logger,
 	}
 }
 
@@ -56,7 +60,7 @@ func (h *extensionHandlerServer) Send(hType mint.HandshakeType, el *mint.Extensi
 	for i, v := range supportedVersions {
 		versions[i] = uint32(v)
 	}
-	utils.Debugf("Sending Transport Parameters: %s", h.ourParams)
+	h.logger.Debugf("Sending Transport Parameters: %s", h.ourParams)
 	data, err := syntax.Marshal(encryptedExtensionsTransportParameters{
 		NegotiatedVersion: uint32(h.version),
 		SupportedVersions: versions,
@@ -108,7 +112,7 @@ func (h *extensionHandlerServer) Receive(hType mint.HandshakeType, el *mint.Exte
 	if err != nil {
 		return err
 	}
-	utils.Debugf("Received Transport Parameters: %s", params)
+	h.logger.Debugf("Received Transport Parameters: %s", params)
 	h.paramsChan <- *params
 	return nil
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/mocks/congestion.go b/vendor/github.com/lucas-clemente/quic-go/internal/mocks/congestion.go
index fec7b6c14..b86ccfea6 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/mocks/congestion.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/mocks/congestion.go
@@ -109,18 +109,6 @@ func (mr *MockSendAlgorithmMockRecorder) OnRetransmissionTimeout(arg0 interface{
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OnRetransmissionTimeout", reflect.TypeOf((*MockSendAlgorithm)(nil).OnRetransmissionTimeout), arg0)
 }
 
-// RetransmissionDelay mocks base method
-func (m *MockSendAlgorithm) RetransmissionDelay() time.Duration {
-	ret := m.ctrl.Call(m, "RetransmissionDelay")
-	ret0, _ := ret[0].(time.Duration)
-	return ret0
-}
-
-// RetransmissionDelay indicates an expected call of RetransmissionDelay
-func (mr *MockSendAlgorithmMockRecorder) RetransmissionDelay() *gomock.Call {
-	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RetransmissionDelay", reflect.TypeOf((*MockSendAlgorithm)(nil).RetransmissionDelay))
-}
-
 // SetNumEmulatedConnections mocks base method
 func (m *MockSendAlgorithm) SetNumEmulatedConnections(arg0 int) {
 	m.ctrl.Call(m, "SetNumEmulatedConnections", arg0)
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/byteinterval_linkedlist.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/byteinterval_linkedlist.go
index 545fc2038..096023ef2 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/utils/byteinterval_linkedlist.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/byteinterval_linkedlist.go
@@ -1,13 +1,10 @@
-// Generated by: main
-// TypeWriter: linkedlist
-// Directive: +gen on ByteInterval
+// This file was automatically generated by genny.
+// Any changes will be lost if this file is regenerated.
+// see https://github.com/cheekybits/genny
 
 package utils
 
-// List is a modification of http://golang.org/pkg/container/list/
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
+// Linked list implementation from the Go standard library.
 
 // ByteIntervalElement is an element of a linked list.
 type ByteIntervalElement struct {
@@ -41,8 +38,7 @@ func (e *ByteIntervalElement) Prev() *ByteIntervalElement {
 	return nil
 }
 
-// ByteIntervalList represents a doubly linked list.
-// The zero value for ByteIntervalList is an empty list ready to use.
+// ByteIntervalList is a linked list of ByteIntervals.
 type ByteIntervalList struct {
 	root ByteIntervalElement // sentinel list element, only &root, root.prev, and root.next are used
 	len  int                 // current list length excluding (this) sentinel element
@@ -63,7 +59,7 @@ func NewByteIntervalList() *ByteIntervalList { return new(ByteIntervalList).Init
 // The complexity is O(1).
 func (l *ByteIntervalList) Len() int { return l.len }
 
-// Front returns the first element of list l or nil.
+// Front returns the first element of list l or nil if the list is empty.
 func (l *ByteIntervalList) Front() *ByteIntervalElement {
 	if l.len == 0 {
 		return nil
@@ -71,7 +67,7 @@ func (l *ByteIntervalList) Front() *ByteIntervalElement {
 	return l.root.next
 }
 
-// Back returns the last element of list l or nil.
+// Back returns the last element of list l or nil if the list is empty.
 func (l *ByteIntervalList) Back() *ByteIntervalElement {
 	if l.len == 0 {
 		return nil
@@ -79,7 +75,7 @@ func (l *ByteIntervalList) Back() *ByteIntervalElement {
 	return l.root.prev
 }
 
-// lazyInit lazily initializes a zero ByteIntervalList value.
+// lazyInit lazily initializes a zero List value.
 func (l *ByteIntervalList) lazyInit() {
 	if l.root.next == nil {
 		l.Init()
@@ -98,7 +94,7 @@ func (l *ByteIntervalList) insert(e, at *ByteIntervalElement) *ByteIntervalEleme
 	return e
 }
 
-// insertValue is a convenience wrapper for insert(&ByteIntervalElement{Value: v}, at).
+// insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
 func (l *ByteIntervalList) insertValue(v ByteInterval, at *ByteIntervalElement) *ByteIntervalElement {
 	return l.insert(&ByteIntervalElement{Value: v}, at)
 }
@@ -116,10 +112,11 @@ func (l *ByteIntervalList) remove(e *ByteIntervalElement) *ByteIntervalElement {
 
 // Remove removes e from l if e is an element of list l.
 // It returns the element value e.Value.
+// The element must not be nil.
 func (l *ByteIntervalList) Remove(e *ByteIntervalElement) ByteInterval {
 	if e.list == l {
 		// if e.list == l, l must have been initialized when e was inserted
-		// in l or l == nil (e is a zero ByteIntervalElement) and l.remove will crash
+		// in l or l == nil (e is a zero Element) and l.remove will crash
 		l.remove(e)
 	}
 	return e.Value
@@ -139,46 +136,51 @@ func (l *ByteIntervalList) PushBack(v ByteInterval) *ByteIntervalElement {
 
 // InsertBefore inserts a new element e with value v immediately before mark and returns e.
 // If mark is not an element of l, the list is not modified.
+// The mark must not be nil.
 func (l *ByteIntervalList) InsertBefore(v ByteInterval, mark *ByteIntervalElement) *ByteIntervalElement {
 	if mark.list != l {
 		return nil
 	}
-	// see comment in ByteIntervalList.Remove about initialization of l
+	// see comment in List.Remove about initialization of l
 	return l.insertValue(v, mark.prev)
 }
 
 // InsertAfter inserts a new element e with value v immediately after mark and returns e.
 // If mark is not an element of l, the list is not modified.
+// The mark must not be nil.
 func (l *ByteIntervalList) InsertAfter(v ByteInterval, mark *ByteIntervalElement) *ByteIntervalElement {
 	if mark.list != l {
 		return nil
 	}
-	// see comment in ByteIntervalList.Remove about initialization of l
+	// see comment in List.Remove about initialization of l
 	return l.insertValue(v, mark)
 }
 
 // MoveToFront moves element e to the front of list l.
 // If e is not an element of l, the list is not modified.
+// The element must not be nil.
 func (l *ByteIntervalList) MoveToFront(e *ByteIntervalElement) {
 	if e.list != l || l.root.next == e {
 		return
 	}
-	// see comment in ByteIntervalList.Remove about initialization of l
+	// see comment in List.Remove about initialization of l
 	l.insert(l.remove(e), &l.root)
 }
 
 // MoveToBack moves element e to the back of list l.
 // If e is not an element of l, the list is not modified.
+// The element must not be nil.
 func (l *ByteIntervalList) MoveToBack(e *ByteIntervalElement) {
 	if e.list != l || l.root.prev == e {
 		return
 	}
-	// see comment in ByteIntervalList.Remove about initialization of l
+	// see comment in List.Remove about initialization of l
 	l.insert(l.remove(e), l.root.prev)
 }
 
 // MoveBefore moves element e to its new position before mark.
 // If e or mark is not an element of l, or e == mark, the list is not modified.
+// The element and mark must not be nil.
 func (l *ByteIntervalList) MoveBefore(e, mark *ByteIntervalElement) {
 	if e.list != l || e == mark || mark.list != l {
 		return
@@ -187,7 +189,8 @@ func (l *ByteIntervalList) MoveBefore(e, mark *ByteIntervalElement) {
 }
 
 // MoveAfter moves element e to its new position after mark.
-// If e is not an element of l, or e == mark, the list is not modified.
+// If e or mark is not an element of l, or e == mark, the list is not modified.
+// The element and mark must not be nil.
 func (l *ByteIntervalList) MoveAfter(e, mark *ByteIntervalElement) {
 	if e.list != l || e == mark || mark.list != l {
 		return
@@ -196,7 +199,7 @@ func (l *ByteIntervalList) MoveAfter(e, mark *ByteIntervalElement) {
 }
 
 // PushBackList inserts a copy of an other list at the back of list l.
-// The lists l and other may be the same.
+// The lists l and other may be the same. They must not be nil.
 func (l *ByteIntervalList) PushBackList(other *ByteIntervalList) {
 	l.lazyInit()
 	for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
@@ -205,7 +208,7 @@ func (l *ByteIntervalList) PushBackList(other *ByteIntervalList) {
 }
 
 // PushFrontList inserts a copy of an other list at the front of list l.
-// The lists l and other may be the same.
+// The lists l and other may be the same. They must not be nil.
 func (l *ByteIntervalList) PushFrontList(other *ByteIntervalList) {
 	l.lazyInit()
 	for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/gen.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/gen.go
new file mode 100644
index 000000000..bb839be66
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/gen.go
@@ -0,0 +1,4 @@
+package utils
+
+//go:generate genny -pkg utils -in linkedlist/linkedlist.go -out byteinterval_linkedlist.go gen Item=ByteInterval
+//go:generate genny -pkg utils -in linkedlist/linkedlist.go -out packetinterval_linkedlist.go gen Item=PacketInterval
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/linkedlist/linkedlist.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/linkedlist/linkedlist.go
new file mode 100644
index 000000000..74b815a81
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/linkedlist/linkedlist.go
@@ -0,0 +1,218 @@
+package linkedlist
+
+import "github.com/cheekybits/genny/generic"
+
+// Linked list implementation from the Go standard library.
+
+// Item is a generic type.
+type Item generic.Type
+
+// ItemElement is an element of a linked list.
+type ItemElement struct {
+	// Next and previous pointers in the doubly-linked list of elements.
+	// To simplify the implementation, internally a list l is implemented
+	// as a ring, such that &l.root is both the next element of the last
+	// list element (l.Back()) and the previous element of the first list
+	// element (l.Front()).
+	next, prev *ItemElement
+
+	// The list to which this element belongs.
+	list *ItemList
+
+	// The value stored with this element.
+	Value Item
+}
+
+// Next returns the next list element or nil.
+func (e *ItemElement) Next() *ItemElement {
+	if p := e.next; e.list != nil && p != &e.list.root {
+		return p
+	}
+	return nil
+}
+
+// Prev returns the previous list element or nil.
+func (e *ItemElement) Prev() *ItemElement {
+	if p := e.prev; e.list != nil && p != &e.list.root {
+		return p
+	}
+	return nil
+}
+
+// ItemList is a linked list of Items.
+type ItemList struct {
+	root ItemElement // sentinel list element, only &root, root.prev, and root.next are used
+	len  int         // current list length excluding (this) sentinel element
+}
+
+// Init initializes or clears list l.
+func (l *ItemList) Init() *ItemList {
+	l.root.next = &l.root
+	l.root.prev = &l.root
+	l.len = 0
+	return l
+}
+
+// NewItemList returns an initialized list.
+func NewItemList() *ItemList { return new(ItemList).Init() }
+
+// Len returns the number of elements of list l.
+// The complexity is O(1).
+func (l *ItemList) Len() int { return l.len }
+
+// Front returns the first element of list l or nil if the list is empty.
+func (l *ItemList) Front() *ItemElement {
+	if l.len == 0 {
+		return nil
+	}
+	return l.root.next
+}
+
+// Back returns the last element of list l or nil if the list is empty.
+func (l *ItemList) Back() *ItemElement {
+	if l.len == 0 {
+		return nil
+	}
+	return l.root.prev
+}
+
+// lazyInit lazily initializes a zero List value.
+func (l *ItemList) lazyInit() {
+	if l.root.next == nil {
+		l.Init()
+	}
+}
+
+// insert inserts e after at, increments l.len, and returns e.
+func (l *ItemList) insert(e, at *ItemElement) *ItemElement {
+	n := at.next
+	at.next = e
+	e.prev = at
+	e.next = n
+	n.prev = e
+	e.list = l
+	l.len++
+	return e
+}
+
+// insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
+func (l *ItemList) insertValue(v Item, at *ItemElement) *ItemElement {
+	return l.insert(&ItemElement{Value: v}, at)
+}
+
+// remove removes e from its list, decrements l.len, and returns e.
+func (l *ItemList) remove(e *ItemElement) *ItemElement {
+	e.prev.next = e.next
+	e.next.prev = e.prev
+	e.next = nil // avoid memory leaks
+	e.prev = nil // avoid memory leaks
+	e.list = nil
+	l.len--
+	return e
+}
+
+// Remove removes e from l if e is an element of list l.
+// It returns the element value e.Value.
+// The element must not be nil.
+func (l *ItemList) Remove(e *ItemElement) Item {
+	if e.list == l {
+		// if e.list == l, l must have been initialized when e was inserted
+		// in l or l == nil (e is a zero Element) and l.remove will crash
+		l.remove(e)
+	}
+	return e.Value
+}
+
+// PushFront inserts a new element e with value v at the front of list l and returns e.
+func (l *ItemList) PushFront(v Item) *ItemElement {
+	l.lazyInit()
+	return l.insertValue(v, &l.root)
+}
+
+// PushBack inserts a new element e with value v at the back of list l and returns e.
+func (l *ItemList) PushBack(v Item) *ItemElement {
+	l.lazyInit()
+	return l.insertValue(v, l.root.prev)
+}
+
+// InsertBefore inserts a new element e with value v immediately before mark and returns e.
+// If mark is not an element of l, the list is not modified.
+// The mark must not be nil.
+func (l *ItemList) InsertBefore(v Item, mark *ItemElement) *ItemElement {
+	if mark.list != l {
+		return nil
+	}
+	// see comment in List.Remove about initialization of l
+	return l.insertValue(v, mark.prev)
+}
+
+// InsertAfter inserts a new element e with value v immediately after mark and returns e.
+// If mark is not an element of l, the list is not modified.
+// The mark must not be nil.
+func (l *ItemList) InsertAfter(v Item, mark *ItemElement) *ItemElement {
+	if mark.list != l {
+		return nil
+	}
+	// see comment in List.Remove about initialization of l
+	return l.insertValue(v, mark)
+}
+
+// MoveToFront moves element e to the front of list l.
+// If e is not an element of l, the list is not modified.
+// The element must not be nil.
+func (l *ItemList) MoveToFront(e *ItemElement) {
+	if e.list != l || l.root.next == e {
+		return
+	}
+	// see comment in List.Remove about initialization of l
+	l.insert(l.remove(e), &l.root)
+}
+
+// MoveToBack moves element e to the back of list l.
+// If e is not an element of l, the list is not modified.
+// The element must not be nil.
+func (l *ItemList) MoveToBack(e *ItemElement) {
+	if e.list != l || l.root.prev == e {
+		return
+	}
+	// see comment in List.Remove about initialization of l
+	l.insert(l.remove(e), l.root.prev)
+}
+
+// MoveBefore moves element e to its new position before mark.
+// If e or mark is not an element of l, or e == mark, the list is not modified.
+// The element and mark must not be nil.
+func (l *ItemList) MoveBefore(e, mark *ItemElement) {
+	if e.list != l || e == mark || mark.list != l {
+		return
+	}
+	l.insert(l.remove(e), mark.prev)
+}
+
+// MoveAfter moves element e to its new position after mark.
+// If e or mark is not an element of l, or e == mark, the list is not modified.
+// The element and mark must not be nil.
+func (l *ItemList) MoveAfter(e, mark *ItemElement) {
+	if e.list != l || e == mark || mark.list != l {
+		return
+	}
+	l.insert(l.remove(e), mark)
+}
+
+// PushBackList inserts a copy of an other list at the back of list l.
+// The lists l and other may be the same. They must not be nil.
+func (l *ItemList) PushBackList(other *ItemList) {
+	l.lazyInit()
+	for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
+		l.insertValue(e.Value, l.root.prev)
+	}
+}
+
+// PushFrontList inserts a copy of an other list at the front of list l.
+// The lists l and other may be the same. They must not be nil.
+func (l *ItemList) PushFrontList(other *ItemList) {
+	l.lazyInit()
+	for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
+		l.insertValue(e.Value, &l.root)
+	}
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/log.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/log.go
index 342d8ddca..62a3d075e 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/utils/log.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/log.go
@@ -11,8 +11,6 @@ import (
 // LogLevel of quic-go
 type LogLevel uint8
 
-const logEnv = "QUIC_GO_LOG_LEVEL"
-
 const (
 	// LogLevelNothing disables
 	LogLevelNothing LogLevel = iota
@@ -24,72 +22,92 @@ const (
 	LogLevelDebug
 )
 
-var (
-	logLevel   = LogLevelNothing
-	timeFormat = ""
-)
+const logEnv = "QUIC_GO_LOG_LEVEL"
+
+// A Logger logs.
+type Logger interface {
+	SetLogLevel(LogLevel)
+	SetLogTimeFormat(format string)
+	Debug() bool
+
+	Errorf(format string, args ...interface{})
+	Infof(format string, args ...interface{})
+	Debugf(format string, args ...interface{})
+}
+
+// DefaultLogger is used by quic-go for logging.
+var DefaultLogger Logger
+
+type defaultLogger struct {
+	logLevel   LogLevel
+	timeFormat string
+}
+
+var _ Logger = &defaultLogger{}
 
 // SetLogLevel sets the log level
-func SetLogLevel(level LogLevel) {
-	logLevel = level
+func (l *defaultLogger) SetLogLevel(level LogLevel) {
+	l.logLevel = level
 }
 
 // SetLogTimeFormat sets the format of the timestamp
 // an empty string disables the logging of timestamps
-func SetLogTimeFormat(format string) {
+func (l *defaultLogger) SetLogTimeFormat(format string) {
 	log.SetFlags(0) // disable timestamp logging done by the log package
-	timeFormat = format
+	l.timeFormat = format
 }
 
 // Debugf logs something
-func Debugf(format string, args ...interface{}) {
-	if logLevel == LogLevelDebug {
-		logMessage(format, args...)
+func (l *defaultLogger) Debugf(format string, args ...interface{}) {
+	if l.logLevel == LogLevelDebug {
+		l.logMessage(format, args...)
 	}
 }
 
 // Infof logs something
-func Infof(format string, args ...interface{}) {
-	if logLevel >= LogLevelInfo {
-		logMessage(format, args...)
+func (l *defaultLogger) Infof(format string, args ...interface{}) {
+	if l.logLevel >= LogLevelInfo {
+		l.logMessage(format, args...)
 	}
 }
 
 // Errorf logs something
-func Errorf(format string, args ...interface{}) {
-	if logLevel >= LogLevelError {
-		logMessage(format, args...)
+func (l *defaultLogger) Errorf(format string, args ...interface{}) {
+	if l.logLevel >= LogLevelError {
+		l.logMessage(format, args...)
 	}
 }
 
-func logMessage(format string, args ...interface{}) {
-	if len(timeFormat) > 0 {
-		log.Printf(time.Now().Format(timeFormat)+" "+format, args...)
+func (l *defaultLogger) logMessage(format string, args ...interface{}) {
+	if len(l.timeFormat) > 0 {
+		log.Printf(time.Now().Format(l.timeFormat)+" "+format, args...)
 	} else {
 		log.Printf(format, args...)
 	}
 }
 
 // Debug returns true if the log level is LogLevelDebug
-func Debug() bool {
-	return logLevel == LogLevelDebug
+func (l *defaultLogger) Debug() bool {
+	return l.logLevel == LogLevelDebug
 }
 
 func init() {
-	readLoggingEnv()
+	DefaultLogger = &defaultLogger{}
+	DefaultLogger.SetLogLevel(readLoggingEnv())
 }
 
-func readLoggingEnv() {
+func readLoggingEnv() LogLevel {
 	switch strings.ToLower(os.Getenv(logEnv)) {
 	case "":
-		return
+		return LogLevelNothing
 	case "debug":
-		logLevel = LogLevelDebug
+		return LogLevelDebug
 	case "info":
-		logLevel = LogLevelInfo
+		return LogLevelInfo
 	case "error":
-		logLevel = LogLevelError
+		return LogLevelError
 	default:
 		fmt.Fprintln(os.Stderr, "invalid quic-go log level, see https://github.com/lucas-clemente/quic-go/wiki/Logging")
+		return LogLevelNothing
 	}
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/packet_interval.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/packet_interval.go
index f49b0c426..62cc8b9cb 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/utils/packet_interval.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/packet_interval.go
@@ -3,7 +3,6 @@ package utils
 import "github.com/lucas-clemente/quic-go/internal/protocol"
 
 // PacketInterval is an interval from one PacketNumber to the other
-// +gen linkedlist
 type PacketInterval struct {
 	Start protocol.PacketNumber
 	End   protocol.PacketNumber
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/packetinterval_linkedlist.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/packetinterval_linkedlist.go
index e3431d68c..b461e85a9 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/utils/packetinterval_linkedlist.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/packetinterval_linkedlist.go
@@ -1,13 +1,10 @@
-// Generated by: main
-// TypeWriter: linkedlist
-// Directive: +gen on PacketInterval
+// This file was automatically generated by genny.
+// Any changes will be lost if this file is regenerated.
+// see https://github.com/cheekybits/genny
 
 package utils
 
-// List is a modification of http://golang.org/pkg/container/list/
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
+// Linked list implementation from the Go standard library.
 
 // PacketIntervalElement is an element of a linked list.
 type PacketIntervalElement struct {
@@ -41,8 +38,7 @@ func (e *PacketIntervalElement) Prev() *PacketIntervalElement {
 	return nil
 }
 
-// PacketIntervalList represents a doubly linked list.
-// The zero value for PacketIntervalList is an empty list ready to use.
+// PacketIntervalList is a linked list of PacketIntervals.
 type PacketIntervalList struct {
 	root PacketIntervalElement // sentinel list element, only &root, root.prev, and root.next are used
 	len  int                   // current list length excluding (this) sentinel element
@@ -63,7 +59,7 @@ func NewPacketIntervalList() *PacketIntervalList { return new(PacketIntervalList
 // The complexity is O(1).
 func (l *PacketIntervalList) Len() int { return l.len }
 
-// Front returns the first element of list l or nil.
+// Front returns the first element of list l or nil if the list is empty.
 func (l *PacketIntervalList) Front() *PacketIntervalElement {
 	if l.len == 0 {
 		return nil
@@ -71,7 +67,7 @@ func (l *PacketIntervalList) Front() *PacketIntervalElement {
 	return l.root.next
 }
 
-// Back returns the last element of list l or nil.
+// Back returns the last element of list l or nil if the list is empty.
 func (l *PacketIntervalList) Back() *PacketIntervalElement {
 	if l.len == 0 {
 		return nil
@@ -79,7 +75,7 @@ func (l *PacketIntervalList) Back() *PacketIntervalElement {
 	return l.root.prev
 }
 
-// lazyInit lazily initializes a zero PacketIntervalList value.
+// lazyInit lazily initializes a zero List value.
 func (l *PacketIntervalList) lazyInit() {
 	if l.root.next == nil {
 		l.Init()
@@ -98,7 +94,7 @@ func (l *PacketIntervalList) insert(e, at *PacketIntervalElement) *PacketInterva
 	return e
 }
 
-// insertValue is a convenience wrapper for insert(&PacketIntervalElement{Value: v}, at).
+// insertValue is a convenience wrapper for insert(&Element{Value: v}, at).
 func (l *PacketIntervalList) insertValue(v PacketInterval, at *PacketIntervalElement) *PacketIntervalElement {
 	return l.insert(&PacketIntervalElement{Value: v}, at)
 }
@@ -116,10 +112,11 @@ func (l *PacketIntervalList) remove(e *PacketIntervalElement) *PacketIntervalEle
 
 // Remove removes e from l if e is an element of list l.
 // It returns the element value e.Value.
+// The element must not be nil.
 func (l *PacketIntervalList) Remove(e *PacketIntervalElement) PacketInterval {
 	if e.list == l {
 		// if e.list == l, l must have been initialized when e was inserted
-		// in l or l == nil (e is a zero PacketIntervalElement) and l.remove will crash
+		// in l or l == nil (e is a zero Element) and l.remove will crash
 		l.remove(e)
 	}
 	return e.Value
@@ -139,46 +136,51 @@ func (l *PacketIntervalList) PushBack(v PacketInterval) *PacketIntervalElement {
 
 // InsertBefore inserts a new element e with value v immediately before mark and returns e.
 // If mark is not an element of l, the list is not modified.
+// The mark must not be nil.
 func (l *PacketIntervalList) InsertBefore(v PacketInterval, mark *PacketIntervalElement) *PacketIntervalElement {
 	if mark.list != l {
 		return nil
 	}
-	// see comment in PacketIntervalList.Remove about initialization of l
+	// see comment in List.Remove about initialization of l
 	return l.insertValue(v, mark.prev)
 }
 
 // InsertAfter inserts a new element e with value v immediately after mark and returns e.
 // If mark is not an element of l, the list is not modified.
+// The mark must not be nil.
 func (l *PacketIntervalList) InsertAfter(v PacketInterval, mark *PacketIntervalElement) *PacketIntervalElement {
 	if mark.list != l {
 		return nil
 	}
-	// see comment in PacketIntervalList.Remove about initialization of l
+	// see comment in List.Remove about initialization of l
 	return l.insertValue(v, mark)
 }
 
 // MoveToFront moves element e to the front of list l.
 // If e is not an element of l, the list is not modified.
+// The element must not be nil.
 func (l *PacketIntervalList) MoveToFront(e *PacketIntervalElement) {
 	if e.list != l || l.root.next == e {
 		return
 	}
-	// see comment in PacketIntervalList.Remove about initialization of l
+	// see comment in List.Remove about initialization of l
 	l.insert(l.remove(e), &l.root)
 }
 
 // MoveToBack moves element e to the back of list l.
 // If e is not an element of l, the list is not modified.
+// The element must not be nil.
 func (l *PacketIntervalList) MoveToBack(e *PacketIntervalElement) {
 	if e.list != l || l.root.prev == e {
 		return
 	}
-	// see comment in PacketIntervalList.Remove about initialization of l
+	// see comment in List.Remove about initialization of l
 	l.insert(l.remove(e), l.root.prev)
 }
 
 // MoveBefore moves element e to its new position before mark.
 // If e or mark is not an element of l, or e == mark, the list is not modified.
+// The element and mark must not be nil.
 func (l *PacketIntervalList) MoveBefore(e, mark *PacketIntervalElement) {
 	if e.list != l || e == mark || mark.list != l {
 		return
@@ -187,7 +189,8 @@ func (l *PacketIntervalList) MoveBefore(e, mark *PacketIntervalElement) {
 }
 
 // MoveAfter moves element e to its new position after mark.
-// If e is not an element of l, or e == mark, the list is not modified.
+// If e or mark is not an element of l, or e == mark, the list is not modified.
+// The element and mark must not be nil.
 func (l *PacketIntervalList) MoveAfter(e, mark *PacketIntervalElement) {
 	if e.list != l || e == mark || mark.list != l {
 		return
@@ -196,7 +199,7 @@ func (l *PacketIntervalList) MoveAfter(e, mark *PacketIntervalElement) {
 }
 
 // PushBackList inserts a copy of an other list at the back of list l.
-// The lists l and other may be the same.
+// The lists l and other may be the same. They must not be nil.
 func (l *PacketIntervalList) PushBackList(other *PacketIntervalList) {
 	l.lazyInit()
 	for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
@@ -205,7 +208,7 @@ func (l *PacketIntervalList) PushBackList(other *PacketIntervalList) {
 }
 
 // PushFrontList inserts a copy of an other list at the front of list l.
-// The lists l and other may be the same.
+// The lists l and other may be the same. They must not be nil.
 func (l *PacketIntervalList) PushFrontList(other *PacketIntervalList) {
 	l.lazyInit()
 	for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/utils/streamframe_interval.go b/vendor/github.com/lucas-clemente/quic-go/internal/utils/streamframe_interval.go
index 3c8325b25..ec16d251b 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/utils/streamframe_interval.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/utils/streamframe_interval.go
@@ -3,7 +3,6 @@ package utils
 import "github.com/lucas-clemente/quic-go/internal/protocol"
 
 // ByteInterval is an interval from one ByteCount to the other
-// +gen linkedlist
 type ByteInterval struct {
 	Start protocol.ByteCount
 	End   protocol.ByteCount
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go
index d85c33a0d..1a95bb9f3 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go
@@ -24,8 +24,8 @@ type AckFrame struct {
 	DelayTime          time.Duration
 }
 
-// ParseAckFrame reads an ACK frame
-func ParseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) {
+// parseAckFrame reads an ACK frame
+func parseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) {
 	if !version.UsesIETFFrameFormat() {
 		return parseAckFrameLegacy(r, version)
 	}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame.go
index e4cad2d6d..1d3e56e59 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame.go
@@ -12,8 +12,8 @@ type BlockedFrame struct {
 	Offset protocol.ByteCount
 }
 
-// ParseBlockedFrame parses a BLOCKED frame
-func ParseBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*BlockedFrame, error) {
+// parseBlockedFrame parses a BLOCKED frame
+func parseBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*BlockedFrame, error) {
 	if _, err := r.ReadByte(); err != nil {
 		return nil, err
 	}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame_legacy.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame_legacy.go
index 41cf0ee7e..9943e1668 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame_legacy.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/blocked_frame_legacy.go
@@ -11,11 +11,11 @@ type blockedFrameLegacy struct {
 	StreamID protocol.StreamID
 }
 
-// ParseBlockedFrameLegacy parses a BLOCKED frame (in gQUIC format)
+// parseBlockedFrameLegacy parses a BLOCKED frame (in gQUIC format)
 // The frame returned is
 // * a STREAM_BLOCKED frame, if the BLOCKED applies to a stream
 // * a BLOCKED frame, if the BLOCKED applies to the connection
-func ParseBlockedFrameLegacy(r *bytes.Reader, _ protocol.VersionNumber) (Frame, error) {
+func parseBlockedFrameLegacy(r *bytes.Reader, _ protocol.VersionNumber) (Frame, error) {
 	if _, err := r.ReadByte(); err != nil { // read the TypeByte
 		return nil, err
 	}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/connection_close_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/connection_close_frame.go
index e2f5b403c..667ded744 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/connection_close_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/connection_close_frame.go
@@ -17,8 +17,8 @@ type ConnectionCloseFrame struct {
 	ReasonPhrase string
 }
 
-// ParseConnectionCloseFrame reads a CONNECTION_CLOSE frame
-func ParseConnectionCloseFrame(r *bytes.Reader, version protocol.VersionNumber) (*ConnectionCloseFrame, error) {
+// parseConnectionCloseFrame reads a CONNECTION_CLOSE frame
+func parseConnectionCloseFrame(r *bytes.Reader, version protocol.VersionNumber) (*ConnectionCloseFrame, error) {
 	if _, err := r.ReadByte(); err != nil { // read the TypeByte
 		return nil, err
 	}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go
new file mode 100644
index 000000000..6911446f9
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go
@@ -0,0 +1,152 @@
+package wire
+
+import (
+	"bytes"
+	"fmt"
+
+	"github.com/lucas-clemente/quic-go/internal/protocol"
+	"github.com/lucas-clemente/quic-go/qerr"
+)
+
+// ParseNextFrame parses the next frame
+// It skips PADDING frames.
+func ParseNextFrame(r *bytes.Reader, hdr *Header, v protocol.VersionNumber) (Frame, error) {
+	if r.Len() == 0 {
+		return nil, nil
+	}
+	typeByte, _ := r.ReadByte()
+	if typeByte == 0x0 { // PADDING frame
+		return ParseNextFrame(r, hdr, v)
+	}
+	r.UnreadByte()
+
+	if !v.UsesIETFFrameFormat() {
+		return parseGQUICFrame(r, typeByte, hdr, v)
+	}
+	return parseIETFFrame(r, typeByte, v)
+}
+
+func parseIETFFrame(r *bytes.Reader, typeByte byte, v protocol.VersionNumber) (Frame, error) {
+	var frame Frame
+	var err error
+	if typeByte&0xf8 == 0x10 {
+		frame, err = parseStreamFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidStreamData, err.Error())
+		}
+		return frame, err
+	}
+	// TODO: implement all IETF QUIC frame types
+	switch typeByte {
+	case 0x1:
+		frame, err = parseRstStreamFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidRstStreamData, err.Error())
+		}
+	case 0x2:
+		frame, err = parseConnectionCloseFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidConnectionCloseData, err.Error())
+		}
+	case 0x4:
+		frame, err = parseMaxDataFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error())
+		}
+	case 0x5:
+		frame, err = parseMaxStreamDataFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error())
+		}
+	case 0x6:
+		frame, err = parseMaxStreamIDFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidFrameData, err.Error())
+		}
+	case 0x7:
+		frame, err = parsePingFrame(r, v)
+	case 0x8:
+		frame, err = parseBlockedFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidBlockedData, err.Error())
+		}
+	case 0x9:
+		frame, err = parseStreamBlockedFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidBlockedData, err.Error())
+		}
+	case 0xa:
+		frame, err = parseStreamIDBlockedFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidFrameData, err.Error())
+		}
+	case 0xc:
+		frame, err = parseStopSendingFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidFrameData, err.Error())
+		}
+	case 0xe:
+		frame, err = parseAckFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidAckData, err.Error())
+		}
+	default:
+		err = qerr.Error(qerr.InvalidFrameData, fmt.Sprintf("unknown type byte 0x%x", typeByte))
+	}
+	return frame, err
+}
+
+func parseGQUICFrame(r *bytes.Reader, typeByte byte, hdr *Header, v protocol.VersionNumber) (Frame, error) {
+	var frame Frame
+	var err error
+	if typeByte&0x80 == 0x80 {
+		frame, err = parseStreamFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidStreamData, err.Error())
+		}
+		return frame, err
+	} else if typeByte&0xc0 == 0x40 {
+		frame, err = parseAckFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidAckData, err.Error())
+		}
+		return frame, err
+	}
+	switch typeByte {
+	case 0x1:
+		frame, err = parseRstStreamFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidRstStreamData, err.Error())
+		}
+	case 0x2:
+		frame, err = parseConnectionCloseFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidConnectionCloseData, err.Error())
+		}
+	case 0x3:
+		frame, err = parseGoawayFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidGoawayData, err.Error())
+		}
+	case 0x4:
+		frame, err = parseWindowUpdateFrame(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error())
+		}
+	case 0x5:
+		frame, err = parseBlockedFrameLegacy(r, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidBlockedData, err.Error())
+		}
+	case 0x6:
+		frame, err = parseStopWaitingFrame(r, hdr.PacketNumber, hdr.PacketNumberLen, v)
+		if err != nil {
+			err = qerr.Error(qerr.InvalidStopWaitingData, err.Error())
+		}
+	case 0x7:
+		frame, err = parsePingFrame(r, v)
+	default:
+		err = qerr.Error(qerr.InvalidFrameData, fmt.Sprintf("unknown type byte 0x%x", typeByte))
+	}
+	return frame, err
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/goaway_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/goaway_frame.go
index 8a91e5023..86bf2b439 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/goaway_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/goaway_frame.go
@@ -16,8 +16,8 @@ type GoawayFrame struct {
 	ReasonPhrase   string
 }
 
-// ParseGoawayFrame parses a GOAWAY frame
-func ParseGoawayFrame(r *bytes.Reader, _ protocol.VersionNumber) (*GoawayFrame, error) {
+// parseGoawayFrame parses a GOAWAY frame
+func parseGoawayFrame(r *bytes.Reader, _ protocol.VersionNumber) (*GoawayFrame, error) {
 	frame := &GoawayFrame{}
 
 	if _, err := r.ReadByte(); err != nil {
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/header.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/header.go
index 207312fff..fc346f3f4 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/header.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/header.go
@@ -4,6 +4,7 @@ import (
 	"bytes"
 
 	"github.com/lucas-clemente/quic-go/internal/protocol"
+	"github.com/lucas-clemente/quic-go/internal/utils"
 )
 
 // Header is the header of a QUIC packet.
@@ -103,10 +104,10 @@ func (h *Header) GetLength(pers protocol.Perspective, version protocol.VersionNu
 }
 
 // Log logs the Header
-func (h *Header) Log() {
+func (h *Header) Log(logger utils.Logger) {
 	if h.isPublicHeader {
-		h.logPublicHeader()
+		h.logPublicHeader(logger)
 	} else {
-		h.logHeader()
+		h.logHeader(logger)
 	}
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/ietf_header.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/ietf_header.go
index 6d18ef394..01bf0a26b 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/ietf_header.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/ietf_header.go
@@ -174,14 +174,14 @@ func (h *Header) getHeaderLength() (protocol.ByteCount, error) {
 	return length, nil
 }
 
-func (h *Header) logHeader() {
+func (h *Header) logHeader(logger utils.Logger) {
 	if h.IsLongHeader {
-		utils.Debugf("   Long Header{Type: %s, ConnectionID: %#x, PacketNumber: %#x, Version: %s}", h.Type, h.ConnectionID, h.PacketNumber, h.Version)
+		logger.Debugf("   Long Header{Type: %s, ConnectionID: %#x, PacketNumber: %#x, Version: %s}", h.Type, h.ConnectionID, h.PacketNumber, h.Version)
 	} else {
 		connID := "(omitted)"
 		if !h.OmitConnectionID {
 			connID = fmt.Sprintf("%#x", h.ConnectionID)
 		}
-		utils.Debugf("   Short Header{ConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, KeyPhase: %d}", connID, h.PacketNumber, h.PacketNumberLen, h.KeyPhase)
+		logger.Debugf("   Short Header{ConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, KeyPhase: %d}", connID, h.PacketNumber, h.PacketNumberLen, h.KeyPhase)
 	}
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/log.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/log.go
index 0e72ea98a..eaf5b1ea9 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/log.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/log.go
@@ -3,8 +3,8 @@ package wire
 import "github.com/lucas-clemente/quic-go/internal/utils"
 
 // LogFrame logs a frame, either sent or received
-func LogFrame(frame Frame, sent bool) {
-	if !utils.Debug() {
+func LogFrame(logger utils.Logger, frame Frame, sent bool) {
+	if !logger.Debug() {
 		return
 	}
 	dir := "<-"
@@ -13,16 +13,16 @@ func LogFrame(frame Frame, sent bool) {
 	}
 	switch f := frame.(type) {
 	case *StreamFrame:
-		utils.Debugf("\t%s &wire.StreamFrame{StreamID: %d, FinBit: %t, Offset: 0x%x, Data length: 0x%x, Offset + Data length: 0x%x}", dir, f.StreamID, f.FinBit, f.Offset, f.DataLen(), f.Offset+f.DataLen())
+		logger.Debugf("\t%s &wire.StreamFrame{StreamID: %d, FinBit: %t, Offset: 0x%x, Data length: 0x%x, Offset + Data length: 0x%x}", dir, f.StreamID, f.FinBit, f.Offset, f.DataLen(), f.Offset+f.DataLen())
 	case *StopWaitingFrame:
 		if sent {
-			utils.Debugf("\t%s &wire.StopWaitingFrame{LeastUnacked: 0x%x, PacketNumberLen: 0x%x}", dir, f.LeastUnacked, f.PacketNumberLen)
+			logger.Debugf("\t%s &wire.StopWaitingFrame{LeastUnacked: 0x%x, PacketNumberLen: 0x%x}", dir, f.LeastUnacked, f.PacketNumberLen)
 		} else {
-			utils.Debugf("\t%s &wire.StopWaitingFrame{LeastUnacked: 0x%x}", dir, f.LeastUnacked)
+			logger.Debugf("\t%s &wire.StopWaitingFrame{LeastUnacked: 0x%x}", dir, f.LeastUnacked)
 		}
 	case *AckFrame:
-		utils.Debugf("\t%s &wire.AckFrame{LargestAcked: 0x%x, LowestAcked: 0x%x, AckRanges: %#v, DelayTime: %s}", dir, f.LargestAcked, f.LowestAcked, f.AckRanges, f.DelayTime.String())
+		logger.Debugf("\t%s &wire.AckFrame{LargestAcked: 0x%x, LowestAcked: 0x%x, AckRanges: %#v, DelayTime: %s}", dir, f.LargestAcked, f.LowestAcked, f.AckRanges, f.DelayTime.String())
 	default:
-		utils.Debugf("\t%s %#v", dir, frame)
+		logger.Debugf("\t%s %#v", dir, frame)
 	}
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_data_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_data_frame.go
index 8ba4fc09a..0bca27da8 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_data_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_data_frame.go
@@ -12,8 +12,8 @@ type MaxDataFrame struct {
 	ByteOffset protocol.ByteCount
 }
 
-// ParseMaxDataFrame parses a MAX_DATA frame
-func ParseMaxDataFrame(r *bytes.Reader, version protocol.VersionNumber) (*MaxDataFrame, error) {
+// parseMaxDataFrame parses a MAX_DATA frame
+func parseMaxDataFrame(r *bytes.Reader, version protocol.VersionNumber) (*MaxDataFrame, error) {
 	// read the TypeByte
 	if _, err := r.ReadByte(); err != nil {
 		return nil, err
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_data_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_data_frame.go
index e88f245b5..6d8be236d 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_data_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_data_frame.go
@@ -13,8 +13,8 @@ type MaxStreamDataFrame struct {
 	ByteOffset protocol.ByteCount
 }
 
-// ParseMaxStreamDataFrame parses a MAX_STREAM_DATA frame
-func ParseMaxStreamDataFrame(r *bytes.Reader, version protocol.VersionNumber) (*MaxStreamDataFrame, error) {
+// parseMaxStreamDataFrame parses a MAX_STREAM_DATA frame
+func parseMaxStreamDataFrame(r *bytes.Reader, version protocol.VersionNumber) (*MaxStreamDataFrame, error) {
 	frame := &MaxStreamDataFrame{}
 
 	// read the TypeByte
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_id_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_id_frame.go
index 31e51ae3d..9f5424daa 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_id_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/max_stream_id_frame.go
@@ -12,8 +12,8 @@ type MaxStreamIDFrame struct {
 	StreamID protocol.StreamID
 }
 
-// ParseMaxStreamIDFrame parses a MAX_STREAM_ID frame
-func ParseMaxStreamIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxStreamIDFrame, error) {
+// parseMaxStreamIDFrame parses a MAX_STREAM_ID frame
+func parseMaxStreamIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxStreamIDFrame, error) {
 	// read the Type byte
 	if _, err := r.ReadByte(); err != nil {
 		return nil, err
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/ping_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/ping_frame.go
index ac4fd7d25..bc1dedac0 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/ping_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/ping_frame.go
@@ -9,8 +9,8 @@ import (
 // A PingFrame is a ping frame
 type PingFrame struct{}
 
-// ParsePingFrame parses a Ping frame
-func ParsePingFrame(r *bytes.Reader, version protocol.VersionNumber) (*PingFrame, error) {
+// parsePingFrame parses a Ping frame
+func parsePingFrame(r *bytes.Reader, version protocol.VersionNumber) (*PingFrame, error) {
 	frame := &PingFrame{}
 
 	_, err := r.ReadByte()
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/public_header.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/public_header.go
index 593ac7711..af996b292 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/public_header.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/public_header.go
@@ -20,6 +20,9 @@ var (
 
 // writePublicHeader writes a Public Header.
 func (h *Header) writePublicHeader(b *bytes.Buffer, pers protocol.Perspective, _ protocol.VersionNumber) error {
+	if h.VersionFlag && pers == protocol.PerspectiveServer {
+		return errors.New("PublicHeader: Writing of Version Negotiation Packets not supported")
+	}
 	if h.VersionFlag && h.ResetFlag {
 		return errResetAndVersionFlagSet
 	}
@@ -228,7 +231,7 @@ func (h *Header) hasPacketNumber(packetSentBy protocol.Perspective) bool {
 	return true
 }
 
-func (h *Header) logPublicHeader() {
+func (h *Header) logPublicHeader(logger utils.Logger) {
 	connID := "(omitted)"
 	if !h.OmitConnectionID {
 		connID = fmt.Sprintf("%#x", h.ConnectionID)
@@ -237,5 +240,5 @@ func (h *Header) logPublicHeader() {
 	if h.Version != 0 {
 		ver = h.Version.String()
 	}
-	utils.Debugf("   Public Header{ConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, Version: %s, DiversificationNonce: %#v}", connID, h.PacketNumber, h.PacketNumberLen, ver, h.DiversificationNonce)
+	logger.Debugf("   Public Header{ConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, Version: %s, DiversificationNonce: %#v}", connID, h.PacketNumber, h.PacketNumberLen, ver, h.DiversificationNonce)
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/rst_stream_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/rst_stream_frame.go
index ea25f381d..209422c28 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/rst_stream_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/rst_stream_frame.go
@@ -16,8 +16,8 @@ type RstStreamFrame struct {
 	ByteOffset protocol.ByteCount
 }
 
-// ParseRstStreamFrame parses a RST_STREAM frame
-func ParseRstStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*RstStreamFrame, error) {
+// parseRstStreamFrame parses a RST_STREAM frame
+func parseRstStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*RstStreamFrame, error) {
 	if _, err := r.ReadByte(); err != nil { // read the TypeByte
 		return nil, err
 	}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_sending_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_sending_frame.go
index 2a33756bd..b5e698047 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_sending_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_sending_frame.go
@@ -13,8 +13,8 @@ type StopSendingFrame struct {
 	ErrorCode protocol.ApplicationErrorCode
 }
 
-// ParseStopSendingFrame parses a STOP_SENDING frame
-func ParseStopSendingFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StopSendingFrame, error) {
+// parseStopSendingFrame parses a STOP_SENDING frame
+func parseStopSendingFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StopSendingFrame, error) {
 	if _, err := r.ReadByte(); err != nil { // read the TypeByte
 		return nil, err
 	}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_waiting_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_waiting_frame.go
index 4ee9578e6..b87606ad3 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_waiting_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stop_waiting_frame.go
@@ -56,8 +56,8 @@ func (f *StopWaitingFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
 	return 1 + protocol.ByteCount(f.PacketNumberLen)
 }
 
-// ParseStopWaitingFrame parses a StopWaiting frame
-func ParseStopWaitingFrame(r *bytes.Reader, packetNumber protocol.PacketNumber, packetNumberLen protocol.PacketNumberLen, _ protocol.VersionNumber) (*StopWaitingFrame, error) {
+// parseStopWaitingFrame parses a StopWaiting frame
+func parseStopWaitingFrame(r *bytes.Reader, packetNumber protocol.PacketNumber, packetNumberLen protocol.PacketNumberLen, _ protocol.VersionNumber) (*StopWaitingFrame, error) {
 	frame := &StopWaitingFrame{}
 
 	// read the TypeByte
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_blocked_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_blocked_frame.go
index 625698cd1..a083a9f59 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_blocked_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_blocked_frame.go
@@ -13,8 +13,8 @@ type StreamBlockedFrame struct {
 	Offset   protocol.ByteCount
 }
 
-// ParseStreamBlockedFrame parses a STREAM_BLOCKED frame
-func ParseStreamBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamBlockedFrame, error) {
+// parseStreamBlockedFrame parses a STREAM_BLOCKED frame
+func parseStreamBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamBlockedFrame, error) {
 	if _, err := r.ReadByte(); err != nil { // read the TypeByte
 		return nil, err
 	}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_frame.go
index b87fce227..d848127ae 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_frame.go
@@ -19,8 +19,8 @@ type StreamFrame struct {
 	Data           []byte
 }
 
-// ParseStreamFrame reads a STREAM frame
-func ParseStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*StreamFrame, error) {
+// parseStreamFrame reads a STREAM frame
+func parseStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*StreamFrame, error) {
 	if !version.UsesIETFFrameFormat() {
 		return parseLegacyStreamFrame(r, version)
 	}
@@ -76,7 +76,8 @@ func ParseStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*StreamF
 	if frame.Offset+frame.DataLen() > protocol.MaxByteCount {
 		return nil, qerr.Error(qerr.InvalidStreamData, "data overflows maximum offset")
 	}
-	if !frame.FinBit && frame.DataLen() == 0 {
+	// empty frames are only allowed if they have offset 0 or the FIN bit set
+	if frame.DataLen() == 0 && !frame.FinBit && frame.Offset != 0 {
 		return nil, qerr.EmptyStreamFrameNoFin
 	}
 	return frame, nil
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_id_blocked_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_id_blocked_frame.go
index 7b390a4d9..6476eb9de 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_id_blocked_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/stream_id_blocked_frame.go
@@ -12,8 +12,8 @@ type StreamIDBlockedFrame struct {
 	StreamID protocol.StreamID
 }
 
-// ParseStreamIDBlockedFrame parses a STREAM_ID_BLOCKED frame
-func ParseStreamIDBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamIDBlockedFrame, error) {
+// parseStreamIDBlockedFrame parses a STREAM_ID_BLOCKED frame
+func parseStreamIDBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamIDBlockedFrame, error) {
 	if _, err := r.ReadByte(); err != nil {
 		return nil, err
 	}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/version_negotiation.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/version_negotiation.go
index dea90ee14..cf72fc2e6 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/version_negotiation.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/version_negotiation.go
@@ -10,17 +10,9 @@ import (
 
 // ComposeGQUICVersionNegotiation composes a Version Negotiation Packet for gQUIC
 func ComposeGQUICVersionNegotiation(connID protocol.ConnectionID, versions []protocol.VersionNumber) []byte {
-	buf := &bytes.Buffer{}
-	ph := Header{
-		ConnectionID:         connID,
-		PacketNumber:         1,
-		VersionFlag:          true,
-		IsVersionNegotiation: true,
-	}
-	if err := ph.writePublicHeader(buf, protocol.PerspectiveServer, protocol.VersionWhatever); err != nil {
-		utils.Errorf("error composing version negotiation packet: %s", err.Error())
-		return nil
-	}
+	buf := bytes.NewBuffer(make([]byte, 0, 1+8+len(versions)*4))
+	buf.Write([]byte{0x1 | 0x8}) // type byte
+	utils.BigEndian.WriteUint64(buf, uint64(connID))
 	for _, v := range versions {
 		utils.BigEndian.WriteUint32(buf, uint32(v))
 	}
diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/window_update_frame.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/window_update_frame.go
index 8f7556e75..606e25cf2 100644
--- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/window_update_frame.go
+++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/window_update_frame.go
@@ -12,11 +12,11 @@ type windowUpdateFrame struct {
 	ByteOffset protocol.ByteCount
 }
 
-// ParseWindowUpdateFrame parses a WINDOW_UPDATE frame
+// parseWindowUpdateFrame parses a WINDOW_UPDATE frame
 // The frame returned is
 // * a MAX_STREAM_DATA frame, if the WINDOW_UPDATE applies to a stream
 // * a MAX_DATA frame, if the WINDOW_UPDATE applies to the connection
-func ParseWindowUpdateFrame(r *bytes.Reader, _ protocol.VersionNumber) (Frame, error) {
+func parseWindowUpdateFrame(r *bytes.Reader, _ protocol.VersionNumber) (Frame, error) {
 	if _, err := r.ReadByte(); err != nil { // read the TypeByte
 		return nil, err
 	}
diff --git a/vendor/github.com/lucas-clemente/quic-go/mint_utils.go b/vendor/github.com/lucas-clemente/quic-go/mint_utils.go
index 5156a6526..b32a09057 100644
--- a/vendor/github.com/lucas-clemente/quic-go/mint_utils.go
+++ b/vendor/github.com/lucas-clemente/quic-go/mint_utils.go
@@ -6,6 +6,7 @@ import (
 	"crypto/tls"
 	"crypto/x509"
 	"errors"
+	"fmt"
 	"io"
 
 	"github.com/bifurcation/mint"
@@ -76,6 +77,7 @@ func tlsToMintConfig(tlsConf *tls.Config, pers protocol.Perspective) (*mint.Conf
 		mconf.ServerName = tlsConf.ServerName
 		mconf.InsecureSkipVerify = tlsConf.InsecureSkipVerify
 		mconf.Certificates = make([]*mint.Certificate, len(tlsConf.Certificates))
+		mconf.RootCAs = tlsConf.RootCAs
 		mconf.VerifyPeerCertificate = tlsConf.VerifyPeerCertificate
 		for i, certChain := range tlsConf.Certificates {
 			mconf.Certificates[i] = &mint.Certificate{
@@ -106,39 +108,45 @@ func tlsToMintConfig(tlsConf *tls.Config, pers protocol.Perspective) (*mint.Conf
 
 // unpackInitialOrRetryPacket unpacks packets Initial and Retry packets
 // These packets must contain a STREAM_FRAME for the crypto stream, starting at offset 0.
-func unpackInitialPacket(aead crypto.AEAD, hdr *wire.Header, data []byte, version protocol.VersionNumber) (*wire.StreamFrame, error) {
-	unpacker := &packetUnpacker{aead: &nullAEAD{aead}, version: version}
-	packet, err := unpacker.Unpack(hdr.Raw, hdr, data)
+func unpackInitialPacket(aead crypto.AEAD, hdr *wire.Header, data []byte, logger utils.Logger, version protocol.VersionNumber) (*wire.StreamFrame, error) {
+	decrypted, err := aead.Open(data[:0], data, hdr.PacketNumber, hdr.Raw)
 	if err != nil {
 		return nil, err
 	}
 	var frame *wire.StreamFrame
-	for _, f := range packet.frames {
+	r := bytes.NewReader(decrypted)
+	for {
+		f, err := wire.ParseNextFrame(r, hdr, version)
+		if err != nil {
+			return nil, err
+		}
 		var ok bool
-		frame, ok = f.(*wire.StreamFrame)
-		if ok {
+		if frame, ok = f.(*wire.StreamFrame); ok || frame == nil {
 			break
 		}
 	}
 	if frame == nil {
 		return nil, errors.New("Packet doesn't contain a STREAM_FRAME")
 	}
+	if frame.StreamID != version.CryptoStreamID() {
+		return nil, fmt.Errorf("Received STREAM_FRAME for wrong stream (Stream ID %d)", frame.StreamID)
+	}
 	// We don't need a check for the stream ID here.
 	// The packetUnpacker checks that there's no unencrypted stream data except for the crypto stream.
 	if frame.Offset != 0 {
 		return nil, errors.New("received stream data with non-zero offset")
 	}
-	if utils.Debug() {
-		utils.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID)
-		hdr.Log()
-		wire.LogFrame(frame, false)
+	if logger.Debug() {
+		logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID)
+		hdr.Log(logger)
+		wire.LogFrame(logger, frame, false)
 	}
 	return frame, nil
 }
 
 // packUnencryptedPacket provides a low-overhead way to pack a packet.
 // It is supposed to be used in the early stages of the handshake, before a session (which owns a packetPacker) is available.
-func packUnencryptedPacket(aead crypto.AEAD, hdr *wire.Header, f wire.Frame, pers protocol.Perspective) ([]byte, error) {
+func packUnencryptedPacket(aead crypto.AEAD, hdr *wire.Header, f wire.Frame, pers protocol.Perspective, logger utils.Logger) ([]byte, error) {
 	raw := *getPacketBuffer()
 	buffer := bytes.NewBuffer(raw[:0])
 	if err := hdr.Write(buffer, pers, hdr.Version); err != nil {
@@ -151,10 +159,10 @@ func packUnencryptedPacket(aead crypto.AEAD, hdr *wire.Header, f wire.Frame, per
 	raw = raw[0:buffer.Len()]
 	_ = aead.Seal(raw[payloadStartIndex:payloadStartIndex], raw[payloadStartIndex:], hdr.PacketNumber, raw[:payloadStartIndex])
 	raw = raw[0 : buffer.Len()+aead.Overhead()]
-	if utils.Debug() {
-		utils.Debugf("-> Sending packet 0x%x (%d bytes) for connection %x, %s", hdr.PacketNumber, len(raw), hdr.ConnectionID, protocol.EncryptionUnencrypted)
-		hdr.Log()
-		wire.LogFrame(f, true)
+	if logger.Debug() {
+		logger.Debugf("-> Sending packet 0x%x (%d bytes) for connection %x, %s", hdr.PacketNumber, len(raw), hdr.ConnectionID, protocol.EncryptionUnencrypted)
+		hdr.Log(logger)
+		wire.LogFrame(logger, f, true)
 	}
 	return raw, nil
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/mockgen.go b/vendor/github.com/lucas-clemente/quic-go/mockgen.go
index 3802a8633..65f385468 100644
--- a/vendor/github.com/lucas-clemente/quic-go/mockgen.go
+++ b/vendor/github.com/lucas-clemente/quic-go/mockgen.go
@@ -9,4 +9,8 @@ package quic
 //go:generate sh -c "./mockgen_private.sh quic mock_crypto_stream_test.go github.com/lucas-clemente/quic-go cryptoStreamI CryptoStream"
 //go:generate sh -c "./mockgen_private.sh quic mock_stream_manager_test.go github.com/lucas-clemente/quic-go streamManager StreamManager"
 //go:generate sh -c "sed -i '' 's/quic_go.//g' mock_stream_getter_test.go mock_stream_manager_test.go"
+//go:generate sh -c "./mockgen_private.sh quic mock_unpacker_test.go github.com/lucas-clemente/quic-go unpacker Unpacker"
+//go:generate sh -c "sed -i '' 's/quic_go.//g' mock_unpacker_test.go mock_unpacker_test.go"
+//go:generate sh -c "./mockgen_private.sh quic mock_quic_aead_test.go github.com/lucas-clemente/quic-go quicAEAD QuicAEAD"
+//go:generate sh -c "./mockgen_private.sh quic mock_gquic_aead_test.go github.com/lucas-clemente/quic-go gQUICAEAD GQUICAEAD"
 //go:generate sh -c "goimports -w mock*_test.go"
diff --git a/vendor/github.com/lucas-clemente/quic-go/packet_packer.go b/vendor/github.com/lucas-clemente/quic-go/packet_packer.go
index b9b71edfe..e4fa653a5 100644
--- a/vendor/github.com/lucas-clemente/quic-go/packet_packer.go
+++ b/vendor/github.com/lucas-clemente/quic-go/packet_packer.go
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"net"
 	"sync"
+	"time"
 
 	"github.com/lucas-clemente/quic-go/internal/ackhandler"
 	"github.com/lucas-clemente/quic-go/internal/handshake"
@@ -28,9 +29,16 @@ func (p *packedPacket) ToAckHandlerPacket() *ackhandler.Packet {
 		Frames:          p.frames,
 		Length:          protocol.ByteCount(len(p.raw)),
 		EncryptionLevel: p.encryptionLevel,
+		SendTime:        time.Now(),
 	}
 }
 
+type sealingManager interface {
+	GetSealer() (protocol.EncryptionLevel, handshake.Sealer)
+	GetSealerForCryptoStream() (protocol.EncryptionLevel, handshake.Sealer)
+	GetSealerWithEncryptionLevel(protocol.EncryptionLevel) (handshake.Sealer, error)
+}
+
 type streamFrameSource interface {
 	HasCryptoStreamData() bool
 	PopCryptoStreamFrame(protocol.ByteCount) *wire.StreamFrame
@@ -41,7 +49,8 @@ type packetPacker struct {
 	connectionID protocol.ConnectionID
 	perspective  protocol.Perspective
 	version      protocol.VersionNumber
-	cryptoSetup  handshake.CryptoSetup
+	divNonce     []byte
+	cryptoSetup  sealingManager
 
 	packetNumberGenerator *packetNumberGenerator
 	getPacketNumberLen    func(protocol.PacketNumber) protocol.PacketNumberLen
@@ -62,7 +71,8 @@ func newPacketPacker(connectionID protocol.ConnectionID,
 	initialPacketNumber protocol.PacketNumber,
 	getPacketNumberLen func(protocol.PacketNumber) protocol.PacketNumberLen,
 	remoteAddr net.Addr, // only used for determining the max packet size
-	cryptoSetup handshake.CryptoSetup,
+	divNonce []byte,
+	cryptoSetup sealingManager,
 	streamFramer streamFrameSource,
 	perspective protocol.Perspective,
 	version protocol.VersionNumber,
@@ -82,6 +92,7 @@ func newPacketPacker(connectionID protocol.ConnectionID,
 	}
 	return &packetPacker{
 		cryptoSetup:           cryptoSetup,
+		divNonce:              divNonce,
 		connectionID:          connectionID,
 		perspective:           perspective,
 		version:               version,
@@ -455,7 +466,7 @@ func (p *packetPacker) getHeader(encLevel protocol.EncryptionLevel) *wire.Header
 	}
 	if !p.version.UsesTLS() {
 		if p.perspective == protocol.PerspectiveServer && encLevel == protocol.EncryptionSecure {
-			header.DiversificationNonce = p.cryptoSetup.DiversificationNonce()
+			header.DiversificationNonce = p.divNonce
 		}
 		if p.perspective == protocol.PerspectiveClient && encLevel != protocol.EncryptionForwardSecure {
 			header.VersionFlag = true
diff --git a/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go b/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go
index a978675d8..994979072 100644
--- a/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go
+++ b/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go
@@ -2,7 +2,6 @@ package quic
 
 import (
 	"bytes"
-	"fmt"
 
 	"github.com/lucas-clemente/quic-go/internal/protocol"
 	"github.com/lucas-clemente/quic-go/internal/wire"
@@ -14,52 +13,65 @@ type unpackedPacket struct {
 	frames          []wire.Frame
 }
 
-type quicAEAD interface {
+type gQUICAEAD interface {
 	Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error)
 }
 
-type packetUnpacker struct {
-	version protocol.VersionNumber
-	aead    quicAEAD
+type quicAEAD interface {
+	OpenHandshake(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error)
+	Open1RTT(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error)
 }
 
-func (u *packetUnpacker) Unpack(headerBinary []byte, hdr *wire.Header, data []byte) (*unpackedPacket, error) {
-	buf := *getPacketBuffer()
-	buf = buf[:0]
-	defer putPacketBuffer(&buf)
-	decrypted, encryptionLevel, err := u.aead.Open(buf, data, hdr.PacketNumber, headerBinary)
-	if err != nil {
-		// Wrap err in quicError so that public reset is sent by session
-		return nil, qerr.Error(qerr.DecryptionFailure, err.Error())
-	}
-	r := bytes.NewReader(decrypted)
+type packetUnpackerBase struct {
+	version protocol.VersionNumber
+}
 
+func (u *packetUnpackerBase) parseFrames(decrypted []byte, hdr *wire.Header) ([]wire.Frame, error) {
+	r := bytes.NewReader(decrypted)
 	if r.Len() == 0 {
 		return nil, qerr.MissingPayload
 	}
 
 	fs := make([]wire.Frame, 0, 2)
-
 	// Read all frames in the packet
-	for r.Len() > 0 {
-		typeByte, _ := r.ReadByte()
-		if typeByte == 0x0 { // PADDING frame
-			continue
-		}
-		r.UnreadByte()
-
-		frame, err := u.parseFrame(r, typeByte, hdr)
+	for {
+		frame, err := wire.ParseNextFrame(r, hdr, u.version)
 		if err != nil {
 			return nil, err
 		}
-		if sf, ok := frame.(*wire.StreamFrame); ok {
-			if sf.StreamID != u.version.CryptoStreamID() && encryptionLevel <= protocol.EncryptionUnencrypted {
-				return nil, qerr.Error(qerr.UnencryptedStreamData, fmt.Sprintf("received unencrypted stream data on stream %d", sf.StreamID))
-			}
-		}
-		if frame != nil {
-			fs = append(fs, frame)
+		if frame == nil {
+			break
 		}
+		fs = append(fs, frame)
+	}
+	return fs, nil
+}
+
+// The packetUnpackerGQUIC unpacks gQUIC packets.
+type packetUnpackerGQUIC struct {
+	packetUnpackerBase
+	aead gQUICAEAD
+}
+
+var _ unpacker = &packetUnpackerGQUIC{}
+
+func newPacketUnpackerGQUIC(aead gQUICAEAD, version protocol.VersionNumber) unpacker {
+	return &packetUnpackerGQUIC{
+		packetUnpackerBase: packetUnpackerBase{version: version},
+		aead:               aead,
+	}
+}
+
+func (u *packetUnpackerGQUIC) Unpack(headerBinary []byte, hdr *wire.Header, data []byte) (*unpackedPacket, error) {
+	decrypted, encryptionLevel, err := u.aead.Open(data[:0], data, hdr.PacketNumber, headerBinary)
+	if err != nil {
+		// Wrap err in quicError so that public reset is sent by session
+		return nil, qerr.Error(qerr.DecryptionFailure, err.Error())
+	}
+
+	fs, err := u.parseFrames(decrypted, hdr)
+	if err != nil {
+		return nil, err
 	}
 
 	return &unpackedPacket{
@@ -68,134 +80,48 @@ func (u *packetUnpacker) Unpack(headerBinary []byte, hdr *wire.Header, data []by
 	}, nil
 }
 
-func (u *packetUnpacker) parseFrame(r *bytes.Reader, typeByte byte, hdr *wire.Header) (wire.Frame, error) {
-	if u.version.UsesIETFFrameFormat() {
-		return u.parseIETFFrame(r, typeByte, hdr)
-	}
-	return u.parseGQUICFrame(r, typeByte, hdr)
+// The packetUnpacker unpacks IETF QUIC packets.
+type packetUnpacker struct {
+	packetUnpackerBase
+	aead quicAEAD
 }
 
-func (u *packetUnpacker) parseIETFFrame(r *bytes.Reader, typeByte byte, hdr *wire.Header) (wire.Frame, error) {
-	var frame wire.Frame
-	var err error
-	if typeByte&0xf8 == 0x10 {
-		frame, err = wire.ParseStreamFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidStreamData, err.Error())
-		}
-		return frame, err
+var _ unpacker = &packetUnpacker{}
+
+func newPacketUnpacker(aead quicAEAD, version protocol.VersionNumber) unpacker {
+	return &packetUnpacker{
+		packetUnpackerBase: packetUnpackerBase{version: version},
+		aead:               aead,
 	}
-	// TODO: implement all IETF QUIC frame types
-	switch typeByte {
-	case 0x1:
-		frame, err = wire.ParseRstStreamFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidRstStreamData, err.Error())
-		}
-	case 0x2:
-		frame, err = wire.ParseConnectionCloseFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidConnectionCloseData, err.Error())
-		}
-	case 0x4:
-		frame, err = wire.ParseMaxDataFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error())
-		}
-	case 0x5:
-		frame, err = wire.ParseMaxStreamDataFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error())
-		}
-	case 0x6:
-		frame, err = wire.ParseMaxStreamIDFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidFrameData, err.Error())
-		}
-	case 0x7:
-		frame, err = wire.ParsePingFrame(r, u.version)
-	case 0x8:
-		frame, err = wire.ParseBlockedFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidBlockedData, err.Error())
-		}
-	case 0x9:
-		frame, err = wire.ParseStreamBlockedFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidBlockedData, err.Error())
-		}
-	case 0xa:
-		frame, err = wire.ParseStreamIDBlockedFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidFrameData, err.Error())
-		}
-	case 0xc:
-		frame, err = wire.ParseStopSendingFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidFrameData, err.Error())
-		}
-	case 0xe:
-		frame, err = wire.ParseAckFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidAckData, err.Error())
-		}
-	default:
-		err = qerr.Error(qerr.InvalidFrameData, fmt.Sprintf("unknown type byte 0x%x", typeByte))
-	}
-	return frame, err
 }
 
-func (u *packetUnpacker) parseGQUICFrame(r *bytes.Reader, typeByte byte, hdr *wire.Header) (wire.Frame, error) {
-	var frame wire.Frame
+func (u *packetUnpacker) Unpack(headerBinary []byte, hdr *wire.Header, data []byte) (*unpackedPacket, error) {
+	buf := *getPacketBuffer()
+	buf = buf[:0]
+	defer putPacketBuffer(&buf)
+
+	var decrypted []byte
+	var encryptionLevel protocol.EncryptionLevel
 	var err error
-	if typeByte&0x80 == 0x80 {
-		frame, err = wire.ParseStreamFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidStreamData, err.Error())
-		}
-		return frame, err
-	} else if typeByte&0xc0 == 0x40 {
-		frame, err = wire.ParseAckFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidAckData, err.Error())
-		}
-		return frame, err
+	if hdr.IsLongHeader {
+		decrypted, err = u.aead.OpenHandshake(buf, data, hdr.PacketNumber, headerBinary)
+		encryptionLevel = protocol.EncryptionUnencrypted
+	} else {
+		decrypted, err = u.aead.Open1RTT(buf, data, hdr.PacketNumber, headerBinary)
+		encryptionLevel = protocol.EncryptionForwardSecure
 	}
-	switch typeByte {
-	case 0x1:
-		frame, err = wire.ParseRstStreamFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidRstStreamData, err.Error())
-		}
-	case 0x2:
-		frame, err = wire.ParseConnectionCloseFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidConnectionCloseData, err.Error())
-		}
-	case 0x3:
-		frame, err = wire.ParseGoawayFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidGoawayData, err.Error())
-		}
-	case 0x4:
-		frame, err = wire.ParseWindowUpdateFrame(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error())
-		}
-	case 0x5:
-		frame, err = wire.ParseBlockedFrameLegacy(r, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidBlockedData, err.Error())
-		}
-	case 0x6:
-		frame, err = wire.ParseStopWaitingFrame(r, hdr.PacketNumber, hdr.PacketNumberLen, u.version)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidStopWaitingData, err.Error())
-		}
-	case 0x7:
-		frame, err = wire.ParsePingFrame(r, u.version)
-	default:
-		err = qerr.Error(qerr.InvalidFrameData, fmt.Sprintf("unknown type byte 0x%x", typeByte))
+	if err != nil {
+		// Wrap err in quicError so that public reset is sent by session
+		return nil, qerr.Error(qerr.DecryptionFailure, err.Error())
 	}
-	return frame, err
+
+	fs, err := u.parseFrames(decrypted, hdr)
+	if err != nil {
+		return nil, err
+	}
+
+	return &unpackedPacket{
+		encryptionLevel: encryptionLevel,
+		frames:          fs,
+	}, nil
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go b/vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go
index a620bd192..42d08c4c5 100644
--- a/vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go
+++ b/vendor/github.com/lucas-clemente/quic-go/qerr/quic_error.go
@@ -2,8 +2,6 @@ package qerr
 
 import (
 	"fmt"
-
-	"github.com/lucas-clemente/quic-go/internal/utils"
 )
 
 // ErrorCode can be used as a normal error without reason.
@@ -51,6 +49,5 @@ func ToQuicError(err error) *QuicError {
 	case ErrorCode:
 		return Error(e, "")
 	}
-	utils.Errorf("Internal error: %v", err)
 	return Error(InternalError, err.Error())
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/server.go b/vendor/github.com/lucas-clemente/quic-go/server.go
index 7a19afcb5..1e56f0b91 100644
--- a/vendor/github.com/lucas-clemente/quic-go/server.go
+++ b/vendor/github.com/lucas-clemente/quic-go/server.go
@@ -50,8 +50,10 @@ type server struct {
 	errorChan    chan struct{}
 
 	// set as members, so they can be set in the tests
-	newSession                func(conn connection, v protocol.VersionNumber, connectionID protocol.ConnectionID, sCfg *handshake.ServerConfig, tlsConf *tls.Config, config *Config) (packetHandler, error)
+	newSession                func(conn connection, v protocol.VersionNumber, connectionID protocol.ConnectionID, sCfg *handshake.ServerConfig, tlsConf *tls.Config, config *Config, logger utils.Logger) (packetHandler, error)
 	deleteClosedSessionsAfter time.Duration
+
+	logger utils.Logger
 }
 
 var _ Listener = &server{}
@@ -110,6 +112,7 @@ func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener,
 		sessionQueue:              make(chan Session, 5),
 		errorChan:                 make(chan struct{}),
 		supportsTLS:               supportsTLS,
+		logger:                    utils.DefaultLogger,
 	}
 	if supportsTLS {
 		if err := s.setupTLS(); err != nil {
@@ -117,16 +120,16 @@ func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener,
 		}
 	}
 	go s.serve()
-	utils.Debugf("Listening for %s connections on %s", conn.LocalAddr().Network(), conn.LocalAddr().String())
+	s.logger.Debugf("Listening for %s connections on %s", conn.LocalAddr().Network(), conn.LocalAddr().String())
 	return s, nil
 }
 
 func (s *server) setupTLS() error {
-	cookieHandler, err := handshake.NewCookieHandler(s.config.AcceptCookie)
+	cookieHandler, err := handshake.NewCookieHandler(s.config.AcceptCookie, s.logger)
 	if err != nil {
 		return err
 	}
-	serverTLS, sessionChan, err := newServerTLS(s.conn, s.config, cookieHandler, s.tlsConf)
+	serverTLS, sessionChan, err := newServerTLS(s.conn, s.config, cookieHandler, s.tlsConf, s.logger)
 	if err != nil {
 		return err
 	}
@@ -245,7 +248,7 @@ func (s *server) serve() {
 		}
 		data = data[:n]
 		if err := s.handlePacket(s.conn, remoteAddr, data); err != nil {
-			utils.Errorf("error handling packet: %s", err.Error())
+			s.logger.Errorf("error handling packet: %s", err.Error())
 		}
 	}
 }
@@ -328,12 +331,12 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
 			var pr *wire.PublicReset
 			pr, err = wire.ParsePublicReset(r)
 			if err != nil {
-				utils.Infof("Received a Public Reset for connection %x. An error occurred parsing the packet.", hdr.ConnectionID)
+				s.logger.Infof("Received a Public Reset for connection %x. An error occurred parsing the packet.", hdr.ConnectionID)
 			} else {
-				utils.Infof("Received a Public Reset for connection %x, rejected packet number: 0x%x.", hdr.ConnectionID, pr.RejectedPacketNumber)
+				s.logger.Infof("Received a Public Reset for connection %x, rejected packet number: 0x%x.", hdr.ConnectionID, pr.RejectedPacketNumber)
 			}
 		} else {
-			utils.Infof("Received Public Reset for unknown connection %x.", hdr.ConnectionID)
+			s.logger.Infof("Received Public Reset for unknown connection %x.", hdr.ConnectionID)
 		}
 		return nil
 	}
@@ -360,7 +363,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
 		if len(packet) < protocol.MinClientHelloSize+len(hdr.Raw) {
 			return errors.New("dropping small packet with unknown version")
 		}
-		utils.Infof("Client offered version %s, sending Version Negotiation Packet", hdr.Version)
+		s.logger.Infof("Client offered version %s, sending Version Negotiation Packet", hdr.Version)
 		_, err := pconn.WriteTo(wire.ComposeGQUICVersionNegotiation(hdr.ConnectionID, s.config.Versions), remoteAddr)
 		return err
 	}
@@ -377,7 +380,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
 			return errors.New("Server BUG: negotiated version not supported")
 		}
 
-		utils.Infof("Serving new connection: %x, version %s from %v", hdr.ConnectionID, version, remoteAddr)
+		s.logger.Infof("Serving new connection: %x, version %s from %v", hdr.ConnectionID, version, remoteAddr)
 		session, err = s.newSession(
 			&conn{pconn: pconn, currentAddr: remoteAddr},
 			version,
@@ -385,6 +388,7 @@ func (s *server) handlePacket(pconn net.PacketConn, remoteAddr net.Addr, packet
 			s.scfg,
 			s.tlsConf,
 			s.config,
+			s.logger,
 		)
 		if err != nil {
 			return err
diff --git a/vendor/github.com/lucas-clemente/quic-go/server_tls.go b/vendor/github.com/lucas-clemente/quic-go/server_tls.go
index 38d7abb15..9f3874090 100644
--- a/vendor/github.com/lucas-clemente/quic-go/server_tls.go
+++ b/vendor/github.com/lucas-clemente/quic-go/server_tls.go
@@ -21,9 +21,12 @@ type nullAEAD struct {
 
 var _ quicAEAD = &nullAEAD{}
 
-func (n *nullAEAD) Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error) {
-	data, err := n.aead.Open(dst, src, packetNumber, associatedData)
-	return data, protocol.EncryptionUnencrypted, err
+func (n *nullAEAD) OpenHandshake(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) {
+	return n.aead.Open(dst, src, packetNumber, associatedData)
+}
+
+func (n *nullAEAD) Open1RTT(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, error) {
+	return nil, errors.New("no 1-RTT keys")
 }
 
 type tlsSession struct {
@@ -40,6 +43,8 @@ type serverTLS struct {
 	newMintConn       func(*handshake.CryptoStreamConn, protocol.VersionNumber) (handshake.MintTLS, <-chan handshake.TransportParameters, error)
 
 	sessionChan chan<- tlsSession
+
+	logger utils.Logger
 }
 
 func newServerTLS(
@@ -47,6 +52,7 @@ func newServerTLS(
 	config *Config,
 	cookieHandler *handshake.CookieHandler,
 	tlsConf *tls.Config,
+	logger utils.Logger,
 ) (*serverTLS, <-chan tlsSession, error) {
 	mconf, err := tlsToMintConfig(tlsConf, protocol.PerspectiveServer)
 	if err != nil {
@@ -74,16 +80,17 @@ func newServerTLS(
 			MaxBidiStreams:              uint16(config.MaxIncomingStreams),
 			MaxUniStreams:               uint16(config.MaxIncomingUniStreams),
 		},
+		logger: logger,
 	}
 	s.newMintConn = s.newMintConnImpl
 	return s, sessionChan, nil
 }
 
 func (s *serverTLS) HandleInitial(remoteAddr net.Addr, hdr *wire.Header, data []byte) {
-	utils.Debugf("Received a Packet. Handling it statelessly.")
+	s.logger.Debugf("Received a Packet. Handling it statelessly.")
 	sess, err := s.handleInitialImpl(remoteAddr, hdr, data)
 	if err != nil {
-		utils.Errorf("Error occurred handling initial packet: %s", err)
+		s.logger.Errorf("Error occurred handling initial packet: %s", err)
 		return
 	}
 	if sess == nil { // a stateless reset was done
@@ -97,7 +104,7 @@ func (s *serverTLS) HandleInitial(remoteAddr net.Addr, hdr *wire.Header, data []
 
 // will be set to s.newMintConn by the constructor
 func (s *serverTLS) newMintConnImpl(bc *handshake.CryptoStreamConn, v protocol.VersionNumber) (handshake.MintTLS, <-chan handshake.TransportParameters, error) {
-	extHandler := handshake.NewExtensionHandlerServer(s.params, s.config.Versions, v)
+	extHandler := handshake.NewExtensionHandlerServer(s.params, s.config.Versions, v, s.logger)
 	conf := s.mintConf.Clone()
 	conf.ExtensionHandler = extHandler
 	return newMintController(bc, conf, protocol.PerspectiveServer), extHandler.GetPeerParams(), nil
@@ -115,7 +122,7 @@ func (s *serverTLS) sendConnectionClose(remoteAddr net.Addr, clientHdr *wire.Hea
 		PacketNumber: 1,                      // random packet number
 		Version:      clientHdr.Version,
 	}
-	data, err := packUnencryptedPacket(aead, replyHdr, ccf, protocol.PerspectiveServer)
+	data, err := packUnencryptedPacket(aead, replyHdr, ccf, protocol.PerspectiveServer, s.logger)
 	if err != nil {
 		return err
 	}
@@ -129,7 +136,7 @@ func (s *serverTLS) handleInitialImpl(remoteAddr net.Addr, hdr *wire.Header, dat
 	}
 	// check version, if not matching send VNP
 	if !protocol.IsSupportedVersion(s.supportedVersions, hdr.Version) {
-		utils.Debugf("Client offered version %s, sending VersionNegotiationPacket", hdr.Version)
+		s.logger.Debugf("Client offered version %s, sending VersionNegotiationPacket", hdr.Version)
 		_, err := s.conn.WriteTo(wire.ComposeVersionNegotiation(hdr.ConnectionID, s.supportedVersions), remoteAddr)
 		return nil, err
 	}
@@ -139,15 +146,15 @@ func (s *serverTLS) handleInitialImpl(remoteAddr net.Addr, hdr *wire.Header, dat
 	if err != nil {
 		return nil, err
 	}
-	frame, err := unpackInitialPacket(aead, hdr, data, hdr.Version)
+	frame, err := unpackInitialPacket(aead, hdr, data, s.logger, hdr.Version)
 	if err != nil {
-		utils.Debugf("Error unpacking initial packet: %s", err)
+		s.logger.Debugf("Error unpacking initial packet: %s", err)
 		return nil, nil
 	}
 	sess, err := s.handleUnpackedInitial(remoteAddr, hdr, frame, aead)
 	if err != nil {
 		if ccerr := s.sendConnectionClose(remoteAddr, hdr, aead, err); ccerr != nil {
-			utils.Debugf("Error sending CONNECTION_CLOSE: %s", ccerr)
+			s.logger.Debugf("Error sending CONNECTION_CLOSE: %s", ccerr)
 		}
 		return nil, err
 	}
@@ -177,7 +184,7 @@ func (s *serverTLS) handleUnpackedInitial(remoteAddr net.Addr, hdr *wire.Header,
 			StreamID: version.CryptoStreamID(),
 			Data:     bc.GetDataForWriting(),
 		}
-		data, err := packUnencryptedPacket(aead, replyHdr, f, protocol.PerspectiveServer)
+		data, err := packUnencryptedPacket(aead, replyHdr, f, protocol.PerspectiveServer, s.logger)
 		if err != nil {
 			return nil, err
 		}
@@ -207,6 +214,7 @@ func (s *serverTLS) handleUnpackedInitial(remoteAddr net.Addr, hdr *wire.Header,
 		aead,
 		&params,
 		version,
+		s.logger,
 	)
 	if err != nil {
 		return nil, err
diff --git a/vendor/github.com/lucas-clemente/quic-go/session.go b/vendor/github.com/lucas-clemente/quic-go/session.go
index 622b668e1..ed73637ce 100644
--- a/vendor/github.com/lucas-clemente/quic-go/session.go
+++ b/vendor/github.com/lucas-clemente/quic-go/session.go
@@ -2,6 +2,7 @@ package quic
 
 import (
 	"context"
+	"crypto/rand"
 	"crypto/tls"
 	"errors"
 	"fmt"
@@ -44,6 +45,11 @@ type streamManager interface {
 	CloseWithError(error)
 }
 
+type cryptoStreamHandler interface {
+	HandleCryptoStream() error
+	ConnectionState() handshake.ConnectionState
+}
+
 type receivedPacket struct {
 	remoteAddr net.Addr
 	header     *wire.Header
@@ -84,7 +90,8 @@ type session struct {
 	unpacker unpacker
 	packer   *packetPacker
 
-	cryptoSetup handshake.CryptoSetup
+	cryptoStreamHandler cryptoStreamHandler
+	divNonceChan        chan<- []byte // only set for the client
 
 	receivedPackets  chan *receivedPacket
 	sendingScheduled chan struct{}
@@ -129,6 +136,8 @@ type session struct {
 	// keepAlivePingSent stores whether a Ping frame was sent to the peer or not
 	// it is reset as soon as we receive a packet from the peer
 	keepAlivePingSent bool
+
+	logger utils.Logger
 }
 
 var _ Session = &session{}
@@ -142,6 +151,7 @@ func newSession(
 	scfg *handshake.ServerConfig,
 	tlsConf *tls.Config,
 	config *Config,
+	logger utils.Logger,
 ) (packetHandler, error) {
 	paramsChan := make(chan handshake.TransportParameters)
 	handshakeEvent := make(chan struct{}, 1)
@@ -153,6 +163,7 @@ func newSession(
 		config:         config,
 		handshakeEvent: handshakeEvent,
 		paramsChan:     paramsChan,
+		logger:         logger,
 	}
 	s.preSetup()
 	transportParams := &handshake.TransportParameters{
@@ -161,23 +172,42 @@ func newSession(
 		MaxStreams:                  uint32(s.config.MaxIncomingStreams),
 		IdleTimeout:                 s.config.IdleTimeout,
 	}
+	divNonce := make([]byte, 32)
+	if _, err := rand.Read(divNonce); err != nil {
+		return nil, err
+	}
 	cs, err := newCryptoSetup(
 		s.cryptoStream,
 		s.connectionID,
 		s.conn.RemoteAddr(),
 		s.version,
+		divNonce,
 		scfg,
 		transportParams,
 		s.config.Versions,
 		s.config.AcceptCookie,
 		paramsChan,
 		handshakeEvent,
+		s.logger,
 	)
 	if err != nil {
 		return nil, err
 	}
-	s.cryptoSetup = cs
-	return s, s.postSetup(1)
+	s.cryptoStreamHandler = cs
+	s.unpacker = newPacketUnpackerGQUIC(cs, s.version)
+	s.streamsMap = newStreamsMapLegacy(s.newStream, s.config.MaxIncomingStreams, s.perspective)
+	s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version)
+	s.packer = newPacketPacker(s.connectionID,
+		1,
+		s.sentPacketHandler.GetPacketNumberLen,
+		s.RemoteAddr(),
+		divNonce,
+		cs,
+		s.streamFramer,
+		s.perspective,
+		s.version,
+	)
+	return s, s.postSetup()
 }
 
 // declare this as a variable, so that we can it mock it in the tests
@@ -190,6 +220,7 @@ var newClientSession = func(
 	config *Config,
 	initialVersion protocol.VersionNumber,
 	negotiatedVersions []protocol.VersionNumber, // needed for validation of the GQUIC version negotiation
+	logger utils.Logger,
 ) (packetHandler, error) {
 	paramsChan := make(chan handshake.TransportParameters)
 	handshakeEvent := make(chan struct{}, 1)
@@ -201,6 +232,7 @@ var newClientSession = func(
 		config:         config,
 		handshakeEvent: handshakeEvent,
 		paramsChan:     paramsChan,
+		logger:         logger,
 	}
 	s.preSetup()
 	transportParams := &handshake.TransportParameters{
@@ -210,7 +242,7 @@ var newClientSession = func(
 		IdleTimeout:                 s.config.IdleTimeout,
 		OmitConnectionID:            s.config.RequestConnectionIDOmission,
 	}
-	cs, err := newCryptoSetupClient(
+	cs, divNonceChan, err := newCryptoSetupClient(
 		s.cryptoStream,
 		hostname,
 		s.connectionID,
@@ -221,12 +253,27 @@ var newClientSession = func(
 		handshakeEvent,
 		initialVersion,
 		negotiatedVersions,
+		s.logger,
 	)
 	if err != nil {
 		return nil, err
 	}
-	s.cryptoSetup = cs
-	return s, s.postSetup(1)
+	s.cryptoStreamHandler = cs
+	s.divNonceChan = divNonceChan
+	s.unpacker = newPacketUnpackerGQUIC(cs, s.version)
+	s.streamsMap = newStreamsMapLegacy(s.newStream, s.config.MaxIncomingStreams, s.perspective)
+	s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version)
+	s.packer = newPacketPacker(s.connectionID,
+		1,
+		s.sentPacketHandler.GetPacketNumberLen,
+		s.RemoteAddr(),
+		nil, // no diversification nonce
+		cs,
+		s.streamFramer,
+		s.perspective,
+		s.version,
+	)
+	return s, s.postSetup()
 }
 
 func newTLSServerSession(
@@ -239,6 +286,7 @@ func newTLSServerSession(
 	nullAEAD crypto.AEAD,
 	peerParams *handshake.TransportParameters,
 	v protocol.VersionNumber,
+	logger utils.Logger,
 ) (packetHandler, error) {
 	handshakeEvent := make(chan struct{}, 1)
 	s := &session{
@@ -248,21 +296,35 @@ func newTLSServerSession(
 		perspective:    protocol.PerspectiveServer,
 		version:        v,
 		handshakeEvent: handshakeEvent,
+		logger:         logger,
 	}
 	s.preSetup()
-	s.cryptoSetup = handshake.NewCryptoSetupTLSServer(
+	cs := handshake.NewCryptoSetupTLSServer(
 		tls,
 		cryptoStreamConn,
 		nullAEAD,
 		handshakeEvent,
 		v,
 	)
-	if err := s.postSetup(initialPacketNumber); err != nil {
+	s.cryptoStreamHandler = cs
+	s.streamsMap = newStreamsMap(s, s.newFlowController, s.config.MaxIncomingStreams, s.config.MaxIncomingUniStreams, s.perspective, s.version)
+	s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version)
+	s.packer = newPacketPacker(s.connectionID,
+		initialPacketNumber,
+		s.sentPacketHandler.GetPacketNumberLen,
+		s.RemoteAddr(),
+		nil, // no diversification nonce
+		cs,
+		s.streamFramer,
+		s.perspective,
+		s.version,
+	)
+	if err := s.postSetup(); err != nil {
 		return nil, err
 	}
 	s.peerParams = peerParams
 	s.processTransportParameters(peerParams)
-	s.unpacker = &packetUnpacker{aead: s.cryptoSetup, version: s.version}
+	s.unpacker = newPacketUnpacker(cs, s.version)
 	return s, nil
 }
 
@@ -276,6 +338,7 @@ var newTLSClientSession = func(
 	tls handshake.MintTLS,
 	paramsChan <-chan handshake.TransportParameters,
 	initialPacketNumber protocol.PacketNumber,
+	logger utils.Logger,
 ) (packetHandler, error) {
 	handshakeEvent := make(chan struct{}, 1)
 	s := &session{
@@ -286,6 +349,7 @@ var newTLSClientSession = func(
 		version:        v,
 		handshakeEvent: handshakeEvent,
 		paramsChan:     paramsChan,
+		logger:         logger,
 	}
 	s.preSetup()
 	tls.SetCryptoStream(s.cryptoStream)
@@ -300,21 +364,36 @@ var newTLSClientSession = func(
 	if err != nil {
 		return nil, err
 	}
-	s.cryptoSetup = cs
-	return s, s.postSetup(initialPacketNumber)
+	s.cryptoStreamHandler = cs
+	s.unpacker = newPacketUnpacker(cs, s.version)
+	s.streamsMap = newStreamsMap(s, s.newFlowController, s.config.MaxIncomingStreams, s.config.MaxIncomingUniStreams, s.perspective, s.version)
+	s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version)
+	s.packer = newPacketPacker(s.connectionID,
+		initialPacketNumber,
+		s.sentPacketHandler.GetPacketNumberLen,
+		s.RemoteAddr(),
+		nil, // no diversification nonce
+		cs,
+		s.streamFramer,
+		s.perspective,
+		s.version,
+	)
+	return s, s.postSetup()
 }
 
 func (s *session) preSetup() {
 	s.rttStats = &congestion.RTTStats{}
+	s.sentPacketHandler = ackhandler.NewSentPacketHandler(s.rttStats, s.logger)
 	s.connFlowController = flowcontrol.NewConnectionFlowController(
 		protocol.ReceiveConnectionFlowControlWindow,
 		protocol.ByteCount(s.config.MaxReceiveConnectionFlowControlWindow),
 		s.rttStats,
+		s.logger,
 	)
 	s.cryptoStream = s.newCryptoStream()
 }
 
-func (s *session) postSetup(initialPacketNumber protocol.PacketNumber) error {
+func (s *session) postSetup() error {
 	s.handshakeChan = make(chan error, 1)
 	s.receivedPackets = make(chan *receivedPacket, protocol.MaxSessionUnprocessedPackets)
 	s.closeChan = make(chan closeError, 1)
@@ -327,26 +406,8 @@ func (s *session) postSetup(initialPacketNumber protocol.PacketNumber) error {
 	s.lastNetworkActivityTime = now
 	s.sessionCreationTime = now
 
-	s.sentPacketHandler = ackhandler.NewSentPacketHandler(s.rttStats)
 	s.receivedPacketHandler = ackhandler.NewReceivedPacketHandler(s.rttStats, s.version)
-
-	if s.version.UsesTLS() {
-		s.streamsMap = newStreamsMap(s, s.newFlowController, s.config.MaxIncomingStreams, s.config.MaxIncomingUniStreams, s.perspective, s.version)
-	} else {
-		s.streamsMap = newStreamsMapLegacy(s.newStream, s.config.MaxIncomingStreams, s.perspective)
-	}
-	s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version)
-	s.packer = newPacketPacker(s.connectionID,
-		initialPacketNumber,
-		s.sentPacketHandler.GetPacketNumberLen,
-		s.RemoteAddr(),
-		s.cryptoSetup,
-		s.streamFramer,
-		s.perspective,
-		s.version,
-	)
 	s.windowUpdateQueue = newWindowUpdateQueue(s.streamsMap, s.cryptoStream, s.packer.QueueControlFrame)
-	s.unpacker = &packetUnpacker{aead: s.cryptoSetup, version: s.version}
 	return nil
 }
 
@@ -355,13 +416,12 @@ func (s *session) run() error {
 	defer s.ctxCancel()
 
 	go func() {
-		if err := s.cryptoSetup.HandleCryptoStream(); err != nil {
+		if err := s.cryptoStreamHandler.HandleCryptoStream(); err != nil {
 			s.Close(err)
 		}
 	}()
 
 	var closeErr closeError
-	handshakeEvent := s.handshakeEvent
 
 runLoop:
 	for {
@@ -370,6 +430,9 @@ runLoop:
 		select {
 		case closeErr = <-s.closeChan:
 			break runLoop
+		case _, ok := <-s.handshakeEvent:
+			// when the handshake is completed, the channel will be closed
+			s.handleHandshakeEvent(!ok)
 		default:
 		}
 
@@ -400,20 +463,9 @@ runLoop:
 			putPacketBuffer(&p.header.Raw)
 		case p := <-s.paramsChan:
 			s.processTransportParameters(&p)
-		case _, ok := <-handshakeEvent:
-			if !ok { // the aeadChanged chan was closed. This means that the handshake is completed.
-				s.handshakeComplete = true
-				handshakeEvent = nil // prevent this case from ever being selected again
-				if !s.version.UsesTLS() && s.perspective == protocol.PerspectiveClient {
-					// In gQUIC, there's no equivalent to the Finished message in TLS
-					// The server knows that the handshake is complete when it receives the first forward-secure packet sent by the client.
-					// We need to make sure that the client actually sends such a packet.
-					s.packer.QueueControlFrame(&wire.PingFrame{})
-				}
-				close(s.handshakeChan)
-			} else {
-				s.tryDecryptingQueuedPackets()
-			}
+		case _, ok := <-s.handshakeEvent:
+			// when the handshake is completed, the channel will be closed
+			s.handleHandshakeEvent(!ok)
 		}
 
 		now := time.Now()
@@ -470,7 +522,7 @@ func (s *session) Context() context.Context {
 }
 
 func (s *session) ConnectionState() ConnectionState {
-	return s.cryptoSetup.ConnectionState()
+	return s.cryptoStreamHandler.ConnectionState()
 }
 
 func (s *session) maybeResetTimer() {
@@ -501,11 +553,27 @@ func (s *session) maybeResetTimer() {
 	s.timer.Reset(deadline)
 }
 
+func (s *session) handleHandshakeEvent(completed bool) {
+	if !completed {
+		s.tryDecryptingQueuedPackets()
+		return
+	}
+	s.handshakeComplete = true
+	s.handshakeEvent = nil // prevent this case from ever being selected again
+	if !s.version.UsesTLS() && s.perspective == protocol.PerspectiveClient {
+		// In gQUIC, there's no equivalent to the Finished message in TLS
+		// The server knows that the handshake is complete when it receives the first forward-secure packet sent by the client.
+		// We need to make sure that the client actually sends such a packet.
+		s.packer.QueueControlFrame(&wire.PingFrame{})
+		s.scheduleSending()
+	}
+	close(s.handshakeChan)
+}
+
 func (s *session) handlePacketImpl(p *receivedPacket) error {
 	if s.perspective == protocol.PerspectiveClient {
-		diversificationNonce := p.header.DiversificationNonce
-		if len(diversificationNonce) > 0 {
-			s.cryptoSetup.SetDiversificationNonce(diversificationNonce)
+		if divNonce := p.header.DiversificationNonce; len(divNonce) > 0 {
+			s.divNonceChan <- divNonce
 		}
 	}
 
@@ -528,13 +596,13 @@ func (s *session) handlePacketImpl(p *receivedPacket) error {
 	)
 
 	packet, err := s.unpacker.Unpack(hdr.Raw, hdr, data)
-	if utils.Debug() {
+	if s.logger.Debug() {
 		if err != nil {
-			utils.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID)
+			s.logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID)
 		} else {
-			utils.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x, %s", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID, packet.encryptionLevel)
+			s.logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %x, %s", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.ConnectionID, packet.encryptionLevel)
 		}
-		hdr.Log()
+		hdr.Log(s.logger)
 	}
 	// if the decryption failed, this might be a packet sent by an attacker
 	if err != nil {
@@ -569,10 +637,10 @@ func (s *session) handlePacketImpl(p *receivedPacket) error {
 func (s *session) handleFrames(fs []wire.Frame, encLevel protocol.EncryptionLevel) error {
 	for _, ff := range fs {
 		var err error
-		wire.LogFrame(ff, false)
+		wire.LogFrame(s.logger, ff, false)
 		switch frame := ff.(type) {
 		case *wire.StreamFrame:
-			err = s.handleStreamFrame(frame)
+			err = s.handleStreamFrame(frame, encLevel)
 		case *wire.AckFrame:
 			err = s.handleAckFrame(frame, encLevel)
 		case *wire.ConnectionCloseFrame:
@@ -615,12 +683,14 @@ func (s *session) handlePacket(p *receivedPacket) {
 	}
 }
 
-func (s *session) handleStreamFrame(frame *wire.StreamFrame) error {
+func (s *session) handleStreamFrame(frame *wire.StreamFrame, encLevel protocol.EncryptionLevel) error {
 	if frame.StreamID == s.version.CryptoStreamID() {
 		if frame.FinBit {
 			return errors.New("Received STREAM frame with FIN bit for the crypto stream")
 		}
 		return s.cryptoStream.handleStreamFrame(frame)
+	} else if encLevel <= protocol.EncryptionUnencrypted {
+		return qerr.Error(qerr.UnencryptedStreamData, fmt.Sprintf("received unencrypted stream data on stream %d", frame.StreamID))
 	}
 	str, err := s.streamsMap.GetOrOpenReceiveStream(frame.StreamID)
 	if err != nil {
@@ -730,9 +800,9 @@ func (s *session) handleCloseError(closeErr closeError) error {
 	}
 	// Don't log 'normal' reasons
 	if quicErr.ErrorCode == qerr.PeerGoingAway || quicErr.ErrorCode == qerr.NetworkIdleTimeout {
-		utils.Infof("Closing connection %x", s.connectionID)
+		s.logger.Infof("Closing connection %x", s.connectionID)
 	} else {
-		utils.Errorf("Closing session with error: %s", closeErr.err.Error())
+		s.logger.Errorf("Closing session with error: %s", closeErr.err.Error())
 	}
 
 	s.cryptoStream.closeForShutdown(quicErr)
@@ -789,6 +859,25 @@ sendLoop:
 			// There will only be a new ACK after receiving new packets.
 			// SendAck is only returned when we're congestion limited, so we don't need to set the pacingt timer.
 			return s.maybeSendAckOnlyPacket()
+		case ackhandler.SendRTO:
+			// try to send a retransmission first
+			sentPacket, err := s.maybeSendRetransmission()
+			if err != nil {
+				return err
+			}
+			if !sentPacket {
+				// In RTO mode, a probe packet has to be sent.
+				// Add a PING frame to make sure a (retransmittable) packet will be sent.
+				s.queueControlFrame(&wire.PingFrame{})
+				sentPacket, err := s.sendPacket()
+				if err != nil {
+					return err
+				}
+				if !sentPacket {
+					return errors.New("session BUG: expected a packet to be sent in RTO mode")
+				}
+			}
+			numPacketsSent++
 		case ackhandler.SendRetransmission:
 			sentPacket, err := s.maybeSendRetransmission()
 			if err != nil {
@@ -858,16 +947,16 @@ func (s *session) maybeSendRetransmission() (bool, error) {
 		// An Initial might have been retransmitted multiple times before we receive a response.
 		// As soon as we receive one response, we don't need to send any more Initials.
 		if s.receivedFirstPacket && retransmitPacket.PacketType == protocol.PacketTypeInitial {
-			utils.Debugf("Skipping retransmission of packet %d. Already received a response to an Initial.", retransmitPacket.PacketNumber)
+			s.logger.Debugf("Skipping retransmission of packet %d. Already received a response to an Initial.", retransmitPacket.PacketNumber)
 			continue
 		}
 		break
 	}
 
 	if retransmitPacket.EncryptionLevel != protocol.EncryptionForwardSecure {
-		utils.Debugf("\tDequeueing handshake retransmission for packet 0x%x", retransmitPacket.PacketNumber)
+		s.logger.Debugf("\tDequeueing handshake retransmission for packet 0x%x", retransmitPacket.PacketNumber)
 	} else {
-		utils.Debugf("\tDequeueing retransmission for packet 0x%x", retransmitPacket.PacketNumber)
+		s.logger.Debugf("\tDequeueing retransmission for packet 0x%x", retransmitPacket.PacketNumber)
 	}
 
 	if s.version.UsesStopWaitingFrames() {
@@ -938,14 +1027,14 @@ func (s *session) sendConnectionClose(quicErr *qerr.QuicError) error {
 }
 
 func (s *session) logPacket(packet *packedPacket) {
-	if !utils.Debug() {
+	if !s.logger.Debug() {
 		// We don't need to allocate the slices for calling the format functions
 		return
 	}
-	utils.Debugf("-> Sending packet 0x%x (%d bytes) for connection %x, %s", packet.header.PacketNumber, len(packet.raw), s.connectionID, packet.encryptionLevel)
-	packet.header.Log()
+	s.logger.Debugf("-> Sending packet 0x%x (%d bytes) for connection %x, %s", packet.header.PacketNumber, len(packet.raw), s.connectionID, packet.encryptionLevel)
+	packet.header.Log(s.logger)
 	for _, frame := range packet.frames {
-		wire.LogFrame(frame, true)
+		wire.LogFrame(s.logger, frame, true)
 	}
 }
 
@@ -1008,6 +1097,7 @@ func (s *session) newFlowController(id protocol.StreamID) flowcontrol.StreamFlow
 		protocol.ByteCount(s.config.MaxReceiveStreamFlowControlWindow),
 		initialSendWindow,
 		s.rttStats,
+		s.logger,
 	)
 }
 
@@ -1021,12 +1111,13 @@ func (s *session) newCryptoStream() cryptoStreamI {
 		protocol.ByteCount(s.config.MaxReceiveStreamFlowControlWindow),
 		0,
 		s.rttStats,
+		s.logger,
 	)
 	return newCryptoStream(s, flowController, s.version)
 }
 
 func (s *session) sendPublicReset(rejectedPacketNumber protocol.PacketNumber) error {
-	utils.Infof("Sending public reset for connection %x, packet number %d", s.connectionID, rejectedPacketNumber)
+	s.logger.Infof("Sending public reset for connection %x, packet number %d", s.connectionID, rejectedPacketNumber)
 	return s.conn.Write(wire.WritePublicReset(s.connectionID, rejectedPacketNumber, 0))
 }
 
@@ -1040,7 +1131,7 @@ func (s *session) scheduleSending() {
 
 func (s *session) tryQueueingUndecryptablePacket(p *receivedPacket) {
 	if s.handshakeComplete {
-		utils.Debugf("Received undecryptable packet from %s after the handshake: %#v, %d bytes data", p.remoteAddr.String(), p.header, len(p.data))
+		s.logger.Debugf("Received undecryptable packet from %s after the handshake: %#v, %d bytes data", p.remoteAddr.String(), p.header, len(p.data))
 		return
 	}
 	if len(s.undecryptablePackets)+1 > protocol.MaxUndecryptablePackets {
@@ -1049,10 +1140,10 @@ func (s *session) tryQueueingUndecryptablePacket(p *receivedPacket) {
 			s.receivedTooManyUndecrytablePacketsTime = time.Now()
 			s.maybeResetTimer()
 		}
-		utils.Infof("Dropping undecrytable packet 0x%x (undecryptable packet queue full)", p.header.PacketNumber)
+		s.logger.Infof("Dropping undecrytable packet 0x%x (undecryptable packet queue full)", p.header.PacketNumber)
 		return
 	}
-	utils.Infof("Queueing packet 0x%x for later decryption", p.header.PacketNumber)
+	s.logger.Infof("Queueing packet 0x%x for later decryption", p.header.PacketNumber)
 	s.undecryptablePackets = append(s.undecryptablePackets, p)
 }
 
diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_generic_helper.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_generic_helper.go
new file mode 100644
index 000000000..f48db212d
--- /dev/null
+++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_generic_helper.go
@@ -0,0 +1,11 @@
+package quic
+
+import "github.com/cheekybits/genny/generic"
+
+// In the auto-generated streams maps, we need to be able to close the streams.
+// Therefore, extend the generic.Type with the stream close method.
+// This definition must be in a file that Genny doesn't process.
+type item interface {
+	generic.Type
+	closeForShutdown(error)
+}
diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_bidi.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_bidi.go
index f7f80a280..317f5e237 100644
--- a/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_bidi.go
+++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_bidi.go
@@ -123,6 +123,9 @@ func (m *incomingBidiStreamsMap) DeleteStream(id protocol.StreamID) error {
 func (m *incomingBidiStreamsMap) CloseWithError(err error) {
 	m.mutex.Lock()
 	m.closeErr = err
+	for _, str := range m.streams {
+		str.closeForShutdown(err)
+	}
 	m.mutex.Unlock()
 	m.cond.Broadcast()
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_generic.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_generic.go
index 40d7b7500..58f1ccbe2 100644
--- a/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_generic.go
+++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_generic.go
@@ -121,6 +121,9 @@ func (m *incomingItemsMap) DeleteStream(id protocol.StreamID) error {
 func (m *incomingItemsMap) CloseWithError(err error) {
 	m.mutex.Lock()
 	m.closeErr = err
+	for _, str := range m.streams {
+		str.closeForShutdown(err)
+	}
 	m.mutex.Unlock()
 	m.cond.Broadcast()
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_uni.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_uni.go
index f9fe97b7e..8e775aac5 100644
--- a/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_uni.go
+++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_incoming_uni.go
@@ -123,6 +123,9 @@ func (m *incomingUniStreamsMap) DeleteStream(id protocol.StreamID) error {
 func (m *incomingUniStreamsMap) CloseWithError(err error) {
 	m.mutex.Lock()
 	m.closeErr = err
+	for _, str := range m.streams {
+		str.closeForShutdown(err)
+	}
 	m.mutex.Unlock()
 	m.cond.Broadcast()
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_bidi.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_bidi.go
index e7d9150be..ea9f47e60 100644
--- a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_bidi.go
+++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_bidi.go
@@ -118,6 +118,9 @@ func (m *outgoingBidiStreamsMap) SetMaxStream(id protocol.StreamID) {
 func (m *outgoingBidiStreamsMap) CloseWithError(err error) {
 	m.mutex.Lock()
 	m.closeErr = err
+	for _, str := range m.streams {
+		str.closeForShutdown(err)
+	}
 	m.cond.Broadcast()
 	m.mutex.Unlock()
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_generic.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_generic.go
index 80236c153..f4b3eb619 100644
--- a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_generic.go
+++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_generic.go
@@ -4,14 +4,11 @@ import (
 	"fmt"
 	"sync"
 
-	"github.com/cheekybits/genny/generic"
 	"github.com/lucas-clemente/quic-go/internal/protocol"
 	"github.com/lucas-clemente/quic-go/internal/wire"
 	"github.com/lucas-clemente/quic-go/qerr"
 )
 
-type item generic.Type
-
 //go:generate genny -in $GOFILE -out streams_map_outgoing_bidi.go gen "item=streamI Item=BidiStream"
 //go:generate genny -in $GOFILE -out streams_map_outgoing_uni.go gen "item=sendStreamI Item=UniStream"
 type outgoingItemsMap struct {
@@ -119,6 +116,9 @@ func (m *outgoingItemsMap) SetMaxStream(id protocol.StreamID) {
 func (m *outgoingItemsMap) CloseWithError(err error) {
 	m.mutex.Lock()
 	m.closeErr = err
+	for _, str := range m.streams {
+		str.closeForShutdown(err)
+	}
 	m.cond.Broadcast()
 	m.mutex.Unlock()
 }
diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_uni.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_uni.go
index fd2701b75..6ad0348c4 100644
--- a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_uni.go
+++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_uni.go
@@ -118,6 +118,9 @@ func (m *outgoingUniStreamsMap) SetMaxStream(id protocol.StreamID) {
 func (m *outgoingUniStreamsMap) CloseWithError(err error) {
 	m.mutex.Lock()
 	m.closeErr = err
+	for _, str := range m.streams {
+		str.closeForShutdown(err)
+	}
 	m.cond.Broadcast()
 	m.mutex.Unlock()
 }
diff --git a/vendor/github.com/xenolf/lego/acmev2/client.go b/vendor/github.com/xenolf/lego/acmev2/client.go
index 40acdbc14..3698f0eca 100644
--- a/vendor/github.com/xenolf/lego/acmev2/client.go
+++ b/vendor/github.com/xenolf/lego/acmev2/client.go
@@ -265,7 +265,7 @@ func (c *Client) QueryRegistration() (*RegistrationResource, error) {
 // your issued certificate as a bundle.
 // This function will never return a partial certificate. If one domain in the list fails,
 // the whole certificate will fail.
-func (c *Client) ObtainCertificateForCSR(csr x509.CertificateRequest, bundle bool) (CertificateResource, map[string]error) {
+func (c *Client) ObtainCertificateForCSR(csr x509.CertificateRequest, bundle bool) (CertificateResource, error) {
 	// figure out what domains it concerns
 	// start with the common name
 	domains := []string{csr.Subject.CommonName}
@@ -292,11 +292,7 @@ DNSNames:
 
 	order, err := c.createOrderForIdentifiers(domains)
 	if err != nil {
-		identErrors := make(map[string]error)
-		for _, auth := range order.Identifiers {
-			identErrors[auth.Value] = err
-		}
-		return CertificateResource{}, identErrors
+		return CertificateResource{}, err
 	}
 	authz, failures := c.getAuthzForOrder(order)
 	// If any challenge fails - return. Do not generate partial SAN certificates.
@@ -338,7 +334,11 @@ DNSNames:
 // your issued certificate as a bundle.
 // This function will never return a partial certificate. If one domain in the list fails,
 // the whole certificate will fail.
-func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto.PrivateKey, mustStaple bool) (CertificateResource, map[string]error) {
+func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto.PrivateKey, mustStaple bool) (CertificateResource, error) {
+	if len(domains) == 0 {
+		return CertificateResource{}, errors.New("Passed no domains into ObtainCertificate")
+	}
+
 	if bundle {
 		logf("[INFO][%s] acme: Obtaining bundled SAN certificate", strings.Join(domains, ", "))
 	} else {
@@ -347,11 +347,7 @@ func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto
 
 	order, err := c.createOrderForIdentifiers(domains)
 	if err != nil {
-		identErrors := make(map[string]error)
-		for _, auth := range order.Identifiers {
-			identErrors[auth.Value] = err
-		}
-		return CertificateResource{}, identErrors
+		return CertificateResource{}, err
 	}
 	authz, failures := c.getAuthzForOrder(order)
 	// If any challenge fails - return. Do not generate partial SAN certificates.
@@ -433,7 +429,7 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b
 			return CertificateResource{}, err
 		}
 		newCert, failures := c.ObtainCertificateForCSR(*csr, bundle)
-		return newCert, failures[cert.Domain]
+		return newCert, failures
 	}
 
 	var privKey crypto.PrivateKey
@@ -445,7 +441,6 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b
 	}
 
 	var domains []string
-	var failures map[string]error
 	// check for SAN certificate
 	if len(x509Cert.DNSNames) > 1 {
 		domains = append(domains, x509Cert.Subject.CommonName)
@@ -459,8 +454,8 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b
 		domains = append(domains, x509Cert.Subject.CommonName)
 	}
 
-	newCert, failures := c.ObtainCertificate(domains, bundle, privKey, mustStaple)
-	return newCert, failures[cert.Domain]
+	newCert, err := c.ObtainCertificate(domains, bundle, privKey, mustStaple)
+	return newCert, err
 }
 
 func (c *Client) createOrderForIdentifiers(domains []string) (orderResource, error) {
@@ -482,6 +477,7 @@ func (c *Client) createOrderForIdentifiers(domains []string) (orderResource, err
 
 	orderRes := orderResource{
 		URL:          hdr.Get("Location"),
+		Domains:      domains,
 		orderMessage: response,
 	}
 	return orderRes, nil
@@ -489,9 +485,9 @@ func (c *Client) createOrderForIdentifiers(domains []string) (orderResource, err
 
 // Looks through the challenge combinations to find a solvable match.
 // Then solves the challenges in series and returns.
-func (c *Client) solveChallengeForAuthz(authorizations []authorization) map[string]error {
+func (c *Client) solveChallengeForAuthz(authorizations []authorization) ObtainError {
 	// loop through the resources, basically through the domains.
-	failures := make(map[string]error)
+	failures := make(ObtainError)
 	for _, authz := range authorizations {
 		if authz.Status == "valid" {
 			// Boulder might recycle recent validated authz (see issue #267)
@@ -527,7 +523,7 @@ func (c *Client) chooseSolver(auth authorization, domain string) (int, solver) {
 }
 
 // Get the challenges needed to proof our identifier to the ACME server.
-func (c *Client) getAuthzForOrder(order orderResource) ([]authorization, map[string]error) {
+func (c *Client) getAuthzForOrder(order orderResource) ([]authorization, ObtainError) {
 	resc, errc := make(chan authorization), make(chan domainError)
 
 	delay := time.Second / overallRequestLimit
@@ -590,7 +586,7 @@ func (c *Client) requestCertificateForOrder(order orderResource, bundle bool, pr
 	}
 
 	// determine certificate name(s) based on the authorization resources
-	commonName := order.Identifiers[0].Value
+	commonName := order.Domains[0]
 	var san []string
 	for _, auth := range order.Identifiers {
 		san = append(san, auth.Value)
@@ -606,12 +602,7 @@ func (c *Client) requestCertificateForOrder(order orderResource, bundle bool, pr
 }
 
 func (c *Client) requestCertificateForCsr(order orderResource, bundle bool, csr []byte, privateKeyPem []byte) (CertificateResource, error) {
-	commonName := order.Identifiers[0].Value
-
-	var authURLs []string
-	for _, auth := range order.Identifiers[1:] {
-		authURLs = append(authURLs, auth.Value)
-	}
+	commonName := order.Domains[0]
 
 	csrString := base64.RawURLEncoding.EncodeToString(csr)
 	var retOrder orderMessage
diff --git a/vendor/github.com/xenolf/lego/acmev2/error.go b/vendor/github.com/xenolf/lego/acmev2/error.go
index 650270b1e..78694debe 100644
--- a/vendor/github.com/xenolf/lego/acmev2/error.go
+++ b/vendor/github.com/xenolf/lego/acmev2/error.go
@@ -1,6 +1,7 @@
 package acme
 
 import (
+	"bytes"
 	"encoding/json"
 	"fmt"
 	"io/ioutil"
@@ -42,6 +43,18 @@ type domainError struct {
 	Error  error
 }
 
+// ObtainError is returned when there are specific errors available
+// per domain. For example in ObtainCertificate
+type ObtainError map[string]error
+
+func (e ObtainError) Error() string {
+	buffer := bytes.NewBufferString("acme: Error -> One or more domains had a problem:\n")
+	for dom, err := range e {
+		buffer.WriteString(fmt.Sprintf("[%s] %s\n", dom, err))
+	}
+	return buffer.String()
+}
+
 func handleHTTPError(resp *http.Response) error {
 	var errorDetail RemoteError
 
diff --git a/vendor/github.com/xenolf/lego/acmev2/messages.go b/vendor/github.com/xenolf/lego/acmev2/messages.go
index 9981851d9..0b7344372 100644
--- a/vendor/github.com/xenolf/lego/acmev2/messages.go
+++ b/vendor/github.com/xenolf/lego/acmev2/messages.go
@@ -34,7 +34,8 @@ type accountMessage struct {
 }
 
 type orderResource struct {
-	URL          string `json:"url,omitempty"`
+	URL          string   `json:"url,omitempty"`
+	Domains      []string `json:"domains,omitempty"`
 	orderMessage `json:"body,omitempty"`
 }
 
diff --git a/vendor/manifest b/vendor/manifest
index 95306189a..b106ecf28 100644
--- a/vendor/manifest
+++ b/vendor/manifest
@@ -129,7 +129,7 @@
 			"importpath": "github.com/lucas-clemente/aes12",
 			"repository": "https://github.com/lucas-clemente/aes12",
 			"vcs": "git",
-			"revision": "25700e67be5c860bcc999137275b9ef8b65932bd",
+			"revision": "cd47fb39b79f867c6e4e5cd39cf7abd799f71670",
 			"branch": "master",
 			"notests": true
 		},
@@ -145,7 +145,7 @@
 			"importpath": "github.com/lucas-clemente/quic-go",
 			"repository": "https://github.com/lucas-clemente/quic-go",
 			"vcs": "git",
-			"revision": "9fa739409e6edddbbd47c8031cb7bb3d1a209cc8",
+			"revision": "da7708e47066ab0aff0f20f66b21c1f329db1eff",
 			"branch": "master",
 			"notests": true
 		},
@@ -193,7 +193,7 @@
 			"importpath": "github.com/xenolf/lego/acmev2",
 			"repository": "https://github.com/xenolf/lego",
 			"vcs": "git",
-			"revision": "805eec97569ff533e1b75b16eac0bdd94e67bdd6",
+			"revision": "6e962fbfb37f9ea4a8201e32acb1b94ffb3b8398",
 			"branch": "acmev2",
 			"path": "/acmev2",
 			"notests": true