Sfoglia il codice sorgente

Update vendored quic-go

Rod Hynes 7 anni fa
parent
commit
16842adc1c
21 ha cambiato i file con 368 aggiunte e 354 eliminazioni
  1. 3 1
      vendor/github.com/lucas-clemente/quic-go/appveyor.yml
  2. 6 11
      vendor/github.com/lucas-clemente/quic-go/client.go
  3. 1 0
      vendor/github.com/lucas-clemente/quic-go/crypto_stream.go
  4. 40 35
      vendor/github.com/lucas-clemente/quic-go/framer.go
  5. 1 1
      vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go
  6. 1 1
      vendor/github.com/lucas-clemente/quic-go/internal/congestion/cubic_sender.go
  7. 56 0
      vendor/github.com/lucas-clemente/quic-go/internal/crypto/hkdf.go
  8. 0 11
      vendor/github.com/lucas-clemente/quic-go/internal/crypto/key_derivation.go
  9. 1 2
      vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_aesgcm.go
  10. 3 4
      vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_client.go
  11. 0 7
      vendor/github.com/lucas-clemente/quic-go/internal/handshake/transport_parameters.go
  12. 15 19
      vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go
  13. 2 7
      vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go
  14. 4 1
      vendor/github.com/lucas-clemente/quic-go/mockgen.go
  15. 148 159
      vendor/github.com/lucas-clemente/quic-go/packet_packer.go
  16. 3 1
      vendor/github.com/lucas-clemente/quic-go/receive_stream.go
  17. 8 1
      vendor/github.com/lucas-clemente/quic-go/send_stream.go
  18. 45 55
      vendor/github.com/lucas-clemente/quic-go/session.go
  19. 1 0
      vendor/github.com/lucas-clemente/quic-go/stream.go
  20. 4 12
      vendor/github.com/lucas-clemente/quic-go/window_update_queue.go
  21. 26 26
      vendor/vendor.json

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

@@ -10,6 +10,9 @@ environment:
     - GOARCH: 386
     - GOARCH: amd64
 
+hosts:
+  quic.clemente.io: 127.0.0.1
+
 clone_folder: c:\gopath\src\github.com\lucas-clemente\quic-go
 
 install:
@@ -19,7 +22,6 @@ install:
   - set PATH=%PATH%;%GOPATH%\bin\windows_%GOARCH%;%GOPATH%\bin
   - echo %PATH%
   - echo %GOPATH%
-  - git submodule update --init --recursive
   - go get github.com/onsi/ginkgo/ginkgo
   - go get github.com/onsi/gomega
   - go version

+ 6 - 11
vendor/github.com/lucas-clemente/quic-go/client.go

@@ -25,8 +25,6 @@ type client struct {
 	// If it is started with Dial, we take a packet conn as a parameter.
 	createdPacketConn bool
 
-	hostname string
-
 	packetHandlers packetHandlerManager
 
 	token      []byte
@@ -143,6 +141,7 @@ func dialContext(
 			}
 		}
 	*/
+
 	packetHandlers, err := getMultiplexer().AddConn(pconn, config.ConnectionIDLength)
 	if err != nil {
 		return nil, err
@@ -167,13 +166,12 @@ func newClient(
 	closeCallback func(protocol.ConnectionID),
 	createdPacketConn bool,
 ) (*client, error) {
-	var hostname string
-	if tlsConf != nil {
-		hostname = tlsConf.ServerName
+	if tlsConf == nil {
+		tlsConf = &tls.Config{}
 	}
-	if hostname == "" {
+	if tlsConf.ServerName == "" {
 		var err error
-		hostname, _, err = net.SplitHostPort(host)
+		tlsConf.ServerName, _, err = net.SplitHostPort(host)
 		if err != nil {
 			return nil, err
 		}
@@ -194,7 +192,6 @@ func newClient(
 	c := &client{
 		conn:              &conn{pconn: pconn, currentAddr: remoteAddr},
 		createdPacketConn: createdPacketConn,
-		hostname:          hostname,
 		tlsConf:           tlsConf,
 		config:            config,
 		version:           config.Versions[0],
@@ -294,7 +291,7 @@ func (c *client) generateConnectionIDs() 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)
+	c.logger.Infof("Starting new connection to %s (%s -> %s), source connection ID %s, destination connection ID %s, version %s", c.tlsConf.ServerName, c.conn.LocalAddr(), c.conn.RemoteAddr(), c.srcConnID, c.destConnID, c.version)
 
 	var err error
 	if c.version.UsesTLS() {
@@ -332,7 +329,6 @@ func (c *client) dialTLS(ctx context.Context) error {
 		return err
 	}
 	mintConf.ExtensionHandler = extHandler
-	mintConf.ServerName = c.hostname
 	c.mintConf = mintConf
 
 	if err := c.createNewTLSSession(extHandler.GetPeerParams(), c.version); err != nil {
@@ -521,7 +517,6 @@ func (c *client) createNewGQUICSession() error {
 	sess, err := newClientSession(
 		c.conn,
 		runner,
-		c.hostname,
 		c.version,
 		c.destConnID,
 		c.srcConnID,

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

@@ -13,6 +13,7 @@ type cryptoStream interface {
 	io.Reader
 	io.Writer
 	handleStreamFrame(*wire.StreamFrame) error
+	hasData() bool
 	popStreamFrame(protocol.ByteCount) (*wire.StreamFrame, bool)
 	closeForShutdown(error)
 	setReadOffset(protocol.ByteCount)

+ 40 - 35
vendor/github.com/lucas-clemente/quic-go/stream_framer.go → vendor/github.com/lucas-clemente/quic-go/framer.go

@@ -7,23 +7,25 @@ import (
 	"github.com/lucas-clemente/quic-go/internal/wire"
 )
 
-type streamFramer struct {
+type framer struct {
 	streamGetter streamGetter
 	cryptoStream cryptoStream
 	version      protocol.VersionNumber
 
-	streamQueueMutex    sync.Mutex
-	activeStreams       map[protocol.StreamID]struct{}
-	streamQueue         []protocol.StreamID
-	hasCryptoStreamData bool
+	streamQueueMutex sync.Mutex
+	activeStreams    map[protocol.StreamID]struct{}
+	streamQueue      []protocol.StreamID
+
+	controlFrameMutex sync.Mutex
+	controlFrames     []wire.Frame
 }
 
-func newStreamFramer(
+func newFramer(
 	cryptoStream cryptoStream,
 	streamGetter streamGetter,
 	v protocol.VersionNumber,
-) *streamFramer {
-	return &streamFramer{
+) *framer {
+	return &framer{
 		streamGetter:  streamGetter,
 		cryptoStream:  cryptoStream,
 		activeStreams: make(map[protocol.StreamID]struct{}),
@@ -31,13 +33,32 @@ func newStreamFramer(
 	}
 }
 
-func (f *streamFramer) AddActiveStream(id protocol.StreamID) {
-	if id == f.version.CryptoStreamID() { // the crypto stream is handled separately
-		f.streamQueueMutex.Lock()
-		f.hasCryptoStreamData = true
-		f.streamQueueMutex.Unlock()
-		return
+func (f *framer) QueueControlFrame(frame wire.Frame) {
+	f.controlFrameMutex.Lock()
+	f.controlFrames = append(f.controlFrames, frame)
+	f.controlFrameMutex.Unlock()
+}
+
+func (f *framer) AppendControlFrames(frames []wire.Frame, maxLen protocol.ByteCount) ([]wire.Frame, protocol.ByteCount) {
+	var length protocol.ByteCount
+	f.controlFrameMutex.Lock()
+	for len(f.controlFrames) > 0 {
+		frame := f.controlFrames[len(f.controlFrames)-1]
+		frameLen := frame.Length(f.version)
+		if length+frameLen > maxLen {
+			break
+		}
+		frames = append(frames, frame)
+		length += frameLen
+		f.controlFrames = f.controlFrames[:len(f.controlFrames)-1]
 	}
+	f.controlFrameMutex.Unlock()
+	return frames, length
+}
+
+// AddActiveStream adds a stream that has data to write.
+// It should not be used for the crypto stream.
+func (f *framer) AddActiveStream(id protocol.StreamID) {
 	f.streamQueueMutex.Lock()
 	if _, ok := f.activeStreams[id]; !ok {
 		f.streamQueue = append(f.streamQueue, id)
@@ -46,29 +67,13 @@ func (f *streamFramer) AddActiveStream(id protocol.StreamID) {
 	f.streamQueueMutex.Unlock()
 }
 
-func (f *streamFramer) HasCryptoStreamData() bool {
-	f.streamQueueMutex.Lock()
-	hasCryptoStreamData := f.hasCryptoStreamData
-	f.streamQueueMutex.Unlock()
-	return hasCryptoStreamData
-}
-
-func (f *streamFramer) PopCryptoStreamFrame(maxLen protocol.ByteCount) *wire.StreamFrame {
-	f.streamQueueMutex.Lock()
-	frame, hasMoreData := f.cryptoStream.popStreamFrame(maxLen)
-	f.hasCryptoStreamData = hasMoreData
-	f.streamQueueMutex.Unlock()
-	return frame
-}
-
-func (f *streamFramer) PopStreamFrames(maxTotalLen protocol.ByteCount) []*wire.StreamFrame {
-	var currentLen protocol.ByteCount
-	var frames []*wire.StreamFrame
+func (f *framer) AppendStreamFrames(frames []wire.Frame, maxLen protocol.ByteCount) []wire.Frame {
+	var length protocol.ByteCount
 	f.streamQueueMutex.Lock()
 	// pop STREAM frames, until less than MinStreamFrameSize bytes are left in the packet
 	numActiveStreams := len(f.streamQueue)
 	for i := 0; i < numActiveStreams; i++ {
-		if maxTotalLen-currentLen < protocol.MinStreamFrameSize {
+		if maxLen-length < protocol.MinStreamFrameSize {
 			break
 		}
 		id := f.streamQueue[0]
@@ -81,7 +86,7 @@ func (f *streamFramer) PopStreamFrames(maxTotalLen protocol.ByteCount) []*wire.S
 			delete(f.activeStreams, id)
 			continue
 		}
-		frame, hasMoreData := str.popStreamFrame(maxTotalLen - currentLen)
+		frame, hasMoreData := str.popStreamFrame(maxLen - length)
 		if hasMoreData { // put the stream back in the queue (at the end)
 			f.streamQueue = append(f.streamQueue, id)
 		} else { // no more data to send. Stream is not active any more
@@ -91,7 +96,7 @@ func (f *streamFramer) PopStreamFrames(maxTotalLen protocol.ByteCount) []*wire.S
 			continue
 		}
 		frames = append(frames, frame)
-		currentLen += frame.Length(f.version)
+		length += frame.Length(f.version)
 	}
 	f.streamQueueMutex.Unlock()
 	return frames

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

@@ -633,7 +633,7 @@ func (h *sentPacketHandler) computeRTOTimeout() time.Duration {
 	}
 	rto = utils.MaxDuration(rto, minRTOTimeout)
 	// Exponential backoff
-	rto = rto << h.rtoCount
+	rto <<= h.rtoCount
 	return utils.MinDuration(rto, maxRTOTimeout)
 }
 

+ 1 - 1
vendor/github.com/lucas-clemente/quic-go/internal/congestion/cubic_sender.go

@@ -193,7 +193,7 @@ func (c *cubicSender) OnPacketLost(
 		if c.congestionWindow >= 2*c.initialCongestionWindow {
 			c.minSlowStartExitWindow = c.congestionWindow / 2
 		}
-		c.congestionWindow = c.congestionWindow - protocol.DefaultTCPMSS
+		c.congestionWindow -= protocol.DefaultTCPMSS
 	} else if c.reno {
 		c.congestionWindow = protocol.ByteCount(float32(c.congestionWindow) * c.RenoBeta())
 	} else {

+ 56 - 0
vendor/github.com/lucas-clemente/quic-go/internal/crypto/hkdf.go

@@ -0,0 +1,56 @@
+package crypto
+
+import (
+	"crypto"
+	"crypto/hmac"
+	"encoding/binary"
+)
+
+// copied from https://github.com/cloudflare/tls-tris/blob/master/hkdf.go
+func hkdfExtract(hash crypto.Hash, secret, salt []byte) []byte {
+	if salt == nil {
+		salt = make([]byte, hash.Size())
+	}
+	if secret == nil {
+		secret = make([]byte, hash.Size())
+	}
+	extractor := hmac.New(hash.New, salt)
+	extractor.Write(secret)
+	return extractor.Sum(nil)
+}
+
+// copied from https://github.com/cloudflare/tls-tris/blob/master/hkdf.go
+func hkdfExpand(hash crypto.Hash, prk, info []byte, l int) []byte {
+	var (
+		expander = hmac.New(hash.New, prk)
+		res      = make([]byte, l)
+		counter  = byte(1)
+		prev     []byte
+	)
+
+	if l > 255*expander.Size() {
+		panic("hkdf: requested too much output")
+	}
+
+	p := res
+	for len(p) > 0 {
+		expander.Reset()
+		expander.Write(prev)
+		expander.Write(info)
+		expander.Write([]byte{counter})
+		prev = expander.Sum(prev[:0])
+		counter++
+		n := copy(p, prev)
+		p = p[n:]
+	}
+
+	return res
+}
+
+func qhkdfExpand(secret []byte, label string, length int) []byte {
+	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))
+	return hkdfExpand(crypto.SHA256, secret, qlabel, length)
+}

+ 0 - 11
vendor/github.com/lucas-clemente/quic-go/internal/crypto/key_derivation.go

@@ -1,9 +1,6 @@
 package crypto
 
 import (
-	"crypto"
-	"encoding/binary"
-
 	"github.com/bifurcation/mint"
 	"github.com/lucas-clemente/quic-go/internal/protocol"
 )
@@ -19,14 +16,6 @@ type TLSExporter interface {
 	ComputeExporter(label string, context []byte, keyLength int) ([]byte, error)
 }
 
-func qhkdfExpand(secret []byte, label string, length int) []byte {
-	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))
-	return mint.HkdfExpand(crypto.SHA256, secret, qlabel, length)
-}
-
 // DeriveAESKeys derives the AES keys and creates a matching AES-GCM AEAD instance
 func DeriveAESKeys(tls TLSExporter, pers protocol.Perspective) (AEAD, error) {
 	var myLabel, otherLabel string

+ 1 - 2
vendor/github.com/lucas-clemente/quic-go/internal/crypto/null_aead_aesgcm.go

@@ -3,7 +3,6 @@ package crypto
 import (
 	"crypto"
 
-	"github.com/bifurcation/mint"
 	"github.com/lucas-clemente/quic-go/internal/protocol"
 )
 
@@ -28,7 +27,7 @@ func newNullAEADAESGCM(connectionID protocol.ConnectionID, pers protocol.Perspec
 }
 
 func computeSecrets(connID protocol.ConnectionID) (clientSecret, serverSecret []byte) {
-	handshakeSecret := mint.HkdfExtract(crypto.SHA256, quicVersion1Salt, connID)
+	handshakeSecret := hkdfExtract(crypto.SHA256, connID, quicVersion1Salt)
 	clientSecret = qhkdfExpand(handshakeSecret, "client hs", crypto.SHA256.Size())
 	serverSecret = qhkdfExpand(handshakeSecret, "server hs", crypto.SHA256.Size())
 	return

+ 3 - 4
vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup_client.go

@@ -69,10 +69,9 @@ var (
 // NewCryptoSetupClient creates a new CryptoSetup instance for a client
 func NewCryptoSetupClient(
 	cryptoStream io.ReadWriter,
-	hostname string,
 	connID protocol.ConnectionID,
 	version protocol.VersionNumber,
-	tlsConfig *tls.Config,
+	tlsConf *tls.Config,
 	params *TransportParameters,
 	paramsChan chan<- TransportParameters,
 	handshakeEvent chan<- struct{},
@@ -87,10 +86,10 @@ func NewCryptoSetupClient(
 	divNonceChan := make(chan struct{})
 	cs := &cryptoSetupClient{
 		cryptoStream:   cryptoStream,
-		hostname:       hostname,
+		hostname:       tlsConf.ServerName,
 		connID:         connID,
 		version:        version,
-		certManager:    crypto.NewCertManager(tlsConfig),
+		certManager:    crypto.NewCertManager(tlsConf),
 		params:         params,
 		keyDerivation:  crypto.DeriveQuicCryptoAESKeys,
 		nullAEAD:       nullAEAD,

+ 0 - 7
vendor/github.com/lucas-clemente/quic-go/internal/handshake/transport_parameters.go

@@ -3,7 +3,6 @@ package handshake
 import (
 	"bytes"
 	"encoding/binary"
-	"errors"
 	"fmt"
 	"time"
 
@@ -97,8 +96,6 @@ func (p *TransportParameters) getHelloMap() map[Tag][]byte {
 }
 
 func (p *TransportParameters) unmarshal(data []byte) error {
-	var foundIdleTimeout bool
-
 	for len(data) >= 4 {
 		paramID := binary.BigEndian.Uint16(data[:2])
 		paramLen := int(binary.BigEndian.Uint16(data[2:4]))
@@ -128,7 +125,6 @@ func (p *TransportParameters) unmarshal(data []byte) error {
 			}
 			p.MaxUniStreams = binary.BigEndian.Uint16(data[:2])
 		case idleTimeoutParameterID:
-			foundIdleTimeout = true
 			if paramLen != 2 {
 				return fmt.Errorf("wrong length for idle_timeout: %d (expected 2)", paramLen)
 			}
@@ -159,9 +155,6 @@ func (p *TransportParameters) unmarshal(data []byte) error {
 	if len(data) != 0 {
 		return fmt.Errorf("should have read all data. Still have %d bytes", len(data))
 	}
-	if !foundIdleTimeout {
-		return errors.New("missing parameter")
-	}
 	return nil
 }
 

+ 15 - 19
vendor/github.com/lucas-clemente/quic-go/internal/wire/ack_frame.go

@@ -19,23 +19,17 @@ type AckFrame struct {
 	DelayTime time.Duration
 }
 
-func parseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) {
-	return parseAckOrAckEcnFrame(r, false, version)
-}
-
-func parseAckEcnFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) {
-	return parseAckOrAckEcnFrame(r, true, version)
-}
-
 // parseAckFrame reads an ACK frame
-func parseAckOrAckEcnFrame(r *bytes.Reader, ecn bool, version protocol.VersionNumber) (*AckFrame, error) {
+func parseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) {
 	if !version.UsesIETFFrameFormat() {
 		return parseAckFrameLegacy(r, version)
 	}
 
-	if _, err := r.ReadByte(); err != nil {
+	typeByte, err := r.ReadByte()
+	if err != nil {
 		return nil, err
 	}
+	ecn := typeByte&0x1 > 0
 
 	frame := &AckFrame{}
 
@@ -50,14 +44,6 @@ func parseAckOrAckEcnFrame(r *bytes.Reader, ecn bool, version protocol.VersionNu
 	}
 	frame.DelayTime = time.Duration(delay*1<<ackDelayExponent) * time.Microsecond
 
-	if ecn {
-		for i := 0; i < 3; i++ {
-			if _, err := utils.ReadVarInt(r); err != nil {
-				return nil, err
-			}
-		}
-	}
-
 	numBlocks, err := utils.ReadVarInt(r)
 	if err != nil {
 		return nil, err
@@ -103,6 +89,16 @@ func parseAckOrAckEcnFrame(r *bytes.Reader, ecn bool, version protocol.VersionNu
 	if !frame.validateAckRanges() {
 		return nil, errInvalidAckRanges
 	}
+
+	// parse (and skip) the ECN section
+	if ecn {
+		for i := 0; i < 3; i++ {
+			if _, err := utils.ReadVarInt(r); err != nil {
+				return nil, err
+			}
+		}
+	}
+
 	return frame, nil
 }
 
@@ -112,7 +108,7 @@ func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error
 		return f.writeLegacy(b, version)
 	}
 
-	b.WriteByte(0x0d)
+	b.WriteByte(0x1a)
 	utils.WriteVarInt(b, uint64(f.LargestAcked()))
 	utils.WriteVarInt(b, encodeAckDelay(f.DelayTime))
 

+ 2 - 7
vendor/github.com/lucas-clemente/quic-go/internal/wire/frame_parser.go

@@ -86,11 +86,6 @@ func parseIETFFrame(r *bytes.Reader, typeByte byte, v protocol.VersionNumber) (F
 		if err != nil {
 			err = qerr.Error(qerr.InvalidFrameData, err.Error())
 		}
-	case 0xd:
-		frame, err = parseAckFrame(r, v)
-		if err != nil {
-			err = qerr.Error(qerr.InvalidAckData, err.Error())
-		}
 	case 0xe:
 		frame, err = parsePathChallengeFrame(r, v)
 		if err != nil {
@@ -101,8 +96,8 @@ func parseIETFFrame(r *bytes.Reader, typeByte byte, v protocol.VersionNumber) (F
 		if err != nil {
 			err = qerr.Error(qerr.InvalidFrameData, err.Error())
 		}
-	case 0x1a:
-		frame, err = parseAckEcnFrame(r, v)
+	case 0x1a, 0x1b:
+		frame, err = parseAckFrame(r, v)
 		if err != nil {
 			err = qerr.Error(qerr.InvalidAckData, err.Error())
 		}

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

@@ -5,10 +5,13 @@ package quic
 //go:generate sh -c "./mockgen_private.sh quic mock_send_stream_internal_test.go github.com/lucas-clemente/quic-go sendStreamI"
 //go:generate sh -c "./mockgen_private.sh quic mock_stream_sender_test.go github.com/lucas-clemente/quic-go streamSender"
 //go:generate sh -c "./mockgen_private.sh quic mock_stream_getter_test.go github.com/lucas-clemente/quic-go streamGetter"
-//go:generate sh -c "./mockgen_private.sh quic mock_stream_frame_source_test.go github.com/lucas-clemente/quic-go streamFrameSource"
+//go:generate sh -c "./mockgen_private.sh quic mock_frame_source_test.go github.com/lucas-clemente/quic-go frameSource"
+//go:generate sh -c "./mockgen_private.sh quic mock_ack_frame_source_test.go github.com/lucas-clemente/quic-go ackFrameSource"
 //go:generate sh -c "./mockgen_private.sh quic mock_crypto_stream_test.go github.com/lucas-clemente/quic-go cryptoStream"
 //go:generate sh -c "./mockgen_private.sh quic mock_stream_manager_test.go github.com/lucas-clemente/quic-go streamManager"
+//go:generate sh -c "./mockgen_private.sh quic mock_sealing_manager_test.go github.com/lucas-clemente/quic-go sealingManager"
 //go:generate sh -c "./mockgen_private.sh quic mock_unpacker_test.go github.com/lucas-clemente/quic-go unpacker"
+//go:generate sh -c "./mockgen_private.sh quic mock_packer_test.go github.com/lucas-clemente/quic-go packer"
 //go:generate sh -c "./mockgen_private.sh quic mock_quic_aead_test.go github.com/lucas-clemente/quic-go quicAEAD"
 //go:generate sh -c "./mockgen_private.sh quic mock_gquic_aead_test.go github.com/lucas-clemente/quic-go gQUICAEAD"
 //go:generate sh -c "./mockgen_private.sh quic mock_session_runner_test.go github.com/lucas-clemente/quic-go sessionRunner"

+ 148 - 159
vendor/github.com/lucas-clemente/quic-go/packet_packer.go

@@ -5,7 +5,6 @@ import (
 	"errors"
 	"fmt"
 	"net"
-	"sync"
 	"time"
 
 	"github.com/lucas-clemente/quic-go/internal/ackhandler"
@@ -15,6 +14,16 @@ import (
 	"github.com/lucas-clemente/quic-go/internal/wire"
 )
 
+type packer interface {
+	PackPacket() (*packedPacket, error)
+	MaybePackAckPacket() (*packedPacket, error)
+	PackRetransmission(packet *ackhandler.Packet) ([]*packedPacket, error)
+	PackConnectionClose(*wire.ConnectionCloseFrame) (*packedPacket, error)
+
+	HandleTransportParameters(*handshake.TransportParameters)
+	ChangeDestConnectionID(protocol.ConnectionID)
+}
+
 type packedPacket struct {
 	header          *wire.Header
 	raw             []byte
@@ -33,16 +42,45 @@ func (p *packedPacket) ToAckHandlerPacket() *ackhandler.Packet {
 	}
 }
 
+func getMaxPacketSize(addr net.Addr) protocol.ByteCount {
+	maxSize := protocol.ByteCount(protocol.MinInitialPacketSize)
+	// If this is not a UDP address, we don't know anything about the MTU.
+	// Use the minimum size of an Initial packet as the max packet size.
+	if udpAddr, ok := addr.(*net.UDPAddr); ok {
+		// If ip is not an IPv4 address, To4 returns nil.
+		// Note that there might be some corner cases, where this is not correct.
+		// See https://stackoverflow.com/questions/22751035/golang-distinguish-ipv4-ipv6.
+		if udpAddr.IP.To4() == nil {
+			maxSize = protocol.MaxPacketSizeIPv6
+		} else {
+			maxSize = protocol.MaxPacketSizeIPv4
+		}
+	}
+	return maxSize
+}
+
 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
-	PopStreamFrames(protocol.ByteCount) []*wire.StreamFrame
+type frameSource interface {
+	AppendStreamFrames([]wire.Frame, protocol.ByteCount) []wire.Frame
+	AppendControlFrames([]wire.Frame, protocol.ByteCount) ([]wire.Frame, protocol.ByteCount)
+}
+
+// sentAndReceivedPacketManager is only needed until STOP_WAITING is removed
+type sentAndReceivedPacketManager struct {
+	ackhandler.SentPacketHandler
+	ackhandler.ReceivedPacketHandler
+}
+
+var _ ackFrameSource = &sentAndReceivedPacketManager{}
+
+type ackFrameSource interface {
+	GetAckFrame() *wire.AckFrame
+	GetStopWaitingFrame(bool) *wire.StopWaitingFrame
 }
 
 type packetPacker struct {
@@ -58,19 +96,18 @@ type packetPacker struct {
 
 	packetNumberGenerator *packetNumberGenerator
 	getPacketNumberLen    func(protocol.PacketNumber) protocol.PacketNumberLen
-	streams               streamFrameSource
-
-	controlFrameMutex sync.Mutex
-	controlFrames     []wire.Frame
+	cryptoStream          cryptoStream
+	framer                frameSource
+	acks                  ackFrameSource
 
-	stopWaiting               *wire.StopWaitingFrame
-	ackFrame                  *wire.AckFrame
 	omitConnectionID          bool
 	maxPacketSize             protocol.ByteCount
 	hasSentPacket             bool // has the packetPacker already sent a packet
 	numNonRetransmittableAcks int
 }
 
+var _ packer = &packetPacker{}
+
 func newPacketPacker(
 	destConnID protocol.ConnectionID,
 	srcConnID protocol.ConnectionID,
@@ -79,25 +116,15 @@ func newPacketPacker(
 	remoteAddr net.Addr, // only used for determining the max packet size
 	token []byte,
 	divNonce []byte,
+	cryptoStream cryptoStream,
 	cryptoSetup sealingManager,
-	streamFramer streamFrameSource,
+	framer frameSource,
+	acks ackFrameSource,
 	perspective protocol.Perspective,
 	version protocol.VersionNumber,
 ) *packetPacker {
-	maxPacketSize := protocol.ByteCount(protocol.MinInitialPacketSize)
-	// If this is not a UDP address, we don't know anything about the MTU.
-	// Use the minimum size of an Initial packet as the max packet size.
-	if udpAddr, ok := remoteAddr.(*net.UDPAddr); ok {
-		// If ip is not an IPv4 address, To4 returns nil.
-		// Note that there might be some corner cases, where this is not correct.
-		// See https://stackoverflow.com/questions/22751035/golang-distinguish-ipv4-ipv6.
-		if udpAddr.IP.To4() == nil {
-			maxPacketSize = protocol.MaxPacketSizeIPv6
-		} else {
-			maxPacketSize = protocol.MaxPacketSizeIPv4
-		}
-	}
 	return &packetPacker{
+		cryptoStream:          cryptoStream,
 		cryptoSetup:           cryptoSetup,
 		divNonce:              divNonce,
 		token:                 token,
@@ -105,10 +132,11 @@ func newPacketPacker(
 		srcConnID:             srcConnID,
 		perspective:           perspective,
 		version:               version,
-		streams:               streamFramer,
+		framer:                framer,
+		acks:                  acks,
 		getPacketNumberLen:    getPacketNumberLen,
 		packetNumberGenerator: newPacketNumberGenerator(initialPacketNumber, protocol.SkipPacketAveragePeriodLength),
-		maxPacketSize:         maxPacketSize,
+		maxPacketSize:         getMaxPacketSize(remoteAddr),
 	}
 }
 
@@ -126,20 +154,22 @@ func (p *packetPacker) PackConnectionClose(ccf *wire.ConnectionCloseFrame) (*pac
 	}, err
 }
 
-func (p *packetPacker) PackAckPacket() (*packedPacket, error) {
-	if p.ackFrame == nil {
-		return nil, errors.New("packet packer BUG: no ack frame queued")
+func (p *packetPacker) MaybePackAckPacket() (*packedPacket, error) {
+	ack := p.acks.GetAckFrame()
+	if ack == nil {
+		return nil, nil
 	}
 	encLevel, sealer := p.cryptoSetup.GetSealer()
 	header := p.getHeader(encLevel)
-	frames := []wire.Frame{p.ackFrame}
-	if p.stopWaiting != nil { // a STOP_WAITING will only be queued when using gQUIC
-		p.stopWaiting.PacketNumber = header.PacketNumber
-		p.stopWaiting.PacketNumberLen = header.PacketNumberLen
-		frames = append(frames, p.stopWaiting)
-		p.stopWaiting = nil
-	}
-	p.ackFrame = nil
+	frames := []wire.Frame{ack}
+	// add a STOP_WAITING frame, when using gQUIC
+	if p.version.UsesStopWaitingFrames() {
+		if swf := p.acks.GetStopWaitingFrame(false); swf != nil {
+			swf.PacketNumber = header.PacketNumber
+			swf.PacketNumberLen = header.PacketNumberLen
+			frames = append(frames, swf)
+		}
+	}
 	raw, err := p.writeAndSealPacket(header, frames, sealer)
 	return &packedPacket{
 		header:          header,
@@ -171,9 +201,14 @@ func (p *packetPacker) PackRetransmission(packet *ackhandler.Packet) ([]*packedP
 
 	var packets []*packedPacket
 	encLevel, sealer := p.cryptoSetup.GetSealer()
+	var swf *wire.StopWaitingFrame
+	// for gQUIC: add a STOP_WAITING for *every* retransmission
+	if p.version.UsesStopWaitingFrames() {
+		swf = p.acks.GetStopWaitingFrame(true)
+	}
 	for len(controlFrames) > 0 || len(streamFrames) > 0 {
 		var frames []wire.Frame
-		var payloadLength protocol.ByteCount
+		var length protocol.ByteCount
 
 		header := p.getHeader(encLevel)
 		headerLength, err := header.GetLength(p.version)
@@ -182,48 +217,34 @@ func (p *packetPacker) PackRetransmission(packet *ackhandler.Packet) ([]*packedP
 		}
 		maxSize := p.maxPacketSize - protocol.ByteCount(sealer.Overhead()) - headerLength
 
-		// for gQUIC: add a STOP_WAITING for *every* retransmission
 		if p.version.UsesStopWaitingFrames() {
-			if p.stopWaiting == nil {
-				return nil, errors.New("PacketPacker BUG: Handshake retransmissions must contain a STOP_WAITING frame")
-			}
-			// create a new StopWaitingFrame, since we might need to send more than one packet as a retransmission
-			swf := &wire.StopWaitingFrame{
-				LeastUnacked:    p.stopWaiting.LeastUnacked,
+			// create a new STOP_WAIITNG Frame, since we might need to send more than one packet as a retransmission
+			stopWaitingFrame := &wire.StopWaitingFrame{
+				LeastUnacked:    swf.LeastUnacked,
 				PacketNumber:    header.PacketNumber,
 				PacketNumberLen: header.PacketNumberLen,
 			}
-			payloadLength += swf.Length(p.version)
-			frames = append(frames, swf)
+			length += stopWaitingFrame.Length(p.version)
+			frames = append(frames, stopWaitingFrame)
 		}
 
 		for len(controlFrames) > 0 {
 			frame := controlFrames[0]
-			length := frame.Length(p.version)
-			if payloadLength+length > maxSize {
+			frameLen := frame.Length(p.version)
+			if length+frameLen > maxSize {
 				break
 			}
-			payloadLength += length
+			length += frameLen
 			frames = append(frames, frame)
 			controlFrames = controlFrames[1:]
 		}
 
-		// temporarily increase the maxFrameSize by the (minimum) length of the DataLen field
-		// this leads to a properly sized packet in all cases, since we do all the packet length calculations with StreamFrames that have the DataLen set
-		// however, for the last STREAM frame in the packet, we can omit the DataLen, thus yielding a packet of exactly the correct size
-		// for gQUIC STREAM frames, DataLen is always 2 bytes
-		// for IETF draft style STREAM frames, the length is encoded to either 1 or 2 bytes
-		if p.version.UsesIETFFrameFormat() {
-			maxSize++
-		} else {
-			maxSize += 2
-		}
-		for len(streamFrames) > 0 && payloadLength+protocol.MinStreamFrameSize < maxSize {
-			// TODO: optimize by setting DataLenPresent = false on all but the last STREAM frame
+		for len(streamFrames) > 0 && length+protocol.MinStreamFrameSize < maxSize {
 			frame := streamFrames[0]
+			frame.DataLenPresent = false
 			frameToAdd := frame
 
-			sf, err := frame.MaybeSplitOffFrame(maxSize-payloadLength, p.version)
+			sf, err := frame.MaybeSplitOffFrame(maxSize-length, p.version)
 			if err != nil {
 				return nil, err
 			}
@@ -232,7 +253,8 @@ func (p *packetPacker) PackRetransmission(packet *ackhandler.Packet) ([]*packedP
 			} else {
 				streamFrames = streamFrames[1:]
 			}
-			payloadLength += frameToAdd.Length(p.version)
+			frame.DataLenPresent = true
+			length += frameToAdd.Length(p.version)
 			frames = append(frames, frameToAdd)
 		}
 		if sf, ok := frames[len(frames)-1].(*wire.StreamFrame); ok {
@@ -249,7 +271,6 @@ func (p *packetPacker) PackRetransmission(packet *ackhandler.Packet) ([]*packedP
 			encryptionLevel: encLevel,
 		})
 	}
-	p.stopWaiting = nil
 	return packets, nil
 }
 
@@ -267,13 +288,9 @@ func (p *packetPacker) packHandshakeRetransmission(packet *ackhandler.Packet) (*
 	header.Type = packet.PacketType
 	var frames []wire.Frame
 	if p.version.UsesStopWaitingFrames() { // for gQUIC: pack a STOP_WAITING first
-		if p.stopWaiting == nil {
-			return nil, errors.New("PacketPacker BUG: Handshake retransmissions must contain a STOP_WAITING frame")
-		}
-		swf := p.stopWaiting
+		swf := p.acks.GetStopWaitingFrame(true)
 		swf.PacketNumber = header.PacketNumber
 		swf.PacketNumberLen = header.PacketNumberLen
-		p.stopWaiting = nil
 		frames = append([]wire.Frame{swf}, packet.Frames...)
 	} else {
 		frames = packet.Frames
@@ -290,14 +307,17 @@ func (p *packetPacker) packHandshakeRetransmission(packet *ackhandler.Packet) (*
 // PackPacket packs a new packet
 // the other controlFrames are sent in the next packet, but might be queued and sent in the next packet if the packet would overflow MaxPacketSize otherwise
 func (p *packetPacker) PackPacket() (*packedPacket, error) {
-	hasCryptoStreamFrame := p.streams.HasCryptoStreamData()
+	packet, err := p.maybePackCryptoPacket()
+	if err != nil {
+		return nil, err
+	}
+	if packet != nil {
+		return packet, nil
+	}
 	// if this is the first packet to be send, make sure it contains stream data
-	if !p.hasSentPacket && !hasCryptoStreamFrame {
+	if !p.hasSentPacket && packet == nil {
 		return nil, nil
 	}
-	if hasCryptoStreamFrame {
-		return p.packCryptoPacket()
-	}
 
 	encLevel, sealer := p.cryptoSetup.GetSealer()
 
@@ -306,54 +326,45 @@ func (p *packetPacker) PackPacket() (*packedPacket, error) {
 	if err != nil {
 		return nil, err
 	}
-	if p.stopWaiting != nil {
-		p.stopWaiting.PacketNumber = header.PacketNumber
-		p.stopWaiting.PacketNumberLen = header.PacketNumberLen
-	}
 
 	maxSize := p.maxPacketSize - protocol.ByteCount(sealer.Overhead()) - headerLength
-	payloadFrames, err := p.composeNextPacket(maxSize, p.canSendData(encLevel))
+	frames, err := p.composeNextPacket(header, maxSize, p.canSendData(encLevel))
 	if err != nil {
 		return nil, err
 	}
 
 	// Check if we have enough frames to send
-	if len(payloadFrames) == 0 {
-		return nil, nil
-	}
-	// Don't send out packets that only contain a StopWaitingFrame
-	if len(payloadFrames) == 1 && p.stopWaiting != nil {
+	if len(frames) == 0 {
 		return nil, nil
 	}
-	if p.ackFrame != nil {
-		// check if this packet only contains an ACK (and maybe a STOP_WAITING)
-		if len(payloadFrames) == 1 || (p.stopWaiting != nil && len(payloadFrames) == 2) {
-			if p.numNonRetransmittableAcks >= protocol.MaxNonRetransmittableAcks {
-				payloadFrames = append(payloadFrames, &wire.PingFrame{})
-				p.numNonRetransmittableAcks = 0
-			} else {
-				p.numNonRetransmittableAcks++
-			}
-		} else {
+	// check if this packet only contains an ACK (and maybe a STOP_WAITING)
+	if !ackhandler.HasRetransmittableFrames(frames) {
+		if p.numNonRetransmittableAcks >= protocol.MaxNonRetransmittableAcks {
+			frames = append(frames, &wire.PingFrame{})
 			p.numNonRetransmittableAcks = 0
+		} else {
+			p.numNonRetransmittableAcks++
 		}
+	} else {
+		p.numNonRetransmittableAcks = 0
 	}
-	p.stopWaiting = nil
-	p.ackFrame = nil
 
-	raw, err := p.writeAndSealPacket(header, payloadFrames, sealer)
+	raw, err := p.writeAndSealPacket(header, frames, sealer)
 	if err != nil {
 		return nil, err
 	}
 	return &packedPacket{
 		header:          header,
 		raw:             raw,
-		frames:          payloadFrames,
+		frames:          frames,
 		encryptionLevel: encLevel,
 	}, nil
 }
 
-func (p *packetPacker) packCryptoPacket() (*packedPacket, error) {
+func (p *packetPacker) maybePackCryptoPacket() (*packedPacket, error) {
+	if !p.cryptoStream.hasData() {
+		return nil, nil
+	}
 	encLevel, sealer := p.cryptoSetup.GetSealerForCryptoStream()
 	header := p.getHeader(encLevel)
 	headerLength, err := header.GetLength(p.version)
@@ -361,7 +372,7 @@ func (p *packetPacker) packCryptoPacket() (*packedPacket, error) {
 		return nil, err
 	}
 	maxLen := p.maxPacketSize - protocol.ByteCount(sealer.Overhead()) - protocol.NonForwardSecurePacketSizeReduction - headerLength
-	sf := p.streams.PopCryptoStreamFrame(maxLen)
+	sf, _ := p.cryptoStream.popStreamFrame(maxLen)
 	sf.DataLenPresent = false
 	frames := []wire.Frame{sf}
 	raw, err := p.writeAndSealPacket(header, frames, sealer)
@@ -377,42 +388,35 @@ func (p *packetPacker) packCryptoPacket() (*packedPacket, error) {
 }
 
 func (p *packetPacker) composeNextPacket(
+	header *wire.Header, // only needed to fill in the STOP_WAITING frame
 	maxFrameSize protocol.ByteCount,
 	canSendStreamFrames bool,
 ) ([]wire.Frame, error) {
-	var payloadLength protocol.ByteCount
-	var payloadFrames []wire.Frame
+	var length protocol.ByteCount
+	var frames []wire.Frame
 
 	// STOP_WAITING and ACK will always fit
-	if p.ackFrame != nil { // ACKs need to go first, so that the sentPacketHandler will recognize them
-		payloadFrames = append(payloadFrames, p.ackFrame)
-		l := p.ackFrame.Length(p.version)
-		payloadLength += l
-	}
-	if p.stopWaiting != nil { // a STOP_WAITING will only be queued when using gQUIC
-		payloadFrames = append(payloadFrames, p.stopWaiting)
-		payloadLength += p.stopWaiting.Length(p.version)
-	}
-
-	p.controlFrameMutex.Lock()
-	for len(p.controlFrames) > 0 {
-		frame := p.controlFrames[len(p.controlFrames)-1]
-		length := frame.Length(p.version)
-		if payloadLength+length > maxFrameSize {
-			break
+	// ACKs need to go first, so that the sentPacketHandler will recognize them
+	if ack := p.acks.GetAckFrame(); ack != nil {
+		frames = append(frames, ack)
+		length += ack.Length(p.version)
+		// add a STOP_WAITING, for gQUIC
+		if p.version.UsesStopWaitingFrames() {
+			if swf := p.acks.GetStopWaitingFrame(false); swf != nil {
+				swf.PacketNumber = header.PacketNumber
+				swf.PacketNumberLen = header.PacketNumberLen
+				frames = append(frames, swf)
+				length += swf.Length(p.version)
+			}
 		}
-		payloadFrames = append(payloadFrames, frame)
-		payloadLength += length
-		p.controlFrames = p.controlFrames[:len(p.controlFrames)-1]
 	}
-	p.controlFrameMutex.Unlock()
 
-	if payloadLength > maxFrameSize {
-		return nil, fmt.Errorf("Packet Packer BUG: packet payload (%d) too large (%d)", payloadLength, maxFrameSize)
-	}
+	var lengthAdded protocol.ByteCount
+	frames, lengthAdded = p.framer.AppendControlFrames(frames, maxFrameSize-length)
+	length += lengthAdded
 
 	if !canSendStreamFrames {
-		return payloadFrames, nil
+		return frames, nil
 	}
 
 	// temporarily increase the maxFrameSize by the (minimum) length of the DataLen field
@@ -426,28 +430,14 @@ func (p *packetPacker) composeNextPacket(
 		maxFrameSize += 2
 	}
 
-	fs := p.streams.PopStreamFrames(maxFrameSize - payloadLength)
-	if len(fs) != 0 {
-		fs[len(fs)-1].DataLenPresent = false
-	}
-
-	for _, f := range fs {
-		payloadFrames = append(payloadFrames, f)
-	}
-	return payloadFrames, nil
-}
-
-func (p *packetPacker) QueueControlFrame(frame wire.Frame) {
-	switch f := frame.(type) {
-	case *wire.StopWaitingFrame:
-		p.stopWaiting = f
-	case *wire.AckFrame:
-		p.ackFrame = f
-	default:
-		p.controlFrameMutex.Lock()
-		p.controlFrames = append(p.controlFrames, f)
-		p.controlFrameMutex.Unlock()
+	frames = p.framer.AppendStreamFrames(frames, maxFrameSize-length)
+	if len(frames) > 0 {
+		lastFrame := frames[len(frames)-1]
+		if sf, ok := lastFrame.(*wire.StreamFrame); ok {
+			sf.DataLenPresent = false
+		}
 	}
+	return frames, nil
 }
 
 func (p *packetPacker) getHeader(encLevel protocol.EncryptionLevel) *wire.Header {
@@ -494,7 +484,7 @@ func (p *packetPacker) getHeader(encLevel protocol.EncryptionLevel) *wire.Header
 
 func (p *packetPacker) writeAndSealPacket(
 	header *wire.Header,
-	payloadFrames []wire.Frame,
+	frames []wire.Frame,
 	sealer handshake.Sealer,
 ) ([]byte, error) {
 	raw := *getPacketBuffer()
@@ -507,7 +497,7 @@ func (p *packetPacker) writeAndSealPacket(
 			header.PayloadLen = protocol.ByteCount(protocol.MinInitialPacketSize) - headerLen
 		} else {
 			payloadLen := protocol.ByteCount(sealer.Overhead())
-			for _, frame := range payloadFrames {
+			for _, frame := range frames {
 				payloadLen += frame.Length(p.version)
 			}
 			header.PayloadLen = payloadLen
@@ -521,12 +511,12 @@ func (p *packetPacker) writeAndSealPacket(
 
 	// the Initial packet needs to be padded, so the last STREAM frame must have the data length present
 	if header.Type == protocol.PacketTypeInitial {
-		lastFrame := payloadFrames[len(payloadFrames)-1]
+		lastFrame := frames[len(frames)-1]
 		if sf, ok := lastFrame.(*wire.StreamFrame); ok {
 			sf.DataLenPresent = true
 		}
 	}
-	for _, frame := range payloadFrames {
+	for _, frame := range frames {
 		if err := frame.Write(buffer, p.version); err != nil {
 			return nil, err
 		}
@@ -563,14 +553,13 @@ func (p *packetPacker) canSendData(encLevel protocol.EncryptionLevel) bool {
 	return encLevel == protocol.EncryptionForwardSecure
 }
 
-func (p *packetPacker) SetOmitConnectionID() {
-	p.omitConnectionID = true
-}
-
 func (p *packetPacker) ChangeDestConnectionID(connID protocol.ConnectionID) {
 	p.destConnID = connID
 }
 
-func (p *packetPacker) SetMaxPacketSize(size protocol.ByteCount) {
-	p.maxPacketSize = utils.MinByteCount(p.maxPacketSize, size)
+func (p *packetPacker) HandleTransportParameters(params *handshake.TransportParameters) {
+	p.omitConnectionID = params.OmitConnectionID
+	if params.MaxPacketSize != 0 {
+		p.maxPacketSize = utils.MinByteCount(p.maxPacketSize, params.MaxPacketSize)
+	}
 }

+ 3 - 1
vendor/github.com/lucas-clemente/quic-go/receive_stream.go

@@ -164,7 +164,9 @@ func (s *receiveStream) readImpl(p []byte) (bool /*stream completed */, int, err
 			s.flowController.AddBytesRead(protocol.ByteCount(m))
 		}
 		// increase the flow control window, if necessary
-		s.flowController.MaybeQueueWindowUpdate()
+		if s.streamID != s.version.CryptoStreamID() {
+			s.flowController.MaybeQueueWindowUpdate()
+		}
 
 		if s.readPosInFrame >= len(s.currentFrame) && s.currentFrameIsLast {
 			s.finRead = true

+ 8 - 1
vendor/github.com/lucas-clemente/quic-go/send_stream.go

@@ -15,6 +15,7 @@ import (
 type sendStreamI interface {
 	SendStream
 	handleStopSendingFrame(*wire.StopSendingFrame)
+	hasData() bool
 	popStreamFrame(maxBytes protocol.ByteCount) (*wire.StreamFrame, bool)
 	closeForShutdown(error)
 	handleMaxStreamDataFrame(*wire.MaxStreamDataFrame)
@@ -181,12 +182,18 @@ func (s *sendStream) popStreamFrameImpl(maxBytes protocol.ByteCount) (bool /* co
 	return frame.FinBit, frame, s.dataForWriting != nil
 }
 
+func (s *sendStream) hasData() bool {
+	s.mutex.Lock()
+	hasData := len(s.dataForWriting) > 0
+	s.mutex.Unlock()
+	return hasData
+}
+
 func (s *sendStream) getDataForWriting(maxBytes protocol.ByteCount) ([]byte, bool /* should send FIN */) {
 	if s.dataForWriting == nil {
 		return nil, s.finishedWriting && !s.finSent
 	}
 
-	// TODO(#657): Flow control for the crypto stream
 	if s.streamID != s.version.CryptoStreamID() {
 		maxBytes = utils.MinByteCount(maxBytes, s.flowController.SendWindowSize())
 	}

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

@@ -92,12 +92,12 @@ type session struct {
 
 	sentPacketHandler     ackhandler.SentPacketHandler
 	receivedPacketHandler ackhandler.ReceivedPacketHandler
-	streamFramer          *streamFramer
+	framer                *framer
 	windowUpdateQueue     *windowUpdateQueue
 	connFlowController    flowcontrol.ConnectionFlowController
 
 	unpacker unpacker
-	packer   *packetPacker
+	packer   packer
 
 	cryptoStreamHandler cryptoStreamHandler
 
@@ -205,7 +205,7 @@ func newSession(
 	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.framer = newFramer(s.cryptoStream, s.streamsMap, s.version)
 	s.packer = newPacketPacker(
 		destConnID,
 		srcConnID,
@@ -214,8 +214,10 @@ func newSession(
 		s.RemoteAddr(),
 		nil, // no token
 		divNonce,
+		s.cryptoStream,
 		cs,
-		s.streamFramer,
+		s.framer,
+		sentAndReceivedPacketManager{s.sentPacketHandler, s.receivedPacketHandler},
 		s.perspective,
 		s.version,
 	)
@@ -226,7 +228,6 @@ func newSession(
 var newClientSession = func(
 	conn connection,
 	sessionRunner sessionRunner,
-	hostname string,
 	v protocol.VersionNumber,
 	destConnID protocol.ConnectionID,
 	srcConnID protocol.ConnectionID,
@@ -261,7 +262,6 @@ var newClientSession = func(
 	}
 	cs, err := newCryptoSetupClient(
 		s.cryptoStream,
-		hostname,
 		destConnID,
 		s.version,
 		tlsConf,
@@ -278,7 +278,7 @@ var newClientSession = func(
 	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.framer = newFramer(s.cryptoStream, s.streamsMap, s.version)
 	s.packer = newPacketPacker(
 		destConnID,
 		srcConnID,
@@ -287,8 +287,10 @@ var newClientSession = func(
 		s.RemoteAddr(),
 		nil, // no token
 		nil, // no diversification nonce
+		s.cryptoStream,
 		cs,
-		s.streamFramer,
+		s.framer,
+		sentAndReceivedPacketManager{s.sentPacketHandler, s.receivedPacketHandler},
 		s.perspective,
 		s.version,
 	)
@@ -333,7 +335,7 @@ func newTLSServerSession(
 	}
 	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.framer = newFramer(s.cryptoStream, s.streamsMap, s.version)
 	s.packer = newPacketPacker(
 		s.destConnID,
 		s.srcConnID,
@@ -342,8 +344,10 @@ func newTLSServerSession(
 		s.RemoteAddr(),
 		nil, // no token
 		nil, // no diversification nonce
+		s.cryptoStream,
 		cs,
-		s.streamFramer,
+		s.framer,
+		sentAndReceivedPacketManager{s.sentPacketHandler, s.receivedPacketHandler},
 		s.perspective,
 		s.version,
 	)
@@ -397,7 +401,7 @@ var newTLSClientSession = func(
 	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.framer = newFramer(s.cryptoStream, s.streamsMap, s.version)
 	s.packer = newPacketPacker(
 		s.destConnID,
 		s.srcConnID,
@@ -406,8 +410,10 @@ var newTLSClientSession = func(
 		s.RemoteAddr(),
 		token,
 		nil, // no diversification nonce
+		s.cryptoStream,
 		cs,
-		s.streamFramer,
+		s.framer,
+		sentAndReceivedPacketManager{s.sentPacketHandler, s.receivedPacketHandler},
 		s.perspective,
 		s.version,
 	)
@@ -417,6 +423,7 @@ var newTLSClientSession = func(
 func (s *session) preSetup() {
 	s.rttStats = &congestion.RTTStats{}
 	s.sentPacketHandler = ackhandler.NewSentPacketHandler(s.rttStats, s.logger, s.version)
+	s.receivedPacketHandler = ackhandler.NewReceivedPacketHandler(s.rttStats, s.logger, s.version)
 	s.connFlowController = flowcontrol.NewConnectionFlowController(
 		protocol.ReceiveConnectionFlowControlWindow,
 		protocol.ByteCount(s.config.MaxReceiveConnectionFlowControlWindow),
@@ -439,8 +446,7 @@ func (s *session) postSetup() error {
 	s.lastNetworkActivityTime = now
 	s.sessionCreationTime = now
 
-	s.receivedPacketHandler = ackhandler.NewReceivedPacketHandler(s.rttStats, s.logger, s.version)
-	s.windowUpdateQueue = newWindowUpdateQueue(s.streamsMap, s.cryptoStream, s.connFlowController, s.packer.QueueControlFrame)
+	s.windowUpdateQueue = newWindowUpdateQueue(s.streamsMap, s.connFlowController, s.framer.QueueControlFrame)
 	return nil
 }
 
@@ -496,6 +502,7 @@ runLoop:
 			putPacketBuffer(&p.header.Raw)
 		case p := <-s.paramsChan:
 			s.processTransportParameters(&p)
+			continue
 		case _, ok := <-s.handshakeEvent:
 			// when the handshake is completed, the channel will be closed
 			s.handleHandshakeEvent(!ok)
@@ -517,7 +524,7 @@ runLoop:
 		if s.config.KeepAlive && !s.keepAlivePingSent && s.handshakeComplete && time.Since(s.lastNetworkActivityTime) >= s.peerParams.IdleTimeout/2 {
 			// send a PING frame since there is no activity in the session
 			s.logger.Debugf("Sending a keep-alive ping to keep the connection alive.")
-			s.packer.QueueControlFrame(&wire.PingFrame{})
+			s.framer.QueueControlFrame(&wire.PingFrame{})
 			s.keepAlivePingSent = true
 		} else if !pacingDeadline.IsZero() && now.Before(pacingDeadline) {
 			// If we get to this point before the pacing deadline, we should wait until that deadline.
@@ -527,18 +534,21 @@ runLoop:
 			continue
 		}
 
-		if err := s.sendPackets(); err != nil {
-			s.closeLocal(err)
-		}
-
 		if !s.receivedTooManyUndecrytablePacketsTime.IsZero() && s.receivedTooManyUndecrytablePacketsTime.Add(protocol.PublicResetTimeout).Before(now) && len(s.undecryptablePackets) != 0 {
 			s.closeLocal(qerr.Error(qerr.DecryptionFailure, "too many undecryptable packets received"))
+			continue
 		}
 		if !s.handshakeComplete && now.Sub(s.sessionCreationTime) >= s.config.HandshakeTimeout {
 			s.closeLocal(qerr.Error(qerr.HandshakeTimeout, "Crypto handshake did not complete in time."))
+			continue
 		}
 		if s.handshakeComplete && now.Sub(s.lastNetworkActivityTime) >= s.config.IdleTimeout {
 			s.closeLocal(qerr.Error(qerr.NetworkIdleTimeout, "No recent network activity."))
+			continue
+		}
+
+		if err := s.sendPackets(); err != nil {
+			s.closeLocal(err)
 		}
 	}
 
@@ -906,12 +916,7 @@ func (s *session) handleCloseError(closeErr closeError) error {
 func (s *session) processTransportParameters(params *handshake.TransportParameters) {
 	s.peerParams = params
 	s.streamsMap.UpdateLimits(params)
-	if params.OmitConnectionID {
-		s.packer.SetOmitConnectionID()
-	}
-	if params.MaxPacketSize != 0 {
-		s.packer.SetMaxPacketSize(params.MaxPacketSize)
-	}
+	s.packer.HandleTransportParameters(params)
 	s.connFlowController.UpdateSendWindow(params.ConnectionFlowControlWindow)
 	// the crypto stream is the only open stream at this moment
 	// so we don't need to update stream flow control windows
@@ -933,6 +938,12 @@ sendLoop:
 		case ackhandler.SendNone:
 			break sendLoop
 		case ackhandler.SendAck:
+			// If we already sent packets, and the send mode switches to SendAck,
+			// we've just become congestion limited.
+			// There's no need to try to send an ACK at this moment.
+			if numPacketsSent > 0 {
+				return nil
+			}
 			// We can at most send a single ACK only packet.
 			// 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.
@@ -978,21 +989,13 @@ sendLoop:
 }
 
 func (s *session) maybeSendAckOnlyPacket() error {
-	ack := s.receivedPacketHandler.GetAckFrame()
-	if ack == nil {
-		return nil
-	}
-	s.packer.QueueControlFrame(ack)
-
-	if s.version.UsesStopWaitingFrames() { // for gQUIC, maybe add a STOP_WAITING
-		if swf := s.sentPacketHandler.GetStopWaitingFrame(false); swf != nil {
-			s.packer.QueueControlFrame(swf)
-		}
-	}
-	packet, err := s.packer.PackAckPacket()
+	packet, err := s.packer.MaybePackAckPacket()
 	if err != nil {
 		return err
 	}
+	if packet == nil {
+		return nil
+	}
 	s.sentPacketHandler.SentPacket(packet.ToAckHandlerPacket())
 	return s.sendPackedPacket(packet)
 }
@@ -1023,9 +1026,6 @@ func (s *session) maybeSendRetransmission() (bool, error) {
 		s.logger.Debugf("Dequeueing retransmission for packet 0x%x", retransmitPacket.PacketNumber)
 	}
 
-	if s.version.UsesStopWaitingFrames() {
-		s.packer.QueueControlFrame(s.sentPacketHandler.GetStopWaitingFrame(true))
-	}
 	packets, err := s.packer.PackRetransmission(retransmitPacket)
 	if err != nil {
 		return false, err
@@ -1050,9 +1050,6 @@ func (s *session) sendProbePacket() error {
 	}
 	s.logger.Debugf("Sending a retransmission for %#x as a probe packet.", p.PacketNumber)
 
-	if s.version.UsesStopWaitingFrames() {
-		s.packer.QueueControlFrame(s.sentPacketHandler.GetStopWaitingFrame(true))
-	}
 	packets, err := s.packer.PackRetransmission(p)
 	if err != nil {
 		return err
@@ -1072,19 +1069,10 @@ func (s *session) sendProbePacket() error {
 
 func (s *session) sendPacket() (bool, error) {
 	if isBlocked, offset := s.connFlowController.IsNewlyBlocked(); isBlocked {
-		s.packer.QueueControlFrame(&wire.BlockedFrame{Offset: offset})
+		s.framer.QueueControlFrame(&wire.BlockedFrame{Offset: offset})
 	}
 	s.windowUpdateQueue.QueueAll()
 
-	if ack := s.receivedPacketHandler.GetAckFrame(); ack != nil {
-		s.packer.QueueControlFrame(ack)
-		if s.version.UsesStopWaitingFrames() {
-			if swf := s.sentPacketHandler.GetStopWaitingFrame(false); swf != nil {
-				s.packer.QueueControlFrame(swf)
-			}
-		}
-	}
-
 	packet, err := s.packer.PackPacket()
 	if err != nil || packet == nil {
 		return false, err
@@ -1245,7 +1233,7 @@ func (s *session) tryDecryptingQueuedPackets() {
 }
 
 func (s *session) queueControlFrame(f wire.Frame) {
-	s.packer.QueueControlFrame(f)
+	s.framer.QueueControlFrame(f)
 	s.scheduleSending()
 }
 
@@ -1260,7 +1248,9 @@ func (s *session) onHasConnectionWindowUpdate() {
 }
 
 func (s *session) onHasStreamData(id protocol.StreamID) {
-	s.streamFramer.AddActiveStream(id)
+	if id != s.version.CryptoStreamID() {
+		s.framer.AddActiveStream(id)
+	}
 	s.scheduleSending()
 }
 

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

@@ -52,6 +52,7 @@ type streamI interface {
 	handleRstStreamFrame(*wire.RstStreamFrame) error
 	getWindowUpdate() protocol.ByteCount
 	// for sending
+	hasData() bool
 	handleStopSendingFrame(*wire.StopSendingFrame)
 	popStreamFrame(maxBytes protocol.ByteCount) (*wire.StreamFrame, bool)
 	handleMaxStreamDataFrame(*wire.MaxStreamDataFrame)

+ 4 - 12
vendor/github.com/lucas-clemente/quic-go/window_update_queue.go

@@ -14,7 +14,6 @@ type windowUpdateQueue struct {
 	queue      map[protocol.StreamID]bool // used as a set
 	queuedConn bool                       // connection-level window update
 
-	cryptoStream       cryptoStream
 	streamGetter       streamGetter
 	connFlowController flowcontrol.ConnectionFlowController
 	callback           func(wire.Frame)
@@ -22,14 +21,12 @@ type windowUpdateQueue struct {
 
 func newWindowUpdateQueue(
 	streamGetter streamGetter,
-	cryptoStream cryptoStream,
 	connFC flowcontrol.ConnectionFlowController,
 	cb func(wire.Frame),
 ) *windowUpdateQueue {
 	return &windowUpdateQueue{
 		queue:              make(map[protocol.StreamID]bool),
 		streamGetter:       streamGetter,
-		cryptoStream:       cryptoStream,
 		connFlowController: connFC,
 		callback:           cb,
 	}
@@ -55,17 +52,12 @@ func (q *windowUpdateQueue) QueueAll() {
 		q.queuedConn = false
 	}
 	// queue all stream-level window updates
-	var offset protocol.ByteCount
 	for id := range q.queue {
-		if id == q.cryptoStream.StreamID() {
-			offset = q.cryptoStream.getWindowUpdate()
-		} else {
-			str, err := q.streamGetter.GetOrOpenReceiveStream(id)
-			if err != nil || str == nil { // the stream can be nil if it was completed before dequeing the window update
-				continue
-			}
-			offset = str.getWindowUpdate()
+		str, err := q.streamGetter.GetOrOpenReceiveStream(id)
+		if err != nil || str == nil { // the stream can be nil if it was completed before dequeing the window update
+			continue
 		}
+		offset := str.getWindowUpdate()
 		if offset == 0 { // can happen if we received a final offset, right after queueing the window update
 			continue
 		}

+ 26 - 26
vendor/vendor.json

@@ -285,10 +285,10 @@
 			"revisionTime": "2017-10-27T16:34:21Z"
 		},
 		{
-			"checksumSHA1": "cqsGwyZE3NAuWLn5lEBrZc99ZKc=",
+			"checksumSHA1": "escUmRFlk6I1tqI7WLOBSm3y8vk=",
 			"path": "github.com/lucas-clemente/quic-go",
-			"revision": "ffdfa1f6760a75b2f919eb495fd99aa5ff1c6ad1",
-			"revisionTime": "2018-08-28T08:02:33Z"
+			"revision": "225106b58c78ac8aaad497c98f1ca7021a4e57b3",
+			"revisionTime": "2018-10-09T08:30:24Z"
 		},
 		{
 			"checksumSHA1": "OA9E+y7g05x/mWJJHmA7oPxWKQo=",
@@ -297,58 +297,58 @@
 			"revisionTime": "2016-08-23T09:51:56Z"
 		},
 		{
-			"checksumSHA1": "xofp3Exz+2Bna8U2fSFil8aeNK4=",
+			"checksumSHA1": "KHLnkk73j1KLvolUEJvJgVcg+4I=",
 			"path": "github.com/lucas-clemente/quic-go/internal/ackhandler",
-			"revision": "ffdfa1f6760a75b2f919eb495fd99aa5ff1c6ad1",
-			"revisionTime": "2018-08-28T08:02:33Z"
+			"revision": "225106b58c78ac8aaad497c98f1ca7021a4e57b3",
+			"revisionTime": "2018-10-09T08:30:24Z"
 		},
 		{
-			"checksumSHA1": "i1yfut7QQqMehw5yE9llhWNnrxk=",
+			"checksumSHA1": "y6iH4e+f/o//eL6f8xwxSe9Q3FI=",
 			"path": "github.com/lucas-clemente/quic-go/internal/congestion",
-			"revision": "ffdfa1f6760a75b2f919eb495fd99aa5ff1c6ad1",
-			"revisionTime": "2018-08-28T08:02:33Z"
+			"revision": "225106b58c78ac8aaad497c98f1ca7021a4e57b3",
+			"revisionTime": "2018-10-09T08:30:24Z"
 		},
 		{
-			"checksumSHA1": "iDyiuv67gAM4KKfl51vU3QtOFz8=",
+			"checksumSHA1": "YbTMl8MrfTJdm6ZlnXIIPUSTT/w=",
 			"path": "github.com/lucas-clemente/quic-go/internal/crypto",
-			"revision": "ffdfa1f6760a75b2f919eb495fd99aa5ff1c6ad1",
-			"revisionTime": "2018-08-28T08:02:33Z"
+			"revision": "225106b58c78ac8aaad497c98f1ca7021a4e57b3",
+			"revisionTime": "2018-10-09T08:30:24Z"
 		},
 		{
 			"checksumSHA1": "hLazAfY6qHoV3USMxA7pSPnTqy8=",
 			"path": "github.com/lucas-clemente/quic-go/internal/flowcontrol",
-			"revision": "ffdfa1f6760a75b2f919eb495fd99aa5ff1c6ad1",
-			"revisionTime": "2018-08-28T08:02:33Z"
+			"revision": "225106b58c78ac8aaad497c98f1ca7021a4e57b3",
+			"revisionTime": "2018-10-09T08:30:24Z"
 		},
 		{
-			"checksumSHA1": "1EPOPYxoK/ZVqB91d7329CMSsE8=",
+			"checksumSHA1": "VVbSeFKYFd5OHQVK+O5KDqANnb0=",
 			"path": "github.com/lucas-clemente/quic-go/internal/handshake",
-			"revision": "ffdfa1f6760a75b2f919eb495fd99aa5ff1c6ad1",
-			"revisionTime": "2018-08-28T08:02:33Z"
+			"revision": "225106b58c78ac8aaad497c98f1ca7021a4e57b3",
+			"revisionTime": "2018-10-09T08:30:24Z"
 		},
 		{
 			"checksumSHA1": "jG7h6FwuKQgXQI+pgymjud5m3Co=",
 			"path": "github.com/lucas-clemente/quic-go/internal/protocol",
-			"revision": "ffdfa1f6760a75b2f919eb495fd99aa5ff1c6ad1",
-			"revisionTime": "2018-08-28T08:02:33Z"
+			"revision": "225106b58c78ac8aaad497c98f1ca7021a4e57b3",
+			"revisionTime": "2018-10-09T08:30:24Z"
 		},
 		{
 			"checksumSHA1": "0vSbWIQ7O34u4kDMR+FHr7/FINk=",
 			"path": "github.com/lucas-clemente/quic-go/internal/utils",
-			"revision": "ffdfa1f6760a75b2f919eb495fd99aa5ff1c6ad1",
-			"revisionTime": "2018-08-28T08:02:33Z"
+			"revision": "225106b58c78ac8aaad497c98f1ca7021a4e57b3",
+			"revisionTime": "2018-10-09T08:30:24Z"
 		},
 		{
-			"checksumSHA1": "KCuro1tWjpbE8Xj91Fl1H2i4Ekw=",
+			"checksumSHA1": "XgecNbm4PtsEfUDX2unzmKE/nGA=",
 			"path": "github.com/lucas-clemente/quic-go/internal/wire",
-			"revision": "ffdfa1f6760a75b2f919eb495fd99aa5ff1c6ad1",
-			"revisionTime": "2018-08-28T08:02:33Z"
+			"revision": "225106b58c78ac8aaad497c98f1ca7021a4e57b3",
+			"revisionTime": "2018-10-09T08:30:24Z"
 		},
 		{
 			"checksumSHA1": "bFSC4TOZGOZGBJEFmLAT3V4ieoo=",
 			"path": "github.com/lucas-clemente/quic-go/qerr",
-			"revision": "ffdfa1f6760a75b2f919eb495fd99aa5ff1c6ad1",
-			"revisionTime": "2018-08-28T08:02:33Z"
+			"revision": "225106b58c78ac8aaad497c98f1ca7021a4e57b3",
+			"revisionTime": "2018-10-09T08:30:24Z"
 		},
 		{
 			"checksumSHA1": "sY8sshVIEXnJgg3S6C5FcN33Vq4=",