diff --git a/session.go b/session.go index 20777796..f711829e 100644 --- a/session.go +++ b/session.go @@ -111,6 +111,7 @@ type session struct { handshakeChan chan error handshakeComplete bool + receivedFirstPacket bool // since packet numbers start at 0, we can't use largestRcvdPacketNumber != 0 for this lastRcvdPacketNumber protocol.PacketNumber // Used to calculate the next packet number from the truncated wire // representation, and sent back in public reset packets @@ -509,6 +510,7 @@ func (s *session) handlePacketImpl(p *receivedPacket) error { p.rcvTime = time.Now() } + s.receivedFirstPacket = true s.lastNetworkActivityTime = p.rcvTime s.keepAlivePingSent = false hdr := p.header @@ -819,6 +821,13 @@ func (s *session) sendPacket() (bool, error) { if retransmitPacket == nil { break } + // Don't retransmit Initial packets if we already received a response. + // An Initial might have been retransmitted multiple times before we receive a response. + // As soon as we receive one response, we don't need to send any more Initials. + if s.receivedFirstPacket && retransmitPacket.PacketType == protocol.PacketTypeInitial { + utils.Debugf("Skipping retransmission of packet %d. Already received a response to an Initial.", retransmitPacket.PacketNumber) + continue + } // retransmit handshake packets if retransmitPacket.EncryptionLevel != protocol.EncryptionForwardSecure { @@ -870,6 +879,7 @@ func (s *session) sendPackedPacket(packet *packedPacket) error { defer putPacketBuffer(packet.raw) err := s.sentPacketHandler.SentPacket(&ackhandler.Packet{ PacketNumber: packet.header.PacketNumber, + PacketType: packet.header.Type, Frames: packet.frames, Length: protocol.ByteCount(len(packet.raw)), EncryptionLevel: packet.encryptionLevel, diff --git a/session_test.go b/session_test.go index 35092e27..b996393f 100644 --- a/session_test.go +++ b/session_test.go @@ -755,6 +755,31 @@ var _ = Describe("Session", func() { Expect(sentPacket.EncryptionLevel).To(Equal(protocol.EncryptionForwardSecure)) Expect(sentPacket.Length).To(BeEquivalentTo(len(<-mconn.written))) }) + + It("doesn't retransmit an initial packet if it already received a response", func() { + sess.unpacker = &mockUnpacker{} + sph := mockackhandler.NewMockSentPacketHandler(mockCtrl) + sph.EXPECT().GetLeastUnacked().AnyTimes() + sph.EXPECT().DequeuePacketForRetransmission().Return(&ackhandler.Packet{ + PacketNumber: 10, + PacketType: protocol.PacketTypeInitial, + }) + sph.EXPECT().DequeuePacketForRetransmission() + rph := mockackhandler.NewMockReceivedPacketHandler(mockCtrl) + rph.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any()) + rph.EXPECT().GetAckFrame() + sess.receivedPacketHandler = rph + sess.sentPacketHandler = sph + err := sess.handlePacketImpl(&receivedPacket{ + header: &wire.Header{}, + data: []byte{0}, + }) + Expect(err).ToNot(HaveOccurred()) + Expect(sess.receivedFirstPacket).To(BeTrue()) + sent, err := sess.sendPacket() + Expect(err).NotTo(HaveOccurred()) + Expect(sent).To(BeFalse()) + }) }) Context("packet pacing", func() {