Browse Source

Update quic-go

- Use DialContext for more effective
  dial cancellation
Rod Hynes 7 years ago
parent
commit
4e83c59998

+ 27 - 25
psiphon/common/quic/quic.go

@@ -125,7 +125,7 @@ func (listener *Listener) Accept() (net.Conn, error) {
 //
 // packetConn is used as the underlying packet connection for QUIC. The dial
 // may be cancelled by ctx; packetConn will be closed if the dial is
-// cancelled.
+// cancelled or fails.
 //
 // Keep alive and idle timeout functionality in QUIC is disabled as these
 // aspects are expected to be handled at a higher level.
@@ -135,6 +135,29 @@ func Dial(
 	remoteAddr *net.UDPAddr,
 	quicSNIAddress string) (net.Conn, error) {
 
+	quicConfig := &quic_go.Config{
+		HandshakeTimeout: time.Duration(1<<63 - 1),
+		IdleTimeout:      CLIENT_IDLE_TIMEOUT,
+		KeepAlive:        true,
+	}
+
+	deadline, ok := ctx.Deadline()
+	if ok {
+		quicConfig.HandshakeTimeout = deadline.Sub(time.Now())
+	}
+
+	session, err := quic_go.DialContext(
+		ctx,
+		packetConn,
+		remoteAddr,
+		quicSNIAddress,
+		&tls.Config{InsecureSkipVerify: true},
+		quicConfig)
+	if err != nil {
+		packetConn.Close()
+		return nil, common.ContextError(err)
+	}
+
 	type dialResult struct {
 		conn *Conn
 		err  error
@@ -144,30 +167,9 @@ func Dial(
 
 	go func() {
 
-		quicConfig := &quic_go.Config{
-			HandshakeTimeout: time.Duration(1<<63 - 1),
-			IdleTimeout:      CLIENT_IDLE_TIMEOUT,
-			KeepAlive:        true,
-		}
-
-		deadline, ok := ctx.Deadline()
-		if ok {
-			quicConfig.HandshakeTimeout = deadline.Sub(time.Now())
-		}
-
-		session, err := quic_go.Dial(
-			packetConn,
-			remoteAddr,
-			quicSNIAddress,
-			&tls.Config{InsecureSkipVerify: true},
-			quicConfig)
-		if err != nil {
-			resultChannel <- dialResult{err: err}
-			return
-		}
-
 		stream, err := session.OpenStream()
 		if err != nil {
+			session.Close(nil)
 			resultChannel <- dialResult{err: err}
 			return
 		}
@@ -182,7 +184,6 @@ func Dial(
 	}()
 
 	var conn *Conn
-	var err error
 
 	select {
 	case result := <-resultChannel:
@@ -190,11 +191,12 @@ func Dial(
 	case <-ctx.Done():
 		err = ctx.Err()
 		// Interrupt the goroutine
-		packetConn.Close()
+		session.Close(nil)
 		<-resultChannel
 	}
 
 	if err != nil {
+		packetConn.Close()
 		return nil, common.ContextError(err)
 	}
 

+ 2 - 0
vendor/github.com/lucas-clemente/quic-go/Changelog.md

@@ -5,6 +5,8 @@
 - Add support for unidirectional streams (for IETF QUIC).
 - Add a `quic.Config` option for the maximum number of incoming streams.
 - Add support for QUIC 42 and 43.
+- Add dial functions that use a context.
+- Multiplex clients on a net.PacketConn, when using Dial(conn).
 
 ## v0.7.0 (2018-02-03)
 

+ 2 - 2
vendor/github.com/lucas-clemente/quic-go/appveyor.yml

@@ -14,8 +14,8 @@ clone_folder: c:\gopath\src\github.com\lucas-clemente\quic-go
 
 install:
   - rmdir c:\go /s /q
-  - appveyor DownloadFile https://storage.googleapis.com/golang/go1.10.2.windows-amd64.zip
-  - 7z x go1.10.2.windows-amd64.zip -y -oC:\ > NUL
+  - appveyor DownloadFile https://storage.googleapis.com/golang/go1.10.3.windows-amd64.zip
+  - 7z x go1.10.3.windows-amd64.zip -y -oC:\ > NUL
   - set PATH=%PATH%;%GOPATH%\bin\windows_%GOARCH%;%GOPATH%\bin
   - echo %PATH%
   - echo %GOPATH%

+ 140 - 69
vendor/github.com/lucas-clemente/quic-go/client.go

@@ -2,6 +2,7 @@ package quic
 
 import (
 	"bytes"
+	"context"
 	"crypto/tls"
 	"errors"
 	"fmt"
@@ -23,6 +24,8 @@ type client struct {
 	conn     connection
 	hostname string
 
+	receivedRetry bool
+
 	versionNegotiated                bool // has the server accepted our version
 	receivedVersionNegotiationPacket bool
 	negotiatedVersions               []protocol.VersionNumber // the list of versions from the version negotiation packet
@@ -39,11 +42,13 @@ type client struct {
 
 	handshakeChan chan struct{}
 
-	session packetHandler
+	session quicSession
 
 	logger utils.Logger
 }
 
+var _ packetHandler = &client{}
+
 var (
 	// make it possible to mock connection ID generation in the tests
 	generateConnectionID         = protocol.GenerateConnectionID
@@ -52,7 +57,22 @@ var (
 
 // DialAddr establishes a new QUIC connection to a server.
 // The hostname for SNI is taken from the given address.
-func DialAddr(addr string, tlsConf *tls.Config, config *Config) (Session, error) {
+func DialAddr(
+	addr string,
+	tlsConf *tls.Config,
+	config *Config,
+) (Session, error) {
+	return DialAddrContext(context.Background(), addr, tlsConf, config)
+}
+
+// DialAddrContext establishes a new QUIC connection to a server using the provided context.
+// The hostname for SNI is taken from the given address.
+func DialAddrContext(
+	ctx context.Context,
+	addr string,
+	tlsConf *tls.Config,
+	config *Config,
+) (Session, error) {
 	udpAddr, err := net.ResolveUDPAddr("udp", addr)
 	if err != nil {
 		return nil, err
@@ -61,7 +81,15 @@ func DialAddr(addr string, tlsConf *tls.Config, config *Config) (Session, error)
 	if err != nil {
 		return nil, err
 	}
-	return Dial(udpConn, udpAddr, addr, tlsConf, config)
+	c, err := newClient(udpConn, udpAddr, config, tlsConf, addr)
+	if err != nil {
+		return nil, err
+	}
+	go c.listen()
+	if err := c.dial(ctx); err != nil {
+		return nil, err
+	}
+	return c.session, nil
 }
 
 // Dial establishes a new QUIC connection to a server using a net.PacketConn.
@@ -73,6 +101,31 @@ func Dial(
 	tlsConf *tls.Config,
 	config *Config,
 ) (Session, error) {
+	return DialContext(context.Background(), pconn, remoteAddr, host, tlsConf, config)
+}
+
+// DialContext establishes a new QUIC connection to a server using a net.PacketConn using the provided context.
+// The host parameter is used for SNI.
+func DialContext(
+	ctx context.Context,
+	pconn net.PacketConn,
+	remoteAddr net.Addr,
+	host string,
+	tlsConf *tls.Config,
+	config *Config,
+) (Session, error) {
+	c, err := newClient(pconn, remoteAddr, config, tlsConf, host)
+	if err != nil {
+		return nil, err
+	}
+	getClientMultiplexer().Add(pconn, c.srcConnID, c)
+	if err := c.dial(ctx); err != nil {
+		return nil, err
+	}
+	return c.session, nil
+}
+
+func newClient(pconn net.PacketConn, remoteAddr net.Addr, config *Config, tlsConf *tls.Config, host string) (*client, error) {
 	clientConfig := populateClientConfig(config)
 	version := clientConfig.Versions[0]
 	srcConnID, err := generateConnectionID()
@@ -106,7 +159,7 @@ func Dial(
 			}
 		}
 	}
-	c := &client{
+	return &client{
 		conn:          &conn{pconn: pconn, currentAddr: remoteAddr},
 		srcConnID:     srcConnID,
 		destConnID:    destConnID,
@@ -116,14 +169,7 @@ func Dial(
 		version:       version,
 		handshakeChan: make(chan struct{}),
 		logger:        utils.DefaultLogger.WithPrefix("client"),
-	}
-
-	c.logger.Infof("Starting new connection to %s (%s -> %s), source connection ID %s, destination connection ID %s, version %s", hostname, c.conn.LocalAddr(), c.conn.RemoteAddr(), c.srcConnID, c.destConnID, c.version)
-
-	if err := c.dial(); err != nil {
-		return nil, err
-	}
-	return c.session, nil
+	}, nil
 }
 
 // populateClientConfig populates fields in the quic.Config with their default values, if none are set
@@ -180,28 +226,29 @@ func populateClientConfig(config *Config) *Config {
 	}
 }
 
-func (c *client) dial() error {
+func (c *client) dial(ctx context.Context) error {
+	c.logger.Infof("Starting new connection to %s (%s -> %s), source connection ID %s, destination connection ID %s, version %s", c.hostname, c.conn.LocalAddr(), c.conn.RemoteAddr(), c.srcConnID, c.destConnID, c.version)
+
 	var err error
 	if c.version.UsesTLS() {
-		err = c.dialTLS()
+		err = c.dialTLS(ctx)
 	} else {
-		err = c.dialGQUIC()
+		err = c.dialGQUIC(ctx)
 	}
 	if err == errCloseSessionForNewVersion {
-		return c.dial()
+		return c.dial(ctx)
 	}
 	return err
 }
 
-func (c *client) dialGQUIC() error {
+func (c *client) dialGQUIC(ctx context.Context) error {
 	if err := c.createNewGQUICSession(); err != nil {
 		return err
 	}
-	go c.listen()
-	return c.establishSecureConnection()
+	return c.establishSecureConnection(ctx)
 }
 
-func (c *client) dialTLS() error {
+func (c *client) dialTLS(ctx context.Context) error {
 	params := &handshake.TransportParameters{
 		StreamFlowControlWindow:     protocol.ReceiveStreamFlowControlWindow,
 		ConnectionFlowControlWindow: protocol.ReceiveConnectionFlowControlWindow,
@@ -223,16 +270,18 @@ func (c *client) dialTLS() error {
 	if err := c.createNewTLSSession(extHandler.GetPeerParams(), c.version); err != nil {
 		return err
 	}
-	go c.listen()
-	if err := c.establishSecureConnection(); err != nil {
+	if err := c.establishSecureConnection(ctx); err != nil {
 		if err != handshake.ErrCloseSessionForRetry {
 			return err
 		}
 		c.logger.Infof("Received a Retry packet. Recreating session.")
+		c.mutex.Lock()
+		c.receivedRetry = true
+		c.mutex.Unlock()
 		if err := c.createNewTLSSession(extHandler.GetPeerParams(), c.version); err != nil {
 			return err
 		}
-		if err := c.establishSecureConnection(); err != nil {
+		if err := c.establishSecureConnection(ctx); err != nil {
 			return err
 		}
 	}
@@ -245,7 +294,7 @@ func (c *client) dialTLS() error {
 // - handshake.ErrCloseSessionForRetry when the server performs a stateless retry (for IETF QUIC)
 // - any other error that might occur
 // - when the connection is secure (for gQUIC), or forward-secure (for IETF QUIC)
-func (c *client) establishSecureConnection() error {
+func (c *client) establishSecureConnection(ctx context.Context) error {
 	errorChan := make(chan error, 1)
 
 	go func() {
@@ -254,6 +303,10 @@ func (c *client) establishSecureConnection() error {
 	}()
 
 	select {
+	case <-ctx.Done():
+		// The session sending a PeerGoingAway error to the server.
+		c.session.Close(nil)
+		return ctx.Err()
 	case err := <-errorChan:
 		return err
 	case <-c.handshakeChan:
@@ -285,65 +338,79 @@ func (c *client) listen() {
 			}
 			break
 		}
-		if err := c.handlePacket(addr, data[:n]); err != nil {
-			c.logger.Errorf("error handling packet: %s", err.Error())
-		}
+		c.handleRead(addr, data[:n])
 	}
 }
 
-func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) error {
+func (c *client) handleRead(remoteAddr net.Addr, packet []byte) {
 	rcvTime := time.Now()
 
 	r := bytes.NewReader(packet)
 	hdr, err := wire.ParseHeaderSentByServer(r)
 	// drop the packet if we can't parse the header
 	if err != nil {
-		return fmt.Errorf("error parsing packet from %s: %s", remoteAddr.String(), err.Error())
-	}
-	// reject packets with truncated connection id if we didn't request truncation
-	if hdr.OmitConnectionID && !c.config.RequestConnectionIDOmission {
-		return errors.New("received packet with truncated connection ID, but didn't request truncation")
+		c.logger.Errorf("error handling packet: %s", err)
+		return
 	}
 	hdr.Raw = packet[:len(packet)-r.Len()]
 	packetData := packet[len(packet)-r.Len():]
+	c.handlePacket(&receivedPacket{
+		remoteAddr: remoteAddr,
+		header:     hdr,
+		data:       packetData,
+		rcvTime:    rcvTime,
+	})
+}
 
+func (c *client) handlePacket(p *receivedPacket) {
+	if err := c.handlePacketImpl(p); err != nil {
+		c.logger.Errorf("error handling packet: %s", err)
+	}
+}
+
+func (c *client) handlePacketImpl(p *receivedPacket) error {
 	c.mutex.Lock()
 	defer c.mutex.Unlock()
 
 	// handle Version Negotiation Packets
-	if hdr.IsVersionNegotiation {
+	if p.header.IsVersionNegotiation {
 		// ignore delayed / duplicated version negotiation packets
 		if c.receivedVersionNegotiationPacket || c.versionNegotiated {
 			return errors.New("received a delayed Version Negotiation Packet")
 		}
 
 		// version negotiation packets have no payload
-		if err := c.handleVersionNegotiationPacket(hdr); err != nil {
+		if err := c.handleVersionNegotiationPacket(p.header); err != nil {
 			c.session.Close(err)
 		}
 		return nil
 	}
 
-	if hdr.IsPublicHeader {
-		return c.handleGQUICPacket(hdr, r, packetData, remoteAddr, rcvTime)
+	if p.header.IsPublicHeader {
+		return c.handleGQUICPacket(p)
 	}
-	return c.handleIETFQUICPacket(hdr, packetData, remoteAddr, rcvTime)
+	return c.handleIETFQUICPacket(p)
 }
 
-func (c *client) handleIETFQUICPacket(hdr *wire.Header, packetData []byte, remoteAddr net.Addr, rcvTime time.Time) error {
+func (c *client) handleIETFQUICPacket(p *receivedPacket) error {
 	// reject packets with the wrong connection ID
-	if !hdr.DestConnectionID.Equal(c.srcConnID) {
-		return fmt.Errorf("received a packet with an unexpected connection ID (%s, expected %s)", hdr.DestConnectionID, c.srcConnID)
-	}
-	if hdr.IsLongHeader {
-		if hdr.Type != protocol.PacketTypeRetry && hdr.Type != protocol.PacketTypeHandshake {
-			return fmt.Errorf("Received unsupported packet type: %s", hdr.Type)
+	if !p.header.DestConnectionID.Equal(c.srcConnID) {
+		return fmt.Errorf("received a packet with an unexpected connection ID (%s, expected %s)", p.header.DestConnectionID, c.srcConnID)
+	}
+	if p.header.IsLongHeader {
+		switch p.header.Type {
+		case protocol.PacketTypeRetry:
+			if c.receivedRetry {
+				return nil
+			}
+		case protocol.PacketTypeHandshake:
+		default:
+			return fmt.Errorf("Received unsupported packet type: %s", p.header.Type)
 		}
-		c.logger.Debugf("len(packet data): %d, payloadLen: %d", len(packetData), hdr.PayloadLen)
-		if protocol.ByteCount(len(packetData)) < hdr.PayloadLen {
-			return fmt.Errorf("packet payload (%d bytes) is smaller than the expected payload length (%d bytes)", len(packetData), hdr.PayloadLen)
+		if protocol.ByteCount(len(p.data)) < p.header.PayloadLen {
+			return fmt.Errorf("packet payload (%d bytes) is smaller than the expected payload length (%d bytes)", len(p.data), p.header.PayloadLen)
 		}
-		packetData = packetData[:int(hdr.PayloadLen)]
+		p.data = p.data[:int(p.header.PayloadLen)]
 		// TODO(#1312): implement parsing of compound packets
 	}
 
@@ -353,29 +420,29 @@ func (c *client) handleIETFQUICPacket(hdr *wire.Header, packetData []byte, remot
 		c.versionNegotiated = true
 	}
 
-	c.session.handlePacket(&receivedPacket{
-		remoteAddr: remoteAddr,
-		header:     hdr,
-		data:       packetData,
-		rcvTime:    rcvTime,
-	})
+	c.session.handlePacket(p)
 	return nil
 }
 
-func (c *client) handleGQUICPacket(hdr *wire.Header, r *bytes.Reader, packetData []byte, remoteAddr net.Addr, rcvTime time.Time) error {
+func (c *client) handleGQUICPacket(p *receivedPacket) error {
+	connID := p.header.DestConnectionID
+	// reject packets with truncated connection id if we didn't request truncation
+	if !c.config.RequestConnectionIDOmission && connID.Len() == 0 {
+		return errors.New("received packet with truncated connection ID, but didn't request truncation")
+	}
 	// reject packets with the wrong connection ID
-	if !hdr.OmitConnectionID && !hdr.DestConnectionID.Equal(c.srcConnID) {
-		return fmt.Errorf("received a packet with an unexpected connection ID (%s, expected %s)", hdr.DestConnectionID, c.srcConnID)
+	if connID.Len() > 0 && !connID.Equal(c.srcConnID) {
+		return fmt.Errorf("received a packet with an unexpected connection ID (%s, expected %s)", connID, c.srcConnID)
 	}
 
-	if hdr.ResetFlag {
+	if p.header.ResetFlag {
 		cr := c.conn.RemoteAddr()
 		// 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.DestConnectionID.Equal(c.srcConnID) {
+		if cr.Network() != p.remoteAddr.Network() || cr.String() != p.remoteAddr.String() || !connID.Equal(c.srcConnID) {
 			return errors.New("Received a spoofed Public Reset")
 		}
-		pr, err := wire.ParsePublicReset(r)
+		pr, err := wire.ParsePublicReset(bytes.NewReader(p.data))
 		if err != nil {
 			return fmt.Errorf("Received a Public Reset. An error occurred parsing the packet: %s", err)
 		}
@@ -390,12 +457,7 @@ func (c *client) handleGQUICPacket(hdr *wire.Header, r *bytes.Reader, packetData
 		c.versionNegotiated = true
 	}
 
-	c.session.handlePacket(&receivedPacket{
-		remoteAddr: remoteAddr,
-		header:     hdr,
-		data:       packetData,
-		rcvTime:    rcvTime,
-	})
+	c.session.handlePacket(p)
 	return nil
 }
 
@@ -439,7 +501,7 @@ func (c *client) createNewGQUICSession() (err error) {
 	c.mutex.Lock()
 	defer c.mutex.Unlock()
 	runner := &runner{
-		onHandshakeCompleteImpl: func(_ packetHandler) { close(c.handshakeChan) },
+		onHandshakeCompleteImpl: func(_ Session) { close(c.handshakeChan) },
 		removeConnectionIDImpl:  func(protocol.ConnectionID) {},
 	}
 	c.session, err = newClientSession(
@@ -464,7 +526,7 @@ func (c *client) createNewTLSSession(
 	c.mutex.Lock()
 	defer c.mutex.Unlock()
 	runner := &runner{
-		onHandshakeCompleteImpl: func(_ packetHandler) { close(c.handshakeChan) },
+		onHandshakeCompleteImpl: func(_ Session) { close(c.handshakeChan) },
 		removeConnectionIDImpl:  func(protocol.ConnectionID) {},
 	}
 	c.session, err = newTLSClientSession(
@@ -482,3 +544,12 @@ func (c *client) createNewTLSSession(
 	)
 	return err
 }
+
+func (c *client) Close(err error) error {
+	c.mutex.Lock()
+	defer c.mutex.Unlock()
+	if c.session == nil {
+		return nil
+	}
+	return c.session.Close(err)
+}

+ 2 - 2
vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go

@@ -301,12 +301,12 @@ func (h *sentPacketHandler) maybeUpdateRTT(largestAcked protocol.PacketNumber, a
 
 func (h *sentPacketHandler) updateLossDetectionAlarm() {
 	// Cancel the alarm if no packets are outstanding
-	if h.packetHistory.Len() == 0 {
+	if !h.packetHistory.HasOutstandingPackets() {
 		h.alarm = time.Time{}
 		return
 	}
 
-	if !h.handshakeComplete {
+	if h.packetHistory.HasOutstandingHandshakePackets() {
 		h.alarm = h.lastSentHandshakePacketTime.Add(h.computeHandshakeTimeout())
 	} else if !h.lossTime.IsZero() {
 		// Early retransmit timer or time loss detection.

+ 41 - 0
vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_history.go

@@ -10,6 +10,9 @@ type sentPacketHistory struct {
 	packetList *PacketList
 	packetMap  map[protocol.PacketNumber]*PacketElement
 
+	numOutstandingPackets          int
+	numOutstandingHandshakePackets int
+
 	firstOutstanding *PacketElement
 }
 
@@ -30,6 +33,12 @@ func (h *sentPacketHistory) sentPacketImpl(p *Packet) *PacketElement {
 	if h.firstOutstanding == nil {
 		h.firstOutstanding = el
 	}
+	if p.canBeRetransmitted {
+		h.numOutstandingPackets++
+		if p.EncryptionLevel < protocol.EncryptionForwardSecure {
+			h.numOutstandingHandshakePackets++
+		}
+	}
 	return el
 }
 
@@ -92,6 +101,18 @@ func (h *sentPacketHistory) MarkCannotBeRetransmitted(pn protocol.PacketNumber)
 	if !ok {
 		return fmt.Errorf("sent packet history: packet %d not found", pn)
 	}
+	if el.Value.canBeRetransmitted {
+		h.numOutstandingPackets--
+		if h.numOutstandingPackets < 0 {
+			panic("numOutstandingHandshakePackets negative")
+		}
+		if el.Value.EncryptionLevel < protocol.EncryptionForwardSecure {
+			h.numOutstandingHandshakePackets--
+			if h.numOutstandingHandshakePackets < 0 {
+				panic("numOutstandingHandshakePackets negative")
+			}
+		}
+	}
 	el.Value.canBeRetransmitted = false
 	if el == h.firstOutstanding {
 		h.readjustFirstOutstanding()
@@ -121,7 +142,27 @@ func (h *sentPacketHistory) Remove(p protocol.PacketNumber) error {
 	if el == h.firstOutstanding {
 		h.readjustFirstOutstanding()
 	}
+	if el.Value.canBeRetransmitted {
+		h.numOutstandingPackets--
+		if h.numOutstandingPackets < 0 {
+			panic("numOutstandingHandshakePackets negative")
+		}
+		if el.Value.EncryptionLevel < protocol.EncryptionForwardSecure {
+			h.numOutstandingHandshakePackets--
+			if h.numOutstandingHandshakePackets < 0 {
+				panic("numOutstandingHandshakePackets negative")
+			}
+		}
+	}
 	h.packetList.Remove(el)
 	delete(h.packetMap, p)
 	return nil
 }
+
+func (h *sentPacketHistory) HasOutstandingPackets() bool {
+	return h.numOutstandingPackets > 0
+}
+
+func (h *sentPacketHistory) HasOutstandingHandshakePackets() bool {
+	return h.numOutstandingHandshakePackets > 0
+}

+ 3 - 0
vendor/github.com/lucas-clemente/quic-go/internal/protocol/server_parameters.go

@@ -151,3 +151,6 @@ const MinPacingDelay time.Duration = 100 * time.Microsecond
 // so we need to know this value in advance (or encode it into the connection ID).
 // TODO: make this configurable
 const ConnectionIDLen = 8
+
+// MinConnectionIDLenInitial is the minimum length of the destination connection ID on an Initial packet.
+const MinConnectionIDLenInitial = 8

+ 0 - 1
vendor/github.com/lucas-clemente/quic-go/internal/wire/header.go

@@ -18,7 +18,6 @@ type Header struct {
 
 	DestConnectionID protocol.ConnectionID
 	SrcConnectionID  protocol.ConnectionID
-	OmitConnectionID bool
 
 	PacketNumberLen protocol.PacketNumberLen
 	PacketNumber    protocol.PacketNumber

+ 12 - 19
vendor/github.com/lucas-clemente/quic-go/internal/wire/public_header.go

@@ -13,7 +13,6 @@ import (
 
 var (
 	errResetAndVersionFlagSet            = errors.New("PublicHeader: Reset Flag and Version Flag should not be set at the same time")
-	errReceivedOmittedConnectionID       = qerr.Error(qerr.InvalidPacketHeader, "receiving packets with omitted ConnectionID is not supported")
 	errInvalidConnectionID               = qerr.Error(qerr.InvalidPacketHeader, "connection ID cannot be 0")
 	errGetLengthNotForVersionNegotiation = errors.New("PublicHeader: GetLength cannot be called for VersionNegotiation packets")
 	errInvalidPacketNumberLen6           = errors.New("invalid packet number length: 6 bytes")
@@ -27,10 +26,10 @@ func (h *Header) writePublicHeader(b *bytes.Buffer, pers protocol.Perspective, _
 	if h.VersionFlag && h.ResetFlag {
 		return errResetAndVersionFlagSet
 	}
-	if !h.DestConnectionID.Equal(h.SrcConnectionID) {
-		return fmt.Errorf("PublicHeader: SrcConnectionID must be equal to DestConnectionID")
+	if h.SrcConnectionID.Len() != 0 {
+		return errors.New("PublicHeader: SrcConnectionID must not be set")
 	}
-	if len(h.DestConnectionID) != 8 {
+	if len(h.DestConnectionID) != 0 && len(h.DestConnectionID) != 8 {
 		return fmt.Errorf("PublicHeader: wrong length for Connection ID: %d (expected 8)", len(h.DestConnectionID))
 	}
 
@@ -41,7 +40,7 @@ func (h *Header) writePublicHeader(b *bytes.Buffer, pers protocol.Perspective, _
 	if h.ResetFlag {
 		publicFlagByte |= 0x02
 	}
-	if !h.OmitConnectionID {
+	if h.DestConnectionID.Len() > 0 {
 		publicFlagByte |= 0x08
 	}
 	if len(h.DiversificationNonce) > 0 {
@@ -63,7 +62,7 @@ func (h *Header) writePublicHeader(b *bytes.Buffer, pers protocol.Perspective, _
 	}
 	b.WriteByte(publicFlagByte)
 
-	if !h.OmitConnectionID {
+	if h.DestConnectionID.Len() > 0 {
 		b.Write(h.DestConnectionID)
 	}
 	if h.VersionFlag && pers == protocol.PerspectiveClient {
@@ -112,9 +111,9 @@ func parsePublicHeader(b *bytes.Reader, packetSentBy protocol.Perspective) (*Hea
 	// 	return nil, errors.New("diversification nonces should only be sent by servers")
 	// }
 
-	header.OmitConnectionID = publicFlagByte&0x08 == 0
-	if header.OmitConnectionID && packetSentBy == protocol.PerspectiveClient {
-		return nil, errReceivedOmittedConnectionID
+	hasConnectionID := publicFlagByte&0x08 > 0
+	if !hasConnectionID && packetSentBy == protocol.PerspectiveClient {
+		return nil, qerr.Error(qerr.InvalidPacketHeader, "receiving packets with omitted ConnectionID is not supported")
 	}
 	if header.hasPacketNumber(packetSentBy) {
 		switch publicFlagByte & 0x30 {
@@ -130,19 +129,15 @@ func parsePublicHeader(b *bytes.Reader, packetSentBy protocol.Perspective) (*Hea
 	}
 
 	// Connection ID
-	if !header.OmitConnectionID {
-		connID := make(protocol.ConnectionID, 8)
-		if _, err := io.ReadFull(b, connID); err != nil {
-			if err == io.ErrUnexpectedEOF {
-				err = io.EOF
-			}
+	if hasConnectionID {
+		connID, err := protocol.ReadConnectionID(b, 8)
+		if err != nil {
 			return nil, err
 		}
 		if connID[0] == 0 && connID[1] == 0 && connID[2] == 0 && connID[3] == 0 && connID[4] == 0 && connID[5] == 0 && connID[6] == 0 && connID[7] == 0 {
 			return nil, errInvalidConnectionID
 		}
 		header.DestConnectionID = connID
-		header.SrcConnectionID = connID
 	}
 
 	// Contrary to what the gQUIC wire spec says, the 0x4 bit only indicates the presence of the diversification nonce for packets sent by the server.
@@ -219,9 +214,7 @@ func (h *Header) getPublicHeaderLength(pers protocol.Perspective) (protocol.Byte
 		}
 		length += protocol.ByteCount(h.PacketNumberLen)
 	}
-	if !h.OmitConnectionID {
-		length += 8 // 8 bytes for the connection ID
-	}
+	length += protocol.ByteCount(h.DestConnectionID.Len()) // if set, always 8 bytes
 	// Version Number in packets sent by the client
 	if h.VersionFlag {
 		length += 4

+ 2 - 2
vendor/github.com/lucas-clemente/quic-go/mockgen.go

@@ -12,7 +12,7 @@ package quic
 //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 "./mockgen_private.sh quic mock_session_runner_test.go github.com/lucas-clemente/quic-go sessionRunner SessionRunner"
-//go:generate sh -c "./mockgen_private.sh quic mock_packet_handler_test.go github.com/lucas-clemente/quic-go packetHandler PacketHandler"
-//go:generate sh -c "./mockgen_private.sh quic mock_session_handler_test.go github.com/lucas-clemente/quic-go sessionHandler SessionHandler"
+//go:generate sh -c "./mockgen_private.sh quic mock_quic_session_test.go github.com/lucas-clemente/quic-go quicSession QuicSession"
+//go:generate sh -c "./mockgen_private.sh quic mock_packet_handler_manager_test.go github.com/lucas-clemente/quic-go packetHandlerManager PacketHandlerManager"
 //go:generate sh -c "find . -type f -name 'mock_*_test.go' | xargs sed -i '' 's/quic_go.//g'"
 //go:generate sh -c "goimports -w mock*_test.go"

+ 5 - 6
vendor/github.com/lucas-clemente/quic-go/packet_packer.go

@@ -451,14 +451,13 @@ func (p *packetPacker) getHeader(encLevel protocol.EncryptionLevel) *wire.Header
 	packetNumberLen := p.getPacketNumberLen(pnum)
 
 	header := &wire.Header{
-		DestConnectionID: p.destConnID,
-		SrcConnectionID:  p.srcConnID,
-		PacketNumber:     pnum,
-		PacketNumberLen:  packetNumberLen,
+		PacketNumber:    pnum,
+		PacketNumberLen: packetNumberLen,
 	}
 
 	if p.version.UsesTLS() && encLevel != protocol.EncryptionForwardSecure {
 		header.IsLongHeader = true
+		header.SrcConnectionID = p.srcConnID
 		// Set the payload len to maximum size.
 		// Since it is encoded as a varint, this guarantees us that the header will end up at most as big as GetLength() returns.
 		header.PayloadLen = p.maxPacketSize
@@ -469,8 +468,8 @@ func (p *packetPacker) getHeader(encLevel protocol.EncryptionLevel) *wire.Header
 		}
 	}
 
-	if p.omitConnectionID && encLevel == protocol.EncryptionForwardSecure {
-		header.OmitConnectionID = true
+	if !p.omitConnectionID || encLevel != protocol.EncryptionForwardSecure {
+		header.DestConnectionID = p.destConnID
 	}
 	if !p.version.UsesTLS() {
 		if p.perspective == protocol.PerspectiveServer && encLevel == protocol.EncryptionSecure {

+ 27 - 24
vendor/github.com/lucas-clemente/quic-go/server.go

@@ -18,36 +18,41 @@ import (
 
 // packetHandler handles packets
 type packetHandler interface {
+	handlePacket(*receivedPacket)
+	Close(error) error
+}
+
+type packetHandlerManager interface {
+	Add(protocol.ConnectionID, packetHandler)
+	Get(protocol.ConnectionID) (packetHandler, bool)
+	Remove(protocol.ConnectionID)
+	Close(error)
+}
+
+type quicSession interface {
 	Session
-	getCryptoStream() cryptoStreamI
 	handlePacket(*receivedPacket)
+	getCryptoStream() cryptoStreamI
 	GetVersion() protocol.VersionNumber
 	run() error
 	closeRemote(error)
 }
 
 type sessionRunner interface {
-	onHandshakeComplete(packetHandler)
+	onHandshakeComplete(Session)
 	removeConnectionID(protocol.ConnectionID)
 }
 
 type runner struct {
-	onHandshakeCompleteImpl func(packetHandler)
+	onHandshakeCompleteImpl func(Session)
 	removeConnectionIDImpl  func(protocol.ConnectionID)
 }
 
-func (r *runner) onHandshakeComplete(p packetHandler)        { r.onHandshakeCompleteImpl(p) }
+func (r *runner) onHandshakeComplete(s Session)              { r.onHandshakeCompleteImpl(s) }
 func (r *runner) removeConnectionID(c protocol.ConnectionID) { r.removeConnectionIDImpl(c) }
 
 var _ sessionRunner = &runner{}
 
-type sessionHandler interface {
-	Add(protocol.ConnectionID, packetHandler)
-	Get(protocol.ConnectionID) (packetHandler, bool)
-	Remove(protocol.ConnectionID)
-	Close()
-}
-
 // A Listener of QUIC
 type server struct {
 	tlsConf *tls.Config
@@ -61,7 +66,7 @@ type server struct {
 	certChain crypto.CertChain
 	scfg      *handshake.ServerConfig
 
-	sessionHandler sessionHandler
+	sessionHandler packetHandlerManager
 
 	serverError error
 
@@ -70,7 +75,7 @@ type server struct {
 
 	sessionRunner sessionRunner
 	// set as a member, so they can be set in the tests
-	newSession func(connection, sessionRunner, protocol.VersionNumber, protocol.ConnectionID, *handshake.ServerConfig, *tls.Config, *Config, utils.Logger) (packetHandler, error)
+	newSession func(connection, sessionRunner, protocol.VersionNumber, protocol.ConnectionID, *handshake.ServerConfig, *tls.Config, *Config, utils.Logger) (quicSession, error)
 
 	logger utils.Logger
 }
@@ -124,7 +129,7 @@ func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener,
 		certChain:      certChain,
 		scfg:           scfg,
 		newSession:     newSession,
-		sessionHandler: newSessionMap(),
+		sessionHandler: newPacketHandlerMap(),
 		sessionQueue:   make(chan Session, 5),
 		errorChan:      make(chan struct{}),
 		supportsTLS:    supportsTLS,
@@ -143,7 +148,7 @@ func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener,
 
 func (s *server) setup() {
 	s.sessionRunner = &runner{
-		onHandshakeCompleteImpl: func(sess packetHandler) { s.sessionQueue <- sess },
+		onHandshakeCompleteImpl: func(sess Session) { s.sessionQueue <- sess },
 		removeConnectionIDImpl:  s.sessionHandler.Remove,
 	}
 }
@@ -165,11 +170,9 @@ func (s *server) setupTLS() error {
 			case <-s.errorChan:
 				return
 			case tlsSession := <-sessionChan:
-				sess := tlsSession.sess
 				// The connection ID is a randomly chosen 8 byte value.
 				// It is safe to assume that it doesn't collide with other randomly chosen values.
-				s.sessionHandler.Add(tlsSession.connID, sess)
-				go sess.run()
+				s.sessionHandler.Add(tlsSession.connID, tlsSession.sess)
 			}
 		}
 	}()
@@ -285,7 +288,7 @@ func (s *server) Accept() (Session, error) {
 
 // Close the server
 func (s *server) Close() error {
-	s.sessionHandler.Close()
+	s.sessionHandler.Close(nil)
 	err := s.conn.Close()
 	<-s.errorChan // wait for serve() to return
 	return err
@@ -390,7 +393,7 @@ func (s *server) handleGQUICPacket(hdr *wire.Header, packetData []byte, remoteAd
 			return errors.New("dropping small packet with unknown version")
 		}
 		s.logger.Infof("Client offered version %s, sending Version Negotiation Packet", hdr.Version)
-		_, err := s.conn.WriteTo(wire.ComposeGQUICVersionNegotiation(hdr.SrcConnectionID, s.config.Versions), remoteAddr)
+		_, err := s.conn.WriteTo(wire.ComposeGQUICVersionNegotiation(hdr.DestConnectionID, s.config.Versions), remoteAddr)
 		return err
 	}
 
@@ -407,8 +410,7 @@ func (s *server) handleGQUICPacket(hdr *wire.Header, packetData []byte, remoteAd
 		}
 
 		s.logger.Infof("Serving new connection: %s, version %s from %v", hdr.DestConnectionID, version, remoteAddr)
-		var err error
-		session, err = s.newSession(
+		sess, err := s.newSession(
 			&conn{pconn: s.conn, currentAddr: remoteAddr},
 			s.sessionRunner,
 			version,
@@ -421,9 +423,10 @@ func (s *server) handleGQUICPacket(hdr *wire.Header, packetData []byte, remoteAd
 		if err != nil {
 			return err
 		}
-		s.sessionHandler.Add(hdr.DestConnectionID, session)
+		s.sessionHandler.Add(hdr.DestConnectionID, sess)
 
-		go session.run()
+		go sess.run()
+		session = sess
 	}
 
 	session.handlePacket(&receivedPacket{

+ 9 - 2
vendor/github.com/lucas-clemente/quic-go/server_tls.go

@@ -42,6 +42,8 @@ type serverTLS struct {
 	params            *handshake.TransportParameters
 	newMintConn       func(*handshake.CryptoStreamConn, protocol.VersionNumber) (handshake.MintTLS, <-chan handshake.TransportParameters, error)
 
+	newSession func(connection, sessionRunner, protocol.ConnectionID, protocol.ConnectionID, protocol.PacketNumber, *Config, handshake.MintTLS, *handshake.CryptoStreamConn, crypto.AEAD, *handshake.TransportParameters, protocol.VersionNumber, utils.Logger) (quicSession, error)
+
 	sessionRunner sessionRunner
 	sessionChan   chan<- tlsSession
 
@@ -83,7 +85,8 @@ func newServerTLS(
 			MaxBidiStreams:              uint16(config.MaxIncomingStreams),
 			MaxUniStreams:               uint16(config.MaxIncomingUniStreams),
 		},
-		logger: logger,
+		newSession: newTLSServerSession,
+		logger:     logger,
 	}
 	s.newMintConn = s.newMintConnImpl
 	return s, sessionChan, nil
@@ -137,6 +140,9 @@ func (s *serverTLS) sendConnectionClose(remoteAddr net.Addr, clientHdr *wire.Hea
 }
 
 func (s *serverTLS) handleInitialImpl(remoteAddr net.Addr, hdr *wire.Header, data []byte) (packetHandler, protocol.ConnectionID, error) {
+	if hdr.DestConnectionID.Len() < protocol.MinConnectionIDLenInitial {
+		return nil, nil, errors.New("dropping Initial packet with too short connection ID")
+	}
 	if len(hdr.Raw)+len(data) < protocol.MinInitialPacketSize {
 		return nil, nil, errors.New("dropping too small Initial packet")
 	}
@@ -222,7 +228,7 @@ func (s *serverTLS) handleUnpackedInitial(remoteAddr net.Addr, hdr *wire.Header,
 		return nil, nil, err
 	}
 	s.logger.Debugf("Changing source connection ID to %s.", connID)
-	sess, err := newTLSServerSession(
+	sess, err := s.newSession(
 		&conn{pconn: s.conn, currentAddr: remoteAddr},
 		s.sessionRunner,
 		hdr.SrcConnectionID,
@@ -242,5 +248,6 @@ func (s *serverTLS) handleUnpackedInitial(remoteAddr net.Addr, hdr *wire.Header,
 	cs := sess.getCryptoStream()
 	cs.setReadOffset(frame.DataLen())
 	bc.SetStream(cs)
+	go sess.run()
 	return sess, connID, nil
 }

+ 18 - 13
vendor/github.com/lucas-clemente/quic-go/session.go

@@ -156,7 +156,7 @@ func newSession(
 	tlsConf *tls.Config,
 	config *Config,
 	logger utils.Logger,
-) (packetHandler, error) {
+) (quicSession, error) {
 	paramsChan := make(chan handshake.TransportParameters)
 	handshakeEvent := make(chan struct{}, 1)
 	s := &session{
@@ -205,7 +205,7 @@ func newSession(
 	s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version)
 	s.packer = newPacketPacker(
 		connectionID,
-		connectionID,
+		nil, // no src connection ID
 		1,
 		s.sentPacketHandler.GetPacketNumberLen,
 		s.RemoteAddr(),
@@ -230,7 +230,7 @@ var newClientSession = func(
 	initialVersion protocol.VersionNumber,
 	negotiatedVersions []protocol.VersionNumber, // needed for validation of the GQUIC version negotiation
 	logger utils.Logger,
-) (packetHandler, error) {
+) (quicSession, error) {
 	paramsChan := make(chan handshake.TransportParameters)
 	handshakeEvent := make(chan struct{}, 1)
 	s := &session{
@@ -275,7 +275,7 @@ var newClientSession = func(
 	s.streamFramer = newStreamFramer(s.cryptoStream, s.streamsMap, s.version)
 	s.packer = newPacketPacker(
 		connectionID,
-		connectionID,
+		nil, // no src connection ID
 		1,
 		s.sentPacketHandler.GetPacketNumberLen,
 		s.RemoteAddr(),
@@ -301,7 +301,7 @@ func newTLSServerSession(
 	peerParams *handshake.TransportParameters,
 	v protocol.VersionNumber,
 	logger utils.Logger,
-) (packetHandler, error) {
+) (quicSession, error) {
 	handshakeEvent := make(chan struct{}, 1)
 	s := &session{
 		conn:           conn,
@@ -359,7 +359,7 @@ var newTLSClientSession = func(
 	paramsChan <-chan handshake.TransportParameters,
 	initialPacketNumber protocol.PacketNumber,
 	logger utils.Logger,
-) (packetHandler, error) {
+) (quicSession, error) {
 	handshakeEvent := make(chan struct{}, 1)
 	s := &session{
 		conn:           conn,
@@ -600,6 +600,13 @@ func (s *session) handleHandshakeEvent(completed bool) {
 }
 
 func (s *session) handlePacketImpl(p *receivedPacket) error {
+	hdr := p.header
+	// The server can change the source connection ID with the first Handshake packet.
+	// After this, all packets with a different source connection have to be ignored.
+	if s.receivedFirstPacket && hdr.IsLongHeader && !hdr.SrcConnectionID.Equal(s.destConnID) {
+		s.logger.Debugf("Dropping packet with unexpected source connection ID: %s (expected %s)", p.header.SrcConnectionID, s.destConnID)
+		return nil
+	}
 	if s.perspective == protocol.PerspectiveClient {
 		if divNonce := p.header.DiversificationNonce; len(divNonce) > 0 {
 			if err := s.cryptoStreamHandler.(divNonceSetter).SetDiversificationNonce(divNonce); err != nil {
@@ -613,9 +620,6 @@ func (s *session) handlePacketImpl(p *receivedPacket) error {
 		p.rcvTime = time.Now()
 	}
 
-	hdr := p.header
-	data := p.data
-
 	// Calculate packet number
 	hdr.PacketNumber = protocol.InferPacketNumber(
 		hdr.PacketNumberLen,
@@ -624,12 +628,12 @@ func (s *session) handlePacketImpl(p *receivedPacket) error {
 		s.version,
 	)
 
-	packet, err := s.unpacker.Unpack(hdr.Raw, hdr, data)
+	packet, err := s.unpacker.Unpack(hdr.Raw, hdr, p.data)
 	if s.logger.Debug() {
 		if err != nil {
-			s.logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %s", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.DestConnectionID)
+			s.logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %s", hdr.PacketNumber, len(p.data)+len(hdr.Raw), hdr.DestConnectionID)
 		} else {
-			s.logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %s, %s", hdr.PacketNumber, len(data)+len(hdr.Raw), hdr.DestConnectionID, packet.encryptionLevel)
+			s.logger.Debugf("<- Reading packet 0x%x (%d bytes) for connection %s, %s", hdr.PacketNumber, len(p.data)+len(hdr.Raw), hdr.DestConnectionID, packet.encryptionLevel)
 		}
 		hdr.Log(s.logger)
 	}
@@ -638,7 +642,8 @@ func (s *session) handlePacketImpl(p *receivedPacket) error {
 		return err
 	}
 
-	if s.perspective == protocol.PerspectiveClient && !s.receivedFirstPacket && !hdr.SrcConnectionID.Equal(s.destConnID) {
+	// The server can change the source connection ID with the first Handshake packet.
+	if s.perspective == protocol.PerspectiveClient && !s.receivedFirstPacket && hdr.IsLongHeader && !hdr.SrcConnectionID.Equal(s.destConnID) {
 		s.logger.Debugf("Received first packet. Switching destination connection ID to: %s", hdr.SrcConnectionID)
 		s.destConnID = hdr.SrcConnectionID
 		s.packer.ChangeDestConnectionID(s.destConnID)

+ 0 - 74
vendor/github.com/lucas-clemente/quic-go/session_map.go

@@ -1,74 +0,0 @@
-package quic
-
-import (
-	"sync"
-	"time"
-
-	"github.com/lucas-clemente/quic-go/internal/protocol"
-)
-
-type sessionMap struct {
-	mutex sync.RWMutex
-
-	sessions map[string] /* string(ConnectionID)*/ packetHandler
-	closed   bool
-
-	deleteClosedSessionsAfter time.Duration
-}
-
-var _ sessionHandler = &sessionMap{}
-
-func newSessionMap() sessionHandler {
-	return &sessionMap{
-		sessions:                  make(map[string]packetHandler),
-		deleteClosedSessionsAfter: protocol.ClosedSessionDeleteTimeout,
-	}
-}
-
-func (h *sessionMap) Get(id protocol.ConnectionID) (packetHandler, bool) {
-	h.mutex.RLock()
-	sess, ok := h.sessions[string(id)]
-	h.mutex.RUnlock()
-	return sess, ok
-}
-
-func (h *sessionMap) Add(id protocol.ConnectionID, sess packetHandler) {
-	h.mutex.Lock()
-	h.sessions[string(id)] = sess
-	h.mutex.Unlock()
-}
-
-func (h *sessionMap) Remove(id protocol.ConnectionID) {
-	h.mutex.Lock()
-	h.sessions[string(id)] = nil
-	h.mutex.Unlock()
-
-	time.AfterFunc(h.deleteClosedSessionsAfter, func() {
-		h.mutex.Lock()
-		delete(h.sessions, string(id))
-		h.mutex.Unlock()
-	})
-}
-
-func (h *sessionMap) Close() {
-	h.mutex.Lock()
-	if h.closed {
-		h.mutex.Unlock()
-		return
-	}
-	h.closed = true
-
-	var wg sync.WaitGroup
-	for _, session := range h.sessions {
-		if session != nil {
-			wg.Add(1)
-			go func(sess packetHandler) {
-				// session.Close() blocks until the CONNECTION_CLOSE has been sent and the run-loop has stopped
-				_ = sess.Close(nil)
-				wg.Done()
-			}(session)
-		}
-	}
-	h.mutex.Unlock()
-	wg.Wait()
-}

+ 24 - 24
vendor/vendor.json

@@ -123,10 +123,10 @@
 			"revisionTime": "2017-10-27T16:34:21Z"
 		},
 		{
-			"checksumSHA1": "EK2IIceH4JfqLhabxrdXEWowVB0=",
+			"checksumSHA1": "bmA5gu03Z9vpvTxj2Jb2DEJMhTs=",
 			"path": "github.com/lucas-clemente/quic-go",
-			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
-			"revisionTime": "2018-06-11T09:15:20Z"
+			"revision": "3aa6c99943fdcd448b02f22eaecfd26ca59bb0de",
+			"revisionTime": "2018-06-25T13:05:42Z"
 		},
 		{
 			"checksumSHA1": "OA9E+y7g05x/mWJJHmA7oPxWKQo=",
@@ -135,58 +135,58 @@
 			"revisionTime": "2016-08-23T09:51:56Z"
 		},
 		{
-			"checksumSHA1": "DGisFbg6dQEUQgDIVeVOGBh0G98=",
+			"checksumSHA1": "q5Mmgdu/11zEFx8Qew7wt0BvR34=",
 			"path": "github.com/lucas-clemente/quic-go/internal/ackhandler",
-			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
-			"revisionTime": "2018-06-11T09:15:20Z"
+			"revision": "3aa6c99943fdcd448b02f22eaecfd26ca59bb0de",
+			"revisionTime": "2018-06-25T13:05:42Z"
 		},
 		{
 			"checksumSHA1": "i1yfut7QQqMehw5yE9llhWNnrxk=",
 			"path": "github.com/lucas-clemente/quic-go/internal/congestion",
-			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
-			"revisionTime": "2018-06-11T09:15:20Z"
+			"revision": "3aa6c99943fdcd448b02f22eaecfd26ca59bb0de",
+			"revisionTime": "2018-06-25T13:05:42Z"
 		},
 		{
 			"checksumSHA1": "8CRRInUpwdxqXFGWnrW1KTUYOUE=",
 			"path": "github.com/lucas-clemente/quic-go/internal/crypto",
-			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
-			"revisionTime": "2018-06-11T09:15:20Z"
+			"revision": "3aa6c99943fdcd448b02f22eaecfd26ca59bb0de",
+			"revisionTime": "2018-06-25T13:05:42Z"
 		},
 		{
 			"checksumSHA1": "rnRicg73lPAeRh9Nko6a0CZQS5I=",
 			"path": "github.com/lucas-clemente/quic-go/internal/flowcontrol",
-			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
-			"revisionTime": "2018-06-11T09:15:20Z"
+			"revision": "3aa6c99943fdcd448b02f22eaecfd26ca59bb0de",
+			"revisionTime": "2018-06-25T13:05:42Z"
 		},
 		{
 			"checksumSHA1": "VDAmO1aQcHrZGfHBolw4bMjlCIo=",
 			"path": "github.com/lucas-clemente/quic-go/internal/handshake",
-			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
-			"revisionTime": "2018-06-11T09:15:20Z"
+			"revision": "3aa6c99943fdcd448b02f22eaecfd26ca59bb0de",
+			"revisionTime": "2018-06-25T13:05:42Z"
 		},
 		{
-			"checksumSHA1": "wRyj35gvDNdwa5SN8lhXY6AbLlA=",
+			"checksumSHA1": "WcERuY6LQVVwsulsp733jXwSXrE=",
 			"path": "github.com/lucas-clemente/quic-go/internal/protocol",
-			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
-			"revisionTime": "2018-06-11T09:15:20Z"
+			"revision": "3aa6c99943fdcd448b02f22eaecfd26ca59bb0de",
+			"revisionTime": "2018-06-25T13:05:42Z"
 		},
 		{
 			"checksumSHA1": "0vSbWIQ7O34u4kDMR+FHr7/FINk=",
 			"path": "github.com/lucas-clemente/quic-go/internal/utils",
-			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
-			"revisionTime": "2018-06-11T09:15:20Z"
+			"revision": "3aa6c99943fdcd448b02f22eaecfd26ca59bb0de",
+			"revisionTime": "2018-06-25T13:05:42Z"
 		},
 		{
-			"checksumSHA1": "k8zqhUkszbP7zw4+cm8UkZ7vccY=",
+			"checksumSHA1": "XffpGTFqeLH70f+ToHMqmmt4wjE=",
 			"path": "github.com/lucas-clemente/quic-go/internal/wire",
-			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
-			"revisionTime": "2018-06-11T09:15:20Z"
+			"revision": "3aa6c99943fdcd448b02f22eaecfd26ca59bb0de",
+			"revisionTime": "2018-06-25T13:05:42Z"
 		},
 		{
 			"checksumSHA1": "bFSC4TOZGOZGBJEFmLAT3V4ieoo=",
 			"path": "github.com/lucas-clemente/quic-go/qerr",
-			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
-			"revisionTime": "2018-06-11T09:15:20Z"
+			"revision": "3aa6c99943fdcd448b02f22eaecfd26ca59bb0de",
+			"revisionTime": "2018-06-25T13:05:42Z"
 		},
 		{
 			"checksumSHA1": "sY8sshVIEXnJgg3S6C5FcN33Vq4=",