cut coalesed packets in the session

This commit is contained in:
Marten Seemann 2019-02-23 10:16:17 +08:00
parent df34e4496e
commit 02e851bd11
12 changed files with 442 additions and 577 deletions

View file

@ -3,7 +3,6 @@ package quic
import (
"bytes"
"errors"
"net"
"time"
"github.com/golang/mock/gomock"
@ -88,11 +87,15 @@ var _ = Describe("Packet Handler Map", func() {
handledPacket1 := make(chan struct{})
handledPacket2 := make(chan struct{})
packetHandler1.EXPECT().handlePacket(gomock.Any()).Do(func(p *receivedPacket) {
Expect(p.hdr.DestConnectionID).To(Equal(connID1))
connID, err := wire.ParseConnectionID(p.data, 0)
Expect(err).ToNot(HaveOccurred())
Expect(connID).To(Equal(connID1))
close(handledPacket1)
})
packetHandler2.EXPECT().handlePacket(gomock.Any()).Do(func(p *receivedPacket) {
Expect(p.hdr.DestConnectionID).To(Equal(connID2))
connID, err := wire.ParseConnectionID(p.data, 0)
Expect(err).ToNot(HaveOccurred())
Expect(connID).To(Equal(connID2))
close(handledPacket2)
})
handler.Add(connID1, packetHandler1)
@ -105,12 +108,10 @@ var _ = Describe("Packet Handler Map", func() {
})
It("drops unparseable packets", func() {
_, err := handler.parsePacket(nil, nil, []byte{0, 1, 2, 3})
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("error parsing packet:"))
handler.handlePacket(nil, nil, []byte{0, 1, 2, 3})
})
It("deletes removed session immediately", func() {
It("deletes removed sessions immediately", func() {
handler.deleteRetiredSessionsAfter = time.Hour
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
handler.Add(connID, NewMockPacketHandler(mockCtrl))
@ -159,64 +160,6 @@ var _ = Describe("Packet Handler Map", func() {
conn.Close()
Eventually(done).Should(BeClosed())
})
Context("coalesced packets", func() {
It("cuts packets to the right length", func() {
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
data := append(getPacketWithLength(connID, 456), make([]byte, 1000)...)
packetHandler := NewMockPacketHandler(mockCtrl)
packetHandler.EXPECT().handlePacket(gomock.Any()).Do(func(p *receivedPacket) {
Expect(p.data).To(HaveLen(456 + int(p.hdr.ParsedLen())))
})
handler.Add(connID, packetHandler)
handler.handlePacket(nil, nil, data)
})
It("handles coalesced packets", func() {
connID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
packetHandler := NewMockPacketHandler(mockCtrl)
handledPackets := make(chan *receivedPacket, 3)
packetHandler.EXPECT().handlePacket(gomock.Any()).Do(func(p *receivedPacket) {
handledPackets <- p
}).Times(3)
handler.Add(connID, packetHandler)
buffer := getPacketBuffer()
packet := buffer.Slice[:0]
packet = append(packet, append(getPacketWithLength(connID, 10), make([]byte, 10-2 /* packet number len */)...)...)
packet = append(packet, append(getPacketWithLength(connID, 20), make([]byte, 20-2 /* packet number len */)...)...)
packet = append(packet, append(getPacketWithLength(connID, 30), make([]byte, 30-2 /* packet number len */)...)...)
conn.dataToRead <- packet
now := time.Now()
for i := 1; i <= 3; i++ {
var p *receivedPacket
Eventually(handledPackets).Should(Receive(&p))
Expect(p.hdr.DestConnectionID).To(Equal(connID))
Expect(p.hdr.Length).To(BeEquivalentTo(10 * i))
Expect(p.data).To(HaveLen(int(p.hdr.ParsedLen() + p.hdr.Length)))
Expect(p.rcvTime).To(BeTemporally("~", now, scaleDuration(20*time.Millisecond)))
Expect(p.buffer.refCount).To(Equal(3))
}
})
It("ignores coalesced packet parts if the connection IDs don't match", func() {
connID1 := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
connID2 := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1}
buffer := getPacketBuffer()
packet := buffer.Slice[:0]
// var packet []byte
packet = append(packet, getPacket(connID1)...)
packet = append(packet, getPacket(connID2)...)
packets, err := handler.parsePacket(&net.UDPAddr{}, buffer, packet)
Expect(err).To(MatchError("coalesced packet has different destination connection ID: 0x0807060504030201, expected 0x0102030405060708"))
Expect(packets).To(HaveLen(1))
Expect(packets[0].hdr.DestConnectionID).To(Equal(connID1))
Expect(packets[0].buffer.refCount).To(Equal(1))
})
})
})
Context("stateless reset handling", func() {
@ -228,7 +171,9 @@ var _ = Describe("Packet Handler Map", func() {
// first send a normal packet
handledPacket := make(chan struct{})
packetHandler.EXPECT().handlePacket(gomock.Any()).Do(func(p *receivedPacket) {
Expect(p.hdr.DestConnectionID).To(Equal(connID))
cid, err := wire.ParseConnectionID(p.data, 0)
Expect(err).ToNot(HaveOccurred())
Expect(cid).To(Equal(connID))
close(handledPacket)
})
conn.dataToRead <- getPacket(connID)
@ -250,24 +195,6 @@ var _ = Describe("Packet Handler Map", func() {
Eventually(destroyed).Should(BeClosed())
})
It("detects a stateless that is coalesced with another packet", func() {
packetHandler := NewMockPacketHandler(mockCtrl)
connID := protocol.ConnectionID{0xde, 0xca, 0xfb, 0xad}
token := [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
handler.AddWithResetToken(connID, packetHandler, token)
fakeConnID := protocol.ConnectionID{1, 2, 3, 4, 5}
packet := getPacket(fakeConnID)
reset := append([]byte{0x40} /* short header packet */, fakeConnID...)
reset = append(reset, make([]byte, 50)...) // add some "random" data
reset = append(reset, token[:]...)
destroyed := make(chan struct{})
packetHandler.EXPECT().destroy(errors.New("received a stateless reset")).Do(func(error) {
close(destroyed)
})
conn.dataToRead <- append(packet, reset...)
Eventually(destroyed).Should(BeClosed())
})
It("deletes reset tokens when the session is retired", func() {
handler.deleteRetiredSessionsAfter = scaleDuration(10 * time.Millisecond)
connID := protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef, 0x42}
@ -291,7 +218,9 @@ var _ = Describe("Packet Handler Map", func() {
p := getPacket(connID)
server := NewMockUnknownPacketHandler(mockCtrl)
server.EXPECT().handlePacket(gomock.Any()).Do(func(p *receivedPacket) {
Expect(p.hdr.DestConnectionID).To(Equal(connID))
cid, err := wire.ParseConnectionID(p.data, 0)
Expect(err).ToNot(HaveOccurred())
Expect(cid).To(Equal(connID))
})
handler.SetServer(server)
handler.handlePacket(nil, nil, p)
@ -299,9 +228,9 @@ var _ = Describe("Packet Handler Map", func() {
It("closes all server sessions", func() {
clientSess := NewMockPacketHandler(mockCtrl)
clientSess.EXPECT().GetPerspective().Return(protocol.PerspectiveClient)
clientSess.EXPECT().getPerspective().Return(protocol.PerspectiveClient)
serverSess := NewMockPacketHandler(mockCtrl)
serverSess.EXPECT().GetPerspective().Return(protocol.PerspectiveServer)
serverSess.EXPECT().getPerspective().Return(protocol.PerspectiveServer)
serverSess.EXPECT().Close()
handler.Add(protocol.ConnectionID{1, 1, 1, 1}, clientSess)