implement parsing of ACK_ECN frames

This commit is contained in:
Marten Seemann 2018-07-14 21:34:08 +02:00
parent 6f0a027f0f
commit 3d087d522c
5 changed files with 68 additions and 2 deletions

View file

@ -17,6 +17,7 @@
"vet"
],
"Linters": {
"vet": "go tool vet -printfuncs=Infof,Debugf,Warningf,Errorf:PATH:LINE:MESSAGE"
"vet": "go tool vet -printfuncs=Infof,Debugf,Warningf,Errorf:PATH:LINE:MESSAGE",
"misspell": "misspell -i ect:PATH:LINE:COL:MESSAGE"
}
}

View file

@ -19,8 +19,16 @@ type AckFrame struct {
DelayTime time.Duration
}
// parseAckFrame reads an ACK frame
func parseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) {
return parseAckOrAckEcnFrame(r, false, version)
}
func parseAckEcnFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) {
return parseAckOrAckEcnFrame(r, true, version)
}
// parseAckFrame reads an ACK frame
func parseAckOrAckEcnFrame(r *bytes.Reader, ecn bool, version protocol.VersionNumber) (*AckFrame, error) {
if !version.UsesIETFFrameFormat() {
return parseAckFrameLegacy(r, version)
}
@ -41,6 +49,15 @@ func parseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame,
return nil, err
}
frame.DelayTime = time.Duration(delay*1<<ackDelayExponent) * time.Microsecond
if ecn {
for i := 0; i < 3; i++ {
if _, err := utils.ReadVarInt(r); err != nil {
return nil, err
}
}
}
numBlocks, err := utils.ReadVarInt(r)
if err != nil {
return nil, err

View file

@ -366,3 +366,45 @@ var _ = Describe("ACK Frame (for IETF QUIC)", func() {
})
})
})
var _ = Describe("ACK_ECN frame", func() {
Context("parsing", func() {
It("parses an ACK_ECN frame", func() {
data := []byte{0xd}
data = append(data, encodeVarInt(100)...) // largest acked
data = append(data, encodeVarInt(0)...) // delay
data = append(data, encodeVarInt(0x42)...) // ECT(0)
data = append(data, encodeVarInt(0x12345)...) // ECT(1)
data = append(data, encodeVarInt(0x12345678)...) // ECN-CE
data = append(data, encodeVarInt(0)...) // num blocks
data = append(data, encodeVarInt(10)...) // first ack block
b := bytes.NewReader(data)
frame, err := parseAckEcnFrame(b, versionIETFFrames)
Expect(err).ToNot(HaveOccurred())
Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(100)))
Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(90)))
Expect(frame.HasMissingRanges()).To(BeFalse())
Expect(b.Len()).To(BeZero())
})
It("errors on EOF", func() {
data := []byte{0x1a}
data = append(data, encodeVarInt(1000)...) // largest acked
data = append(data, encodeVarInt(0)...) // delay
data = append(data, encodeVarInt(0x42)...) // ECT(0)
data = append(data, encodeVarInt(0x12345)...) // ECT(1)
data = append(data, encodeVarInt(0x12345678)...) // ECN-CE
data = append(data, encodeVarInt(1)...) // num blocks
data = append(data, encodeVarInt(100)...) // first ack block
data = append(data, encodeVarInt(98)...) // gap
data = append(data, encodeVarInt(50)...) // ack block
_, err := parseAckEcnFrame(bytes.NewReader(data), versionIETFFrames)
Expect(err).NotTo(HaveOccurred())
for i := range data {
_, err := parseAckEcnFrame(bytes.NewReader(data[0:i]), versionIETFFrames)
Expect(err).To(MatchError(io.EOF))
}
})
})
})

View file

@ -100,6 +100,11 @@ func parseIETFFrame(r *bytes.Reader, typeByte byte, v protocol.VersionNumber) (F
if err != nil {
err = qerr.Error(qerr.InvalidFrameData, err.Error())
}
case 0x1a:
frame, err = parseAckEcnFrame(r, v)
if err != nil {
err = qerr.Error(qerr.InvalidAckData, err.Error())
}
default:
err = qerr.Error(qerr.InvalidFrameData, fmt.Sprintf("unknown type byte 0x%x", typeByte))
}

View file

@ -331,6 +331,7 @@ var _ = Describe("Frame parsing", func() {
0x0e: qerr.InvalidFrameData,
0x0f: qerr.InvalidFrameData,
0x10: qerr.InvalidStreamData,
0x1a: qerr.InvalidAckData,
} {
_, err := ParseNextFrame(bytes.NewReader([]byte{b}), nil, versionIETFFrames)
Expect(err).To(HaveOccurred())