TUN-4922: Downgrade quic-go library to 0.20.0

This commit is contained in:
Sudarsan Reddy
2021-08-13 15:45:13 +01:00
parent 5f6e867685
commit 1082ac1c36
278 changed files with 3528 additions and 18344 deletions

View File

@@ -9,13 +9,12 @@ import (
// NewAckHandler creates a new SentPacketHandler and a new ReceivedPacketHandler
func NewAckHandler(
initialPacketNumber protocol.PacketNumber,
initialMaxDatagramSize protocol.ByteCount,
rttStats *utils.RTTStats,
pers protocol.Perspective,
tracer logging.ConnectionTracer,
logger utils.Logger,
version protocol.VersionNumber,
) (SentPacketHandler, ReceivedPacketHandler) {
sph := newSentPacketHandler(initialPacketNumber, initialMaxDatagramSize, rttStats, pers, tracer, logger)
sph := newSentPacketHandler(initialPacketNumber, rttStats, pers, tracer, logger)
return sph, newReceivedPacketHandler(sph, rttStats, logger, version)
}

View File

@@ -27,7 +27,7 @@ type Packet struct {
type SentPacketHandler interface {
// SentPacket may modify the packet
SentPacket(packet *Packet)
ReceivedAck(ackFrame *wire.AckFrame, encLevel protocol.EncryptionLevel, recvTime time.Time) (bool /* 1-RTT packet acked */, error)
ReceivedAck(ackFrame *wire.AckFrame, encLevel protocol.EncryptionLevel, recvTime time.Time) error
ReceivedBytes(protocol.ByteCount)
DropPackets(protocol.EncryptionLevel)
ResetForRetry() error

View File

@@ -21,8 +21,6 @@ const (
packetThreshold = 3
// Before validating the client's address, the server won't send more than 3x bytes than it received.
amplificationFactor = 3
// We use Retry packets to derive an RTT estimate. Make sure we don't set the RTT to a super low value yet.
minRTTAfterRetry = 5 * time.Millisecond
)
type packetNumberSpace struct {
@@ -103,7 +101,6 @@ var (
func newSentPacketHandler(
initialPN protocol.PacketNumber,
initialMaxDatagramSize protocol.ByteCount,
rttStats *utils.RTTStats,
pers protocol.Perspective,
tracer logging.ConnectionTracer,
@@ -112,7 +109,6 @@ func newSentPacketHandler(
congestion := congestion.NewCubicSender(
congestion.DefaultClock{},
rttStats,
initialMaxDatagramSize,
true, // use Reno
tracer,
)
@@ -198,17 +194,12 @@ func (h *sentPacketHandler) dropPackets(encLevel protocol.EncryptionLevel) {
}
func (h *sentPacketHandler) ReceivedBytes(n protocol.ByteCount) {
wasAmplificationLimit := h.isAmplificationLimited()
h.bytesReceived += n
if wasAmplificationLimit && !h.isAmplificationLimited() {
h.setLossDetectionTimer()
}
}
func (h *sentPacketHandler) ReceivedPacket(l protocol.EncryptionLevel) {
if h.perspective == protocol.PerspectiveServer && l == protocol.EncryptionHandshake && !h.peerAddressValidated {
func (h *sentPacketHandler) ReceivedPacket(encLevel protocol.EncryptionLevel) {
if h.perspective == protocol.PerspectiveServer && encLevel == protocol.EncryptionHandshake {
h.peerAddressValidated = true
h.setLossDetectionTimer()
}
}
@@ -277,15 +268,12 @@ func (h *sentPacketHandler) sentPacketImpl(packet *Packet) bool /* is ack-elicit
return isAckEliciting
}
func (h *sentPacketHandler) ReceivedAck(ack *wire.AckFrame, encLevel protocol.EncryptionLevel, rcvTime time.Time) (bool /* contained 1-RTT packet */, error) {
func (h *sentPacketHandler) ReceivedAck(ack *wire.AckFrame, encLevel protocol.EncryptionLevel, rcvTime time.Time) error {
pnSpace := h.getPacketNumberSpace(encLevel)
largestAcked := ack.LargestAcked()
if largestAcked > pnSpace.largestSent {
return false, &qerr.TransportError{
ErrorCode: qerr.ProtocolViolation,
ErrorMessage: "received ACK for an unsent packet",
}
return qerr.NewError(qerr.ProtocolViolation, "Received ACK for an unsent packet")
}
pnSpace.largestAcked = utils.MaxPacketNumber(pnSpace.largestAcked, largestAcked)
@@ -302,7 +290,7 @@ func (h *sentPacketHandler) ReceivedAck(ack *wire.AckFrame, encLevel protocol.En
priorInFlight := h.bytesInFlight
ackedPackets, err := h.detectAndRemoveAckedPackets(ack, encLevel)
if err != nil || len(ackedPackets) == 0 {
return false, err
return err
}
// update the RTT, if the largest acked is newly acknowledged
if len(ackedPackets) > 0 {
@@ -320,16 +308,15 @@ func (h *sentPacketHandler) ReceivedAck(ack *wire.AckFrame, encLevel protocol.En
}
}
if err := h.detectLostPackets(rcvTime, encLevel); err != nil {
return false, err
return err
}
var acked1RTTPacket bool
for _, p := range ackedPackets {
if p.skippedPacket {
return fmt.Errorf("received an ACK for skipped packet number: %d (%s)", p.PacketNumber, encLevel)
}
if p.includedInBytesInFlight && !p.declaredLost {
h.congestion.OnPacketAcked(p.PacketNumber, p.Length, priorInFlight, rcvTime)
}
if p.EncryptionLevel == protocol.Encryption1RTT {
acked1RTTPacket = true
}
h.removeFromBytesInFlight(p)
}
@@ -348,7 +335,7 @@ func (h *sentPacketHandler) ReceivedAck(ack *wire.AckFrame, encLevel protocol.En
pnSpace.history.DeleteOldPackets(rcvTime)
h.setLossDetectionTimer()
return acked1RTTPacket, nil
return nil
}
func (h *sentPacketHandler) GetLowestPacketNotConfirmedAcked() protocol.PacketNumber {
@@ -380,20 +367,15 @@ func (h *sentPacketHandler) detectAndRemoveAckedPackets(ack *wire.AckFrame, encL
ackRange = ack.AckRanges[len(ack.AckRanges)-1-ackRangeIndex]
}
if p.PacketNumber < ackRange.Smallest { // packet not contained in ACK range
return true, nil
}
if p.PacketNumber > ackRange.Largest {
return false, fmt.Errorf("BUG: ackhandler would have acked wrong packet %d, while evaluating range %d -> %d", p.PacketNumber, ackRange.Smallest, ackRange.Largest)
if p.PacketNumber >= ackRange.Smallest { // packet i contained in ACK range
if p.PacketNumber > ackRange.Largest {
return false, fmt.Errorf("BUG: ackhandler would have acked wrong packet %d, while evaluating range %d -> %d", p.PacketNumber, ackRange.Smallest, ackRange.Largest)
}
h.ackedPackets = append(h.ackedPackets, p)
}
} else {
h.ackedPackets = append(h.ackedPackets, p)
}
if p.skippedPacket {
return false, &qerr.TransportError{
ErrorCode: qerr.ProtocolViolation,
ErrorMessage: fmt.Sprintf("received an ACK for skipped packet number: %d (%s)", p.PacketNumber, encLevel),
}
}
h.ackedPackets = append(h.ackedPackets, p)
return true, nil
})
if h.logger.Debug() && len(h.ackedPackets) > 0 {
@@ -417,9 +399,6 @@ func (h *sentPacketHandler) detectAndRemoveAckedPackets(ack *wire.AckFrame, encL
if err := pnSpace.history.Remove(p.PacketNumber); err != nil {
return nil, err
}
if h.tracer != nil {
h.tracer.AcknowledgedPacket(encLevel, p.PacketNumber)
}
}
return h.ackedPackets, err
@@ -445,20 +424,20 @@ func (h *sentPacketHandler) getLossTimeAndSpace() (time.Time, protocol.Encryptio
}
// same logic as getLossTimeAndSpace, but for lastAckElicitingPacketTime instead of lossTime
func (h *sentPacketHandler) getPTOTimeAndSpace() (pto time.Time, encLevel protocol.EncryptionLevel, ok bool) {
// We only send application data probe packets once the handshake is confirmed,
// because before that, we don't have the keys to decrypt ACKs sent in 1-RTT packets.
if !h.handshakeConfirmed && !h.hasOutstandingCryptoPackets() {
if h.peerCompletedAddressValidation {
return
}
func (h *sentPacketHandler) getPTOTimeAndSpace() (time.Time, protocol.EncryptionLevel) {
if !h.hasOutstandingPackets() {
t := time.Now().Add(h.rttStats.PTO(false) << h.ptoCount)
if h.initialPackets != nil {
return t, protocol.EncryptionInitial, true
return t, protocol.EncryptionInitial
}
return t, protocol.EncryptionHandshake, true
return t, protocol.EncryptionHandshake
}
var (
encLevel protocol.EncryptionLevel
pto time.Time
)
if h.initialPackets != nil {
encLevel = protocol.EncryptionInitial
if t := h.initialPackets.lastAckElicitingPacketTime; !t.IsZero() {
@@ -479,7 +458,7 @@ func (h *sentPacketHandler) getPTOTimeAndSpace() (pto time.Time, encLevel protoc
encLevel = protocol.Encryption1RTT
}
}
return pto, encLevel, true
return pto, encLevel
}
func (h *sentPacketHandler) hasOutstandingCryptoPackets() bool {
@@ -494,13 +473,15 @@ func (h *sentPacketHandler) hasOutstandingCryptoPackets() bool {
}
func (h *sentPacketHandler) hasOutstandingPackets() bool {
return h.appDataPackets.history.HasOutstandingPackets() || h.hasOutstandingCryptoPackets()
// We only send application data probe packets once the handshake completes,
// because before that, we don't have the keys to decrypt ACKs sent in 1-RTT packets.
return (h.handshakeConfirmed && h.appDataPackets.history.HasOutstandingPackets()) ||
h.hasOutstandingCryptoPackets()
}
func (h *sentPacketHandler) setLossDetectionTimer() {
oldAlarm := h.alarm // only needed in case tracing is enabled
lossTime, encLevel := h.getLossTimeAndSpace()
if !lossTime.IsZero() {
if lossTime, encLevel := h.getLossTimeAndSpace(); !lossTime.IsZero() {
// Early retransmit timer or time loss detection.
h.alarm = lossTime
if h.tracer != nil && h.alarm != oldAlarm {
@@ -509,35 +490,18 @@ func (h *sentPacketHandler) setLossDetectionTimer() {
return
}
// Cancel the alarm if amplification limited.
if h.isAmplificationLimited() {
h.alarm = time.Time{}
if !oldAlarm.IsZero() {
h.logger.Debugf("Canceling loss detection timer. Amplification limited.")
if h.tracer != nil {
h.tracer.LossTimerCanceled()
}
}
return
}
// Cancel the alarm if no packets are outstanding
if !h.hasOutstandingPackets() && h.peerCompletedAddressValidation {
h.alarm = time.Time{}
if !oldAlarm.IsZero() {
h.logger.Debugf("Canceling loss detection timer. No packets in flight.")
if h.tracer != nil {
h.tracer.LossTimerCanceled()
}
h.logger.Debugf("Canceling loss detection timer. No packets in flight.")
if h.tracer != nil && !oldAlarm.IsZero() {
h.tracer.LossTimerCanceled()
}
return
}
// PTO alarm
ptoTime, encLevel, ok := h.getPTOTimeAndSpace()
if !ok {
return
}
ptoTime, encLevel := h.getPTOTimeAndSpace()
h.alarm = ptoTime
if h.tracer != nil && h.alarm != oldAlarm {
h.tracer.SetLossTimer(logging.TimerTypePTO, encLevel, h.alarm)
@@ -605,7 +569,20 @@ func (h *sentPacketHandler) detectLostPackets(now time.Time, encLevel protocol.E
}
func (h *sentPacketHandler) OnLossDetectionTimeout() error {
defer h.setLossDetectionTimer()
// When all outstanding are acknowledged, the alarm is canceled in
// setLossDetectionTimer. This doesn't reset the timer in the session though.
// When OnAlarm is called, we therefore need to make sure that there are
// actually packets outstanding.
if h.hasOutstandingPackets() || !h.peerCompletedAddressValidation {
if err := h.onVerifiedLossDetectionTimeout(); err != nil {
return err
}
}
h.setLossDetectionTimer()
return nil
}
func (h *sentPacketHandler) onVerifiedLossDetectionTimeout() error {
earliestLossTime, encLevel := h.getLossTimeAndSpace()
if !earliestLossTime.IsZero() {
if h.logger.Debug() {
@@ -619,12 +596,34 @@ func (h *sentPacketHandler) OnLossDetectionTimeout() error {
}
// PTO
// When all outstanding are acknowledged, the alarm is canceled in
// setLossDetectionTimer. This doesn't reset the timer in the session though.
// When OnAlarm is called, we therefore need to make sure that there are
// actually packets outstanding.
if h.bytesInFlight == 0 && !h.peerCompletedAddressValidation {
h.ptoCount++
h.ptoCount++
if h.bytesInFlight > 0 {
_, encLevel = h.getPTOTimeAndSpace()
if h.logger.Debug() {
h.logger.Debugf("Loss detection alarm for %s fired in PTO mode. PTO count: %d", encLevel, h.ptoCount)
}
if h.tracer != nil {
h.tracer.LossTimerExpired(logging.TimerTypePTO, encLevel)
h.tracer.UpdatedPTOCount(h.ptoCount)
}
h.numProbesToSend += 2
//nolint:exhaustive // We never arm a PTO timer for 0-RTT packets.
switch encLevel {
case protocol.EncryptionInitial:
h.ptoMode = SendPTOInitial
case protocol.EncryptionHandshake:
h.ptoMode = SendPTOHandshake
case protocol.Encryption1RTT:
// skip a packet number in order to elicit an immediate ACK
_ = h.PopPacketNumber(protocol.Encryption1RTT)
h.ptoMode = SendPTOAppData
default:
return fmt.Errorf("PTO timer in unexpected encryption level: %s", encLevel)
}
} else {
if h.perspective == protocol.PerspectiveServer {
return errors.New("sentPacketHandler BUG: PTO fired, but bytes_in_flight is 0")
}
h.numProbesToSend++
if h.initialPackets != nil {
h.ptoMode = SendPTOInitial
@@ -633,37 +632,6 @@ func (h *sentPacketHandler) OnLossDetectionTimeout() error {
} else {
return errors.New("sentPacketHandler BUG: PTO fired, but bytes_in_flight is 0 and Initial and Handshake already dropped")
}
return nil
}
_, encLevel, ok := h.getPTOTimeAndSpace()
if !ok {
return nil
}
if ps := h.getPacketNumberSpace(encLevel); !ps.history.HasOutstandingPackets() && !h.peerCompletedAddressValidation {
return nil
}
h.ptoCount++
if h.logger.Debug() {
h.logger.Debugf("Loss detection alarm for %s fired in PTO mode. PTO count: %d", encLevel, h.ptoCount)
}
if h.tracer != nil {
h.tracer.LossTimerExpired(logging.TimerTypePTO, encLevel)
h.tracer.UpdatedPTOCount(h.ptoCount)
}
h.numProbesToSend += 2
//nolint:exhaustive // We never arm a PTO timer for 0-RTT packets.
switch encLevel {
case protocol.EncryptionInitial:
h.ptoMode = SendPTOInitial
case protocol.EncryptionHandshake:
h.ptoMode = SendPTOHandshake
case protocol.Encryption1RTT:
// skip a packet number in order to elicit an immediate ACK
_ = h.PopPacketNumber(protocol.Encryption1RTT)
h.ptoMode = SendPTOAppData
default:
return fmt.Errorf("PTO timer in unexpected encryption level: %s", encLevel)
}
return nil
}
@@ -800,9 +768,8 @@ func (h *sentPacketHandler) ResetForRetry() error {
// Only use the Retry to estimate the RTT if we didn't send any retransmission for the Initial.
// Otherwise, we don't know which Initial the Retry was sent in response to.
if h.ptoCount == 0 {
// Don't set the RTT to a value lower than 5ms here.
now := time.Now()
h.rttStats.UpdateRTT(utils.MaxDuration(minRTTAfterRetry, now.Sub(firstPacketSendTime)), 0, now)
h.rttStats.UpdateRTT(now.Sub(firstPacketSendTime), 0, now)
if h.logger.Debug() {
h.logger.Debugf("\tupdated RTT: %s (σ: %s)", h.rttStats.SmoothedRTT(), h.rttStats.MeanDeviation())
}

View File

@@ -64,9 +64,8 @@ func (h *sentPacketHistory) Iterate(cb func(*Packet) (cont bool, err error)) err
// FirstOutStanding returns the first outstanding packet.
func (h *sentPacketHistory) FirstOutstanding() *Packet {
for el := h.packetList.Front(); el != nil; el = el.Next() {
p := &el.Value
if !p.declaredLost && !p.skippedPacket && !p.IsPathMTUProbePacket {
return p
if !el.Value.declaredLost && !el.Value.skippedPacket {
return &el.Value
}
}
return nil

View File

@@ -1,7 +1,6 @@
package congestion
import (
"fmt"
"time"
"github.com/lucas-clemente/quic-go/internal/protocol"
@@ -15,8 +14,9 @@ const (
initialMaxDatagramSize = protocol.ByteCount(protocol.InitialPacketSizeIPv4)
maxBurstPackets = 3
renoBeta = 0.7 // Reno backoff factor.
initialMaxCongestionWindow = protocol.MaxCongestionWindowPackets * initialMaxDatagramSize
minCongestionWindowPackets = 2
initialCongestionWindow = 32
initialCongestionWindow = 32 * initialMaxDatagramSize
)
type cubicSender struct {
@@ -65,33 +65,11 @@ var (
)
// NewCubicSender makes a new cubic sender
func NewCubicSender(
clock Clock,
rttStats *utils.RTTStats,
initialMaxDatagramSize protocol.ByteCount,
reno bool,
tracer logging.ConnectionTracer,
) *cubicSender {
return newCubicSender(
clock,
rttStats,
reno,
initialMaxDatagramSize,
initialCongestionWindow*initialMaxDatagramSize,
protocol.MaxCongestionWindowPackets*initialMaxDatagramSize,
tracer,
)
func NewCubicSender(clock Clock, rttStats *utils.RTTStats, reno bool, tracer logging.ConnectionTracer) *cubicSender {
return newCubicSender(clock, rttStats, reno, initialCongestionWindow, initialMaxCongestionWindow, tracer)
}
func newCubicSender(
clock Clock,
rttStats *utils.RTTStats,
reno bool,
initialMaxDatagramSize,
initialCongestionWindow,
initialMaxCongestionWindow protocol.ByteCount,
tracer logging.ConnectionTracer,
) *cubicSender {
func newCubicSender(clock Clock, rttStats *utils.RTTStats, reno bool, initialCongestionWindow, initialMaxCongestionWindow protocol.ByteCount, tracer logging.ConnectionTracer) *cubicSender {
c := &cubicSender{
rttStats: rttStats,
largestSentPacketNumber: protocol.InvalidPacketNumber,
@@ -305,7 +283,7 @@ func (c *cubicSender) maybeTraceStateChange(new logging.CongestionState) {
func (c *cubicSender) SetMaxDatagramSize(s protocol.ByteCount) {
if s < c.maxDatagramSize {
panic(fmt.Sprintf("congestion BUG: decreased max datagram size from %d to %d", c.maxDatagramSize, s))
panic("congestion BUG: decreased max datagram size")
}
cwndIsMinCwnd := c.congestionWindow == c.minCongestionWindow()
c.maxDatagramSize = s

View File

@@ -50,10 +50,7 @@ func (c *connectionFlowController) IncrementHighestReceived(increment protocol.B
c.highestReceived += increment
if c.checkFlowControlViolation() {
return &qerr.TransportError{
ErrorCode: qerr.FlowControlError,
ErrorMessage: fmt.Sprintf("received %d bytes for the connection, allowed %d bytes", c.highestReceived, c.receiveWindow),
}
return qerr.NewError(qerr.FlowControlError, fmt.Sprintf("Received %d bytes for the connection, allowed %d bytes", c.highestReceived, c.receiveWindow))
}
return nil
}

View File

@@ -54,17 +54,11 @@ func (c *streamFlowController) UpdateHighestReceived(offset protocol.ByteCount,
if c.receivedFinalOffset {
// If we receive another final offset, check that it's the same.
if final && offset != c.highestReceived {
return &qerr.TransportError{
ErrorCode: qerr.FinalSizeError,
ErrorMessage: fmt.Sprintf("received inconsistent final offset for stream %d (old: %d, new: %d bytes)", c.streamID, c.highestReceived, offset),
}
return qerr.NewError(qerr.FinalSizeError, fmt.Sprintf("Received inconsistent final offset for stream %d (old: %d, new: %d bytes)", c.streamID, c.highestReceived, offset))
}
// Check that the offset is below the final offset.
if offset > c.highestReceived {
return &qerr.TransportError{
ErrorCode: qerr.FinalSizeError,
ErrorMessage: fmt.Sprintf("received offset %d for stream %d, but final offset was already received at %d", offset, c.streamID, c.highestReceived),
}
return qerr.NewError(qerr.FinalSizeError, fmt.Sprintf("Received offset %d for stream %d. Final offset was already received at %d", offset, c.streamID, c.highestReceived))
}
}
@@ -78,10 +72,7 @@ func (c *streamFlowController) UpdateHighestReceived(offset protocol.ByteCount,
// This can happen due to reordering.
if offset <= c.highestReceived {
if final {
return &qerr.TransportError{
ErrorCode: qerr.FinalSizeError,
ErrorMessage: fmt.Sprintf("received final offset %d for stream %d, but already received offset %d before", offset, c.streamID, c.highestReceived),
}
return qerr.NewError(qerr.FinalSizeError, fmt.Sprintf("Received final offset %d for stream %d, but already received offset %d before", offset, c.streamID, c.highestReceived))
}
return nil
}
@@ -89,10 +80,7 @@ func (c *streamFlowController) UpdateHighestReceived(offset protocol.ByteCount,
increment := offset - c.highestReceived
c.highestReceived = offset
if c.checkFlowControlViolation() {
return &qerr.TransportError{
ErrorCode: qerr.FlowControlError,
ErrorMessage: fmt.Sprintf("received %d bytes on stream %d, allowed %d bytes", offset, c.streamID, c.receiveWindow),
}
return qerr.NewError(qerr.FlowControlError, fmt.Sprintf("Received %d bytes on stream %d, allowed %d bytes", offset, c.streamID, c.receiveWindow))
}
return c.connection.IncrementHighestReceived(increment)
}

View File

@@ -403,10 +403,7 @@ func (h *cryptoSetup) checkEncryptionLevel(msgType messageType, encLevel protoco
func (h *cryptoSetup) handleTransportParameters(data []byte) {
var tp wire.TransportParameters
if err := tp.Unmarshal(data, h.perspective.Opposite()); err != nil {
h.runner.OnError(&qerr.TransportError{
ErrorCode: qerr.TransportParameterError,
ErrorMessage: err.Error(),
})
h.runner.OnError(qerr.NewError(qerr.TransportParameterError, err.Error()))
}
h.peerParams = &tp
h.runner.OnReceivedParams(h.peerParams)
@@ -558,7 +555,7 @@ func (h *cryptoSetup) SetReadKey(encLevel qtls.EncryptionLevel, suite *qtls.Ciph
newHeaderProtector(suite, trafficSecret, true),
)
h.mutex.Unlock()
h.logger.Debugf("Installed 0-RTT Read keys (using %s)", tls.CipherSuiteName(suite.ID))
h.logger.Debugf("Installed 0-RTT Read keys (using %s)", qtls.CipherSuiteName(suite.ID))
if h.tracer != nil {
h.tracer.UpdatedKeyFromTLS(protocol.Encryption0RTT, h.perspective.Opposite())
}
@@ -571,12 +568,12 @@ func (h *cryptoSetup) SetReadKey(encLevel qtls.EncryptionLevel, suite *qtls.Ciph
h.dropInitialKeys,
h.perspective,
)
h.logger.Debugf("Installed Handshake Read keys (using %s)", tls.CipherSuiteName(suite.ID))
h.logger.Debugf("Installed Handshake Read keys (using %s)", qtls.CipherSuiteName(suite.ID))
case qtls.EncryptionApplication:
h.readEncLevel = protocol.Encryption1RTT
h.aead.SetReadKey(suite, trafficSecret)
h.has1RTTOpener = true
h.logger.Debugf("Installed 1-RTT Read keys (using %s)", tls.CipherSuiteName(suite.ID))
h.logger.Debugf("Installed 1-RTT Read keys (using %s)", qtls.CipherSuiteName(suite.ID))
default:
panic("unexpected read encryption level")
}
@@ -598,7 +595,7 @@ func (h *cryptoSetup) SetWriteKey(encLevel qtls.EncryptionLevel, suite *qtls.Cip
newHeaderProtector(suite, trafficSecret, true),
)
h.mutex.Unlock()
h.logger.Debugf("Installed 0-RTT Write keys (using %s)", tls.CipherSuiteName(suite.ID))
h.logger.Debugf("Installed 0-RTT Write keys (using %s)", qtls.CipherSuiteName(suite.ID))
if h.tracer != nil {
h.tracer.UpdatedKeyFromTLS(protocol.Encryption0RTT, h.perspective)
}
@@ -611,12 +608,12 @@ func (h *cryptoSetup) SetWriteKey(encLevel qtls.EncryptionLevel, suite *qtls.Cip
h.dropInitialKeys,
h.perspective,
)
h.logger.Debugf("Installed Handshake Write keys (using %s)", tls.CipherSuiteName(suite.ID))
h.logger.Debugf("Installed Handshake Write keys (using %s)", qtls.CipherSuiteName(suite.ID))
case qtls.EncryptionApplication:
h.writeEncLevel = protocol.Encryption1RTT
h.aead.SetWriteKey(suite, trafficSecret)
h.has1RTTSealer = true
h.logger.Debugf("Installed 1-RTT Write keys (using %s)", tls.CipherSuiteName(suite.ID))
h.logger.Debugf("Installed 1-RTT Write keys (using %s)", qtls.CipherSuiteName(suite.ID))
if h.zeroRTTSealer != nil {
h.zeroRTTSealer = nil
h.logger.Debugf("Dropping 0-RTT keys.")

View File

@@ -4,8 +4,6 @@ import (
"crypto"
"crypto/tls"
"golang.org/x/crypto/hkdf"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/qtls"
)
@@ -16,7 +14,7 @@ var (
)
func getSalt(v protocol.VersionNumber) []byte {
if v == protocol.VersionDraft34 || v == protocol.Version1 {
if v == protocol.VersionDraft34 {
return quicSaltDraft34
}
return quicSaltOld
@@ -51,7 +49,7 @@ func NewInitialAEAD(connID protocol.ConnectionID, pers protocol.Perspective, v p
}
func computeSecrets(connID protocol.ConnectionID, v protocol.VersionNumber) (clientSecret, serverSecret []byte) {
initialSecret := hkdf.Extract(crypto.SHA256.New, connID, getSalt(v))
initialSecret := qtls.HkdfExtract(crypto.SHA256, connID, getSalt(v))
clientSecret = hkdfExpandLabel(crypto.SHA256, initialSecret, []byte{}, "client in", crypto.SHA256.Size())
serverSecret = hkdfExpandLabel(crypto.SHA256, initialSecret, []byte{}, "server in", crypto.SHA256.Size())
return

View File

@@ -48,7 +48,7 @@ func GetRetryIntegrityTag(retry []byte, origDestConnID protocol.ConnectionID, ve
var tag [16]byte
var sealed []byte
if version != protocol.VersionDraft34 && version != protocol.Version1 {
if version != protocol.VersionDraft34 {
sealed = oldRetryAEAD.Seal(tag[:0], oldRetryNonce[:], nil, retryBuf.Bytes())
} else {
sealed = retryAEAD.Seal(tag[:0], retryNonce[:], nil, retryBuf.Bytes())

View File

@@ -24,7 +24,7 @@ var _ tlsExtensionHandler = &extensionHandler{}
// newExtensionHandler creates a new extension handler
func newExtensionHandler(params []byte, pers protocol.Perspective, v protocol.VersionNumber) tlsExtensionHandler {
et := uint16(quicTLSExtensionType)
if v != protocol.VersionDraft34 && v != protocol.Version1 {
if v != protocol.VersionDraft34 {
et = quicTLSExtensionTypeOldDrafts
}
return &extensionHandler{

View File

@@ -163,7 +163,7 @@ func (a *updatableAEAD) Open(dst, src []byte, rcvTime time.Time, pn protocol.Pac
if err == ErrDecryptionFailed {
a.invalidPacketCount++
if a.invalidPacketCount >= a.invalidPacketLimit {
return nil, &qerr.TransportError{ErrorCode: qerr.AEADLimitReached}
return nil, qerr.AEADLimitReached
}
}
if err == nil {
@@ -201,10 +201,7 @@ func (a *updatableAEAD) open(dst, src []byte, rcvTime time.Time, pn protocol.Pac
}
// Opening succeeded. Check if the peer was allowed to update.
if a.keyPhase > 0 && a.firstSentWithCurrentKey == protocol.InvalidPacketNumber {
return nil, &qerr.TransportError{
ErrorCode: qerr.KeyUpdateError,
ErrorMessage: "keys updated too quickly",
}
return nil, qerr.NewError(qerr.KeyUpdateError, "keys updated too quickly")
}
a.rollKeys()
a.logger.Debugf("Peer updated keys to %d", a.keyPhase)
@@ -253,10 +250,7 @@ func (a *updatableAEAD) Seal(dst, src []byte, pn protocol.PacketNumber, ad []byt
func (a *updatableAEAD) SetLargestAcked(pn protocol.PacketNumber) error {
if a.firstSentWithCurrentKey != protocol.InvalidPacketNumber &&
pn >= a.firstSentWithCurrentKey && a.numRcvdWithCurrentKey == 0 {
return &qerr.TransportError{
ErrorCode: qerr.KeyUpdateError,
ErrorMessage: fmt.Sprintf("received ACK for key phase %d, but peer didn't update keys", a.keyPhase),
}
return qerr.NewError(qerr.KeyUpdateError, fmt.Sprintf("received ACK for key phase %d, but peer didn't update keys", a.keyPhase))
}
a.largestAcked = pn
return nil

View File

@@ -52,6 +52,9 @@ const MaxByteCount = ByteCount(1<<62 - 1)
// InvalidByteCount is an invalid byte count
const InvalidByteCount ByteCount = -1
// An ApplicationErrorCode is an application-defined error code.
type ApplicationErrorCode uint64
// A StatelessResetToken is a stateless reset token.
type StatelessResetToken [16]byte

View File

@@ -18,18 +18,17 @@ const (
// The version numbers, making grepping easier
const (
VersionTLS VersionNumber = 0x1
VersionWhatever VersionNumber = math.MaxUint32 - 1 // for when the version doesn't matter
VersionTLS VersionNumber = 0xff00001d // draft-29
VersionWhatever VersionNumber = 1 // for when the version doesn't matter
VersionUnknown VersionNumber = math.MaxUint32
VersionDraft29 VersionNumber = 0xff00001d
VersionDraft32 VersionNumber = 0xff000020
VersionDraft34 VersionNumber = 0xff000022
Version1 VersionNumber = 0x1
VersionDraft34 VersionNumber = 0xff000022 // If everything goes according to plan at the IETF, this will one day be QUIC v1.
)
// SupportedVersions lists the versions that the server supports
// must be in sorted descending order
var SupportedVersions = []VersionNumber{Version1, VersionDraft34, VersionDraft32, VersionDraft29}
var SupportedVersions = []VersionNumber{VersionDraft29, VersionDraft34, VersionDraft32}
// IsValidVersion says if the version is known to quic-go
func IsValidVersion(v VersionNumber) bool {
@@ -39,7 +38,7 @@ func IsValidVersion(v VersionNumber) bool {
func (vn VersionNumber) String() string {
// For releases, VersionTLS will be set to a draft version.
// A switch statement can't contain duplicate cases.
if vn == VersionTLS && VersionTLS != VersionDraft29 && VersionTLS != VersionDraft32 && VersionTLS != Version1 {
if vn == VersionTLS && VersionTLS != VersionDraft29 && VersionTLS != VersionDraft32 {
return "TLS dev version (WIP)"
}
//nolint:exhaustive
@@ -54,8 +53,6 @@ func (vn VersionNumber) String() string {
return "draft-32"
case VersionDraft34:
return "draft-34"
case Version1:
return "v1"
default:
if vn.isGQUIC() {
return fmt.Sprintf("gQUIC %d", vn.toGQUICVersion())

View File

@@ -6,44 +6,51 @@ import (
"github.com/lucas-clemente/quic-go/internal/qtls"
)
// TransportErrorCode is a QUIC transport error.
type TransportErrorCode uint64
// ErrorCode can be used as a normal error without reason.
type ErrorCode uint64
// The error codes defined by QUIC
const (
NoError TransportErrorCode = 0x0
InternalError TransportErrorCode = 0x1
ConnectionRefused TransportErrorCode = 0x2
FlowControlError TransportErrorCode = 0x3
StreamLimitError TransportErrorCode = 0x4
StreamStateError TransportErrorCode = 0x5
FinalSizeError TransportErrorCode = 0x6
FrameEncodingError TransportErrorCode = 0x7
TransportParameterError TransportErrorCode = 0x8
ConnectionIDLimitError TransportErrorCode = 0x9
ProtocolViolation TransportErrorCode = 0xa
InvalidToken TransportErrorCode = 0xb
ApplicationErrorErrorCode TransportErrorCode = 0xc
CryptoBufferExceeded TransportErrorCode = 0xd
KeyUpdateError TransportErrorCode = 0xe
AEADLimitReached TransportErrorCode = 0xf
NoViablePathError TransportErrorCode = 0x10
NoError ErrorCode = 0x0
InternalError ErrorCode = 0x1
ConnectionRefused ErrorCode = 0x2
FlowControlError ErrorCode = 0x3
StreamLimitError ErrorCode = 0x4
StreamStateError ErrorCode = 0x5
FinalSizeError ErrorCode = 0x6
FrameEncodingError ErrorCode = 0x7
TransportParameterError ErrorCode = 0x8
ConnectionIDLimitError ErrorCode = 0x9
ProtocolViolation ErrorCode = 0xa
InvalidToken ErrorCode = 0xb
ApplicationError ErrorCode = 0xc
CryptoBufferExceeded ErrorCode = 0xd
KeyUpdateError ErrorCode = 0xe
AEADLimitReached ErrorCode = 0xf
NoViablePathError ErrorCode = 0x10
)
func (e TransportErrorCode) IsCryptoError() bool {
func (e ErrorCode) isCryptoError() bool {
return e >= 0x100 && e < 0x200
}
func (e ErrorCode) Error() string {
if e.isCryptoError() {
return fmt.Sprintf("%s: %s", e.String(), e.Message())
}
return e.String()
}
// Message is a description of the error.
// It only returns a non-empty string for crypto errors.
func (e TransportErrorCode) Message() string {
if !e.IsCryptoError() {
func (e ErrorCode) Message() string {
if !e.isCryptoError() {
return ""
}
return qtls.Alert(e - 0x100).Error()
}
func (e TransportErrorCode) String() string {
func (e ErrorCode) String() string {
switch e {
case NoError:
return "NO_ERROR"
@@ -69,7 +76,7 @@ func (e TransportErrorCode) String() string {
return "PROTOCOL_VIOLATION"
case InvalidToken:
return "INVALID_TOKEN"
case ApplicationErrorErrorCode:
case ApplicationError:
return "APPLICATION_ERROR"
case CryptoBufferExceeded:
return "CRYPTO_BUFFER_EXCEEDED"
@@ -80,7 +87,7 @@ func (e TransportErrorCode) String() string {
case NoViablePathError:
return "NO_VIABLE_PATH"
default:
if e.IsCryptoError() {
if e.isCryptoError() {
return fmt.Sprintf("CRYPTO_ERROR (%#x)", uint16(e))
}
return fmt.Sprintf("unknown error code: %#x", uint16(e))

View File

@@ -1,106 +0,0 @@
package qerr
import (
"fmt"
"net"
"github.com/lucas-clemente/quic-go/internal/protocol"
)
var (
ErrHandshakeTimeout = &HandshakeTimeoutError{}
ErrIdleTimeout = &IdleTimeoutError{}
)
type TransportError struct {
Remote bool
FrameType uint64
ErrorCode TransportErrorCode
ErrorMessage string
}
var _ error = &TransportError{}
// NewCryptoError create a new TransportError instance for a crypto error
func NewCryptoError(tlsAlert uint8, errorMessage string) *TransportError {
return &TransportError{
ErrorCode: 0x100 + TransportErrorCode(tlsAlert),
ErrorMessage: errorMessage,
}
}
func (e *TransportError) Error() string {
str := e.ErrorCode.String()
if e.FrameType != 0 {
str += fmt.Sprintf(" (frame type: %#x)", e.FrameType)
}
msg := e.ErrorMessage
if len(msg) == 0 {
msg = e.ErrorCode.Message()
}
if len(msg) == 0 {
return str
}
return str + ": " + msg
}
// An ApplicationErrorCode is an application-defined error code.
type ApplicationErrorCode uint64
// A StreamErrorCode is an error code used to cancel streams.
type StreamErrorCode uint64
type ApplicationError struct {
Remote bool
ErrorCode ApplicationErrorCode
ErrorMessage string
}
var _ error = &ApplicationError{}
func (e *ApplicationError) Error() string {
if len(e.ErrorMessage) == 0 {
return fmt.Sprintf("Application error %#x", e.ErrorCode)
}
return fmt.Sprintf("Application error %#x: %s", e.ErrorCode, e.ErrorMessage)
}
type IdleTimeoutError struct{}
var _ error = &IdleTimeoutError{}
func (e *IdleTimeoutError) Timeout() bool { return true }
func (e *IdleTimeoutError) Temporary() bool { return false }
func (e *IdleTimeoutError) Error() string { return "timeout: no recent network activity" }
type HandshakeTimeoutError struct{}
var _ error = &HandshakeTimeoutError{}
func (e *HandshakeTimeoutError) Timeout() bool { return true }
func (e *HandshakeTimeoutError) Temporary() bool { return false }
func (e *HandshakeTimeoutError) Error() string { return "timeout: handshake did not complete in time" }
// A VersionNegotiationError occurs when the client and the server can't agree on a QUIC version.
type VersionNegotiationError struct {
Ours []protocol.VersionNumber
Theirs []protocol.VersionNumber
}
func (e *VersionNegotiationError) Error() string {
return fmt.Sprintf("no compatible QUIC version found (we support %s, server offered %s)", e.Ours, e.Theirs)
}
// A StatelessResetError occurs when we receive a stateless reset.
type StatelessResetError struct {
Token protocol.StatelessResetToken
}
var _ net.Error = &StatelessResetError{}
func (e *StatelessResetError) Error() string {
return fmt.Sprintf("received a stateless reset with token %x", e.Token)
}
func (e *StatelessResetError) Timeout() bool { return false }
func (e *StatelessResetError) Temporary() bool { return true }

View File

@@ -1,55 +0,0 @@
// +build go1.16
package qerr
import (
"net"
)
func (e *TransportError) Is(target error) bool {
_, ok := target.(*TransportError)
if ok {
return true
}
return target == net.ErrClosed
}
func (e *ApplicationError) Is(target error) bool {
_, ok := target.(*ApplicationError)
if ok {
return true
}
return target == net.ErrClosed
}
func (e *IdleTimeoutError) Is(target error) bool {
_, ok := target.(*IdleTimeoutError)
if ok {
return true
}
return target == net.ErrClosed
}
func (e *HandshakeTimeoutError) Is(target error) bool {
_, ok := target.(*HandshakeTimeoutError)
if ok {
return true
}
return target == net.ErrClosed
}
func (e *VersionNegotiationError) Is(target error) bool {
_, ok := target.(*VersionNegotiationError)
if ok {
return true
}
return target == net.ErrClosed
}
func (e *StatelessResetError) Is(target error) bool {
_, ok := target.(*StatelessResetError)
if ok {
return true
}
return target == net.ErrClosed
}

View File

@@ -1,33 +0,0 @@
// +build !go1.16
package qerr
func (e *TransportError) Is(target error) bool {
_, ok := target.(*TransportError)
return ok
}
func (e *ApplicationError) Is(target error) bool {
_, ok := target.(*ApplicationError)
return ok
}
func (e *IdleTimeoutError) Is(target error) bool {
_, ok := target.(*IdleTimeoutError)
return ok
}
func (e *HandshakeTimeoutError) Is(target error) bool {
_, ok := target.(*HandshakeTimeoutError)
return ok
}
func (e *VersionNegotiationError) Is(target error) bool {
_, ok := target.(*VersionNegotiationError)
return ok
}
func (e *StatelessResetError) Is(target error) bool {
_, ok := target.(*StatelessResetError)
return ok
}

View File

@@ -0,0 +1,112 @@
package qerr
import (
"fmt"
"net"
)
// A QuicError consists of an error code plus a error reason
type QuicError struct {
ErrorCode ErrorCode
FrameType uint64 // only valid if this not an application error
ErrorMessage string
isTimeout bool
isApplicationError bool
}
var _ net.Error = &QuicError{}
// NewError creates a new QuicError instance
func NewError(errorCode ErrorCode, errorMessage string) *QuicError {
return &QuicError{
ErrorCode: errorCode,
ErrorMessage: errorMessage,
}
}
// NewErrorWithFrameType creates a new QuicError instance for a specific frame type
func NewErrorWithFrameType(errorCode ErrorCode, frameType uint64, errorMessage string) *QuicError {
return &QuicError{
ErrorCode: errorCode,
FrameType: frameType,
ErrorMessage: errorMessage,
}
}
// NewTimeoutError creates a new QuicError instance for a timeout error
func NewTimeoutError(errorMessage string) *QuicError {
return &QuicError{
ErrorMessage: errorMessage,
isTimeout: true,
}
}
// NewCryptoError create a new QuicError instance for a crypto error
func NewCryptoError(tlsAlert uint8, errorMessage string) *QuicError {
return &QuicError{
ErrorCode: 0x100 + ErrorCode(tlsAlert),
ErrorMessage: errorMessage,
}
}
// NewApplicationError creates a new QuicError instance for an application error
func NewApplicationError(errorCode ErrorCode, errorMessage string) *QuicError {
return &QuicError{
ErrorCode: errorCode,
ErrorMessage: errorMessage,
isApplicationError: true,
}
}
func (e *QuicError) Error() string {
if e.isApplicationError {
if len(e.ErrorMessage) == 0 {
return fmt.Sprintf("Application error %#x", uint64(e.ErrorCode))
}
return fmt.Sprintf("Application error %#x: %s", uint64(e.ErrorCode), e.ErrorMessage)
}
str := e.ErrorCode.String()
if e.FrameType != 0 {
str += fmt.Sprintf(" (frame type: %#x)", e.FrameType)
}
msg := e.ErrorMessage
if len(msg) == 0 {
msg = e.ErrorCode.Message()
}
if len(msg) == 0 {
return str
}
return str + ": " + msg
}
// IsCryptoError says if this error is a crypto error
func (e *QuicError) IsCryptoError() bool {
return e.ErrorCode.isCryptoError()
}
// IsApplicationError says if this error is an application error
func (e *QuicError) IsApplicationError() bool {
return e.isApplicationError
}
// Temporary says if the error is temporary.
func (e *QuicError) Temporary() bool {
return false
}
// Timeout says if this error is a timeout.
func (e *QuicError) Timeout() bool {
return e.isTimeout
}
// ToQuicError converts an arbitrary error to a QuicError. It leaves QuicErrors
// unchanged, and properly handles `ErrorCode`s.
func ToQuicError(err error) *QuicError {
switch e := err.(type) {
case *QuicError:
return e
case ErrorCode:
return NewError(e, "")
}
return NewError(InternalError, err.Error())
}

View File

@@ -10,7 +10,7 @@ import (
"net"
"unsafe"
"github.com/marten-seemann/qtls-go1-15"
qtls "github.com/marten-seemann/qtls-go1-15"
)
type (
@@ -53,6 +53,21 @@ const (
EncryptionApplication = qtls.EncryptionApplication
)
// CipherSuiteName gets the name of a cipher suite.
func CipherSuiteName(id uint16) string {
return qtls.CipherSuiteName(id)
}
// HkdfExtract generates a pseudorandom key for use with Expand from an input secret and an optional independent salt.
func HkdfExtract(hash crypto.Hash, newSecret, currentSecret []byte) []byte {
return qtls.HkdfExtract(hash, newSecret, currentSecret)
}
// HkdfExpandLabel HKDF expands a label
func HkdfExpandLabel(hash crypto.Hash, secret, hashValue []byte, label string, L int) []byte {
return qtls.HkdfExpandLabel(hash, secret, hashValue, label, L)
}
// AEADAESGCMTLS13 creates a new AES-GCM AEAD for TLS 1.3
func AEADAESGCMTLS13(key, fixedNonce []byte) cipher.AEAD {
return qtls.AEADAESGCMTLS13(key, fixedNonce)

View File

@@ -1,5 +1,4 @@
// +build go1.16
// +build !go1.17
package qtls
@@ -10,7 +9,7 @@ import (
"net"
"unsafe"
"github.com/marten-seemann/qtls-go1-16"
qtls "github.com/marten-seemann/qtls-go1-16"
)
type (
@@ -53,6 +52,21 @@ const (
EncryptionApplication = qtls.EncryptionApplication
)
// CipherSuiteName gets the name of a cipher suite.
func CipherSuiteName(id uint16) string {
return qtls.CipherSuiteName(id)
}
// HkdfExtract generates a pseudorandom key for use with Expand from an input secret and an optional independent salt.
func HkdfExtract(hash crypto.Hash, newSecret, currentSecret []byte) []byte {
return qtls.HkdfExtract(hash, newSecret, currentSecret)
}
// HkdfExpandLabel HKDF expands a label
func HkdfExpandLabel(hash crypto.Hash, secret, hashValue []byte, label string, L int) []byte {
return qtls.HkdfExpandLabel(hash, secret, hashValue, label, L)
}
// AEADAESGCMTLS13 creates a new AES-GCM AEAD for TLS 1.3
func AEADAESGCMTLS13(key, fixedNonce []byte) cipher.AEAD {
return qtls.AEADAESGCMTLS13(key, fixedNonce)

View File

@@ -1,99 +0,0 @@
// +build go1.17
package qtls
import (
"crypto"
"crypto/cipher"
"crypto/tls"
"net"
"unsafe"
"github.com/marten-seemann/qtls-go1-17"
)
type (
// Alert is a TLS alert
Alert = qtls.Alert
// A Certificate is qtls.Certificate.
Certificate = qtls.Certificate
// CertificateRequestInfo contains inforamtion about a certificate request.
CertificateRequestInfo = qtls.CertificateRequestInfo
// A CipherSuiteTLS13 is a cipher suite for TLS 1.3
CipherSuiteTLS13 = qtls.CipherSuiteTLS13
// ClientHelloInfo contains information about a ClientHello.
ClientHelloInfo = qtls.ClientHelloInfo
// ClientSessionCache is a cache used for session resumption.
ClientSessionCache = qtls.ClientSessionCache
// ClientSessionState is a state needed for session resumption.
ClientSessionState = qtls.ClientSessionState
// A Config is a qtls.Config.
Config = qtls.Config
// A Conn is a qtls.Conn.
Conn = qtls.Conn
// ConnectionState contains information about the state of the connection.
ConnectionState = qtls.ConnectionStateWith0RTT
// EncryptionLevel is the encryption level of a message.
EncryptionLevel = qtls.EncryptionLevel
// Extension is a TLS extension
Extension = qtls.Extension
// ExtraConfig is the qtls.ExtraConfig
ExtraConfig = qtls.ExtraConfig
// RecordLayer is a qtls RecordLayer.
RecordLayer = qtls.RecordLayer
)
const (
// EncryptionHandshake is the Handshake encryption level
EncryptionHandshake = qtls.EncryptionHandshake
// Encryption0RTT is the 0-RTT encryption level
Encryption0RTT = qtls.Encryption0RTT
// EncryptionApplication is the application data encryption level
EncryptionApplication = qtls.EncryptionApplication
)
// AEADAESGCMTLS13 creates a new AES-GCM AEAD for TLS 1.3
func AEADAESGCMTLS13(key, fixedNonce []byte) cipher.AEAD {
return qtls.AEADAESGCMTLS13(key, fixedNonce)
}
// Client returns a new TLS client side connection.
func Client(conn net.Conn, config *Config, extraConfig *ExtraConfig) *Conn {
return qtls.Client(conn, config, extraConfig)
}
// Server returns a new TLS server side connection.
func Server(conn net.Conn, config *Config, extraConfig *ExtraConfig) *Conn {
return qtls.Server(conn, config, extraConfig)
}
func GetConnectionState(conn *Conn) ConnectionState {
return conn.ConnectionStateWith0RTT()
}
// ToTLSConnectionState extracts the tls.ConnectionState
func ToTLSConnectionState(cs ConnectionState) tls.ConnectionState {
return cs.ConnectionState
}
type cipherSuiteTLS13 struct {
ID uint16
KeyLen int
AEAD func(key, fixedNonce []byte) cipher.AEAD
Hash crypto.Hash
}
//go:linkname cipherSuiteTLS13ByID github.com/marten-seemann/qtls-go1-17.cipherSuiteTLS13ByID
func cipherSuiteTLS13ByID(id uint16) *cipherSuiteTLS13
// CipherSuiteTLS13ByID gets a TLS 1.3 cipher suite.
func CipherSuiteTLS13ByID(id uint16) *CipherSuiteTLS13 {
val := cipherSuiteTLS13ByID(id)
cs := (*cipherSuiteTLS13)(unsafe.Pointer(val))
return &qtls.CipherSuiteTLS13{
ID: cs.ID,
KeyLen: cs.KeyLen,
AEAD: cs.AEAD,
Hash: cs.Hash,
}
}

View File

@@ -1,5 +0,0 @@
// +build go1.18
package qtls
var _ int = "quic-go doesn't build on Go 1.18 yet."

View File

@@ -5,13 +5,14 @@ import (
"io"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/qerr"
"github.com/lucas-clemente/quic-go/quicvarint"
)
// A ConnectionCloseFrame is a CONNECTION_CLOSE frame
type ConnectionCloseFrame struct {
IsApplicationError bool
ErrorCode uint64
ErrorCode qerr.ErrorCode
FrameType uint64
ReasonPhrase string
}
@@ -27,7 +28,7 @@ func parseConnectionCloseFrame(r *bytes.Reader, _ protocol.VersionNumber) (*Conn
if err != nil {
return nil, err
}
f.ErrorCode = ec
f.ErrorCode = qerr.ErrorCode(ec)
// read the Frame Type, if this is not an application error
if !f.IsApplicationError {
ft, err := quicvarint.Read(r)
@@ -58,8 +59,8 @@ func parseConnectionCloseFrame(r *bytes.Reader, _ protocol.VersionNumber) (*Conn
}
// Length of a written frame
func (f *ConnectionCloseFrame) Length(protocol.VersionNumber) protocol.ByteCount {
length := 1 + quicvarint.Len(f.ErrorCode) + quicvarint.Len(uint64(len(f.ReasonPhrase))) + protocol.ByteCount(len(f.ReasonPhrase))
func (f *ConnectionCloseFrame) Length(version protocol.VersionNumber) protocol.ByteCount {
length := 1 + quicvarint.Len(uint64(f.ErrorCode)) + quicvarint.Len(uint64(len(f.ReasonPhrase))) + protocol.ByteCount(len(f.ReasonPhrase))
if !f.IsApplicationError {
length += quicvarint.Len(f.FrameType) // for the frame type
}
@@ -73,7 +74,7 @@ func (f *ConnectionCloseFrame) Write(b *bytes.Buffer, version protocol.VersionNu
b.WriteByte(0x1c)
}
quicvarint.Write(b, f.ErrorCode)
quicvarint.Write(b, uint64(f.ErrorCode))
if !f.IsApplicationError {
quicvarint.Write(b, f.FrameType)
}

View File

@@ -26,7 +26,7 @@ func NewFrameParser(supportsDatagrams bool, v protocol.VersionNumber) FrameParse
}
}
// ParseNext parses the next frame.
// ParseNextFrame parses the next frame
// It skips PADDING frames.
func (p *frameParser) ParseNext(r *bytes.Reader, encLevel protocol.EncryptionLevel) (Frame, error) {
for r.Len() != 0 {
@@ -38,11 +38,7 @@ func (p *frameParser) ParseNext(r *bytes.Reader, encLevel protocol.EncryptionLev
f, err := p.parseFrame(r, typeByte, encLevel)
if err != nil {
return nil, &qerr.TransportError{
FrameType: uint64(typeByte),
ErrorCode: qerr.FrameEncodingError,
ErrorMessage: err.Error(),
}
return nil, qerr.NewErrorWithFrameType(qerr.FrameEncodingError, uint64(typeByte), err.Error())
}
return f, nil
}

View File

@@ -4,14 +4,13 @@ import (
"bytes"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/qerr"
"github.com/lucas-clemente/quic-go/quicvarint"
)
// A ResetStreamFrame is a RESET_STREAM frame in QUIC
type ResetStreamFrame struct {
StreamID protocol.StreamID
ErrorCode qerr.StreamErrorCode
ErrorCode protocol.ApplicationErrorCode
FinalSize protocol.ByteCount
}
@@ -39,7 +38,7 @@ func parseResetStreamFrame(r *bytes.Reader, _ protocol.VersionNumber) (*ResetStr
return &ResetStreamFrame{
StreamID: streamID,
ErrorCode: qerr.StreamErrorCode(errorCode),
ErrorCode: protocol.ApplicationErrorCode(errorCode),
FinalSize: byteOffset,
}, nil
}

View File

@@ -4,14 +4,13 @@ import (
"bytes"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/qerr"
"github.com/lucas-clemente/quic-go/quicvarint"
)
// A StopSendingFrame is a STOP_SENDING frame
type StopSendingFrame struct {
StreamID protocol.StreamID
ErrorCode qerr.StreamErrorCode
ErrorCode protocol.ApplicationErrorCode
}
// parseStopSendingFrame parses a STOP_SENDING frame
@@ -31,7 +30,7 @@ func parseStopSendingFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StopSend
return &StopSendingFrame{
StreamID: protocol.StreamID(streamID),
ErrorCode: qerr.StreamErrorCode(errorCode),
ErrorCode: protocol.ApplicationErrorCode(errorCode),
}, nil
}

View File

@@ -6,6 +6,7 @@ import (
"io"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/qerr"
"github.com/lucas-clemente/quic-go/quicvarint"
)
@@ -78,7 +79,7 @@ func parseStreamFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamFrame,
}
}
if frame.Offset+frame.DataLen() > protocol.MaxByteCount {
return nil, errors.New("stream data overflows maximum offset")
return nil, qerr.NewError(qerr.FrameEncodingError, "stream data overflows maximum offset")
}
return frame, nil
}

View File

@@ -90,10 +90,7 @@ type TransportParameters struct {
// Unmarshal the transport parameters
func (p *TransportParameters) Unmarshal(data []byte, sentBy protocol.Perspective) error {
if err := p.unmarshal(bytes.NewReader(data), sentBy, false); err != nil {
return &qerr.TransportError{
ErrorCode: qerr.TransportParameterError,
ErrorMessage: err.Error(),
}
return qerr.NewError(qerr.TransportParameterError, err.Error())
}
return nil
}
@@ -262,7 +259,7 @@ func (p *TransportParameters) readNumericTransportParameter(
return fmt.Errorf("error while reading transport parameter %d: %s", paramID, err)
}
if remainingLen-r.Len() != expectedLen {
return fmt.Errorf("inconsistent transport parameter length for transport parameter %#x", paramID)
return fmt.Errorf("inconsistent transport parameter length for %d", paramID)
}
//nolint:exhaustive // This only covers the numeric transport parameters.
switch paramID {