forked from quic-go/quic-go
implement parsing of ACK_ECN frames
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
"vet"
|
"vet"
|
||||||
],
|
],
|
||||||
"Linters": {
|
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,16 @@ type AckFrame struct {
|
|||||||
DelayTime time.Duration
|
DelayTime time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseAckFrame reads an ACK frame
|
|
||||||
func parseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, error) {
|
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() {
|
if !version.UsesIETFFrameFormat() {
|
||||||
return parseAckFrameLegacy(r, version)
|
return parseAckFrameLegacy(r, version)
|
||||||
}
|
}
|
||||||
@@ -41,6 +49,15 @@ func parseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
frame.DelayTime = time.Duration(delay*1<<ackDelayExponent) * time.Microsecond
|
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)
|
numBlocks, err := utils.ReadVarInt(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -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))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
@@ -100,6 +100,11 @@ func parseIETFFrame(r *bytes.Reader, typeByte byte, v protocol.VersionNumber) (F
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
err = qerr.Error(qerr.InvalidFrameData, err.Error())
|
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:
|
default:
|
||||||
err = qerr.Error(qerr.InvalidFrameData, fmt.Sprintf("unknown type byte 0x%x", typeByte))
|
err = qerr.Error(qerr.InvalidFrameData, fmt.Sprintf("unknown type byte 0x%x", typeByte))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -331,6 +331,7 @@ var _ = Describe("Frame parsing", func() {
|
|||||||
0x0e: qerr.InvalidFrameData,
|
0x0e: qerr.InvalidFrameData,
|
||||||
0x0f: qerr.InvalidFrameData,
|
0x0f: qerr.InvalidFrameData,
|
||||||
0x10: qerr.InvalidStreamData,
|
0x10: qerr.InvalidStreamData,
|
||||||
|
0x1a: qerr.InvalidAckData,
|
||||||
} {
|
} {
|
||||||
_, err := ParseNextFrame(bytes.NewReader([]byte{b}), nil, versionIETFFrames)
|
_, err := ParseNextFrame(bytes.NewReader([]byte{b}), nil, versionIETFFrames)
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
|
|||||||
Reference in New Issue
Block a user