implement closing of the TLS crypto setup

When the crypto setup is closed, the go rounine running the
qtls.Handshake() needs to return.
This commit is contained in:
Marten Seemann
2018-10-28 12:41:40 +07:00
parent 35c0721b88
commit 4a326ad00a
3 changed files with 43 additions and 0 deletions

View File

@@ -67,6 +67,8 @@ type cryptoSetupTLS struct {
handshakeComplete chan<- struct{}
// transport parameters are sent on the receivedTransportParams, as soon as they are received
receivedTransportParams <-chan TransportParameters
// is closed when Close() is called
closeChan chan struct{}
clientHelloWritten bool
clientHelloWrittenChan chan struct{}
@@ -196,6 +198,7 @@ func newCryptoSetupTLS(
messageChan: make(chan []byte, 100),
receivedReadKey: make(chan struct{}),
receivedWriteKey: make(chan struct{}),
closeChan: make(chan struct{}),
}
var extHandler tlsExtensionHandler
switch perspective {
@@ -243,6 +246,11 @@ func (h *cryptoSetupTLS) RunHandshake() error {
}()
select {
case <-h.closeChan:
close(h.messageChan)
// wait until the Handshake() go routine has returned
<-handshakeErrChan
return errors.New("Handshake aborted")
case <-handshakeComplete: // return when the handshake is done
close(h.handshakeComplete)
return nil
@@ -261,6 +269,11 @@ func (h *cryptoSetupTLS) RunHandshake() error {
}
}
func (h *cryptoSetupTLS) Close() error {
close(h.closeChan)
return nil
}
// handleMessage handles a TLS handshake message.
// It is called by the crypto streams when a new message is available.
// It returns if it is done with messages on the same encryption level.

View File

@@ -116,6 +116,34 @@ var _ = Describe("Crypto Setup TLS", func() {
Eventually(done).Should(BeClosed())
})
It("returns Handshake() when it is closed", func() {
_, sInitialStream, sHandshakeStream := initStreams()
server, err := NewCryptoSetupTLSServer(
sInitialStream,
sHandshakeStream,
protocol.ConnectionID{},
&TransportParameters{},
func(p *TransportParameters) {},
make(chan struct{}),
testdata.GetTLSConfig(),
[]protocol.VersionNumber{protocol.VersionTLS},
protocol.VersionTLS,
utils.DefaultLogger.WithPrefix("server"),
protocol.PerspectiveServer,
)
Expect(err).ToNot(HaveOccurred())
done := make(chan struct{})
go func() {
defer GinkgoRecover()
err := server.RunHandshake()
Expect(err).To(MatchError("Handshake aborted"))
close(done)
}()
Expect(server.Close()).To(Succeed())
Eventually(done).Should(BeClosed())
})
Context("doing the handshake", func() {
generateCert := func() tls.Certificate {
priv, err := rsa.GenerateKey(rand.Reader, 2048)

View File

@@ -2,6 +2,7 @@ package handshake
import (
"crypto/x509"
"io"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/marten-seemann/qtls"
@@ -44,6 +45,7 @@ type CryptoSetup interface {
type CryptoSetupTLS interface {
baseCryptoSetup
io.Closer
HandleMessage([]byte, protocol.EncryptionLevel) bool
OpenInitial(dst, src []byte, pn protocol.PacketNumber, ad []byte) ([]byte, error)
OpenHandshake(dst, src []byte, pn protocol.PacketNumber, ad []byte) ([]byte, error)