From fc3087fab3017172437c1d29530f9dd5795159d2 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Sun, 29 Oct 2017 16:44:03 +0700 Subject: [PATCH] handle IETF draft style Version Negotiation Packets --- client.go | 29 ++++++++++++++++------------- client_test.go | 1 + 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/client.go b/client.go index ca56ce43..d3b21dc2 100644 --- a/client.go +++ b/client.go @@ -286,26 +286,29 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) { return } - // ignore delayed / duplicated version negotiation packets - if (c.receivedVersionNegotiationPacket || c.versionNegotiated) && hdr.VersionFlag { - return - } + isVersionNegotiationPacket := hdr.VersionFlag /* gQUIC Version Negotiation Packet */ || hdr.Type == protocol.PacketTypeVersionNegotiation /* IETF draft style Version Negotiation Packet */ - // this is the first packet after the client sent a packet with the VersionFlag set - // if the server doesn't send a version negotiation packet, it supports the suggested version - if !hdr.VersionFlag && !c.versionNegotiated { - c.versionNegotiated = true - close(c.versionNegotiationChan) - } + // handle Version Negotiation Packets + if isVersionNegotiationPacket { + // ignore delayed / duplicated version negotiation packets + if c.receivedVersionNegotiationPacket || c.versionNegotiated { + return + } - if hdr.VersionFlag { // version negotiation packets have no payload - if err := c.handlePacketWithVersionFlag(hdr); err != nil { + if err := c.handleVersionNegotiationPacket(hdr); err != nil { c.session.Close(err) } return } + // this is the first packet we are receiving + // since it is not a Version Negotiation Packet, this means the server supports the suggested version + if !c.versionNegotiated { + c.versionNegotiated = true + close(c.versionNegotiationChan) + } + c.session.handlePacket(&receivedPacket{ remoteAddr: remoteAddr, header: hdr, @@ -314,7 +317,7 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) { }) } -func (c *client) handlePacketWithVersionFlag(hdr *wire.Header) error { +func (c *client) handleVersionNegotiationPacket(hdr *wire.Header) error { for _, v := range hdr.SupportedVersions { if v == c.version { // the version negotiation packet contains the version that we offered diff --git a/client_test.go b/client_test.go index 1d8e1aa5..0f438f8d 100644 --- a/client_test.go +++ b/client_test.go @@ -246,6 +246,7 @@ var _ = Describe("Client", func() { testErr := errors.New("late handshake error") packetConn.dataToRead = acceptClientVersionPacket(cl.connectionID) go func() { + defer GinkgoRecover() _, dialErr := Dial(packetConn, addr, "quic.clemente.io:1337", nil, config) Expect(dialErr).To(MatchError(testErr)) close(done)