mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-04 20:57:36 +03:00
parent
2f6e2c1201
commit
3683763dc0
8 changed files with 71 additions and 25 deletions
|
@ -23,7 +23,7 @@ type ReceivedPacketHandler interface {
|
||||||
ReceivedPacket(packetNumber protocol.PacketNumber, entropyBit bool) error
|
ReceivedPacket(packetNumber protocol.PacketNumber, entropyBit bool) error
|
||||||
ReceivedStopWaiting(*frames.StopWaitingFrame) error
|
ReceivedStopWaiting(*frames.StopWaitingFrame) error
|
||||||
|
|
||||||
DequeueAckFrame() *frames.AckFrame
|
DequeueAckFrame() (*frames.AckFrame, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StopWaitingManager manages StopWaitings for sent packets
|
// StopWaitingManager manages StopWaitings for sent packets
|
||||||
|
|
|
@ -11,6 +11,8 @@ import (
|
||||||
// ErrDuplicatePacket occurres when a duplicate packet is received
|
// ErrDuplicatePacket occurres when a duplicate packet is received
|
||||||
var ErrDuplicatePacket = errors.New("ReceivedPacketHandler: Duplicate Packet")
|
var ErrDuplicatePacket = errors.New("ReceivedPacketHandler: Duplicate Packet")
|
||||||
|
|
||||||
|
var errInvalidPacketNumber = errors.New("ReceivedPacketHandler: Invalid packet number")
|
||||||
|
|
||||||
type packetHistoryEntry struct {
|
type packetHistoryEntry struct {
|
||||||
EntropyBit bool
|
EntropyBit bool
|
||||||
TimeReceived time.Time
|
TimeReceived time.Time
|
||||||
|
@ -33,7 +35,7 @@ func NewReceivedPacketHandler() ReceivedPacketHandler {
|
||||||
|
|
||||||
func (h *receivedPacketHandler) ReceivedPacket(packetNumber protocol.PacketNumber, entropyBit bool) error {
|
func (h *receivedPacketHandler) ReceivedPacket(packetNumber protocol.PacketNumber, entropyBit bool) error {
|
||||||
if packetNumber == 0 {
|
if packetNumber == 0 {
|
||||||
return errors.New("Invalid packet number")
|
return errInvalidPacketNumber
|
||||||
}
|
}
|
||||||
_, ok := h.packetHistory[packetNumber]
|
_, ok := h.packetHistory[packetNumber]
|
||||||
if packetNumber <= h.highestInOrderObserved || ok {
|
if packetNumber <= h.highestInOrderObserved || ok {
|
||||||
|
@ -98,17 +100,25 @@ func (h *receivedPacketHandler) getNackRanges() ([]frames.NackRange, EntropyAccu
|
||||||
return ranges, entropy
|
return ranges, entropy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *receivedPacketHandler) DequeueAckFrame() *frames.AckFrame {
|
func (h *receivedPacketHandler) DequeueAckFrame() (*frames.AckFrame, error) {
|
||||||
if !h.stateChanged {
|
if !h.stateChanged {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
h.stateChanged = false
|
h.stateChanged = false
|
||||||
|
|
||||||
|
p, ok := h.packetHistory[h.largestObserved]
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("bla")
|
||||||
|
}
|
||||||
|
packetReceivedTime := p.TimeReceived
|
||||||
|
|
||||||
nackRanges, entropy := h.getNackRanges()
|
nackRanges, entropy := h.getNackRanges()
|
||||||
return &frames.AckFrame{
|
ack := frames.AckFrame{
|
||||||
LargestObserved: h.largestObserved,
|
LargestObserved: h.largestObserved,
|
||||||
Entropy: byte(entropy),
|
Entropy: byte(entropy),
|
||||||
NackRanges: nackRanges,
|
NackRanges: nackRanges,
|
||||||
|
PacketReceivedTime: packetReceivedTime,
|
||||||
}
|
}
|
||||||
|
return &ack, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,12 @@ var _ = Describe("receivedPacketHandler", func() {
|
||||||
Expect(handler.packetHistory).To(HaveKey(protocol.PacketNumber(3)))
|
Expect(handler.packetHistory).To(HaveKey(protocol.PacketNumber(3)))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("rejects packets with packet number 0", func() {
|
||||||
|
err := handler.ReceivedPacket(protocol.PacketNumber(0), false)
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
Expect(err).To(Equal(errInvalidPacketNumber))
|
||||||
|
})
|
||||||
|
|
||||||
It("rejects a duplicate package with PacketNumber equal to LargestObserved", func() {
|
It("rejects a duplicate package with PacketNumber equal to LargestObserved", func() {
|
||||||
for i := 1; i < 5; i++ {
|
for i := 1; i < 5; i++ {
|
||||||
err := handler.ReceivedPacket(protocol.PacketNumber(i), false)
|
err := handler.ReceivedPacket(protocol.PacketNumber(i), false)
|
||||||
|
@ -243,7 +249,10 @@ var _ = Describe("receivedPacketHandler", func() {
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
err = handler.ReceivedPacket(protocol.PacketNumber(2), true)
|
err = handler.ReceivedPacket(protocol.PacketNumber(2), true)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(handler.DequeueAckFrame()).To(Equal(&frames.AckFrame{LargestObserved: 2, Entropy: byte(entropy)}))
|
ack, err := handler.DequeueAckFrame()
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(ack.LargestObserved).To(Equal(protocol.PacketNumber(2)))
|
||||||
|
Expect(ack.Entropy).To(Equal(byte(entropy)))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("generates an ACK frame with a NACK range", func() {
|
It("generates an ACK frame with a NACK range", func() {
|
||||||
|
@ -254,12 +263,11 @@ var _ = Describe("receivedPacketHandler", func() {
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
err = handler.ReceivedPacket(protocol.PacketNumber(4), true)
|
err = handler.ReceivedPacket(protocol.PacketNumber(4), true)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
expectedAck := frames.AckFrame{
|
ack, err := handler.DequeueAckFrame()
|
||||||
LargestObserved: 4,
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Entropy: byte(entropy),
|
Expect(ack.LargestObserved).To(Equal(protocol.PacketNumber(4)))
|
||||||
NackRanges: []frames.NackRange{frames.NackRange{FirstPacketNumber: 2, LastPacketNumber: 3}},
|
Expect(ack.Entropy).To(Equal(byte(entropy)))
|
||||||
}
|
Expect(ack.NackRanges).To(Equal([]frames.NackRange{frames.NackRange{FirstPacketNumber: 2, LastPacketNumber: 3}}))
|
||||||
Expect(handler.DequeueAckFrame()).To(Equal(&expectedAck))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("does not generate an ACK if an ACK has already been sent for the largest Packet", func() {
|
It("does not generate an ACK if an ACK has already been sent for the largest Packet", func() {
|
||||||
|
|
|
@ -15,9 +15,11 @@ var errInvalidNackRanges = errors.New("AckFrame: ACK frame contains invalid NACK
|
||||||
type AckFrame struct {
|
type AckFrame struct {
|
||||||
LargestObserved protocol.PacketNumber
|
LargestObserved protocol.PacketNumber
|
||||||
Entropy byte
|
Entropy byte
|
||||||
DelayTime time.Duration
|
|
||||||
NackRanges []NackRange // has to be ordered. The NACK range with the highest FirstPacketNumber goes first, the NACK range with the lowest FirstPacketNumber goes last
|
NackRanges []NackRange // has to be ordered. The NACK range with the highest FirstPacketNumber goes first, the NACK range with the lowest FirstPacketNumber goes last
|
||||||
Truncated bool
|
Truncated bool
|
||||||
|
|
||||||
|
DelayTime time.Duration
|
||||||
|
PacketReceivedTime time.Time // only for received packets. Will not be modified for received ACKs frames
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes an ACK frame.
|
// Write writes an ACK frame.
|
||||||
|
@ -28,6 +30,8 @@ func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error
|
||||||
typeByte |= (0x20 | 0x03)
|
typeByte |= (0x20 | 0x03)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f.DelayTime = time.Now().Sub(f.PacketReceivedTime)
|
||||||
|
|
||||||
b.WriteByte(typeByte)
|
b.WriteByte(typeByte)
|
||||||
b.WriteByte(f.Entropy)
|
b.WriteByte(f.Entropy)
|
||||||
utils.WriteUint48(b, uint64(f.LargestObserved)) // TODO: send the correct length
|
utils.WriteUint48(b, uint64(f.LargestObserved)) // TODO: send the correct length
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go/protocol"
|
"github.com/lucas-clemente/quic-go/protocol"
|
||||||
|
"github.com/lucas-clemente/quic-go/utils"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
)
|
)
|
||||||
|
@ -251,7 +252,22 @@ var _ = Describe("AckFrame", func() {
|
||||||
}
|
}
|
||||||
err := frame.Write(b, 32)
|
err := frame.Write(b, 32)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(b.Bytes()).To(Equal([]byte{0x4c, 0x02, 0x01, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}))
|
// check all values except the DelayTime
|
||||||
|
Expect(b.Bytes()[0:8]).To(Equal([]byte{0x4c, 0x02, 0x01, 0, 0, 0, 0, 0}))
|
||||||
|
Expect(b.Bytes()[10:]).To(Equal([]byte{1, 0, 0, 0, 0, 0}))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("calculates the DelayTime", func() {
|
||||||
|
frame := AckFrame{
|
||||||
|
LargestObserved: 5,
|
||||||
|
PacketReceivedTime: time.Now().Add(-750 * time.Millisecond),
|
||||||
|
}
|
||||||
|
frame.Write(b, 32)
|
||||||
|
Expect(frame.DelayTime).To(BeNumerically("~", 750*time.Millisecond, 10*time.Millisecond))
|
||||||
|
delayTime := frame.DelayTime
|
||||||
|
var b2 bytes.Buffer
|
||||||
|
utils.WriteUfloat16(&b2, uint64(delayTime/time.Microsecond))
|
||||||
|
Expect(b.Bytes()[8:10]).To(Equal(b2.Bytes()))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("writes a frame with one NACK range", func() {
|
It("writes a frame with one NACK range", func() {
|
||||||
|
|
|
@ -2,10 +2,10 @@ package quic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go/crypto"
|
"github.com/lucas-clemente/quic-go/crypto"
|
||||||
"github.com/lucas-clemente/quic-go/frames"
|
"github.com/lucas-clemente/quic-go/frames"
|
||||||
|
"github.com/lucas-clemente/quic-go/protocol"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
@ -60,15 +60,18 @@ var _ = Describe("Packet unpacker", func() {
|
||||||
|
|
||||||
It("unpacks ack frames", func() {
|
It("unpacks ack frames", func() {
|
||||||
f := &frames.AckFrame{
|
f := &frames.AckFrame{
|
||||||
LargestObserved: 1,
|
LargestObserved: 0x13,
|
||||||
DelayTime: time.Microsecond,
|
Entropy: 0x37,
|
||||||
}
|
}
|
||||||
err := f.Write(buf, 32)
|
err := f.Write(buf, 32)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
setReader(buf.Bytes())
|
setReader(buf.Bytes())
|
||||||
packet, err := unpacker.Unpack(hdrBin, hdr, r)
|
packet, err := unpacker.Unpack(hdrBin, hdr, r)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(packet.frames).To(Equal([]frames.Frame{f}))
|
Expect(len(packet.frames)).To(Equal(1))
|
||||||
|
readFrame := packet.frames[0].(*frames.AckFrame)
|
||||||
|
Expect(readFrame.LargestObserved).To(Equal(protocol.PacketNumber(0x13)))
|
||||||
|
Expect(readFrame.Entropy).To(Equal(byte(0x37)))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("errors on CONGESTION_FEEDBACK frames", func() {
|
It("errors on CONGESTION_FEEDBACK frames", func() {
|
||||||
|
|
|
@ -397,7 +397,10 @@ func (s *Session) sendPacket() error {
|
||||||
|
|
||||||
stopWaitingFrame := s.stopWaitingManager.GetStopWaitingFrame()
|
stopWaitingFrame := s.stopWaitingManager.GetStopWaitingFrame()
|
||||||
|
|
||||||
ack := s.receivedPacketHandler.DequeueAckFrame()
|
ack, err := s.receivedPacketHandler.DequeueAckFrame()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if ack != nil {
|
if ack != nil {
|
||||||
controlFrames = append(controlFrames, ack)
|
controlFrames = append(controlFrames, ack)
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,7 +321,8 @@ var _ = Describe("Session", func() {
|
||||||
err := session.sendPacket()
|
err := session.sendPacket()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(conn.written).To(HaveLen(1))
|
Expect(conn.written).To(HaveLen(1))
|
||||||
Expect(conn.written[0]).To(ContainSubstring(string([]byte{0x4c, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0})))
|
// test for the beginning of an ACK frame: TypeByte until LargestObserved
|
||||||
|
Expect(conn.written[0]).To(ContainSubstring(string([]byte{0x4c, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0})))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("sends queued stream frames", func() {
|
It("sends queued stream frames", func() {
|
||||||
|
@ -333,7 +334,8 @@ var _ = Describe("Session", func() {
|
||||||
err := session.sendPacket()
|
err := session.sendPacket()
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(conn.written).To(HaveLen(1))
|
Expect(conn.written).To(HaveLen(1))
|
||||||
Expect(conn.written[0]).To(ContainSubstring(string([]byte{0x4c, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0})))
|
// test for the beginning of an ACK frame: TypeByte until LargestObserved
|
||||||
|
Expect(conn.written[0]).To(ContainSubstring(string([]byte{0x4c, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0})))
|
||||||
Expect(conn.written[0]).To(ContainSubstring(string("foobar")))
|
Expect(conn.written[0]).To(ContainSubstring(string("foobar")))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue