diff --git a/ackhandler/interfaces.go b/ackhandler/interfaces.go index 05bbb1131..8167dac25 100644 --- a/ackhandler/interfaces.go +++ b/ackhandler/interfaces.go @@ -1,6 +1,8 @@ package ackhandler import ( + "time" + "github.com/lucas-clemente/quic-go/frames" "github.com/lucas-clemente/quic-go/protocol" ) @@ -8,7 +10,7 @@ import ( // SentPacketHandler handles ACKs received for outgoing packets type SentPacketHandler interface { SentPacket(packet *Packet) error - ReceivedAck(ackFrame *frames.AckFrame) error + ReceivedAck(ackFrame *frames.AckFrame) (time.Duration, error) DequeuePacketForRetransmission() (packet *Packet) } diff --git a/ackhandler/packet.go b/ackhandler/packet.go index 4f783f620..3c807dc4a 100644 --- a/ackhandler/packet.go +++ b/ackhandler/packet.go @@ -1,6 +1,8 @@ package ackhandler import ( + "time" + "github.com/lucas-clemente/quic-go/frames" "github.com/lucas-clemente/quic-go/protocol" ) @@ -14,6 +16,8 @@ type Packet struct { MissingReports uint8 Retransmitted bool // has this Packet ever been retransmitted + + sendTime time.Time } func (p *Packet) GetStreamFramesForRetransmission() []*frames.StreamFrame { diff --git a/ackhandler/sent_packet_handler.go b/ackhandler/sent_packet_handler.go index 417077def..4336e1bdc 100644 --- a/ackhandler/sent_packet_handler.go +++ b/ackhandler/sent_packet_handler.go @@ -2,6 +2,7 @@ package ackhandler import ( "errors" + "time" "github.com/lucas-clemente/quic-go/frames" "github.com/lucas-clemente/quic-go/protocol" @@ -77,6 +78,7 @@ func (h *sentPacketHandler) SentPacket(packet *Packet) error { if h.lastSentPacketNumber+1 != packet.PacketNumber { return errors.New("Packet number must be increased by exactly 1") } + packet.sendTime = time.Now() h.lastSentPacketEntropy.Add(packet.PacketNumber, packet.EntropyBit) packet.Entropy = h.lastSentPacketEntropy @@ -114,28 +116,31 @@ func (h *sentPacketHandler) calculateExpectedEntropy(ackFrame *frames.AckFrame) return expectedEntropy, nil } -func (h *sentPacketHandler) ReceivedAck(ackFrame *frames.AckFrame) error { +func (h *sentPacketHandler) ReceivedAck(ackFrame *frames.AckFrame) (time.Duration, error) { if ackFrame.LargestObserved > h.lastSentPacketNumber { - return errAckForUnsentPacket + return 0, errAckForUnsentPacket } if ackFrame.LargestObserved <= h.LargestObserved { // duplicate or out-of-order AckFrame - return ErrDuplicateOrOutOfOrderAck + return 0, ErrDuplicateOrOutOfOrderAck } expectedEntropy, err := h.calculateExpectedEntropy(ackFrame) if err != nil { - return err + return 0, err } if byte(expectedEntropy) != ackFrame.Entropy { - return ErrEntropy + return 0, ErrEntropy } // Entropy ok. Now actually process the ACK packet h.LargestObserved = ackFrame.LargestObserved highestInOrderAckedPacketNumber := ackFrame.GetHighestInOrderPacketNumber() + // Calculate the RTT + timeDelta := time.Now().Sub(h.packetHistory[h.LargestObserved].sendTime) + // ACK all packets below the highestInOrderAckedPacketNumber for i := h.highestInOrderAckedPacketNumber; i <= highestInOrderAckedPacketNumber; i++ { h.ackPacket(i) @@ -161,7 +166,7 @@ func (h *sentPacketHandler) ReceivedAck(ackFrame *frames.AckFrame) error { h.highestInOrderAckedPacketNumber = highestInOrderAckedPacketNumber - return nil + return timeDelta, nil } func (h *sentPacketHandler) DequeuePacketForRetransmission() (packet *Packet) { diff --git a/ackhandler/sent_packet_handler_test.go b/ackhandler/sent_packet_handler_test.go index a4c489b8d..a3570542d 100644 --- a/ackhandler/sent_packet_handler_test.go +++ b/ackhandler/sent_packet_handler_test.go @@ -1,6 +1,8 @@ package ackhandler import ( + "time" + "github.com/lucas-clemente/quic-go/frames" "github.com/lucas-clemente/quic-go/protocol" . "github.com/onsi/ginkgo" @@ -73,7 +75,7 @@ var _ = Describe("SentPacketHandler", func() { LargestObserved: 1, Entropy: byte(entropy), } - err = handler.ReceivedAck(&ack) + _, err = handler.ReceivedAck(&ack) Expect(err).ToNot(HaveOccurred()) err = handler.SentPacket(&packet2) Expect(err).ToNot(HaveOccurred()) @@ -81,6 +83,13 @@ var _ = Describe("SentPacketHandler", func() { entropy.Add(packet2.PacketNumber, packet2.EntropyBit) Expect(handler.packetHistory[2].Entropy).To(Equal(entropy)) }) + + It("stores the sent time", func() { + packet := Packet{PacketNumber: 1, Frames: []frames.Frame{&streamFrame}, EntropyBit: true} + err := handler.SentPacket(&packet) + Expect(err).ToNot(HaveOccurred()) + Expect(handler.packetHistory[1].sendTime.Unix()).To(BeNumerically("~", time.Now().Unix(), 1)) + }) }) Context("ACK entropy calculations", func() { @@ -175,7 +184,7 @@ var _ = Describe("SentPacketHandler", func() { LargestObserved: 4, Entropy: 1, } - err := handler.ReceivedAck(&ack) + _, err := handler.ReceivedAck(&ack) Expect(err).To(HaveOccurred()) Expect(err).To(Equal(ErrEntropy)) }) @@ -190,7 +199,7 @@ var _ = Describe("SentPacketHandler", func() { LargestObserved: protocol.PacketNumber(largestObserved), Entropy: byte(entropy), } - err := handler.ReceivedAck(&ack) + _, err := handler.ReceivedAck(&ack) Expect(err).ToNot(HaveOccurred()) Expect(handler.LargestObserved).To(Equal(protocol.PacketNumber(largestObserved))) Expect(handler.highestInOrderAckedPacketNumber).To(Equal(protocol.PacketNumber(largestObserved))) @@ -215,7 +224,7 @@ var _ = Describe("SentPacketHandler", func() { frames.NackRange{FirstPacketNumber: 3, LastPacketNumber: 3}, }, } - err := handler.ReceivedAck(&ack) + _, err := handler.ReceivedAck(&ack) Expect(err).ToNot(HaveOccurred()) Expect(handler.LargestObserved).To(Equal(protocol.PacketNumber(largestObserved))) Expect(handler.highestInOrderAckedPacketNumber).To(Equal(protocol.PacketNumber(2))) @@ -250,9 +259,9 @@ var _ = Describe("SentPacketHandler", func() { ack := frames.AckFrame{ LargestObserved: protocol.PacketNumber(largestObserved), } - err := handler.ReceivedAck(&ack) + _, err := handler.ReceivedAck(&ack) Expect(err).ToNot(HaveOccurred()) - err = handler.ReceivedAck(&ack) + _, err = handler.ReceivedAck(&ack) Expect(err).To(HaveOccurred()) Expect(err).To(Equal(ErrDuplicateOrOutOfOrderAck)) }) @@ -262,10 +271,10 @@ var _ = Describe("SentPacketHandler", func() { ack := frames.AckFrame{ LargestObserved: protocol.PacketNumber(largestObserved), } - err := handler.ReceivedAck(&ack) + _, err := handler.ReceivedAck(&ack) Expect(err).ToNot(HaveOccurred()) ack.LargestObserved-- - err = handler.ReceivedAck(&ack) + _, err = handler.ReceivedAck(&ack) Expect(err).To(HaveOccurred()) Expect(err).To(Equal(ErrDuplicateOrOutOfOrderAck)) Expect(handler.LargestObserved).To(Equal(protocol.PacketNumber(largestObserved))) @@ -275,12 +284,30 @@ var _ = Describe("SentPacketHandler", func() { ack := frames.AckFrame{ LargestObserved: packets[len(packets)-1].PacketNumber + 1337, } - err := handler.ReceivedAck(&ack) + _, err := handler.ReceivedAck(&ack) Expect(err).To(HaveOccurred()) Expect(err).To(Equal(errAckForUnsentPacket)) Expect(handler.highestInOrderAckedPacketNumber).To(Equal(protocol.PacketNumber(0))) }) }) + + It("calculates the time delta", func() { + now := time.Now() + // First, fake the sent times of the first, second and last packet + handler.packetHistory[1].sendTime = now.Add(-10 * time.Minute) + handler.packetHistory[2].sendTime = now.Add(-5 * time.Minute) + handler.packetHistory[6].sendTime = now.Add(-1 * time.Minute) + // Now, check that the proper times are used when calculating the deltas + d, err := handler.ReceivedAck(&frames.AckFrame{LargestObserved: 1}) + Expect(err).NotTo(HaveOccurred()) + Expect(d).To(BeNumerically("~", 10*time.Minute, 1*time.Second)) + d, err = handler.ReceivedAck(&frames.AckFrame{LargestObserved: 2}) + Expect(err).NotTo(HaveOccurred()) + Expect(d).To(BeNumerically("~", 5*time.Minute, 1*time.Second)) + d, err = handler.ReceivedAck(&frames.AckFrame{LargestObserved: 6}) + Expect(err).NotTo(HaveOccurred()) + Expect(d).To(BeNumerically("~", 1*time.Minute, 1*time.Second)) + }) }) Context("Retransmission handler", func() { @@ -345,7 +372,7 @@ var _ = Describe("SentPacketHandler", func() { LargestObserved: 4, NackRanges: []frames.NackRange{frames.NackRange{FirstPacketNumber: 3, LastPacketNumber: 3}}, } - err := handler.ReceivedAck(&ack) + _, err := handler.ReceivedAck(&ack) Expect(err).ToNot(HaveOccurred()) Expect(handler.highestInOrderAckedPacketNumber).To(Equal(protocol.PacketNumber(2))) handler.nackPacket(3) // this is the second NACK for this packet diff --git a/session.go b/session.go index 902edb207..2c0cb050c 100644 --- a/session.go +++ b/session.go @@ -139,7 +139,7 @@ func (s *Session) handlePacket(remoteAddr interface{}, publicHeader *PublicHeade case *frames.StreamFrame: err = s.handleStreamFrame(frame) case *frames.AckFrame: - err = s.sentPacketHandler.ReceivedAck(frame) + _, err = s.sentPacketHandler.ReceivedAck(frame) // ToDo: send right error in ConnectionClose frame case *frames.ConnectionCloseFrame: fmt.Printf("%#v\n", frame)