allow receiving of multiple packets before sending a packet

By draining the channel holding received packets, we reduce the number
of spurious ACKs we send. We also make sure that sending and receiving
packets is balanced, as we allow sending of a large number of packets
(if we have cwnd available and the pacing frequency is high enough).
This commit is contained in:
Marten Seemann 2021-01-05 16:09:29 +08:00
parent 4bdccca0cf
commit 219ced5437
2 changed files with 77 additions and 10 deletions

View file

@ -671,8 +671,9 @@ var _ = Describe("Session", func() {
buf := &bytes.Buffer{}
Expect(extHdr.Write(buf, sess.version)).To(Succeed())
return &receivedPacket{
data: append(buf.Bytes(), data...),
buffer: getPacketBuffer(),
data: append(buf.Bytes(), data...),
buffer: getPacketBuffer(),
rcvTime: time.Now(),
}
}
@ -857,6 +858,51 @@ var _ = Describe("Session", func() {
Eventually(sess.Context().Done()).Should(BeClosed())
})
It("processes multiple received packets before sending one", func() {
sess.sessionCreationTime = time.Now()
var pn protocol.PacketNumber
unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(hdr *wire.Header, rcvTime time.Time, data []byte) (*unpackedPacket, error) {
pn++
return &unpackedPacket{
data: []byte{0}, // PADDING frame
encryptionLevel: protocol.Encryption1RTT,
packetNumber: pn,
hdr: &wire.ExtendedHeader{Header: *hdr},
}, nil
}).Times(3)
tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(hdr *wire.ExtendedHeader, _ protocol.ByteCount, _ []logging.Frame) {
}).Times(3)
packer.EXPECT().PackCoalescedPacket() // only expect a single call
for i := 0; i < 3; i++ {
sess.handlePacket(getPacket(&wire.ExtendedHeader{
Header: wire.Header{DestConnectionID: srcConnID},
PacketNumber: 0x1337,
PacketNumberLen: protocol.PacketNumberLen2,
}, []byte("foobar")))
}
go func() {
defer GinkgoRecover()
cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
sess.run()
}()
Consistently(sess.Context().Done()).ShouldNot(BeClosed())
// make the go routine return
streamManager.EXPECT().CloseWithError(gomock.Any())
cryptoSetup.EXPECT().Close()
packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
expectReplaceWithClosed()
tracer.EXPECT().ClosedConnection(gomock.Any())
tracer.EXPECT().Close()
mconn.EXPECT().Write(gomock.Any())
fmt.Println("close")
sess.closeLocal(errors.New("close"))
Eventually(sess.Context().Done()).Should(BeClosed())
})
It("closes the session when unpacking fails because the reserved bits were incorrect", func() {
unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, wire.ErrInvalidReservedBits)
streamManager.EXPECT().CloseWithError(gomock.Any())