Browse Source

Update quic-go

Rod Hynes 7 years ago
parent
commit
f960bf193a

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

@@ -4,6 +4,7 @@
 
 - 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.
 
 ## v0.7.0 (2018-02-03)
 

+ 2 - 1
vendor/github.com/lucas-clemente/quic-go/README.md

@@ -3,7 +3,8 @@
 <img src="docs/quic.png" width=303 height=124>
 
 [![Godoc Reference](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](https://godoc.org/github.com/lucas-clemente/quic-go)
-[![Linux Build Status](https://img.shields.io/travis/lucas-clemente/quic-go/master.svg?style=flat-square&label=linux+build)](https://travis-ci.org/lucas-clemente/quic-go)
+[![Travis Build Status](https://img.shields.io/travis/lucas-clemente/quic-go/master.svg?style=flat-square&label=Travis+build)](https://travis-ci.org/lucas-clemente/quic-go)
+[![CircleCI Build Status](https://img.shields.io/circleci/project/github/lucas-clemente/quic-go.svg?style=flat-square&label=CircleCI+build)](https://circleci.com/gh/lucas-clemente/quic-go)
 [![Windows Build Status](https://img.shields.io/appveyor/ci/lucas-clemente/quic-go/master.svg?style=flat-square&label=windows+build)](https://ci.appveyor.com/project/lucas-clemente/quic-go/branch/master)
 [![Code Coverage](https://img.shields.io/codecov/c/github/lucas-clemente/quic-go/master.svg?style=flat-square)](https://codecov.io/gh/lucas-clemente/quic-go/)
 

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

@@ -74,10 +74,12 @@ type sentPacketHandler struct {
 	alarm time.Time
 
 	logger utils.Logger
+
+	version protocol.VersionNumber
 }
 
 // NewSentPacketHandler creates a new sentPacketHandler
-func NewSentPacketHandler(rttStats *congestion.RTTStats, logger utils.Logger) SentPacketHandler {
+func NewSentPacketHandler(rttStats *congestion.RTTStats, logger utils.Logger, version protocol.VersionNumber) SentPacketHandler {
 	congestion := congestion.NewCubicSender(
 		congestion.DefaultClock{},
 		rttStats,
@@ -92,6 +94,7 @@ func NewSentPacketHandler(rttStats *congestion.RTTStats, logger utils.Logger) Se
 		rttStats:           rttStats,
 		congestion:         congestion,
 		logger:             logger,
+		version:            version,
 	}
 }
 
@@ -494,7 +497,7 @@ func (h *sentPacketHandler) DequeuePacketForRetransmission() *Packet {
 }
 
 func (h *sentPacketHandler) GetPacketNumberLen(p protocol.PacketNumber) protocol.PacketNumberLen {
-	return protocol.GetPacketNumberLengthForHeader(p, h.lowestUnacked())
+	return protocol.GetPacketNumberLengthForHeader(p, h.lowestUnacked(), h.version)
 }
 
 func (h *sentPacketHandler) GetStopWaitingFrame(force bool) *wire.StopWaitingFrame {

+ 0 - 8
vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_server.go

@@ -60,11 +60,6 @@ type cryptoSetupServer struct {
 
 var _ CryptoSetup = &cryptoSetupServer{}
 
-// ErrHOLExperiment is returned when the client sends the FHL2 tag in the CHLO.
-// This is an experiment implemented by Chrome in QUIC 36, which we don't support.
-// TODO: remove this when dropping support for QUIC 36
-var ErrHOLExperiment = qerr.Error(qerr.InvalidCryptoMessageParameter, "HOL experiment. Unsupported")
-
 // ErrNSTPExperiment is returned when the client sends the NSTP tag in the CHLO.
 // This is an experiment implemented by Chrome in QUIC 38, which we don't support at this point.
 var ErrNSTPExperiment = qerr.Error(qerr.InvalidCryptoMessageParameter, "NSTP experiment. Unsupported")
@@ -132,9 +127,6 @@ func (h *cryptoSetupServer) HandleCryptoStream() error {
 }
 
 func (h *cryptoSetupServer) handleMessage(chloData []byte, cryptoData map[Tag][]byte) (bool, error) {
-	if _, isHOLExperiment := cryptoData[TagFHL2]; isHOLExperiment {
-		return false, ErrHOLExperiment
-	}
 	if _, isNSTPExperiment := cryptoData[TagNSTP]; isNSTPExperiment {
 		return false, ErrNSTPExperiment
 	}

+ 0 - 4
vendor/github.com/lucas-clemente/quic-go/internal/handshake/tags.go

@@ -50,10 +50,6 @@ const (
 	// TagSFCW is the initial stream flow control receive window.
 	TagSFCW Tag = 'S' + 'F'<<8 + 'C'<<16 + 'W'<<24
 
-	// TagFHL2 forces head of line blocking.
-	// Chrome experiment (see https://codereview.chromium.org/2115033002)
-	// unsupported by quic-go
-	TagFHL2 Tag = 'F' + 'H'<<8 + 'L'<<16 + '2'<<24
 	// TagNSTP is the no STOP_WAITING experiment
 	// currently unsupported by quic-go
 	TagNSTP Tag = 'N' + 'S'<<8 + 'T'<<16 + 'P'<<24

+ 1 - 1
vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension.go

@@ -6,7 +6,7 @@ import (
 
 type transportParameterID uint16
 
-const quicTLSExtensionType = 26
+const quicTLSExtensionType = 0xff5
 
 const (
 	initialMaxStreamDataParameterID  transportParameterID = 0x0

+ 22 - 4
vendor/github.com/lucas-clemente/quic-go/internal/protocol/packet_number.go

@@ -1,8 +1,25 @@
 package protocol
 
 // InferPacketNumber calculates the packet number based on the received packet number, its length and the last seen packet number
-func InferPacketNumber(packetNumberLength PacketNumberLen, lastPacketNumber PacketNumber, wirePacketNumber PacketNumber) PacketNumber {
-	epochDelta := PacketNumber(1) << (uint8(packetNumberLength) * 8)
+func InferPacketNumber(
+	packetNumberLength PacketNumberLen,
+	lastPacketNumber PacketNumber,
+	wirePacketNumber PacketNumber,
+	version VersionNumber,
+) PacketNumber {
+	var epochDelta PacketNumber
+	if version.UsesVarintPacketNumbers() {
+		switch packetNumberLength {
+		case PacketNumberLen1:
+			epochDelta = PacketNumber(1) << 7
+		case PacketNumberLen2:
+			epochDelta = PacketNumber(1) << 14
+		case PacketNumberLen4:
+			epochDelta = PacketNumber(1) << 30
+		}
+	} else {
+		epochDelta = PacketNumber(1) << (uint8(packetNumberLength) * 8)
+	}
 	epoch := lastPacketNumber & ^(epochDelta - 1)
 	prevEpochBegin := epoch - epochDelta
 	nextEpochBegin := epoch + epochDelta
@@ -29,9 +46,10 @@ func delta(a, b PacketNumber) PacketNumber {
 
 // GetPacketNumberLengthForHeader gets the length of the packet number for the public header
 // it never chooses a PacketNumberLen of 1 byte, since this is too short under certain circumstances
-func GetPacketNumberLengthForHeader(packetNumber PacketNumber, leastUnacked PacketNumber) PacketNumberLen {
+func GetPacketNumberLengthForHeader(packetNumber, leastUnacked PacketNumber, version VersionNumber) PacketNumberLen {
 	diff := uint64(packetNumber - leastUnacked)
-	if diff < (1 << (uint8(PacketNumberLen2)*8 - 1)) {
+	if version.UsesVarintPacketNumbers() && diff < (1<<(14-1)) ||
+		!version.UsesVarintPacketNumbers() && diff < (1<<(16-1)) {
 		return PacketNumberLen2
 	}
 	return PacketNumberLen4

+ 11 - 3
vendor/github.com/lucas-clemente/quic-go/internal/protocol/version.go

@@ -18,7 +18,9 @@ const (
 
 // The version numbers, making grepping easier
 const (
-	Version39       VersionNumber = gquicVersion0 + 3*0x100 + 0x9 + iota
+	Version39       VersionNumber = gquicVersion0 + 3*0x100 + 0x9
+	Version42       VersionNumber = gquicVersion0 + 4*0x100 + 0x2
+	Version43       VersionNumber = gquicVersion0 + 4*0x100 + 0x3
 	VersionTLS      VersionNumber = 101
 	VersionWhatever VersionNumber = 0 // for when the version doesn't matter
 	VersionUnknown  VersionNumber = math.MaxUint32
@@ -27,6 +29,8 @@ const (
 // SupportedVersions lists the versions that the server supports
 // must be in sorted descending order
 var SupportedVersions = []VersionNumber{
+	Version43,
+	Version42,
 	Version39,
 }
 
@@ -74,12 +78,16 @@ func (vn VersionNumber) CryptoStreamID() StreamID {
 
 // UsesIETFFrameFormat tells if this version uses the IETF frame format
 func (vn VersionNumber) UsesIETFFrameFormat() bool {
-	return vn != Version39
+	return !vn.isGQUIC()
 }
 
 // UsesStopWaitingFrames tells if this version uses STOP_WAITING frames
 func (vn VersionNumber) UsesStopWaitingFrames() bool {
-	return vn == Version39
+	return vn.isGQUIC()
+}
+
+func (vn VersionNumber) UsesVarintPacketNumbers() bool {
+	return !vn.isGQUIC()
 }
 
 // StreamContributesToConnectionFlowControl says if a stream contributes to connection-level flow control

+ 50 - 0
vendor/github.com/lucas-clemente/quic-go/internal/utils/varint_packetnumber.go

@@ -0,0 +1,50 @@
+package utils
+
+import (
+	"bytes"
+	"fmt"
+
+	"github.com/lucas-clemente/quic-go/internal/protocol"
+)
+
+// ReadVarIntPacketNumber reads a number in the QUIC varint packet number format
+func ReadVarIntPacketNumber(b *bytes.Reader) (protocol.PacketNumber, protocol.PacketNumberLen, error) {
+	b1, err := b.ReadByte()
+	if err != nil {
+		return 0, 0, err
+	}
+	if b1&0x80 == 0 {
+		return protocol.PacketNumber(b1), protocol.PacketNumberLen1, nil
+	}
+	b2, err := b.ReadByte()
+	if err != nil {
+		return 0, 0, err
+	}
+	if b1&0x40 == 0 {
+		return protocol.PacketNumber(uint64(b1&0x3f)<<8 + uint64(b2)), protocol.PacketNumberLen2, nil
+	}
+	b3, err := b.ReadByte()
+	if err != nil {
+		return 0, 0, err
+	}
+	b4, err := b.ReadByte()
+	if err != nil {
+		return 0, 0, err
+	}
+	return protocol.PacketNumber(uint64(b1&0x3f)<<24 + uint64(b2)<<16 + uint64(b3)<<8 + uint64(b4)), protocol.PacketNumberLen4, nil
+}
+
+// WriteVarIntPacketNumber writes a packet number in the QUIC varint packet number format
+func WriteVarIntPacketNumber(b *bytes.Buffer, i protocol.PacketNumber, len protocol.PacketNumberLen) error {
+	switch len {
+	case protocol.PacketNumberLen1:
+		b.WriteByte(uint8(i & 0x7f))
+	case protocol.PacketNumberLen2:
+		b.Write([]byte{(uint8(i>>8) & 0x3f) | 0x80, uint8(i)})
+	case protocol.PacketNumberLen4:
+		b.Write([]byte{(uint8(i>>24) & 0x3f) | 0xc0, uint8(i >> 16), uint8(i >> 8), uint8(i)})
+	default:
+		return fmt.Errorf("invalid packet number length: %d", len)
+	}
+	return nil
+}

+ 9 - 38
vendor/github.com/lucas-clemente/quic-go/internal/wire/ietf_header.go

@@ -72,12 +72,12 @@ func parseLongHeader(b *bytes.Reader, typeByte byte) (*Header, error) {
 		return nil, err
 	}
 	h.PayloadLen = protocol.ByteCount(pl)
-	pn, err := utils.BigEndian.ReadUint32(b)
+	pn, pnLen, err := utils.ReadVarIntPacketNumber(b)
 	if err != nil {
 		return nil, err
 	}
-	h.PacketNumber = protocol.PacketNumber(pn)
-	h.PacketNumberLen = protocol.PacketNumberLen4
+	h.PacketNumber = pn
+	h.PacketNumberLen = pnLen
 	h.Type = protocol.PacketType(typeByte & 0x7f)
 
 	if h.Type != protocol.PacketTypeInitial && h.Type != protocol.PacketTypeRetry && h.Type != protocol.PacketType0RTT && h.Type != protocol.PacketTypeHandshake {
@@ -98,25 +98,14 @@ func parseShortHeader(b *bytes.Reader, typeByte byte) (*Header, error) {
 	if typeByte&0x38 != 0x30 {
 		return nil, errors.New("invalid bits 3, 4 and 5")
 	}
-	var pnLen protocol.PacketNumberLen
-	switch typeByte & 0x3 {
-	case 0x0:
-		pnLen = protocol.PacketNumberLen1
-	case 0x1:
-		pnLen = protocol.PacketNumberLen2
-	case 0x2:
-		pnLen = protocol.PacketNumberLen4
-	default:
-		return nil, errors.New("invalid short header type")
-	}
-	pn, err := utils.BigEndian.ReadUintN(b, uint8(pnLen))
+	pn, pnLen, err := utils.ReadVarIntPacketNumber(b)
 	if err != nil {
 		return nil, err
 	}
 	return &Header{
 		KeyPhase:         int(typeByte&0x40) >> 6,
 		DestConnectionID: connID,
-		PacketNumber:     protocol.PacketNumber(pn),
+		PacketNumber:     pn,
 		PacketNumberLen:  pnLen,
 	}, nil
 }
@@ -144,39 +133,21 @@ func (h *Header) writeLongHeader(b *bytes.Buffer) error {
 	b.Write(h.DestConnectionID.Bytes())
 	b.Write(h.SrcConnectionID.Bytes())
 	utils.WriteVarInt(b, uint64(h.PayloadLen))
-	utils.BigEndian.WriteUint32(b, uint32(h.PacketNumber))
-	return nil
+	return utils.WriteVarIntPacketNumber(b, h.PacketNumber, h.PacketNumberLen)
 }
 
 func (h *Header) writeShortHeader(b *bytes.Buffer) error {
 	typeByte := byte(0x30)
 	typeByte |= byte(h.KeyPhase << 6)
-	switch h.PacketNumberLen {
-	case protocol.PacketNumberLen1:
-	case protocol.PacketNumberLen2:
-		typeByte |= 0x1
-	case protocol.PacketNumberLen4:
-		typeByte |= 0x2
-	default:
-		return fmt.Errorf("invalid packet number length: %d", h.PacketNumberLen)
-	}
 	b.WriteByte(typeByte)
 
 	b.Write(h.DestConnectionID.Bytes())
-	switch h.PacketNumberLen {
-	case protocol.PacketNumberLen1:
-		b.WriteByte(uint8(h.PacketNumber))
-	case protocol.PacketNumberLen2:
-		utils.BigEndian.WriteUint16(b, uint16(h.PacketNumber))
-	case protocol.PacketNumberLen4:
-		utils.BigEndian.WriteUint32(b, uint32(h.PacketNumber))
-	}
-	return nil
+	return utils.WriteVarIntPacketNumber(b, h.PacketNumber, h.PacketNumberLen)
 }
 
 func (h *Header) getHeaderLength() (protocol.ByteCount, error) {
 	if h.IsLongHeader {
-		return 1 /* type byte */ + 4 /* version */ + 1 /* conn id len byte */ + protocol.ByteCount(h.DestConnectionID.Len()+h.SrcConnectionID.Len()) + utils.VarIntLen(uint64(h.PayloadLen)) + 4 /* packet number */, nil
+		return 1 /* type byte */ + 4 /* version */ + 1 /* conn id len byte */ + protocol.ByteCount(h.DestConnectionID.Len()+h.SrcConnectionID.Len()) + utils.VarIntLen(uint64(h.PayloadLen)) + protocol.ByteCount(h.PacketNumberLen), nil
 	}
 
 	length := protocol.ByteCount(1 /* type byte */ + h.DestConnectionID.Len())
@@ -192,7 +163,7 @@ func (h *Header) logHeader(logger utils.Logger) {
 		if h.Version == 0 {
 			logger.Debugf("\tVersionNegotiationPacket{DestConnectionID: %s, SrcConnectionID: %s, SupportedVersions: %s}", h.DestConnectionID, h.SrcConnectionID, h.SupportedVersions)
 		} else {
-			logger.Debugf("\tLong Header{Type: %s, DestConnectionID: %s, SrcConnectionID: %s, PacketNumber: %#x, PayloadLen: %d, Version: %s}", h.Type, h.DestConnectionID, h.SrcConnectionID, h.PacketNumber, h.PayloadLen, h.Version)
+			logger.Debugf("\tLong Header{Type: %s, DestConnectionID: %s, SrcConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, PayloadLen: %d, Version: %s}", h.Type, h.DestConnectionID, h.SrcConnectionID, h.PacketNumber, h.PacketNumberLen, h.PayloadLen, h.Version)
 		}
 	} else {
 		logger.Debugf("\tShort Header{DestConnectionID: %s, PacketNumber: %#x, PacketNumberLen: %d, KeyPhase: %d}", h.DestConnectionID, h.PacketNumber, h.PacketNumberLen, h.KeyPhase)

+ 0 - 1
vendor/github.com/lucas-clemente/quic-go/packet_packer.go

@@ -458,7 +458,6 @@ func (p *packetPacker) getHeader(encLevel protocol.EncryptionLevel) *wire.Header
 	}
 
 	if p.version.UsesTLS() && encLevel != protocol.EncryptionForwardSecure {
-		header.PacketNumberLen = protocol.PacketNumberLen4
 		header.IsLongHeader = true
 		// 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.

+ 34 - 20
vendor/github.com/lucas-clemente/quic-go/receive_stream.go

@@ -73,44 +73,52 @@ func (s *receiveStream) StreamID() protocol.StreamID {
 
 // Read implements io.Reader. It is not thread safe!
 func (s *receiveStream) Read(p []byte) (int, error) {
+	completed, n, err := s.readImpl(p)
+	if completed {
+		s.sender.onStreamCompleted(s.streamID)
+	}
+	return n, err
+}
+
+func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, error) {
 	s.mutex.Lock()
 	defer s.mutex.Unlock()
 
 	if s.finRead {
-		return 0, io.EOF
+		return false, 0, io.EOF
 	}
 	if s.canceledRead {
-		return 0, s.cancelReadErr
+		return false, 0, s.cancelReadErr
 	}
 	if s.resetRemotely {
-		return 0, s.resetRemotelyErr
+		return false, 0, s.resetRemotelyErr
 	}
 	if s.closedForShutdown {
-		return 0, s.closeForShutdownErr
+		return false, 0, s.closeForShutdownErr
 	}
 
 	bytesRead := 0
 	for bytesRead < len(p) {
 		frame := s.frameQueue.Head()
 		if frame == nil && bytesRead > 0 {
-			return bytesRead, s.closeForShutdownErr
+			return false, bytesRead, s.closeForShutdownErr
 		}
 
 		for {
 			// Stop waiting on errors
 			if s.closedForShutdown {
-				return bytesRead, s.closeForShutdownErr
+				return false, bytesRead, s.closeForShutdownErr
 			}
 			if s.canceledRead {
-				return bytesRead, s.cancelReadErr
+				return false, bytesRead, s.cancelReadErr
 			}
 			if s.resetRemotely {
-				return bytesRead, s.resetRemotelyErr
+				return false, bytesRead, s.resetRemotelyErr
 			}
 
 			deadline := s.readDeadline
 			if !deadline.IsZero() && !time.Now().Before(deadline) {
-				return bytesRead, errDeadline
+				return false, bytesRead, errDeadline
 			}
 
 			if frame != nil {
@@ -132,10 +140,10 @@ func (s *receiveStream) Read(p []byte) (int, error) {
 		}
 
 		if bytesRead > len(p) {
-			return bytesRead, fmt.Errorf("BUG: bytesRead (%d) > len(p) (%d) in stream.Read", bytesRead, len(p))
+			return false, bytesRead, fmt.Errorf("BUG: bytesRead (%d) > len(p) (%d) in stream.Read", bytesRead, len(p))
 		}
 		if s.readPosInFrame > int(frame.DataLen()) {
-			return bytesRead, fmt.Errorf("BUG: readPosInFrame (%d) > frame.DataLen (%d) in stream.Read", s.readPosInFrame, frame.DataLen())
+			return false, bytesRead, fmt.Errorf("BUG: readPosInFrame (%d) > frame.DataLen (%d) in stream.Read", s.readPosInFrame, frame.DataLen())
 		}
 
 		s.mutex.Unlock()
@@ -158,12 +166,11 @@ func (s *receiveStream) Read(p []byte) (int, error) {
 			s.frameQueue.Pop()
 			s.finRead = frame.FinBit
 			if frame.FinBit {
-				s.sender.onStreamCompleted(s.streamID)
-				return bytesRead, io.EOF
+				return true, bytesRead, io.EOF
 			}
 		}
 	}
-	return bytesRead, nil
+	return false, bytesRead, nil
 }
 
 func (s *receiveStream) CancelRead(errorCode protocol.ApplicationErrorCode) error {
@@ -204,25 +211,33 @@ func (s *receiveStream) handleStreamFrame(frame *wire.StreamFrame) error {
 }
 
 func (s *receiveStream) handleRstStreamFrame(frame *wire.RstStreamFrame) error {
+	completed, err := s.handleRstStreamFrameImpl(frame)
+	if completed {
+		s.sender.onStreamCompleted(s.streamID)
+	}
+	return err
+}
+
+func (s *receiveStream) handleRstStreamFrameImpl(frame *wire.RstStreamFrame) (bool /*completed */, error) {
 	s.mutex.Lock()
 	defer s.mutex.Unlock()
 
 	if s.closedForShutdown {
-		return nil
+		return false, nil
 	}
 	if err := s.flowController.UpdateHighestReceived(frame.ByteOffset, true); err != nil {
-		return err
+		return false, err
 	}
 	// In gQUIC, error code 0 has a special meaning.
 	// The peer will reliably continue transmitting, but is not interested in reading from the stream.
 	// We should therefore just continue reading from the stream, until we encounter the FIN bit.
 	if !s.version.UsesIETFFrameFormat() && frame.ErrorCode == 0 {
-		return nil
+		return false, nil
 	}
 
 	// ignore duplicate RST_STREAM frames for this stream (after checking their final offset)
 	if s.resetRemotely {
-		return nil
+		return false, nil
 	}
 	s.resetRemotely = true
 	s.resetRemotelyErr = streamCanceledError{
@@ -230,8 +245,7 @@ func (s *receiveStream) handleRstStreamFrame(frame *wire.RstStreamFrame) error {
 		error:     fmt.Errorf("Stream %d was reset with error code %d", s.streamID, frame.ErrorCode),
 	}
 	s.signalRead()
-	s.sender.onStreamCompleted(s.streamID)
-	return nil
+	return true, nil
 }
 
 func (s *receiveStream) CloseRemote(offset protocol.ByteCount) {

+ 34 - 19
vendor/github.com/lucas-clemente/quic-go/send_stream.go

@@ -133,11 +133,19 @@ func (s *sendStream) Write(p []byte) (int, error) {
 // popStreamFrame returns the next STREAM frame that is supposed to be sent on this stream
 // maxBytes is the maximum length this frame (including frame header) will have.
 func (s *sendStream) popStreamFrame(maxBytes protocol.ByteCount) (*wire.StreamFrame, bool /* has more data to send */) {
+	completed, frame, hasMoreData := s.popStreamFrameImpl(maxBytes)
+	if completed {
+		s.sender.onStreamCompleted(s.streamID)
+	}
+	return frame, hasMoreData
+}
+
+func (s *sendStream) popStreamFrameImpl(maxBytes protocol.ByteCount) (bool /* completed */, *wire.StreamFrame, bool /* has more data to send */) {
 	s.mutex.Lock()
 	defer s.mutex.Unlock()
 
 	if s.closeForShutdownErr != nil {
-		return nil, false
+		return false, nil, false
 	}
 
 	frame := &wire.StreamFrame{
@@ -147,7 +155,7 @@ func (s *sendStream) popStreamFrame(maxBytes protocol.ByteCount) (*wire.StreamFr
 	}
 	maxDataLen := frame.MaxDataLen(maxBytes, s.version)
 	if maxDataLen == 0 { // a STREAM frame must have at least one byte of data
-		return nil, s.dataForWriting != nil
+		return false, nil, s.dataForWriting != nil
 	}
 	frame.Data, frame.FinBit = s.getDataForWriting(maxDataLen)
 	if len(frame.Data) == 0 && !frame.FinBit {
@@ -156,24 +164,24 @@ func (s *sendStream) popStreamFrame(maxBytes protocol.ByteCount) (*wire.StreamFr
 		// - there's data for writing, but the stream is stream-level flow control blocked
 		// - there's data for writing, but the stream is connection-level flow control blocked
 		if s.dataForWriting == nil {
-			return nil, false
+			return false, nil, false
 		}
 		isBlocked, _ := s.flowController.IsBlocked()
-		return nil, !isBlocked
+		return false, nil, !isBlocked
 	}
 	if frame.FinBit {
 		s.finSent = true
-		s.sender.onStreamCompleted(s.streamID)
+		return true, frame, s.dataForWriting != nil
 	} else if s.streamID != s.version.CryptoStreamID() { // TODO(#657): Flow control for the crypto stream
 		if isBlocked, offset := s.flowController.IsBlocked(); isBlocked {
 			s.sender.queueControlFrame(&wire.StreamBlockedFrame{
 				StreamID: s.streamID,
 				Offset:   offset,
 			})
-			return frame, false
+			return false, frame, false
 		}
 	}
-	return frame, s.dataForWriting != nil
+	return false, frame, s.dataForWriting != nil
 }
 
 func (s *sendStream) getDataForWriting(maxBytes protocol.ByteCount) ([]byte, bool /* should send FIN */) {
@@ -218,18 +226,22 @@ func (s *sendStream) Close() error {
 
 func (s *sendStream) CancelWrite(errorCode protocol.ApplicationErrorCode) error {
 	s.mutex.Lock()
-	defer s.mutex.Unlock()
+	completed, err := s.cancelWriteImpl(errorCode, fmt.Errorf("Write on stream %d canceled with error code %d", s.streamID, errorCode))
+	s.mutex.Unlock()
 
-	return s.cancelWriteImpl(errorCode, fmt.Errorf("Write on stream %d canceled with error code %d", s.streamID, errorCode))
+	if completed {
+		s.sender.onStreamCompleted(s.streamID)
+	}
+	return err
 }
 
 // must be called after locking the mutex
-func (s *sendStream) cancelWriteImpl(errorCode protocol.ApplicationErrorCode, writeErr error) error {
+func (s *sendStream) cancelWriteImpl(errorCode protocol.ApplicationErrorCode, writeErr error) (bool /*completed */, error) {
 	if s.canceledWrite {
-		return nil
+		return false, nil
 	}
 	if s.finishedWriting {
-		return fmt.Errorf("CancelWrite for closed stream %d", s.streamID)
+		return false, fmt.Errorf("CancelWrite for closed stream %d", s.streamID)
 	}
 	s.canceledWrite = true
 	s.cancelWriteErr = writeErr
@@ -241,14 +253,13 @@ func (s *sendStream) cancelWriteImpl(errorCode protocol.ApplicationErrorCode, wr
 	})
 	// TODO(#991): cancel retransmissions for this stream
 	s.ctxCancel()
-	s.sender.onStreamCompleted(s.streamID)
-	return nil
+	return true, nil
 }
 
 func (s *sendStream) handleStopSendingFrame(frame *wire.StopSendingFrame) {
-	s.mutex.Lock()
-	defer s.mutex.Unlock()
-	s.handleStopSendingFrameImpl(frame)
+	if completed := s.handleStopSendingFrameImpl(frame); completed {
+		s.sender.onStreamCompleted(s.streamID)
+	}
 }
 
 func (s *sendStream) handleMaxStreamDataFrame(frame *wire.MaxStreamDataFrame) {
@@ -261,7 +272,10 @@ func (s *sendStream) handleMaxStreamDataFrame(frame *wire.MaxStreamDataFrame) {
 }
 
 // must be called after locking the mutex
-func (s *sendStream) handleStopSendingFrameImpl(frame *wire.StopSendingFrame) {
+func (s *sendStream) handleStopSendingFrameImpl(frame *wire.StopSendingFrame) bool /*completed*/ {
+	s.mutex.Lock()
+	defer s.mutex.Unlock()
+
 	writeErr := streamCanceledError{
 		errorCode: frame.ErrorCode,
 		error:     fmt.Errorf("Stream %d was reset with error code %d", s.streamID, frame.ErrorCode),
@@ -270,7 +284,8 @@ func (s *sendStream) handleStopSendingFrameImpl(frame *wire.StopSendingFrame) {
 	if !s.version.UsesIETFFrameFormat() {
 		errorCode = errorCodeStoppingGQUIC
 	}
-	s.cancelWriteImpl(errorCode, writeErr)
+	completed, _ := s.cancelWriteImpl(errorCode, writeErr)
+	return completed
 }
 
 func (s *sendStream) Context() context.Context {

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

@@ -125,6 +125,7 @@ func (s *serverTLS) sendConnectionClose(remoteAddr net.Addr, clientHdr *wire.Hea
 		SrcConnectionID:  clientHdr.DestConnectionID,
 		DestConnectionID: clientHdr.SrcConnectionID,
 		PacketNumber:     1, // random packet number
+		PacketNumberLen:  protocol.PacketNumberLen1,
 		Version:          clientHdr.Version,
 	}
 	data, err := packUnencryptedPacket(aead, replyHdr, ccf, protocol.PerspectiveServer, s.logger)
@@ -193,6 +194,7 @@ func (s *serverTLS) handleUnpackedInitial(remoteAddr net.Addr, hdr *wire.Header,
 			SrcConnectionID:  hdr.DestConnectionID,
 			PayloadLen:       f.Length(version) + protocol.ByteCount(aead.Overhead()),
 			PacketNumber:     hdr.PacketNumber, // echo the client's packet number
+			PacketNumberLen:  hdr.PacketNumberLen,
 			Version:          version,
 		}
 		data, err := packUnencryptedPacket(aead, replyHdr, f, protocol.PerspectiveServer, s.logger)

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

@@ -407,7 +407,7 @@ var newTLSClientSession = func(
 
 func (s *session) preSetup() {
 	s.rttStats = &congestion.RTTStats{}
-	s.sentPacketHandler = ackhandler.NewSentPacketHandler(s.rttStats, s.logger)
+	s.sentPacketHandler = ackhandler.NewSentPacketHandler(s.rttStats, s.logger, s.version)
 	s.connFlowController = flowcontrol.NewConnectionFlowController(
 		protocol.ReceiveConnectionFlowControlWindow,
 		protocol.ByteCount(s.config.MaxReceiveConnectionFlowControlWindow),
@@ -621,6 +621,7 @@ func (s *session) handlePacketImpl(p *receivedPacket) error {
 		hdr.PacketNumberLen,
 		s.largestRcvdPacketNumber,
 		hdr.PacketNumber,
+		s.version,
 	)
 
 	packet, err := s.unpacker.Unpack(hdr.Raw, hdr, data)
@@ -867,7 +868,6 @@ func (s *session) handleCloseError(closeErr closeError) error {
 	}
 
 	if quicErr.ErrorCode == qerr.DecryptionFailure ||
-		quicErr == handshake.ErrHOLExperiment ||
 		quicErr == handshake.ErrNSTPExperiment {
 		return s.sendPublicReset(s.lastRcvdPacketNumber)
 	}

+ 1 - 0
vendor/github.com/lucas-clemente/quic-go/stream.go

@@ -19,6 +19,7 @@ const (
 type streamSender interface {
 	queueControlFrame(wire.Frame)
 	onHasStreamData(protocol.StreamID)
+	// must be called without holding the mutex that is acquired by closeForShutdown
 	onStreamCompleted(protocol.StreamID)
 }
 

+ 26 - 26
vendor/vendor.json

@@ -123,10 +123,10 @@
 			"revisionTime": "2017-10-27T16:34:21Z"
 		},
 		{
-			"checksumSHA1": "7BT+L+ga9hhblzSvSP8Mtkve/is=",
+			"checksumSHA1": "EK2IIceH4JfqLhabxrdXEWowVB0=",
 			"path": "github.com/lucas-clemente/quic-go",
-			"revision": "036131e084df1d1a37ae861aaa1717ce0d794a32",
-			"revisionTime": "2018-05-30T14:31:10Z"
+			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
+			"revisionTime": "2018-06-11T09:15:20Z"
 		},
 		{
 			"checksumSHA1": "OA9E+y7g05x/mWJJHmA7oPxWKQo=",
@@ -135,58 +135,58 @@
 			"revisionTime": "2016-08-23T09:51:56Z"
 		},
 		{
-			"checksumSHA1": "hYpTIYEUy7Nfx4MGRQjy//F5PZs=",
+			"checksumSHA1": "DGisFbg6dQEUQgDIVeVOGBh0G98=",
 			"path": "github.com/lucas-clemente/quic-go/internal/ackhandler",
-			"revision": "036131e084df1d1a37ae861aaa1717ce0d794a32",
-			"revisionTime": "2018-05-30T14:31:10Z"
+			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
+			"revisionTime": "2018-06-11T09:15:20Z"
 		},
 		{
 			"checksumSHA1": "i1yfut7QQqMehw5yE9llhWNnrxk=",
 			"path": "github.com/lucas-clemente/quic-go/internal/congestion",
-			"revision": "036131e084df1d1a37ae861aaa1717ce0d794a32",
-			"revisionTime": "2018-05-30T14:31:10Z"
+			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
+			"revisionTime": "2018-06-11T09:15:20Z"
 		},
 		{
 			"checksumSHA1": "8CRRInUpwdxqXFGWnrW1KTUYOUE=",
 			"path": "github.com/lucas-clemente/quic-go/internal/crypto",
-			"revision": "036131e084df1d1a37ae861aaa1717ce0d794a32",
-			"revisionTime": "2018-05-30T14:31:10Z"
+			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
+			"revisionTime": "2018-06-11T09:15:20Z"
 		},
 		{
 			"checksumSHA1": "rnRicg73lPAeRh9Nko6a0CZQS5I=",
 			"path": "github.com/lucas-clemente/quic-go/internal/flowcontrol",
-			"revision": "036131e084df1d1a37ae861aaa1717ce0d794a32",
-			"revisionTime": "2018-05-30T14:31:10Z"
+			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
+			"revisionTime": "2018-06-11T09:15:20Z"
 		},
 		{
-			"checksumSHA1": "A9fe2DfiT694bmD1deedP84eUsE=",
+			"checksumSHA1": "VDAmO1aQcHrZGfHBolw4bMjlCIo=",
 			"path": "github.com/lucas-clemente/quic-go/internal/handshake",
-			"revision": "036131e084df1d1a37ae861aaa1717ce0d794a32",
-			"revisionTime": "2018-05-30T14:31:10Z"
+			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
+			"revisionTime": "2018-06-11T09:15:20Z"
 		},
 		{
-			"checksumSHA1": "NwrPs5iGdniZnUEbJGlAcpoEPEY=",
+			"checksumSHA1": "wRyj35gvDNdwa5SN8lhXY6AbLlA=",
 			"path": "github.com/lucas-clemente/quic-go/internal/protocol",
-			"revision": "036131e084df1d1a37ae861aaa1717ce0d794a32",
-			"revisionTime": "2018-05-30T14:31:10Z"
+			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
+			"revisionTime": "2018-06-11T09:15:20Z"
 		},
 		{
-			"checksumSHA1": "pLLgXVkiZu1tCKa9oZgNQUfJdTE=",
+			"checksumSHA1": "0vSbWIQ7O34u4kDMR+FHr7/FINk=",
 			"path": "github.com/lucas-clemente/quic-go/internal/utils",
-			"revision": "036131e084df1d1a37ae861aaa1717ce0d794a32",
-			"revisionTime": "2018-05-30T14:31:10Z"
+			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
+			"revisionTime": "2018-06-11T09:15:20Z"
 		},
 		{
-			"checksumSHA1": "QbmFCVJHmGlqqO4hIoD7wivvP9w=",
+			"checksumSHA1": "k8zqhUkszbP7zw4+cm8UkZ7vccY=",
 			"path": "github.com/lucas-clemente/quic-go/internal/wire",
-			"revision": "036131e084df1d1a37ae861aaa1717ce0d794a32",
-			"revisionTime": "2018-05-30T14:31:10Z"
+			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
+			"revisionTime": "2018-06-11T09:15:20Z"
 		},
 		{
 			"checksumSHA1": "bFSC4TOZGOZGBJEFmLAT3V4ieoo=",
 			"path": "github.com/lucas-clemente/quic-go/qerr",
-			"revision": "036131e084df1d1a37ae861aaa1717ce0d794a32",
-			"revisionTime": "2018-05-30T14:31:10Z"
+			"revision": "7431602a892ffef6c736794434136d6b91bfcb76",
+			"revisionTime": "2018-06-11T09:15:20Z"
 		},
 		{
 			"checksumSHA1": "sY8sshVIEXnJgg3S6C5FcN33Vq4=",