allow reuse of connection IDs

fixes #347
This commit is contained in:
Marten Seemann
2017-01-07 18:17:22 +07:00
parent bf615659d6
commit 72e9994c9c
3 changed files with 40 additions and 8 deletions

View File

@@ -97,5 +97,9 @@ const MaxIdleTimeout = 1 * time.Minute
// MaxTimeForCryptoHandshake is the default timeout for a connection until the crypto handshake succeeds.
const MaxTimeForCryptoHandshake = 10 * time.Second
// ClosedSessionDeleteTimeout the server ignores packets arriving on a connection that is already closed
// after this time all information about the old connection will be deleted
const ClosedSessionDeleteTimeout = time.Minute
// NumCachedCertificates is the number of cached compressed certificate chains, each taking ~1K space
const NumCachedCertificates = 128

View File

@@ -35,6 +35,7 @@ type Server struct {
sessions map[protocol.ConnectionID]packetHandler
sessionsMutex sync.RWMutex
deleteClosedSessionsAfter time.Duration
streamCallback StreamCallback
@@ -69,6 +70,7 @@ func NewServer(addr string, tlsConfig *tls.Config, cb StreamCallback) (*Server,
streamCallback: cb,
sessions: map[protocol.ConnectionID]packetHandler{},
newSession: newSession,
deleteClosedSessionsAfter: protocol.ClosedSessionDeleteTimeout,
}, nil
}
@@ -220,6 +222,12 @@ func (s *Server) closeCallback(id protocol.ConnectionID) {
s.sessionsMutex.Lock()
s.sessions[id] = nil
s.sessionsMutex.Unlock()
time.AfterFunc(s.deleteClosedSessionsAfter, func() {
s.sessionsMutex.Lock()
delete(s.sessions, id)
s.sessionsMutex.Unlock()
})
}
func composeVersionNegotiation(connectionID protocol.ConnectionID) []byte {

View File

@@ -3,6 +3,7 @@ package quic
import (
"bytes"
"net"
"time"
"github.com/lucas-clemente/quic-go/crypto"
"github.com/lucas-clemente/quic-go/handshake"
@@ -82,12 +83,23 @@ var _ = Describe("Server", func() {
err := server.handlePacket(nil, nil, append(firstPacket, (&crypto.NullAEAD{}).Seal(nil, nil, 0, firstPacket)...))
Expect(err).ToNot(HaveOccurred())
Expect(server.sessions).To(HaveLen(1))
Expect(server.sessions[0x4cfa9f9b668619f6]).ToNot(BeNil())
server.closeCallback(0x4cfa9f9b668619f6)
// The server should now have closed the session, leaving a nil value in the sessions map
Expect(server.sessions).To(HaveLen(1))
Expect(server.sessions[0x4cfa9f9b668619f6]).To(BeNil())
})
It("deletes nil session entries after a wait time", func() {
server.deleteClosedSessionsAfter = 15 * time.Millisecond
err := server.handlePacket(nil, nil, append(firstPacket, (&crypto.NullAEAD{}).Seal(nil, nil, 0, firstPacket)...))
Expect(err).ToNot(HaveOccurred())
Expect(server.sessions).To(HaveLen(1))
server.closeCallback(0x4cfa9f9b668619f6)
Consistently(func() map[protocol.ConnectionID]packetHandler { return server.sessions }, 10*time.Millisecond, time.Millisecond).Should(HaveKey(protocol.ConnectionID(0x4cfa9f9b668619f6)))
Eventually(func() map[protocol.ConnectionID]packetHandler { return server.sessions }, 100*time.Millisecond).ShouldNot(HaveKey(protocol.ConnectionID(0x4cfa9f9b668619f6)))
})
It("closes sessions when Close is called", func() {
session := &mockSession{}
server.sessions[1] = session
@@ -159,6 +171,14 @@ var _ = Describe("Server", func() {
})
})
It("setups with the right values", func() {
server, err := NewServer("", testdata.GetTLSConfig(), nil)
Expect(err).ToNot(HaveOccurred())
Expect(server.deleteClosedSessionsAfter).To(Equal(protocol.ClosedSessionDeleteTimeout))
Expect(server.sessions).ToNot(BeNil())
Expect(server.scfg).ToNot(BeNil())
})
It("setups and responds with version negotiation", func(done Done) {
addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
Expect(err).ToNot(HaveOccurred())