From ab0ddd4313a2bccc3138166bf17fe7ee4a8293f9 Mon Sep 17 00:00:00 2001 From: Darien Raymond Date: Mon, 14 Jan 2019 20:52:10 +0100 Subject: [PATCH] sync quic package. fixes #1503 --- .../lucas-clemente/quic-go/interface.go | 14 +- .../ackhandler/received_packet_handler.go | 2 +- .../quic-go/internal/ackhandler/send_mode.go | 12 +- .../ackhandler/sent_packet_handler.go | 118 ++++------------ .../quic-go/internal/handshake/aead.go | 60 +++----- .../internal/handshake/crypto_setup.go | 38 ++--- .../internal/handshake/initial_aead.go | 36 ++--- .../internal/handshake/tls_extension.go | 2 +- .../quic-go/internal/protocol/params.go | 4 + .../quic-go/internal/protocol/version.go | 2 +- .../quic-go/internal/wire/extended_header.go | 1 - .../quic-go/packet_handler_map.go | 18 +-- .../lucas-clemente/quic-go/packet_unpacker.go | 42 ++---- .../lucas-clemente/quic-go/server.go | 79 ++++++++++- .../lucas-clemente/quic-go/session.go | 133 ++++++++++-------- .../lucas-clemente/quic-go/streams_map.go | 12 ++ .../quic-go/streams_map_outgoing_bidi.go | 14 +- .../quic-go/streams_map_outgoing_generic.go | 14 +- .../quic-go/streams_map_outgoing_uni.go | 14 +- .../marten-seemann/qtls/cipher_suites.go | 5 + 20 files changed, 304 insertions(+), 316 deletions(-) diff --git a/vendor/github.com/lucas-clemente/quic-go/interface.go b/vendor/github.com/lucas-clemente/quic-go/interface.go index 6342fbb0c..689647553 100644 --- a/vendor/github.com/lucas-clemente/quic-go/interface.go +++ b/vendor/github.com/lucas-clemente/quic-go/interface.go @@ -124,20 +124,22 @@ type Session interface { // AcceptUniStream returns the next unidirectional stream opened by the peer, blocking until one is available. AcceptUniStream() (ReceiveStream, error) // OpenStream opens a new bidirectional QUIC stream. - // It returns a special error when the peer's concurrent stream limit is reached. // There is no signaling to the peer about new streams: // The peer can only accept the stream after data has been sent on the stream. - // TODO(#1152): Enable testing for the special error + // If the error is non-nil, it satisfies the net.Error interface. + // When reaching the peer's stream limit, err.Temporary() will be true. OpenStream() (Stream, error) // OpenStreamSync opens a new bidirectional QUIC stream. - // It blocks until the peer's concurrent stream limit allows a new stream to be opened. + // It blocks until a new stream can be opened. + // If the error is non-nil, it satisfies the net.Error interface. OpenStreamSync() (Stream, error) // OpenUniStream opens a new outgoing unidirectional QUIC stream. - // It returns a special error when the peer's concurrent stream limit is reached. - // TODO(#1152): Enable testing for the special error + // If the error is non-nil, it satisfies the net.Error interface. + // When reaching the peer's stream limit, Temporary() will be true. OpenUniStream() (SendStream, error) // OpenUniStreamSync opens a new outgoing unidirectional QUIC stream. - // It blocks until the peer's concurrent stream limit allows a new stream to be opened. + // It blocks until a new stream can be opened. + // If the error is non-nil, it satisfies the net.Error interface. OpenUniStreamSync() (SendStream, error) // LocalAddr returns the local address. LocalAddr() net.Addr diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/received_packet_handler.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/received_packet_handler.go index 8af213245..93931b4eb 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/received_packet_handler.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/received_packet_handler.go @@ -74,7 +74,7 @@ func (h *receivedPacketHandler) ReceivedPacket(packetNumber protocol.PacketNumbe } isMissing := h.isMissing(packetNumber) - if packetNumber > h.largestObserved { + if packetNumber >= h.largestObserved { h.largestObserved = packetNumber h.largestObservedReceivedTime = rcvTime } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/send_mode.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/send_mode.go index 76c833c4b..8cdaa7e6b 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/send_mode.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/send_mode.go @@ -12,10 +12,8 @@ const ( SendAck // SendRetransmission means that retransmissions should be sent SendRetransmission - // SendRTO means that an RTO probe packet should be sent - SendRTO - // SendTLP means that a TLP probe packet should be sent - SendTLP + // SendPTO means that a probe packet should be sent + SendPTO // SendAny means that any packet should be sent SendAny ) @@ -28,10 +26,8 @@ func (s SendMode) String() string { return "ack" case SendRetransmission: return "retransmission" - case SendRTO: - return "rto" - case SendTLP: - return "tlp" + case SendPTO: + return "pto" case SendAny: return "any" default: diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go index 776f87a89..0c67b0da4 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/ackhandler/sent_packet_handler.go @@ -17,16 +17,8 @@ const ( // Maximum reordering in time space before time based loss detection considers a packet lost. // In fraction of an RTT. timeReorderingFraction = 1.0 / 8 - // defaultRTOTimeout is the RTO time on new connections - defaultRTOTimeout = 500 * time.Millisecond - // Minimum time in the future a tail loss probe alarm may be set for. - minTPLTimeout = 10 * time.Millisecond - // Maximum number of tail loss probes before an RTO fires. - maxTLPs = 2 - // Minimum time in the future an RTO alarm may be set for. - minRTOTimeout = 200 * time.Millisecond - // maxRTOTimeout is the maximum RTO time - maxRTOTimeout = 60 * time.Second + // Timer granularity. The timer will not be set to a value smaller than granularity. + granularity = time.Millisecond ) type sentPacketHandler struct { @@ -44,7 +36,6 @@ type sentPacketHandler struct { // example: we send an ACK for packets 90-100 with packet number 20 // once we receive an ACK from the peer for packet 20, the lowestPacketNotConfirmedAcked is 101 lowestPacketNotConfirmedAcked protocol.PacketNumber - largestSentBeforeRTO protocol.PacketNumber packetHistory *sentPacketHistory @@ -56,17 +47,13 @@ type sentPacketHandler struct { rttStats *congestion.RTTStats handshakeComplete bool + // The number of times the crypto packets have been retransmitted without receiving an ack. cryptoCount uint32 - - // The number of times a TLP has been sent without receiving an ack. - tlpCount uint32 - allowTLP bool - - // The number of times an RTO has been sent without receiving an ack. - rtoCount uint32 - // The number of RTO probe packets that should be sent. - numRTOs int + // The number of times a PTO has been sent without receiving an ack. + ptoCount uint32 + // The number of PTO probe packets that should be sent. + numProbesToSend int // The time at which the next packet will be considered lost based on early transmit or exceeding the reordering window in time. lossTime time.Time @@ -173,10 +160,9 @@ func (h *sentPacketHandler) sentPacketImpl(packet *Packet) bool /* isRetransmitt packet.includedInBytesInFlight = true h.bytesInFlight += packet.Length packet.canBeRetransmitted = true - if h.numRTOs > 0 { - h.numRTOs-- + if h.numProbesToSend > 0 { + h.numProbesToSend-- } - h.allowTLP = false } h.congestion.OnPacketSent(packet.SendTime, h.bytesInFlight, packet.PacketNumber, packet.Length, isRetransmittable) @@ -210,6 +196,9 @@ func (h *sentPacketHandler) ReceivedAck(ackFrame *wire.AckFrame, withPacketNumbe if err != nil { return err } + if len(ackedPackets) == 0 { + return nil + } priorInFlight := h.bytesInFlight for _, p := range ackedPackets { @@ -235,6 +224,10 @@ func (h *sentPacketHandler) ReceivedAck(ackFrame *wire.AckFrame, withPacketNumbe if err := h.detectLostPackets(rcvTime, priorInFlight); err != nil { return err } + + h.ptoCount = 0 + h.cryptoCount = 0 + h.updateLossDetectionAlarm() return nil } @@ -310,15 +303,8 @@ func (h *sentPacketHandler) updateLossDetectionAlarm() { } else if !h.lossTime.IsZero() { // Early retransmit timer or time loss detection. h.alarm = h.lossTime - } else { - // RTO or TLP alarm - alarmDuration := h.computeRTOTimeout() - if h.tlpCount < maxTLPs { - tlpAlarm := h.computeTLPTimeout() - // if the RTO duration is shorter than the TLP duration, use the RTO duration - alarmDuration = utils.MinDuration(alarmDuration, tlpAlarm) - } - h.alarm = h.lastSentRetransmittablePacketTime.Add(alarmDuration) + } else { // PTO alarm + h.alarm = h.lastSentRetransmittablePacketTime.Add(h.computePTOTimeout()) } } @@ -346,6 +332,7 @@ func (h *sentPacketHandler) detectLostPackets(now time.Time, priorInFlight proto } return true, nil }) + if h.logger.Debug() && len(lostPackets) > 0 { pns := make([]protocol.PacketNumber, len(lostPackets)) for i, p := range lostPackets { @@ -399,21 +386,12 @@ func (h *sentPacketHandler) onVerifiedAlarm() error { } // Early retransmit or time loss detection err = h.detectLostPackets(time.Now(), h.bytesInFlight) - } else if h.tlpCount < maxTLPs { // TLP + } else { // PTO if h.logger.Debug() { - h.logger.Debugf("Loss detection alarm fired in TLP mode. TLP count: %d", h.tlpCount) + h.logger.Debugf("Loss detection alarm fired in PTO mode. PTO count: %d", h.ptoCount) } - h.allowTLP = true - h.tlpCount++ - } else { // RTO - if h.logger.Debug() { - h.logger.Debugf("Loss detection alarm fired in RTO mode. RTO count: %d", h.rtoCount) - } - if h.rtoCount == 0 { - h.largestSentBeforeRTO = h.lastSentPacketNumber - } - h.rtoCount++ - h.numRTOs += 2 + h.ptoCount++ + h.numProbesToSend += 2 } return err } @@ -454,15 +432,9 @@ func (h *sentPacketHandler) onPacketAcked(p *Packet, rcvTime time.Time) error { if p.includedInBytesInFlight { h.bytesInFlight -= p.Length } - if h.rtoCount > 0 { - h.verifyRTO(p.PacketNumber) - } if err := h.stopRetransmissionsFor(p); err != nil { return err } - h.rtoCount = 0 - h.tlpCount = 0 - h.cryptoCount = 0 return h.packetHistory.Remove(p.PacketNumber) } @@ -480,18 +452,6 @@ func (h *sentPacketHandler) stopRetransmissionsFor(p *Packet) error { return nil } -func (h *sentPacketHandler) verifyRTO(pn protocol.PacketNumber) { - if pn <= h.largestSentBeforeRTO { - h.logger.Debugf("Spurious RTO detected. Received an ACK for %#x (largest sent before RTO: %#x)", pn, h.largestSentBeforeRTO) - // Replace SRTT with latest_rtt and increase the variance to prevent - // a spurious RTO from happening again. - h.rttStats.ExpireSmoothedMetrics() - return - } - h.logger.Debugf("RTO verified. Received an ACK for %#x (largest sent before RTO: %#x", pn, h.largestSentBeforeRTO) - h.congestion.OnRetransmissionTimeout(true) -} - func (h *sentPacketHandler) DequeuePacketForRetransmission() *Packet { if len(h.retransmissionQueue) == 0 { return nil @@ -539,11 +499,8 @@ func (h *sentPacketHandler) SendMode() SendMode { } return SendNone } - if h.allowTLP { - return SendTLP - } - if h.numRTOs > 0 { - return SendRTO + if h.numProbesToSend > 0 { + return SendPTO } // Only send ACKs if we're congestion limited. if cwnd := h.congestion.GetCongestionWindow(); h.bytesInFlight > cwnd { @@ -570,9 +527,9 @@ func (h *sentPacketHandler) TimeUntilSend() time.Time { } func (h *sentPacketHandler) ShouldSendNumPackets() int { - if h.numRTOs > 0 { + if h.numProbesToSend > 0 { // RTO probes should not be paced, but must be sent immediately. - return h.numRTOs + return h.numProbesToSend } delay := h.congestion.TimeUntilSend(h.bytesInFlight) if delay == 0 || delay > protocol.MinPacingDelay { @@ -610,27 +567,14 @@ func (h *sentPacketHandler) queuePacketForRetransmission(p *Packet) error { } func (h *sentPacketHandler) computeCryptoTimeout() time.Duration { - duration := utils.MaxDuration(2*h.rttStats.SmoothedOrInitialRTT(), minTPLTimeout) + duration := utils.MaxDuration(2*h.rttStats.SmoothedOrInitialRTT(), granularity) // exponential backoff // There's an implicit limit to this set by the crypto timeout. return duration << h.cryptoCount } -func (h *sentPacketHandler) computeTLPTimeout() time.Duration { +func (h *sentPacketHandler) computePTOTimeout() time.Duration { // TODO(#1236): include the max_ack_delay - return utils.MaxDuration(h.rttStats.SmoothedOrInitialRTT()*3/2, minTPLTimeout) -} - -func (h *sentPacketHandler) computeRTOTimeout() time.Duration { - var rto time.Duration - rtt := h.rttStats.SmoothedRTT() - if rtt == 0 { - rto = defaultRTOTimeout - } else { - rto = rtt + 4*h.rttStats.MeanDeviation() - } - rto = utils.MaxDuration(rto, minRTOTimeout) - // Exponential backoff - rto <<= h.rtoCount - return utils.MinDuration(rto, maxRTOTimeout) + duration := utils.MaxDuration(h.rttStats.SmoothedOrInitialRTT()+4*h.rttStats.MeanDeviation(), granularity) + return duration << h.ptoCount } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/aead.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/aead.go index 26d481df2..07ce74f74 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/aead.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/aead.go @@ -8,13 +8,12 @@ import ( ) type sealer struct { - iv []byte aead cipher.AEAD - pnEncrypter cipher.Block + hpEncrypter cipher.Block // use a single slice to avoid allocations nonceBuf []byte - pnMask []byte + hpMask []byte // short headers protect 5 bits in the first byte, long headers only 4 is1RTT bool @@ -22,41 +21,35 @@ type sealer struct { var _ Sealer = &sealer{} -func newSealer(aead cipher.AEAD, iv []byte, pnEncrypter cipher.Block, is1RTT bool) Sealer { +func newSealer(aead cipher.AEAD, hpEncrypter cipher.Block, is1RTT bool) Sealer { return &sealer{ - iv: iv, aead: aead, nonceBuf: make([]byte, aead.NonceSize()), is1RTT: is1RTT, - pnEncrypter: pnEncrypter, - pnMask: make([]byte, pnEncrypter.BlockSize()), + hpEncrypter: hpEncrypter, + hpMask: make([]byte, hpEncrypter.BlockSize()), } } func (s *sealer) Seal(dst, src []byte, pn protocol.PacketNumber, ad []byte) []byte { binary.BigEndian.PutUint64(s.nonceBuf[len(s.nonceBuf)-8:], uint64(pn)) - for i := 0; i < len(s.nonceBuf); i++ { - s.nonceBuf[i] ^= s.iv[i] - } - sealed := s.aead.Seal(dst, s.nonceBuf, src, ad) - for i := 0; i < len(s.nonceBuf); i++ { - s.nonceBuf[i] = 0 - } - return sealed + // The AEAD we're using here will be the qtls.aeadAESGCM13. + // It uses the nonce provided here and XOR it with the IV. + return s.aead.Seal(dst, s.nonceBuf, src, ad) } func (s *sealer) EncryptHeader(sample []byte, firstByte *byte, pnBytes []byte) { - if len(sample) != s.pnEncrypter.BlockSize() { + if len(sample) != s.hpEncrypter.BlockSize() { panic("invalid sample size") } - s.pnEncrypter.Encrypt(s.pnMask, sample) + s.hpEncrypter.Encrypt(s.hpMask, sample) if s.is1RTT { - *firstByte ^= s.pnMask[0] & 0x1f + *firstByte ^= s.hpMask[0] & 0x1f } else { - *firstByte ^= s.pnMask[0] & 0xf + *firstByte ^= s.hpMask[0] & 0xf } for i := range pnBytes { - pnBytes[i] ^= s.pnMask[i+1] + pnBytes[i] ^= s.hpMask[i+1] } } @@ -65,13 +58,12 @@ func (s *sealer) Overhead() int { } type opener struct { - iv []byte aead cipher.AEAD pnDecrypter cipher.Block // use a single slice to avoid allocations nonceBuf []byte - pnMask []byte + hpMask []byte // short headers protect 5 bits in the first byte, long headers only 4 is1RTT bool @@ -79,40 +71,34 @@ type opener struct { var _ Opener = &opener{} -func newOpener(aead cipher.AEAD, iv []byte, pnDecrypter cipher.Block, is1RTT bool) Opener { +func newOpener(aead cipher.AEAD, pnDecrypter cipher.Block, is1RTT bool) Opener { return &opener{ - iv: iv, aead: aead, nonceBuf: make([]byte, aead.NonceSize()), is1RTT: is1RTT, pnDecrypter: pnDecrypter, - pnMask: make([]byte, pnDecrypter.BlockSize()), + hpMask: make([]byte, pnDecrypter.BlockSize()), } } func (o *opener) Open(dst, src []byte, pn protocol.PacketNumber, ad []byte) ([]byte, error) { binary.BigEndian.PutUint64(o.nonceBuf[len(o.nonceBuf)-8:], uint64(pn)) - for i := 0; i < len(o.nonceBuf); i++ { - o.nonceBuf[i] ^= o.iv[i] - } - opened, err := o.aead.Open(dst, o.nonceBuf, src, ad) - for i := 0; i < len(o.nonceBuf); i++ { - o.nonceBuf[i] = 0 - } - return opened, err + // The AEAD we're using here will be the qtls.aeadAESGCM13. + // It uses the nonce provided here and XOR it with the IV. + return o.aead.Open(dst, o.nonceBuf, src, ad) } func (o *opener) DecryptHeader(sample []byte, firstByte *byte, pnBytes []byte) { if len(sample) != o.pnDecrypter.BlockSize() { panic("invalid sample size") } - o.pnDecrypter.Encrypt(o.pnMask, sample) + o.pnDecrypter.Encrypt(o.hpMask, sample) if o.is1RTT { - *firstByte ^= o.pnMask[0] & 0x1f + *firstByte ^= o.hpMask[0] & 0x1f } else { - *firstByte ^= o.pnMask[0] & 0xf + *firstByte ^= o.hpMask[0] & 0xf } for i := range pnBytes { - pnBytes[i] ^= o.pnMask[i+1] + pnBytes[i] ^= o.hpMask[i+1] } } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup.go index e5afaab63..42a0c4e95 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/crypto_setup.go @@ -181,7 +181,7 @@ func newCryptoSetup( logger utils.Logger, perspective protocol.Perspective, ) (CryptoSetup, <-chan struct{} /* ClientHello written */, error) { - initialSealer, initialOpener, err := newInitialAEAD(connID, perspective) + initialSealer, initialOpener, err := NewInitialAEAD(connID, perspective) if err != nil { return nil, nil, err } @@ -410,28 +410,22 @@ func (h *cryptoSetup) ReadHandshakeMessage() ([]byte, error) { } func (h *cryptoSetup) SetReadKey(suite *qtls.CipherSuite, trafficSecret []byte) { - key := qtls.HkdfExpandLabel(suite.Hash(), trafficSecret, []byte{}, "key", suite.KeyLen()) - iv := qtls.HkdfExpandLabel(suite.Hash(), trafficSecret, []byte{}, "iv", suite.IVLen()) - pnKey := qtls.HkdfExpandLabel(suite.Hash(), trafficSecret, []byte{}, "pn", suite.KeyLen()) - pnDecrypter, err := aes.NewCipher(pnKey) + key := qtls.HkdfExpandLabel(suite.Hash(), trafficSecret, []byte{}, "quic key", suite.KeyLen()) + iv := qtls.HkdfExpandLabel(suite.Hash(), trafficSecret, []byte{}, "quic iv", suite.IVLen()) + hpKey := qtls.HkdfExpandLabel(suite.Hash(), trafficSecret, []byte{}, "quic hp", suite.KeyLen()) + hpDecrypter, err := aes.NewCipher(hpKey) if err != nil { panic(fmt.Sprintf("error creating new AES cipher: %s", err)) } - opener := newOpener( - suite.AEAD(key, iv), - iv, - pnDecrypter, - h.readEncLevel == protocol.Encryption1RTT, - ) switch h.readEncLevel { case protocol.EncryptionInitial: h.readEncLevel = protocol.EncryptionHandshake - h.handshakeOpener = opener + h.handshakeOpener = newOpener(suite.AEAD(key, iv), hpDecrypter, false) h.logger.Debugf("Installed Handshake Read keys") case protocol.EncryptionHandshake: h.readEncLevel = protocol.Encryption1RTT - h.opener = opener + h.opener = newOpener(suite.AEAD(key, iv), hpDecrypter, true) h.logger.Debugf("Installed 1-RTT Read keys") default: panic("unexpected read encryption level") @@ -440,28 +434,22 @@ func (h *cryptoSetup) SetReadKey(suite *qtls.CipherSuite, trafficSecret []byte) } func (h *cryptoSetup) SetWriteKey(suite *qtls.CipherSuite, trafficSecret []byte) { - key := qtls.HkdfExpandLabel(suite.Hash(), trafficSecret, []byte{}, "key", suite.KeyLen()) - iv := qtls.HkdfExpandLabel(suite.Hash(), trafficSecret, []byte{}, "iv", suite.IVLen()) - pnKey := qtls.HkdfExpandLabel(suite.Hash(), trafficSecret, []byte{}, "pn", suite.KeyLen()) - pnEncrypter, err := aes.NewCipher(pnKey) + key := qtls.HkdfExpandLabel(suite.Hash(), trafficSecret, []byte{}, "quic key", suite.KeyLen()) + iv := qtls.HkdfExpandLabel(suite.Hash(), trafficSecret, []byte{}, "quic iv", suite.IVLen()) + hpKey := qtls.HkdfExpandLabel(suite.Hash(), trafficSecret, []byte{}, "quic hp", suite.KeyLen()) + hpEncrypter, err := aes.NewCipher(hpKey) if err != nil { panic(fmt.Sprintf("error creating new AES cipher: %s", err)) } - sealer := newSealer( - suite.AEAD(key, iv), - iv, - pnEncrypter, - h.writeEncLevel == protocol.Encryption1RTT, - ) switch h.writeEncLevel { case protocol.EncryptionInitial: h.writeEncLevel = protocol.EncryptionHandshake - h.handshakeSealer = sealer + h.handshakeSealer = newSealer(suite.AEAD(key, iv), hpEncrypter, false) h.logger.Debugf("Installed Handshake Write keys") case protocol.EncryptionHandshake: h.writeEncLevel = protocol.Encryption1RTT - h.sealer = sealer + h.sealer = newSealer(suite.AEAD(key, iv), hpEncrypter, true) h.logger.Debugf("Installed 1-RTT Write keys") default: panic("unexpected write encryption level") diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/initial_aead.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/initial_aead.go index 1a6efb086..90334a1b0 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/initial_aead.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/initial_aead.go @@ -3,7 +3,6 @@ package handshake import ( "crypto" "crypto/aes" - "crypto/cipher" "github.com/lucas-clemente/quic-go/internal/protocol" "github.com/marten-seemann/qtls" @@ -11,7 +10,8 @@ import ( var quicVersion1Salt = []byte{0xef, 0x4f, 0xb0, 0xab, 0xb4, 0x74, 0x70, 0xc4, 0x1b, 0xef, 0xcf, 0x80, 0x31, 0x33, 0x4f, 0xae, 0x48, 0x5e, 0x09, 0xa0} -func newInitialAEAD(connID protocol.ConnectionID, pers protocol.Perspective) (Sealer, Opener, error) { +// NewInitialAEAD creates a new AEAD for Initial encryption / decryption. +func NewInitialAEAD(connID protocol.ConnectionID, pers protocol.Perspective) (Sealer, Opener, error) { clientSecret, serverSecret := computeSecrets(connID) var mySecret, otherSecret []byte if pers == protocol.PerspectiveClient { @@ -21,34 +21,20 @@ func newInitialAEAD(connID protocol.ConnectionID, pers protocol.Perspective) (Se mySecret = serverSecret otherSecret = clientSecret } - myKey, myPNKey, myIV := computeInitialKeyAndIV(mySecret) - otherKey, otherPNKey, otherIV := computeInitialKeyAndIV(otherSecret) + myKey, myHPKey, myIV := computeInitialKeyAndIV(mySecret) + otherKey, otherHPKey, otherIV := computeInitialKeyAndIV(otherSecret) - encrypterCipher, err := aes.NewCipher(myKey) + encrypter := qtls.AEADAESGCM13(myKey, myIV) + hpEncrypter, err := aes.NewCipher(myHPKey) if err != nil { return nil, nil, err } - encrypter, err := cipher.NewGCM(encrypterCipher) + decrypter := qtls.AEADAESGCM13(otherKey, otherIV) + hpDecrypter, err := aes.NewCipher(otherHPKey) if err != nil { return nil, nil, err } - pnEncrypter, err := aes.NewCipher(myPNKey) - if err != nil { - return nil, nil, err - } - decrypterCipher, err := aes.NewCipher(otherKey) - if err != nil { - return nil, nil, err - } - decrypter, err := cipher.NewGCM(decrypterCipher) - if err != nil { - return nil, nil, err - } - pnDecrypter, err := aes.NewCipher(otherPNKey) - if err != nil { - return nil, nil, err - } - return newSealer(encrypter, myIV, pnEncrypter, false), newOpener(decrypter, otherIV, pnDecrypter, false), nil + return newSealer(encrypter, hpEncrypter, false), newOpener(decrypter, hpDecrypter, false), nil } func computeSecrets(connID protocol.ConnectionID) (clientSecret, serverSecret []byte) { @@ -58,9 +44,9 @@ func computeSecrets(connID protocol.ConnectionID) (clientSecret, serverSecret [] return } -func computeInitialKeyAndIV(secret []byte) (key, pnKey, iv []byte) { +func computeInitialKeyAndIV(secret []byte) (key, hpKey, iv []byte) { key = qtls.HkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic key", 16) - pnKey = qtls.HkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic hp", 16) + hpKey = qtls.HkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic hp", 16) iv = qtls.HkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic iv", 12) return } diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension.go b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension.go index 9cfb665a3..96b890bf2 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/handshake/tls_extension.go @@ -10,7 +10,7 @@ import ( "github.com/lucas-clemente/quic-go/internal/utils" ) -const quicTLSExtensionType = 0xff5 +const quicTLSExtensionType = 0xffa5 type clientHelloTransportParameters struct { InitialVersion protocol.VersionNumber diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/protocol/params.go b/vendor/github.com/lucas-clemente/quic-go/internal/protocol/params.go index 7f4661e81..e6f9493fa 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/protocol/params.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/protocol/params.go @@ -53,6 +53,10 @@ const SkipPacketAveragePeriodLength PacketNumber = 500 // MaxTrackedSkippedPackets is the maximum number of skipped packet numbers the SentPacketHandler keep track of for Optimistic ACK attack mitigation const MaxTrackedSkippedPackets = 10 +// MaxAcceptQueueSize is the maximum number of sessions that the server queues for accepting. +// If the queue is full, new connection attempts will be rejected. +const MaxAcceptQueueSize = 32 + // CookieExpiryTime is the valid time of a cookie const CookieExpiryTime = 24 * time.Hour diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/protocol/version.go b/vendor/github.com/lucas-clemente/quic-go/internal/protocol/version.go index 9c5d3830a..3406cfa46 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/protocol/version.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/protocol/version.go @@ -18,7 +18,7 @@ const ( // The version numbers, making grepping easier const ( - VersionTLS VersionNumber = 101 + VersionTLS VersionNumber = 0x51474fff VersionWhatever VersionNumber = 1 // for when the version doesn't matter VersionUnknown VersionNumber = math.MaxUint32 ) diff --git a/vendor/github.com/lucas-clemente/quic-go/internal/wire/extended_header.go b/vendor/github.com/lucas-clemente/quic-go/internal/wire/extended_header.go index b95c9cc6b..19a0b064e 100644 --- a/vendor/github.com/lucas-clemente/quic-go/internal/wire/extended_header.go +++ b/vendor/github.com/lucas-clemente/quic-go/internal/wire/extended_header.go @@ -15,7 +15,6 @@ type ExtendedHeader struct { Header typeByte byte - Raw []byte PacketNumberLen protocol.PacketNumberLen PacketNumber protocol.PacketNumber diff --git a/vendor/github.com/lucas-clemente/quic-go/packet_handler_map.go b/vendor/github.com/lucas-clemente/quic-go/packet_handler_map.go index ce4c55156..3c0f5bdd3 100644 --- a/vendor/github.com/lucas-clemente/quic-go/packet_handler_map.go +++ b/vendor/github.com/lucas-clemente/quic-go/packet_handler_map.go @@ -186,10 +186,6 @@ func (h *packetHandlerMap) parsePacket( var counter int var lastConnID protocol.ConnectionID for len(data) > 0 { - if counter > 0 && h.logger.Debug() { - h.logger.Debugf("Parsed a coalesced packet. Part %d: %d bytes", counter, len(packets[counter-1].data)) - } - hdr, err := wire.ParseHeader(bytes.NewReader(data), h.connIDLen) // drop the packet if we can't parse the header if err != nil { @@ -221,6 +217,12 @@ func (h *packetHandlerMap) parsePacket( data: data, buffer: buffer, }) + + // only log if this actually a coalesced packet + if h.logger.Debug() && (counter > 1 || len(rest) > 0) { + h.logger.Debugf("Parsed a coalesced packet. Part %d: %d bytes. Remaining: %d bytes.", counter, len(packets[counter-1].data), len(rest)) + } + data = rest } return packets, nil @@ -252,11 +254,11 @@ func (h *packetHandlerMap) handleParsedPackets(packets []*receivedPacket) { // TODO(#943): send a stateless reset h.logger.Debugf("received a short header packet with an unexpected connection ID %s", p.hdr.DestConnectionID) break // a short header packet is always the last in a coalesced packet - } - if h.server != nil { // no server set - h.server.handlePacket(p) + if h.server == nil { // no server set + h.logger.Debugf("received a packet with an unexpected connection ID %s", p.hdr.DestConnectionID) + continue } - h.logger.Debugf("received a packet with an unexpected connection ID %s", p.hdr.DestConnectionID) + h.server.handlePacket(p) } } diff --git a/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go b/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go index cda222324..f3b5a2f77 100644 --- a/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go +++ b/vendor/github.com/lucas-clemente/quic-go/packet_unpacker.go @@ -6,7 +6,6 @@ import ( "github.com/lucas-clemente/quic-go/internal/handshake" "github.com/lucas-clemente/quic-go/internal/protocol" - "github.com/lucas-clemente/quic-go/internal/qerr" "github.com/lucas-clemente/quic-go/internal/utils" "github.com/lucas-clemente/quic-go/internal/wire" ) @@ -15,7 +14,7 @@ type unpackedPacket struct { packetNumber protocol.PacketNumber // the decoded packet number hdr *wire.ExtendedHeader encryptionLevel protocol.EncryptionLevel - frames []wire.Frame + data []byte } // The packetUnpacker unpacks QUIC packets. @@ -56,6 +55,9 @@ func (u *packetUnpacker) Unpack(hdr *wire.Header, data []byte) (*unpackedPacket, return nil, err } hdrLen := int(hdr.ParsedLen()) + if len(data) < hdrLen+4+16 { + return nil, fmt.Errorf("Packet too small. Expected at least 20 bytes after the header, got %d", len(data)-hdrLen) + } // The packet number can be up to 4 bytes long, but we won't know the length until we decrypt it. // 1. save a copy of the 4 bytes origPNBytes := make([]byte, 4) @@ -66,18 +68,16 @@ func (u *packetUnpacker) Unpack(hdr *wire.Header, data []byte) (*unpackedPacket, &data[0], data[hdrLen:hdrLen+4], ) - // 3. parse the header (and learn the actual length of the packet number) extHdr, err := hdr.ParseExtended(r, u.version) if err != nil { return nil, fmt.Errorf("error parsing extended header: %s", err) } - extHdr.Raw = data[:hdrLen+int(extHdr.PacketNumberLen)] + extHdrLen := hdrLen + int(extHdr.PacketNumberLen) // 4. if the packet number is shorter than 4 bytes, replace the remaining bytes with the copy we saved earlier if extHdr.PacketNumberLen != protocol.PacketNumberLen4 { - copy(data[hdrLen+int(extHdr.PacketNumberLen):hdrLen+4], origPNBytes[int(extHdr.PacketNumberLen):]) + copy(data[extHdrLen:hdrLen+4], origPNBytes[int(extHdr.PacketNumberLen):]) } - data = data[hdrLen+int(extHdr.PacketNumberLen):] pn := protocol.DecodePacketNumber( extHdr.PacketNumberLen, @@ -85,7 +85,7 @@ func (u *packetUnpacker) Unpack(hdr *wire.Header, data []byte) (*unpackedPacket, extHdr.PacketNumber, ) - decrypted, err := opener.Open(data[:0], data, pn, extHdr.Raw) + decrypted, err := opener.Open(data[extHdrLen:extHdrLen], data[extHdrLen:], pn, data[:extHdrLen]) if err != nil { return nil, err } @@ -93,36 +93,10 @@ func (u *packetUnpacker) Unpack(hdr *wire.Header, data []byte) (*unpackedPacket, // Only do this after decrypting, so we are sure the packet is not attacker-controlled u.largestRcvdPacketNumber = utils.MaxPacketNumber(u.largestRcvdPacketNumber, pn) - fs, err := u.parseFrames(decrypted) - if err != nil { - return nil, err - } - return &unpackedPacket{ hdr: extHdr, packetNumber: pn, encryptionLevel: encLevel, - frames: fs, + data: decrypted, }, nil } - -func (u *packetUnpacker) parseFrames(decrypted []byte) ([]wire.Frame, error) { - r := bytes.NewReader(decrypted) - if r.Len() == 0 { - return nil, qerr.MissingPayload - } - - fs := make([]wire.Frame, 0, 2) - // Read all frames in the packet - for { - frame, err := wire.ParseNextFrame(r, u.version) - if err != nil { - return nil, err - } - if frame == nil { - break - } - fs = append(fs, frame) - } - return fs, nil -} diff --git a/vendor/github.com/lucas-clemente/quic-go/server.go b/vendor/github.com/lucas-clemente/quic-go/server.go index 3fb1ca7a3..f1277838f 100644 --- a/vendor/github.com/lucas-clemente/quic-go/server.go +++ b/vendor/github.com/lucas-clemente/quic-go/server.go @@ -8,10 +8,12 @@ import ( "io" "net" "sync" + "sync/atomic" "time" "github.com/lucas-clemente/quic-go/internal/handshake" "github.com/lucas-clemente/quic-go/internal/protocol" + "github.com/lucas-clemente/quic-go/internal/qerr" "github.com/lucas-clemente/quic-go/internal/utils" "github.com/lucas-clemente/quic-go/internal/wire" ) @@ -88,7 +90,8 @@ type server struct { errorChan chan struct{} closed bool - sessionQueue chan Session + sessionQueue chan Session + sessionQueueLen int32 // to be used as an atomic sessionRunner sessionRunner @@ -149,7 +152,7 @@ func listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (*server, tlsConf: tlsConf, config: config, sessionHandler: sessionHandler, - sessionQueue: make(chan Session, 5), + sessionQueue: make(chan Session), errorChan: make(chan struct{}), newSession: newSession, logger: utils.DefaultLogger.WithPrefix("server"), @@ -164,9 +167,20 @@ func listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (*server, func (s *server) setup() error { s.sessionRunner = &runner{ - onHandshakeCompleteImpl: func(sess Session) { s.sessionQueue <- sess }, - retireConnectionIDImpl: s.sessionHandler.Retire, - removeConnectionIDImpl: s.sessionHandler.Remove, + onHandshakeCompleteImpl: func(sess Session) { + go func() { + atomic.AddInt32(&s.sessionQueueLen, 1) + defer atomic.AddInt32(&s.sessionQueueLen, -1) + select { + case s.sessionQueue <- sess: + // blocks until the session is accepted + case <-sess.Context().Done(): + // don't pass sessions that were already closed to Accept() + } + }() + }, + retireConnectionIDImpl: s.sessionHandler.Retire, + removeConnectionIDImpl: s.sessionHandler.Remove, } cookieGenerator, err := handshake.NewCookieGenerator() if err != nil { @@ -333,7 +347,7 @@ func (s *server) handleInitial(p *receivedPacket) { s.logger.Errorf("Error occurred handling initial packet: %s", err) return } - if sess == nil { // a retry was done + if sess == nil { // a retry was done, or the connection attempt was rejected p.buffer.Release() return } @@ -371,6 +385,11 @@ func (s *server) handleInitialImpl(p *receivedPacket) (quicSession, protocol.Con return nil, nil, s.sendRetry(p.remoteAddr, hdr) } + if queueLen := atomic.LoadInt32(&s.sessionQueueLen); queueLen >= protocol.MaxAcceptQueueSize { + s.logger.Debugf("Rejecting new connection. Server currently busy. Accept queue length: %d (max %d)", queueLen, protocol.MaxAcceptQueueSize) + return nil, nil, s.sendServerBusy(p.remoteAddr, hdr) + } + connID, err := protocol.GenerateConnectionID(s.config.ConnectionIDLength) if err != nil { return nil, nil, err @@ -460,6 +479,54 @@ func (s *server) sendRetry(remoteAddr net.Addr, hdr *wire.Header) error { return nil } +func (s *server) sendServerBusy(remoteAddr net.Addr, hdr *wire.Header) error { + sealer, _, err := handshake.NewInitialAEAD(hdr.DestConnectionID, protocol.PerspectiveServer) + if err != nil { + return err + } + packetBuffer := getPacketBuffer() + defer packetBuffer.Release() + buf := bytes.NewBuffer(packetBuffer.Slice[:0]) + + // TODO(#1567): use the SERVER_BUSY error code + ccf := &wire.ConnectionCloseFrame{ErrorCode: qerr.PeerGoingAway} + + replyHdr := &wire.ExtendedHeader{} + replyHdr.IsLongHeader = true + replyHdr.Type = protocol.PacketTypeInitial + replyHdr.Version = hdr.Version + replyHdr.SrcConnectionID = hdr.DestConnectionID + replyHdr.DestConnectionID = hdr.SrcConnectionID + replyHdr.PacketNumberLen = protocol.PacketNumberLen4 + replyHdr.Length = 4 /* packet number len */ + ccf.Length(hdr.Version) + protocol.ByteCount(sealer.Overhead()) + if err := replyHdr.Write(buf, hdr.Version); err != nil { + return err + } + payloadOffset := buf.Len() + + if err := ccf.Write(buf, hdr.Version); err != nil { + return err + } + + raw := buf.Bytes() + _ = sealer.Seal(raw[payloadOffset:payloadOffset], raw[payloadOffset:], replyHdr.PacketNumber, raw[:payloadOffset]) + raw = raw[0 : buf.Len()+sealer.Overhead()] + + pnOffset := payloadOffset - int(replyHdr.PacketNumberLen) + sealer.EncryptHeader( + raw[pnOffset+4:pnOffset+4+16], + &raw[0], + raw[pnOffset:payloadOffset], + ) + + replyHdr.Log(s.logger) + wire.LogFrame(s.logger, ccf, true) + if _, err := s.conn.WriteTo(raw, remoteAddr); err != nil { + s.logger.Debugf("Error rejecting connection: %s", err) + } + return nil +} + func (s *server) sendVersionNegotiationPacket(p *receivedPacket) { defer p.buffer.Release() hdr := p.hdr diff --git a/vendor/github.com/lucas-clemente/quic-go/session.go b/vendor/github.com/lucas-clemente/quic-go/session.go index 63aa3d9d7..3021e782d 100644 --- a/vendor/github.com/lucas-clemente/quic-go/session.go +++ b/vendor/github.com/lucas-clemente/quic-go/session.go @@ -1,12 +1,14 @@ package quic import ( + "bytes" "context" "crypto/tls" "errors" "fmt" "io" "net" + "reflect" "sync" "time" @@ -495,14 +497,17 @@ func (s *session) handlePacketImpl(p *receivedPacket) bool /* was the packet suc } packet, err := s.unpacker.Unpack(p.hdr, p.data) - // if the decryption failed, this might be a packet sent by an attacker if err != nil { if err == handshake.ErrOpenerNotYetAvailable { + // Sealer for this encryption level not yet available. + // Try again later. wasQueued = true s.tryQueueingUndecryptablePacket(p) return false } - s.closeLocal(err) + // This might be a packet injected by an attacker. + // Drop it. + s.logger.Debugf("Dropping packet that could not be unpacked. Unpack error: %s", err) return false } @@ -519,6 +524,10 @@ func (s *session) handlePacketImpl(p *receivedPacket) bool /* was the packet suc } func (s *session) handleUnpackedPacket(packet *unpackedPacket, rcvTime time.Time) error { + if len(packet.data) == 0 { + return qerr.MissingPayload + } + // The server can change the source connection ID with the first Handshake packet. if s.perspective == protocol.PerspectiveClient && !s.receivedFirstPacket && packet.hdr.IsLongHeader && !packet.hdr.SrcConnectionID.Equal(s.destConnID) { s.logger.Debugf("Received first packet. Switching destination connection ID to: %s", packet.hdr.SrcConnectionID) @@ -539,66 +548,72 @@ func (s *session) handleUnpackedPacket(packet *unpackedPacket, rcvTime time.Time } } - // If this is a Retry packet, there's no need to send an ACK. - // The session will be closed and recreated as soon as the crypto setup processed the HRR. - if packet.hdr.Type != protocol.PacketTypeRetry { - isRetransmittable := ackhandler.HasRetransmittableFrames(packet.frames) - if err := s.receivedPacketHandler.ReceivedPacket(packet.packetNumber, rcvTime, isRetransmittable); err != nil { - return err - } - } - - return s.handleFrames(packet.frames, packet.packetNumber, packet.encryptionLevel) -} - -func (s *session) handleFrames(fs []wire.Frame, pn protocol.PacketNumber, encLevel protocol.EncryptionLevel) error { - for _, ff := range fs { - var err error - wire.LogFrame(s.logger, ff, false) - switch frame := ff.(type) { - case *wire.CryptoFrame: - err = s.handleCryptoFrame(frame, encLevel) - case *wire.StreamFrame: - err = s.handleStreamFrame(frame, encLevel) - case *wire.AckFrame: - err = s.handleAckFrame(frame, pn, encLevel) - case *wire.ConnectionCloseFrame: - s.closeRemote(qerr.Error(frame.ErrorCode, frame.ReasonPhrase)) - case *wire.ResetStreamFrame: - err = s.handleResetStreamFrame(frame) - case *wire.MaxDataFrame: - s.handleMaxDataFrame(frame) - case *wire.MaxStreamDataFrame: - err = s.handleMaxStreamDataFrame(frame) - case *wire.MaxStreamsFrame: - err = s.handleMaxStreamsFrame(frame) - case *wire.DataBlockedFrame: - case *wire.StreamDataBlockedFrame: - case *wire.StreamsBlockedFrame: - case *wire.StopSendingFrame: - err = s.handleStopSendingFrame(frame) - case *wire.PingFrame: - case *wire.PathChallengeFrame: - s.handlePathChallengeFrame(frame) - case *wire.PathResponseFrame: - // since we don't send PATH_CHALLENGEs, we don't expect PATH_RESPONSEs - err = errors.New("unexpected PATH_RESPONSE frame") - case *wire.NewTokenFrame: - case *wire.NewConnectionIDFrame: - case *wire.RetireConnectionIDFrame: - // since we don't send new connection IDs, we don't expect retirements - err = errors.New("unexpected RETIRE_CONNECTION_ID frame") - default: - return errors.New("Session BUG: unexpected frame type") - } - + r := bytes.NewReader(packet.data) + var isRetransmittable bool + for { + frame, err := wire.ParseNextFrame(r, s.version) if err != nil { return err } + if frame == nil { + break + } + if ackhandler.IsFrameRetransmittable(frame) { + isRetransmittable = true + } + if err := s.handleFrame(frame, packet.packetNumber, packet.encryptionLevel); err != nil { + return err + } + } + + if err := s.receivedPacketHandler.ReceivedPacket(packet.packetNumber, rcvTime, isRetransmittable); err != nil { + return err } return nil } +func (s *session) handleFrame(f wire.Frame, pn protocol.PacketNumber, encLevel protocol.EncryptionLevel) error { + var err error + wire.LogFrame(s.logger, f, false) + switch frame := f.(type) { + case *wire.CryptoFrame: + err = s.handleCryptoFrame(frame, encLevel) + case *wire.StreamFrame: + err = s.handleStreamFrame(frame, encLevel) + case *wire.AckFrame: + err = s.handleAckFrame(frame, pn, encLevel) + case *wire.ConnectionCloseFrame: + s.closeRemote(qerr.Error(frame.ErrorCode, frame.ReasonPhrase)) + case *wire.ResetStreamFrame: + err = s.handleResetStreamFrame(frame) + case *wire.MaxDataFrame: + s.handleMaxDataFrame(frame) + case *wire.MaxStreamDataFrame: + err = s.handleMaxStreamDataFrame(frame) + case *wire.MaxStreamsFrame: + err = s.handleMaxStreamsFrame(frame) + case *wire.DataBlockedFrame: + case *wire.StreamDataBlockedFrame: + case *wire.StreamsBlockedFrame: + case *wire.StopSendingFrame: + err = s.handleStopSendingFrame(frame) + case *wire.PingFrame: + case *wire.PathChallengeFrame: + s.handlePathChallengeFrame(frame) + case *wire.PathResponseFrame: + // since we don't send PATH_CHALLENGEs, we don't expect PATH_RESPONSEs + err = errors.New("unexpected PATH_RESPONSE frame") + case *wire.NewTokenFrame: + case *wire.NewConnectionIDFrame: + case *wire.RetireConnectionIDFrame: + // since we don't send new connection IDs, we don't expect retirements + err = errors.New("unexpected RETIRE_CONNECTION_ID frame") + default: + err = fmt.Errorf("unexpected frame type: %s", reflect.ValueOf(&frame).Elem().Type().Name()) + } + return err +} + // handlePacket is called by the server with a new packet func (s *session) handlePacket(p *receivedPacket) { if s.closed.Get() { @@ -787,11 +802,7 @@ func (s *session) handleCloseError(closeErr closeError) error { if closeErr.remote { return nil } - - if quicErr.ErrorCode == qerr.DecryptionFailure { - // TODO(#943): send a stateless reset - return nil - } + // otherwise send a CONNECTION_CLOSE return s.sendConnectionClose(quicErr) } @@ -830,7 +841,7 @@ sendLoop: // There will only be a new ACK after receiving new packets. // SendAck is only returned when we're congestion limited, so we don't need to set the pacingt timer. return s.maybeSendAckOnlyPacket() - case ackhandler.SendTLP, ackhandler.SendRTO: + case ackhandler.SendPTO: if err := s.sendProbePacket(); err != nil { return err } diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map.go b/vendor/github.com/lucas-clemente/quic-go/streams_map.go index 4be37bf43..b71953756 100644 --- a/vendor/github.com/lucas-clemente/quic-go/streams_map.go +++ b/vendor/github.com/lucas-clemente/quic-go/streams_map.go @@ -1,7 +1,9 @@ package quic import ( + "errors" "fmt" + "net" "github.com/lucas-clemente/quic-go/internal/flowcontrol" "github.com/lucas-clemente/quic-go/internal/handshake" @@ -9,6 +11,16 @@ import ( "github.com/lucas-clemente/quic-go/internal/wire" ) +type streamOpenErr struct{ error } + +var _ net.Error = &streamOpenErr{} + +func (e streamOpenErr) Temporary() bool { return e.error == errTooManyOpenStreams } +func (streamOpenErr) Timeout() bool { return false } + +// errTooManyOpenStreams is used internally by the outgoing streams maps. +var errTooManyOpenStreams = errors.New("too many open streams") + type streamsMap struct { perspective protocol.Perspective diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_bidi.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_bidi.go index 6405e4381..480d8d774 100644 --- a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_bidi.go +++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_bidi.go @@ -49,7 +49,11 @@ func (m *outgoingBidiStreamsMap) OpenStream() (streamI, error) { m.mutex.Lock() defer m.mutex.Unlock() - return m.openStreamImpl() + str, err := m.openStreamImpl() + if err != nil { + return nil, streamOpenErr{err} + } + return str, nil } func (m *outgoingBidiStreamsMap) OpenStreamSync() (streamI, error) { @@ -59,10 +63,10 @@ func (m *outgoingBidiStreamsMap) OpenStreamSync() (streamI, error) { for { str, err := m.openStreamImpl() if err == nil { - return str, err + return str, nil } - if err != nil && err != qerr.TooManyOpenStreams { - return nil, err + if err != nil && err != errTooManyOpenStreams { + return nil, streamOpenErr{err} } m.cond.Wait() } @@ -87,7 +91,7 @@ func (m *outgoingBidiStreamsMap) openStreamImpl() (streamI, error) { } m.blockedSent = true } - return nil, qerr.TooManyOpenStreams + return nil, errTooManyOpenStreams } s := m.newStream(m.nextStream) m.streams[m.nextStream] = s diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_generic.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_generic.go index 23bd19176..e9cff98b9 100644 --- a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_generic.go +++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_generic.go @@ -47,7 +47,11 @@ func (m *outgoingItemsMap) OpenStream() (item, error) { m.mutex.Lock() defer m.mutex.Unlock() - return m.openStreamImpl() + str, err := m.openStreamImpl() + if err != nil { + return nil, streamOpenErr{err} + } + return str, nil } func (m *outgoingItemsMap) OpenStreamSync() (item, error) { @@ -57,10 +61,10 @@ func (m *outgoingItemsMap) OpenStreamSync() (item, error) { for { str, err := m.openStreamImpl() if err == nil { - return str, err + return str, nil } - if err != nil && err != qerr.TooManyOpenStreams { - return nil, err + if err != nil && err != errTooManyOpenStreams { + return nil, streamOpenErr{err} } m.cond.Wait() } @@ -85,7 +89,7 @@ func (m *outgoingItemsMap) openStreamImpl() (item, error) { } m.blockedSent = true } - return nil, qerr.TooManyOpenStreams + return nil, errTooManyOpenStreams } s := m.newStream(m.nextStream) m.streams[m.nextStream] = s diff --git a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_uni.go b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_uni.go index 838c9aa9d..98456bfd1 100644 --- a/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_uni.go +++ b/vendor/github.com/lucas-clemente/quic-go/streams_map_outgoing_uni.go @@ -49,7 +49,11 @@ func (m *outgoingUniStreamsMap) OpenStream() (sendStreamI, error) { m.mutex.Lock() defer m.mutex.Unlock() - return m.openStreamImpl() + str, err := m.openStreamImpl() + if err != nil { + return nil, streamOpenErr{err} + } + return str, nil } func (m *outgoingUniStreamsMap) OpenStreamSync() (sendStreamI, error) { @@ -59,10 +63,10 @@ func (m *outgoingUniStreamsMap) OpenStreamSync() (sendStreamI, error) { for { str, err := m.openStreamImpl() if err == nil { - return str, err + return str, nil } - if err != nil && err != qerr.TooManyOpenStreams { - return nil, err + if err != nil && err != errTooManyOpenStreams { + return nil, streamOpenErr{err} } m.cond.Wait() } @@ -87,7 +91,7 @@ func (m *outgoingUniStreamsMap) openStreamImpl() (sendStreamI, error) { } m.blockedSent = true } - return nil, qerr.TooManyOpenStreams + return nil, errTooManyOpenStreams } s := m.newStream(m.nextStream) m.streams[m.nextStream] = s diff --git a/vendor/github.com/lucas-clemente/quic-go/vendor/github.com/marten-seemann/qtls/cipher_suites.go b/vendor/github.com/lucas-clemente/quic-go/vendor/github.com/marten-seemann/qtls/cipher_suites.go index 3bbc0b90d..781c32282 100644 --- a/vendor/github.com/lucas-clemente/quic-go/vendor/github.com/marten-seemann/qtls/cipher_suites.go +++ b/vendor/github.com/lucas-clemente/quic-go/vendor/github.com/marten-seemann/qtls/cipher_suites.go @@ -250,6 +250,11 @@ func aeadAESGCM12(key, fixedNonce []byte) cipher.AEAD { return ret } +// AEADAESGCM13 creates a new AES-GCM AEAD for TLS 1.3 +func AEADAESGCM13(key, fixedNonce []byte) cipher.AEAD { + return aeadAESGCM13(key, fixedNonce) +} + func aeadAESGCM13(key, fixedNonce []byte) cipher.AEAD { aes, err := aes.NewCipher(key) if err != nil {