Merge pull request #1724 from lucas-clemente/ack-delay-exponent

implement the ack_delay_exponent
This commit is contained in:
Marten Seemann
2019-01-28 22:00:38 +09:00
committed by GitHub
13 changed files with 191 additions and 72 deletions

View File

@@ -23,8 +23,9 @@ var _ = Describe("Transport Parameters", func() {
MaxUniStreams: 7331,
IdleTimeout: 42 * time.Second,
OriginalConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef},
AckDelayExponent: 14,
}
Expect(p.String()).To(Equal("&handshake.TransportParameters{OriginalConnectionID: 0xdeadbeef, InitialMaxStreamDataBidiLocal: 0x1234, InitialMaxStreamDataBidiRemote: 0x2345, InitialMaxStreamDataUni: 0x3456, InitialMaxData: 0x4567, MaxBidiStreams: 1337, MaxUniStreams: 7331, IdleTimeout: 42s}"))
Expect(p.String()).To(Equal("&handshake.TransportParameters{OriginalConnectionID: 0xdeadbeef, InitialMaxStreamDataBidiLocal: 0x1234, InitialMaxStreamDataBidiRemote: 0x2345, InitialMaxStreamDataUni: 0x3456, InitialMaxData: 0x4567, MaxBidiStreams: 1337, MaxUniStreams: 7331, IdleTimeout: 42s, AckDelayExponent: 14}"))
})
getRandomValue := func() uint64 {
@@ -45,6 +46,7 @@ var _ = Describe("Transport Parameters", func() {
DisableMigration: true,
StatelessResetToken: bytes.Repeat([]byte{100}, 16),
OriginalConnectionID: protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef},
AckDelayExponent: 13,
}
b := &bytes.Buffer{}
params.marshal(b)
@@ -61,6 +63,7 @@ var _ = Describe("Transport Parameters", func() {
Expect(p.DisableMigration).To(Equal(params.DisableMigration))
Expect(p.StatelessResetToken).To(Equal(params.StatelessResetToken))
Expect(p.OriginalConnectionID).To(Equal(protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}))
Expect(p.AckDelayExponent).To(Equal(uint8(13)))
})
It("errors when the stateless_reset_token has the wrong length", func() {
@@ -89,6 +92,22 @@ var _ = Describe("Transport Parameters", func() {
Expect(p.unmarshal(b.Bytes(), protocol.PerspectiveServer)).To(MatchError("wrong length for disable_migration: 6 (expected empty)"))
})
It("errors when the ack_delay_exponenent is too large", func() {
b := &bytes.Buffer{}
(&TransportParameters{AckDelayExponent: 21}).marshal(b)
p := &TransportParameters{}
Expect(p.unmarshal(b.Bytes(), protocol.PerspectiveServer)).To(MatchError("invalid value for ack_delay_exponent: 21 (maximum 20)"))
})
It("doesn't send the ack_delay_exponent, if it has the default value", func() {
b := &bytes.Buffer{}
(&TransportParameters{AckDelayExponent: protocol.DefaultAckDelayExponent}).marshal(b)
defaultLen := b.Len()
b.Reset()
(&TransportParameters{AckDelayExponent: protocol.DefaultAckDelayExponent + 1}).marshal(b)
Expect(b.Len()).To(Equal(defaultLen + 2 /* parameter ID */ + 2 /* length field */ + 1 /* value */))
})
It("errors when the varint value has the wrong length", func() {
b := &bytes.Buffer{}
utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataBidiLocalParameterID))

View File

@@ -25,6 +25,7 @@ const (
initialMaxStreamDataUniParameterID transportParameterID = 0x7
initialMaxStreamsBidiParameterID transportParameterID = 0x8
initialMaxStreamsUniParameterID transportParameterID = 0x9
ackDelayExponentParameterID transportParameterID = 0xa
disableMigrationParameterID transportParameterID = 0xc
)
@@ -35,6 +36,8 @@ type TransportParameters struct {
InitialMaxStreamDataUni protocol.ByteCount
InitialMaxData protocol.ByteCount
AckDelayExponent uint8
MaxPacketSize protocol.ByteCount
MaxUniStreams uint64
@@ -65,7 +68,8 @@ func (p *TransportParameters) unmarshal(data []byte, sentBy protocol.Perspective
initialMaxStreamsBidiParameterID,
initialMaxStreamsUniParameterID,
idleTimeoutParameterID,
maxPacketSizeParameterID:
maxPacketSizeParameterID,
ackDelayExponentParameterID:
if err := p.readNumericTransportParameter(r, paramID, int(paramLen)); err != nil {
return err
}
@@ -147,6 +151,11 @@ func (p *TransportParameters) readNumericTransportParameter(
return fmt.Errorf("invalid value for max_packet_size: %d (minimum 1200)", val)
}
p.MaxPacketSize = protocol.ByteCount(val)
case ackDelayExponentParameterID:
if val > protocol.MaxAckDelayExponent {
return fmt.Errorf("invalid value for ack_delay_exponent: %d (maximum %d)", val, protocol.MaxAckDelayExponent)
}
p.AckDelayExponent = uint8(val)
default:
return fmt.Errorf("TransportParameter BUG: transport parameter %d not found", paramID)
}
@@ -186,6 +195,13 @@ func (p *TransportParameters) marshal(b *bytes.Buffer) {
utils.BigEndian.WriteUint16(b, uint16(maxPacketSizeParameterID))
utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(uint64(protocol.MaxReceivePacketSize))))
utils.WriteVarInt(b, uint64(protocol.MaxReceivePacketSize))
// ack_delay_exponent
// Only send it if is different from the default value.
if p.AckDelayExponent != protocol.DefaultAckDelayExponent {
utils.BigEndian.WriteUint16(b, uint16(ackDelayExponentParameterID))
utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(uint64(p.AckDelayExponent))))
utils.WriteVarInt(b, uint64(p.AckDelayExponent))
}
// disable_migration
if p.DisableMigration {
utils.BigEndian.WriteUint16(b, uint16(disableMigrationParameterID))
@@ -206,5 +222,5 @@ func (p *TransportParameters) marshal(b *bytes.Buffer) {
// String returns a string representation, intended for logging.
func (p *TransportParameters) String() string {
return fmt.Sprintf("&handshake.TransportParameters{OriginalConnectionID: %s, InitialMaxStreamDataBidiLocal: %#x, InitialMaxStreamDataBidiRemote: %#x, InitialMaxStreamDataUni: %#x, InitialMaxData: %#x, MaxBidiStreams: %d, MaxUniStreams: %d, IdleTimeout: %s}", p.OriginalConnectionID, p.InitialMaxStreamDataBidiLocal, p.InitialMaxStreamDataBidiRemote, p.InitialMaxStreamDataUni, p.InitialMaxData, p.MaxBidiStreams, p.MaxUniStreams, p.IdleTimeout)
return fmt.Sprintf("&handshake.TransportParameters{OriginalConnectionID: %s, InitialMaxStreamDataBidiLocal: %#x, InitialMaxStreamDataBidiRemote: %#x, InitialMaxStreamDataUni: %#x, InitialMaxData: %#x, MaxBidiStreams: %d, MaxUniStreams: %d, IdleTimeout: %s, AckDelayExponent: %d}", p.OriginalConnectionID, p.InitialMaxStreamDataBidiLocal, p.InitialMaxStreamDataBidiRemote, p.InitialMaxStreamDataUni, p.InitialMaxData, p.MaxBidiStreams, p.MaxUniStreams, p.IdleTimeout, p.AckDelayExponent)
}

View File

@@ -117,3 +117,6 @@ const MinPacingDelay time.Duration = 100 * time.Microsecond
// DefaultConnectionIDLength is the connection ID length that is used for multiplexed connections
// if no other value is configured.
const DefaultConnectionIDLength = 4
// AckDelayExponent is the ack delay exponent used when sending ACKs.
const AckDelayExponent = 3

View File

@@ -63,3 +63,9 @@ const MinStatelessResetSize = 1 /* first byte */ + 22 /* random bytes */ + 16 /*
// MinConnectionIDLenInitial is the minimum length of the destination connection ID on an Initial packet.
const MinConnectionIDLenInitial = 8
// DefaultAckDelayExponent is the default ack delay exponent
const DefaultAckDelayExponent = 3
// MaxAckDelayExponent is the maximum ack delay exponent
const MaxAckDelayExponent = 20

View File

@@ -10,9 +10,6 @@ import (
"github.com/lucas-clemente/quic-go/internal/utils"
)
// TODO: use the value sent in the transport parameters
const ackDelayExponent = 3
var errInvalidAckRanges = errors.New("AckFrame: ACK frame contains invalid ACK ranges")
// An AckFrame is an ACK frame
@@ -22,7 +19,7 @@ type AckFrame struct {
}
// parseAckFrame reads an ACK frame
func parseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) {
func parseAckFrame(r *bytes.Reader, ackDelayExponent uint8, version protocol.VersionNumber) (*AckFrame, error) {
typeByte, err := r.ReadByte()
if err != nil {
return nil, err
@@ -225,5 +222,5 @@ func (f *AckFrame) AcksPacket(p protocol.PacketNumber) bool {
}
func encodeAckDelay(delay time.Duration) uint64 {
return uint64(delay.Nanoseconds() / (1000 * (1 << ackDelayExponent)))
return uint64(delay.Nanoseconds() / (1000 * (1 << protocol.AckDelayExponent)))
}

View File

@@ -19,7 +19,7 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
data = append(data, encodeVarInt(0)...) // num blocks
data = append(data, encodeVarInt(10)...) // first ack block
b := bytes.NewReader(data)
frame, err := parseAckFrame(b, versionIETFFrames)
frame, err := parseAckFrame(b, protocol.AckDelayExponent, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(100)))
Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(90)))
@@ -34,7 +34,7 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
data = append(data, encodeVarInt(0)...) // num blocks
data = append(data, encodeVarInt(0)...) // first ack block
b := bytes.NewReader(data)
frame, err := parseAckFrame(b, versionIETFFrames)
frame, err := parseAckFrame(b, protocol.AckDelayExponent, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(55)))
Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(55)))
@@ -49,7 +49,7 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
data = append(data, encodeVarInt(0)...) // num blocks
data = append(data, encodeVarInt(20)...) // first ack block
b := bytes.NewReader(data)
frame, err := parseAckFrame(b, versionIETFFrames)
frame, err := parseAckFrame(b, protocol.AckDelayExponent, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(20)))
Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(0)))
@@ -64,7 +64,7 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
data = append(data, encodeVarInt(0)...) // num blocks
data = append(data, encodeVarInt(21)...) // first ack block
b := bytes.NewReader(data)
_, err := parseAckFrame(b, versionIETFFrames)
_, err := parseAckFrame(b, protocol.AckDelayExponent, versionIETFFrames)
Expect(err).To(MatchError("invalid first ACK range"))
})
@@ -77,7 +77,7 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
data = append(data, encodeVarInt(98)...) // gap
data = append(data, encodeVarInt(50)...) // ack block
b := bytes.NewReader(data)
frame, err := parseAckFrame(b, versionIETFFrames)
frame, err := parseAckFrame(b, protocol.AckDelayExponent, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(1000)))
Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(750)))
@@ -100,7 +100,7 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
data = append(data, encodeVarInt(1)...) // gap
data = append(data, encodeVarInt(1)...) // ack block
b := bytes.NewReader(data)
frame, err := parseAckFrame(b, versionIETFFrames)
frame, err := parseAckFrame(b, protocol.AckDelayExponent, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(100)))
Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(94)))
@@ -113,6 +113,22 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
Expect(b.Len()).To(BeZero())
})
It("uses the ack delay exponent", func() {
const delayTime = 1 << 10 * time.Millisecond
buf := &bytes.Buffer{}
f := &AckFrame{
AckRanges: []AckRange{{Smallest: 1, Largest: 1}},
DelayTime: delayTime,
}
Expect(f.Write(buf, versionIETFFrames)).To(Succeed())
for i := uint8(0); i < 8; i++ {
b := bytes.NewReader(buf.Bytes())
frame, err := parseAckFrame(b, protocol.AckDelayExponent+i, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
Expect(frame.DelayTime).To(Equal(delayTime * (1 << i)))
}
})
It("errors on EOF", func() {
data := []byte{0x2}
data = append(data, encodeVarInt(1000)...) // largest acked
@@ -121,10 +137,10 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
data = append(data, encodeVarInt(100)...) // first ack block
data = append(data, encodeVarInt(98)...) // gap
data = append(data, encodeVarInt(50)...) // ack block
_, err := parseAckFrame(bytes.NewReader(data), versionIETFFrames)
_, err := parseAckFrame(bytes.NewReader(data), protocol.AckDelayExponent, versionIETFFrames)
Expect(err).NotTo(HaveOccurred())
for i := range data {
_, err := parseAckFrame(bytes.NewReader(data[0:i]), versionIETFFrames)
_, err := parseAckFrame(bytes.NewReader(data[0:i]), protocol.AckDelayExponent, versionIETFFrames)
Expect(err).To(MatchError(io.EOF))
}
})
@@ -140,7 +156,7 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
data = append(data, encodeVarInt(0x12345)...) // ECT(1)
data = append(data, encodeVarInt(0x12345678)...) // ECN-CE
b := bytes.NewReader(data)
frame, err := parseAckFrame(b, versionIETFFrames)
frame, err := parseAckFrame(b, protocol.AckDelayExponent, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(100)))
Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(90)))
@@ -159,10 +175,10 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
data = append(data, encodeVarInt(0x42)...) // ECT(0)
data = append(data, encodeVarInt(0x12345)...) // ECT(1)
data = append(data, encodeVarInt(0x12345678)...) // ECN-CE
_, err := parseAckFrame(bytes.NewReader(data), versionIETFFrames)
_, err := parseAckFrame(bytes.NewReader(data), protocol.AckDelayExponent, versionIETFFrames)
Expect(err).NotTo(HaveOccurred())
for i := range data {
_, err := parseAckFrame(bytes.NewReader(data[0:i]), versionIETFFrames)
_, err := parseAckFrame(bytes.NewReader(data[0:i]), protocol.AckDelayExponent, versionIETFFrames)
Expect(err).To(MatchError(io.EOF))
}
})
@@ -196,7 +212,7 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
Expect(err).ToNot(HaveOccurred())
Expect(f.Length(versionIETFFrames)).To(BeEquivalentTo(buf.Len()))
b := bytes.NewReader(buf.Bytes())
frame, err := parseAckFrame(b, versionIETFFrames)
frame, err := parseAckFrame(b, protocol.AckDelayExponent, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
Expect(frame.HasMissingRanges()).To(BeFalse())
@@ -213,7 +229,7 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
Expect(err).ToNot(HaveOccurred())
Expect(f.Length(versionIETFFrames)).To(BeEquivalentTo(buf.Len()))
b := bytes.NewReader(buf.Bytes())
frame, err := parseAckFrame(b, versionIETFFrames)
frame, err := parseAckFrame(b, protocol.AckDelayExponent, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
Expect(frame.HasMissingRanges()).To(BeFalse())
@@ -233,7 +249,7 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
Expect(err).ToNot(HaveOccurred())
Expect(f.Length(versionIETFFrames)).To(BeEquivalentTo(buf.Len()))
b := bytes.NewReader(buf.Bytes())
frame, err := parseAckFrame(b, versionIETFFrames)
frame, err := parseAckFrame(b, protocol.AckDelayExponent, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
Expect(frame.HasMissingRanges()).To(BeTrue())
@@ -255,7 +271,7 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
Expect(err).ToNot(HaveOccurred())
Expect(f.Length(versionIETFFrames)).To(BeEquivalentTo(buf.Len()))
b := bytes.NewReader(buf.Bytes())
frame, err := parseAckFrame(b, versionIETFFrames)
frame, err := parseAckFrame(b, protocol.AckDelayExponent, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
Expect(frame.HasMissingRanges()).To(BeTrue())
@@ -278,7 +294,7 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
Expect(buf.Len()).To(BeNumerically(">", protocol.MaxAckFrameSize-5))
Expect(buf.Len()).To(BeNumerically("<=", protocol.MaxAckFrameSize))
b := bytes.NewReader(buf.Bytes())
frame, err := parseAckFrame(b, versionIETFFrames)
frame, err := parseAckFrame(b, protocol.AckDelayExponent, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
Expect(frame.HasMissingRanges()).To(BeTrue())
Expect(b.Len()).To(BeZero())

View File

@@ -8,9 +8,20 @@ import (
"github.com/lucas-clemente/quic-go/internal/qerr"
)
type frameParser struct {
ackDelayExponent uint8
version protocol.VersionNumber
}
// NewFrameParser creates a new frame parser.
func NewFrameParser(v protocol.VersionNumber) FrameParser {
return &frameParser{version: v}
}
// ParseNextFrame parses the next frame
// It skips PADDING frames.
func ParseNextFrame(r *bytes.Reader, v protocol.VersionNumber) (Frame, error) {
func (p *frameParser) ParseNext(r *bytes.Reader, encLevel protocol.EncryptionLevel) (Frame, error) {
for r.Len() != 0 {
typeByte, _ := r.ReadByte()
if typeByte == 0x0 { // PADDING frame
@@ -18,16 +29,16 @@ func ParseNextFrame(r *bytes.Reader, v protocol.VersionNumber) (Frame, error) {
}
r.UnreadByte()
return parseFrame(r, typeByte, v)
return p.parseFrame(r, typeByte, encLevel)
}
return nil, nil
}
func parseFrame(r *bytes.Reader, typeByte byte, v protocol.VersionNumber) (Frame, error) {
func (p *frameParser) parseFrame(r *bytes.Reader, typeByte byte, encLevel protocol.EncryptionLevel) (Frame, error) {
var frame Frame
var err error
if typeByte&0xf8 == 0x8 {
frame, err = parseStreamFrame(r, v)
frame, err = parseStreamFrame(r, p.version)
if err != nil {
return nil, qerr.Error(qerr.InvalidFrameData, err.Error())
}
@@ -35,39 +46,43 @@ func parseFrame(r *bytes.Reader, typeByte byte, v protocol.VersionNumber) (Frame
}
switch typeByte {
case 0x1:
frame, err = parsePingFrame(r, v)
frame, err = parsePingFrame(r, p.version)
case 0x2, 0x3:
frame, err = parseAckFrame(r, v)
ackDelayExponent := p.ackDelayExponent
if encLevel != protocol.Encryption1RTT {
ackDelayExponent = protocol.DefaultAckDelayExponent
}
frame, err = parseAckFrame(r, ackDelayExponent, p.version)
case 0x4:
frame, err = parseResetStreamFrame(r, v)
frame, err = parseResetStreamFrame(r, p.version)
case 0x5:
frame, err = parseStopSendingFrame(r, v)
frame, err = parseStopSendingFrame(r, p.version)
case 0x6:
frame, err = parseCryptoFrame(r, v)
frame, err = parseCryptoFrame(r, p.version)
case 0x7:
frame, err = parseNewTokenFrame(r, v)
frame, err = parseNewTokenFrame(r, p.version)
case 0x10:
frame, err = parseMaxDataFrame(r, v)
frame, err = parseMaxDataFrame(r, p.version)
case 0x11:
frame, err = parseMaxStreamDataFrame(r, v)
frame, err = parseMaxStreamDataFrame(r, p.version)
case 0x12, 0x13:
frame, err = parseMaxStreamsFrame(r, v)
frame, err = parseMaxStreamsFrame(r, p.version)
case 0x14:
frame, err = parseDataBlockedFrame(r, v)
frame, err = parseDataBlockedFrame(r, p.version)
case 0x15:
frame, err = parseStreamDataBlockedFrame(r, v)
frame, err = parseStreamDataBlockedFrame(r, p.version)
case 0x16, 0x17:
frame, err = parseStreamsBlockedFrame(r, v)
frame, err = parseStreamsBlockedFrame(r, p.version)
case 0x18:
frame, err = parseNewConnectionIDFrame(r, v)
frame, err = parseNewConnectionIDFrame(r, p.version)
case 0x19:
frame, err = parseRetireConnectionIDFrame(r, v)
frame, err = parseRetireConnectionIDFrame(r, p.version)
case 0x1a:
frame, err = parsePathChallengeFrame(r, v)
frame, err = parsePathChallengeFrame(r, p.version)
case 0x1b:
frame, err = parsePathResponseFrame(r, v)
frame, err = parsePathResponseFrame(r, p.version)
case 0x1c, 0x1d:
frame, err = parseConnectionCloseFrame(r, v)
frame, err = parseConnectionCloseFrame(r, p.version)
default:
err = fmt.Errorf("unknown type byte 0x%x", typeByte)
}
@@ -76,3 +91,7 @@ func parseFrame(r *bytes.Reader, typeByte byte, v protocol.VersionNumber) (Frame
}
return frame, nil
}
func (p *frameParser) SetAckDelayExponent(exp uint8) {
p.ackDelayExponent = exp
}

View File

@@ -2,6 +2,7 @@ package wire
import (
"bytes"
"time"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/qerr"
@@ -10,14 +11,18 @@ import (
)
var _ = Describe("Frame parsing", func() {
var buf *bytes.Buffer
var (
buf *bytes.Buffer
parser FrameParser
)
BeforeEach(func() {
buf = &bytes.Buffer{}
parser = NewFrameParser(versionIETFFrames)
})
It("returns nil if there's nothing more to read", func() {
f, err := ParseNextFrame(bytes.NewReader(nil), protocol.VersionWhatever)
f, err := parser.ParseNext(bytes.NewReader(nil), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(f).To(BeNil())
})
@@ -25,14 +30,14 @@ var _ = Describe("Frame parsing", func() {
It("skips PADDING frames", func() {
buf.Write([]byte{0}) // PADDING frame
(&PingFrame{}).Write(buf, versionIETFFrames)
f, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
f, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(f).To(Equal(&PingFrame{}))
})
It("handles PADDING at the end", func() {
r := bytes.NewReader([]byte{0, 0, 0})
f, err := ParseNextFrame(r, versionIETFFrames)
f, err := parser.ParseNext(r, protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(f).To(BeNil())
Expect(r.Len()).To(BeZero())
@@ -42,13 +47,39 @@ var _ = Describe("Frame parsing", func() {
f := &AckFrame{AckRanges: []AckRange{{Smallest: 1, Largest: 0x13}}}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).ToNot(BeNil())
Expect(frame).To(BeAssignableToTypeOf(f))
Expect(frame.(*AckFrame).LargestAcked()).To(Equal(protocol.PacketNumber(0x13)))
})
It("uses the custom ack delay exponent for 1RTT packets", func() {
parser.SetAckDelayExponent(protocol.AckDelayExponent + 2)
f := &AckFrame{
AckRanges: []AckRange{{Smallest: 1, Largest: 1}},
DelayTime: time.Second,
}
Expect(f.Write(buf, versionIETFFrames)).To(Succeed())
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
// The ACK frame is always written using the protocol.AckDelayExponent.
// That's why we expect a different value when parsing.
Expect(frame.(*AckFrame).DelayTime).To(Equal(4 * time.Second))
})
It("uses the default ack delay exponent for non-1RTT packets", func() {
parser.SetAckDelayExponent(protocol.AckDelayExponent + 2)
f := &AckFrame{
AckRanges: []AckRange{{Smallest: 1, Largest: 1}},
DelayTime: time.Second,
}
Expect(f.Write(buf, versionIETFFrames)).To(Succeed())
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.EncryptionHandshake)
Expect(err).ToNot(HaveOccurred())
Expect(frame.(*AckFrame).DelayTime).To(Equal(time.Second))
})
It("unpacks RESET_STREAM frames", func() {
f := &ResetStreamFrame{
StreamID: 0xdeadbeef,
@@ -57,7 +88,7 @@ var _ = Describe("Frame parsing", func() {
}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
})
@@ -67,7 +98,7 @@ var _ = Describe("Frame parsing", func() {
buf := &bytes.Buffer{}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
})
@@ -79,7 +110,7 @@ var _ = Describe("Frame parsing", func() {
}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).ToNot(BeNil())
Expect(frame).To(Equal(f))
@@ -89,7 +120,7 @@ var _ = Describe("Frame parsing", func() {
f := &NewTokenFrame{Token: []byte("foobar")}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).ToNot(BeNil())
Expect(frame).To(Equal(f))
@@ -104,7 +135,7 @@ var _ = Describe("Frame parsing", func() {
}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).ToNot(BeNil())
Expect(frame).To(Equal(f))
@@ -117,7 +148,7 @@ var _ = Describe("Frame parsing", func() {
buf := &bytes.Buffer{}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
})
@@ -130,7 +161,7 @@ var _ = Describe("Frame parsing", func() {
buf := &bytes.Buffer{}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
})
@@ -143,7 +174,7 @@ var _ = Describe("Frame parsing", func() {
buf := &bytes.Buffer{}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
})
@@ -153,7 +184,7 @@ var _ = Describe("Frame parsing", func() {
buf := &bytes.Buffer{}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
})
@@ -165,7 +196,7 @@ var _ = Describe("Frame parsing", func() {
}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
})
@@ -178,7 +209,7 @@ var _ = Describe("Frame parsing", func() {
buf := &bytes.Buffer{}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
})
@@ -191,7 +222,7 @@ var _ = Describe("Frame parsing", func() {
}
buf := &bytes.Buffer{}
Expect(f.Write(buf, versionIETFFrames)).To(Succeed())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
})
@@ -200,7 +231,7 @@ var _ = Describe("Frame parsing", func() {
f := &RetireConnectionIDFrame{SequenceNumber: 0x1337}
buf := &bytes.Buffer{}
Expect(f.Write(buf, versionIETFFrames)).To(Succeed())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
})
@@ -209,7 +240,7 @@ var _ = Describe("Frame parsing", func() {
f := &PathChallengeFrame{Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).ToNot(BeNil())
Expect(frame).To(BeAssignableToTypeOf(f))
@@ -220,7 +251,7 @@ var _ = Describe("Frame parsing", func() {
f := &PathResponseFrame{Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).ToNot(BeNil())
Expect(frame).To(BeAssignableToTypeOf(f))
@@ -235,13 +266,13 @@ var _ = Describe("Frame parsing", func() {
buf := &bytes.Buffer{}
err := f.Write(buf, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
frame, err := ParseNextFrame(bytes.NewReader(buf.Bytes()), versionIETFFrames)
frame, err := parser.ParseNext(bytes.NewReader(buf.Bytes()), protocol.Encryption1RTT)
Expect(err).ToNot(HaveOccurred())
Expect(frame).To(Equal(f))
})
It("errors on invalid type", func() {
_, err := ParseNextFrame(bytes.NewReader([]byte{0x42}), versionIETFFrames)
_, err := parser.ParseNext(bytes.NewReader([]byte{0x42}), protocol.Encryption1RTT)
Expect(err).To(MatchError("InvalidFrameData: unknown type byte 0x42"))
})
@@ -252,7 +283,7 @@ var _ = Describe("Frame parsing", func() {
}
b := &bytes.Buffer{}
f.Write(b, versionIETFFrames)
_, err := ParseNextFrame(bytes.NewReader(b.Bytes()[:b.Len()-2]), versionIETFFrames)
_, err := parser.ParseNext(bytes.NewReader(b.Bytes()[:b.Len()-2]), protocol.Encryption1RTT)
Expect(err).To(HaveOccurred())
Expect(err.(*qerr.QuicError).ErrorCode).To(Equal(qerr.InvalidFrameData))
})

View File

@@ -11,3 +11,9 @@ type Frame interface {
Write(b *bytes.Buffer, version protocol.VersionNumber) error
Length(version protocol.VersionNumber) protocol.ByteCount
}
// A FrameParser parses QUIC frames, one by one.
type FrameParser interface {
ParseNext(*bytes.Reader, protocol.EncryptionLevel) (Frame, error)
SetAckDelayExponent(uint8)
}