forked from quic-go/quic-go
add a MaxDataLen function for DATAGRAM frames
This commit is contained in:
@@ -57,6 +57,24 @@ func (f *DatagramFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MaxDataLen returns the maximum data length
|
||||||
|
func (f *DatagramFrame) MaxDataLen(maxSize protocol.ByteCount, version protocol.VersionNumber) protocol.ByteCount {
|
||||||
|
headerLen := protocol.ByteCount(1)
|
||||||
|
if f.DataLenPresent {
|
||||||
|
// pretend that the data size will be 1 bytes
|
||||||
|
// if it turns out that varint encoding the length will consume 2 bytes, we need to adjust the data length afterwards
|
||||||
|
headerLen++
|
||||||
|
}
|
||||||
|
if headerLen > maxSize {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
maxDataLen := maxSize - headerLen
|
||||||
|
if f.DataLenPresent && utils.VarIntLen(uint64(maxDataLen)) != 1 {
|
||||||
|
maxDataLen--
|
||||||
|
}
|
||||||
|
return maxDataLen
|
||||||
|
}
|
||||||
|
|
||||||
// Length of a written frame
|
// Length of a written frame
|
||||||
func (f *DatagramFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
|
func (f *DatagramFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
|
||||||
length := 1 + protocol.ByteCount(len(f.Data))
|
length := 1 + protocol.ByteCount(len(f.Data))
|
||||||
|
|||||||
@@ -95,4 +95,59 @@ var _ = Describe("STREAM frame", func() {
|
|||||||
Expect(f.Length(versionIETFFrames)).To(Equal(protocol.ByteCount(1 + 6)))
|
Expect(f.Length(versionIETFFrames)).To(Equal(protocol.ByteCount(1 + 6)))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Context("max data length", func() {
|
||||||
|
const maxSize = 3000
|
||||||
|
|
||||||
|
It("returns a data length such that the resulting frame has the right size, if data length is not present", func() {
|
||||||
|
data := make([]byte, maxSize)
|
||||||
|
f := &DatagramFrame{}
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
for i := 1; i < 3000; i++ {
|
||||||
|
b.Reset()
|
||||||
|
f.Data = nil
|
||||||
|
maxDataLen := f.MaxDataLen(protocol.ByteCount(i), versionIETFFrames)
|
||||||
|
if maxDataLen == 0 { // 0 means that no valid STREAM frame can be written
|
||||||
|
// check that writing a minimal size STREAM frame (i.e. with 1 byte data) is actually larger than the desired size
|
||||||
|
f.Data = []byte{0}
|
||||||
|
Expect(f.Write(b, versionIETFFrames)).To(Succeed())
|
||||||
|
Expect(b.Len()).To(BeNumerically(">", i))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
f.Data = data[:int(maxDataLen)]
|
||||||
|
Expect(f.Write(b, versionIETFFrames)).To(Succeed())
|
||||||
|
Expect(b.Len()).To(Equal(i))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("always returns a data length such that the resulting frame has the right size, if data length is present", func() {
|
||||||
|
data := make([]byte, maxSize)
|
||||||
|
f := &DatagramFrame{DataLenPresent: true}
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
var frameOneByteTooSmallCounter int
|
||||||
|
for i := 1; i < 3000; i++ {
|
||||||
|
b.Reset()
|
||||||
|
f.Data = nil
|
||||||
|
maxDataLen := f.MaxDataLen(protocol.ByteCount(i), versionIETFFrames)
|
||||||
|
if maxDataLen == 0 { // 0 means that no valid STREAM frame can be written
|
||||||
|
// check that writing a minimal size STREAM frame (i.e. with 1 byte data) is actually larger than the desired size
|
||||||
|
f.Data = []byte{0}
|
||||||
|
Expect(f.Write(b, versionIETFFrames)).To(Succeed())
|
||||||
|
Expect(b.Len()).To(BeNumerically(">", i))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
f.Data = data[:int(maxDataLen)]
|
||||||
|
Expect(f.Write(b, versionIETFFrames)).To(Succeed())
|
||||||
|
// There's *one* pathological case, where a data length of x can be encoded into 1 byte
|
||||||
|
// but a data lengths of x+1 needs 2 bytes
|
||||||
|
// In that case, it's impossible to create a STREAM frame of the desired size
|
||||||
|
if b.Len() == i-1 {
|
||||||
|
frameOneByteTooSmallCounter++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
Expect(b.Len()).To(Equal(i))
|
||||||
|
}
|
||||||
|
Expect(frameOneByteTooSmallCounter).To(Equal(1))
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user