github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/internal/qtls/client_session_cache_test.go (about)

     1  //go:build go1.21
     2  
     3  package qtls
     4  
     5  import (
     6  	"crypto/tls"
     7  	"fmt"
     8  	"net"
     9  
    10  	"github.com/metacubex/quic-go/internal/testdata"
    11  
    12  	. "github.com/onsi/ginkgo/v2"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  var _ = Describe("Client Session Cache", func() {
    17  	It("adds data to and restores data from a session ticket", func() {
    18  		ln, err := tls.Listen("tcp4", "localhost:0", testdata.GetTLSConfig())
    19  		Expect(err).ToNot(HaveOccurred())
    20  
    21  		done := make(chan struct{})
    22  		go func() {
    23  			defer GinkgoRecover()
    24  			defer close(done)
    25  
    26  			for {
    27  				conn, err := ln.Accept()
    28  				if err != nil {
    29  					return
    30  				}
    31  				_, err = conn.Read(make([]byte, 10))
    32  				Expect(err).ToNot(HaveOccurred())
    33  				_, err = conn.Write([]byte("foobar"))
    34  				Expect(err).ToNot(HaveOccurred())
    35  			}
    36  		}()
    37  
    38  		restored := make(chan []byte, 1)
    39  		clientConf := &tls.Config{
    40  			RootCAs: testdata.GetRootCA(),
    41  			ClientSessionCache: &clientSessionCache{
    42  				wrapped: tls.NewLRUClientSessionCache(10),
    43  				getData: func(bool) []byte { return []byte("session") },
    44  				setData: func(data []byte, earlyData bool) bool {
    45  					Expect(earlyData).To(BeFalse()) // running on top of TCP, we can only test non-0-RTT here
    46  					restored <- data
    47  					return true
    48  				},
    49  			},
    50  		}
    51  		conn, err := tls.Dial(
    52  			"tcp4",
    53  			fmt.Sprintf("localhost:%d", ln.Addr().(*net.TCPAddr).Port),
    54  			clientConf,
    55  		)
    56  		Expect(err).ToNot(HaveOccurred())
    57  		_, err = conn.Write([]byte("foobar"))
    58  		Expect(err).ToNot(HaveOccurred())
    59  		Expect(conn.ConnectionState().DidResume).To(BeFalse())
    60  		Expect(restored).To(HaveLen(0))
    61  		_, err = conn.Read(make([]byte, 10))
    62  		Expect(err).ToNot(HaveOccurred())
    63  		Expect(conn.Close()).To(Succeed())
    64  
    65  		// make sure the cache can deal with nonsensical inputs
    66  		clientConf.ClientSessionCache.Put("foo", nil)
    67  		clientConf.ClientSessionCache.Put("bar", &tls.ClientSessionState{})
    68  
    69  		conn, err = tls.Dial(
    70  			"tcp4",
    71  			fmt.Sprintf("localhost:%d", ln.Addr().(*net.TCPAddr).Port),
    72  			clientConf,
    73  		)
    74  		Expect(err).ToNot(HaveOccurred())
    75  		_, err = conn.Write([]byte("foobar"))
    76  		Expect(err).ToNot(HaveOccurred())
    77  		Expect(conn.ConnectionState().DidResume).To(BeTrue())
    78  		var restoredData []byte
    79  		Expect(restored).To(Receive(&restoredData))
    80  		Expect(restoredData).To(Equal([]byte("session")))
    81  		Expect(conn.Close()).To(Succeed())
    82  
    83  		Expect(ln.Close()).To(Succeed())
    84  		Eventually(done).Should(BeClosed())
    85  	})
    86  })