From 3818fa16b31d4967c94cf63c9e465342a875fefa Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Wed, 10 Jan 2018 17:10:50 +0700 Subject: [PATCH] make the client send a packet when the handshake completes (in gQUIC) In gQUIC, there's no equivalent to the Finished message in TLS. The server knows that the handshake is complete when it receives the first forward-secure packet sent by the client. If the protocol demands that the server sends the first data, this would never happen. We need to make sure that the client actually sends such a packet. Queueing a PING frame is an easy way to do so. --- session.go | 6 ++++++ session_test.go | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/session.go b/session.go index 1ed80132a..09af8c09d 100644 --- a/session.go +++ b/session.go @@ -394,6 +394,12 @@ runLoop: s.handshakeComplete = true handshakeEvent = nil // prevent this case from ever being selected again s.sentPacketHandler.SetHandshakeComplete() + if !s.version.UsesTLS() && s.perspective == protocol.PerspectiveClient { + // In gQUIC, there's no equivalent to the Finished message in TLS + // The server knows that the handshake is complete when it receives the first forward-secure packet sent by the client. + // We need to make sure that the client actually sends such a packet. + s.packer.QueueControlFrame(&wire.PingFrame{}) + } close(s.handshakeChan) } else { s.tryDecryptingQueuedPackets() diff --git a/session_test.go b/session_test.go index a51b87751..6438b45db 100644 --- a/session_test.go +++ b/session_test.go @@ -1470,6 +1470,22 @@ var _ = Describe("Client Session", func() { newCryptoSetupClient = handshake.NewCryptoSetupClient }) + It("sends a forward-secure packet when the handshake completes", func() { + sess.packer.hasSentPacket = true + done := make(chan struct{}) + go func() { + defer GinkgoRecover() + err := sess.run() + Expect(err).ToNot(HaveOccurred()) + close(done) + }() + close(handshakeChan) + Eventually(mconn.written).Should(Receive()) + //make sure the go routine returns + Expect(sess.Close(nil)).To(Succeed()) + Eventually(done).Should(BeClosed()) + }) + Context("receiving packets", func() { var hdr *wire.Header