forked from quic-go/quic-go
only accept one version negotiation packet
This commit is contained in:
11
client.go
11
client.go
@@ -26,6 +26,7 @@ type client struct {
|
|||||||
|
|
||||||
versionNegotiationChan chan struct{} // the versionNegotiationChan is closed as soon as the server accepted the suggested version
|
versionNegotiationChan chan struct{} // the versionNegotiationChan is closed as soon as the server accepted the suggested version
|
||||||
versionNegotiated bool // has version negotiation completed yet
|
versionNegotiated bool // has version negotiation completed yet
|
||||||
|
receivedVersionNegotiationPacket bool
|
||||||
|
|
||||||
tlsConf *tls.Config
|
tlsConf *tls.Config
|
||||||
config *Config
|
config *Config
|
||||||
@@ -187,12 +188,10 @@ func (c *client) establishSecureConnection() error {
|
|||||||
errorChan := make(chan struct{})
|
errorChan := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
// session.run() returns as soon as the session is closed
|
// session.run() returns as soon as the session is closed
|
||||||
for {
|
|
||||||
runErr = c.session.run()
|
runErr = c.session.run()
|
||||||
if runErr == errCloseSessionForNewVersion {
|
if runErr == errCloseSessionForNewVersion {
|
||||||
continue
|
// run the new session
|
||||||
}
|
runErr = c.session.run()
|
||||||
break
|
|
||||||
}
|
}
|
||||||
close(errorChan)
|
close(errorChan)
|
||||||
utils.Infof("Connection %x closed.", c.connectionID)
|
utils.Infof("Connection %x closed.", c.connectionID)
|
||||||
@@ -278,7 +277,7 @@ func (c *client) handlePacket(remoteAddr net.Addr, packet []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ignore delayed / duplicated version negotiation packets
|
// ignore delayed / duplicated version negotiation packets
|
||||||
if c.versionNegotiated && hdr.VersionFlag {
|
if (c.receivedVersionNegotiationPacket || c.versionNegotiated) && hdr.VersionFlag {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,6 +314,8 @@ func (c *client) handlePacketWithVersionFlag(hdr *wire.PublicHeader) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.receivedVersionNegotiationPacket = true
|
||||||
|
|
||||||
newVersion := protocol.ChooseSupportedVersion(c.config.Versions, hdr.SupportedVersions)
|
newVersion := protocol.ChooseSupportedVersion(c.config.Versions, hdr.SupportedVersions)
|
||||||
if newVersion == protocol.VersionUnsupported {
|
if newVersion == protocol.VersionUnsupported {
|
||||||
return qerr.InvalidVersion
|
return qerr.InvalidVersion
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||||
@@ -355,6 +356,34 @@ var _ = Describe("Client", func() {
|
|||||||
Eventually(established).Should(BeClosed())
|
Eventually(established).Should(BeClosed())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("only accepts one version negotiation packet", func() {
|
||||||
|
sessionCounter := uint32(0)
|
||||||
|
newClientSession = func(
|
||||||
|
_ connection,
|
||||||
|
_ string,
|
||||||
|
_ protocol.VersionNumber,
|
||||||
|
connectionID protocol.ConnectionID,
|
||||||
|
_ *tls.Config,
|
||||||
|
_ *Config,
|
||||||
|
negotiatedVersionsP []protocol.VersionNumber,
|
||||||
|
) (packetHandler, <-chan handshakeEvent, error) {
|
||||||
|
atomic.AddUint32(&sessionCounter, 1)
|
||||||
|
return sess, nil, nil
|
||||||
|
}
|
||||||
|
go cl.establishSecureConnection()
|
||||||
|
Eventually(func() uint32 { return atomic.LoadUint32(&sessionCounter) }).Should(BeEquivalentTo(1))
|
||||||
|
newVersion := protocol.VersionNumber(77)
|
||||||
|
Expect(newVersion).ToNot(Equal(cl.version))
|
||||||
|
Expect(config.Versions).To(ContainElement(newVersion))
|
||||||
|
cl.handlePacket(nil, wire.ComposeVersionNegotiation(0x1337, []protocol.VersionNumber{newVersion}))
|
||||||
|
Expect(atomic.LoadUint32(&sessionCounter)).To(BeEquivalentTo(2))
|
||||||
|
newVersion = protocol.VersionNumber(78)
|
||||||
|
Expect(newVersion).ToNot(Equal(cl.version))
|
||||||
|
Expect(config.Versions).To(ContainElement(newVersion))
|
||||||
|
cl.handlePacket(nil, wire.ComposeVersionNegotiation(0x1337, []protocol.VersionNumber{newVersion}))
|
||||||
|
Expect(atomic.LoadUint32(&sessionCounter)).To(BeEquivalentTo(2))
|
||||||
|
})
|
||||||
|
|
||||||
It("errors if no matching version is found", func() {
|
It("errors if no matching version is found", func() {
|
||||||
cl.handlePacket(nil, wire.ComposeVersionNegotiation(0x1337, []protocol.VersionNumber{1}))
|
cl.handlePacket(nil, wire.ComposeVersionNegotiation(0x1337, []protocol.VersionNumber{1}))
|
||||||
Expect(cl.session.(*mockSession).closed).To(BeTrue())
|
Expect(cl.session.(*mockSession).closed).To(BeTrue())
|
||||||
|
|||||||
Reference in New Issue
Block a user