github.com/apernet/quic-go@v0.43.1-0.20240515053213-5e9e635fd9f0/integrationtests/self/resumption_test.go (about)

     1  package self_test
     2  
     3  import (
     4  	"context"
     5  	"crypto/tls"
     6  	"fmt"
     7  	"net"
     8  	"time"
     9  
    10  	"github.com/apernet/quic-go"
    11  
    12  	. "github.com/onsi/ginkgo/v2"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  type clientSessionCache struct {
    17  	cache tls.ClientSessionCache
    18  
    19  	gets chan<- string
    20  	puts chan<- string
    21  }
    22  
    23  func newClientSessionCache(cache tls.ClientSessionCache, gets, puts chan<- string) *clientSessionCache {
    24  	return &clientSessionCache{
    25  		cache: cache,
    26  		gets:  gets,
    27  		puts:  puts,
    28  	}
    29  }
    30  
    31  var _ tls.ClientSessionCache = &clientSessionCache{}
    32  
    33  func (c *clientSessionCache) Get(sessionKey string) (*tls.ClientSessionState, bool) {
    34  	session, ok := c.cache.Get(sessionKey)
    35  	if c.gets != nil {
    36  		c.gets <- sessionKey
    37  	}
    38  	return session, ok
    39  }
    40  
    41  func (c *clientSessionCache) Put(sessionKey string, cs *tls.ClientSessionState) {
    42  	c.cache.Put(sessionKey, cs)
    43  	if c.puts != nil {
    44  		c.puts <- sessionKey
    45  	}
    46  }
    47  
    48  var _ = Describe("TLS session resumption", func() {
    49  	It("uses session resumption", func() {
    50  		server, err := quic.ListenAddr("localhost:0", getTLSConfig(), getQuicConfig(nil))
    51  		Expect(err).ToNot(HaveOccurred())
    52  		defer server.Close()
    53  
    54  		gets := make(chan string, 100)
    55  		puts := make(chan string, 100)
    56  		cache := newClientSessionCache(tls.NewLRUClientSessionCache(10), gets, puts)
    57  		tlsConf := getTLSClientConfig()
    58  		tlsConf.ClientSessionCache = cache
    59  		conn1, err := quic.DialAddr(
    60  			context.Background(),
    61  			fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
    62  			tlsConf,
    63  			getQuicConfig(nil),
    64  		)
    65  		Expect(err).ToNot(HaveOccurred())
    66  		defer conn1.CloseWithError(0, "")
    67  		var sessionKey string
    68  		Eventually(puts).Should(Receive(&sessionKey))
    69  		Expect(conn1.ConnectionState().TLS.DidResume).To(BeFalse())
    70  
    71  		serverConn, err := server.Accept(context.Background())
    72  		Expect(err).ToNot(HaveOccurred())
    73  		Expect(serverConn.ConnectionState().TLS.DidResume).To(BeFalse())
    74  
    75  		conn2, err := quic.DialAddr(
    76  			context.Background(),
    77  			fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
    78  			tlsConf,
    79  			getQuicConfig(nil),
    80  		)
    81  		Expect(err).ToNot(HaveOccurred())
    82  		Expect(gets).To(Receive(Equal(sessionKey)))
    83  		Expect(conn2.ConnectionState().TLS.DidResume).To(BeTrue())
    84  
    85  		serverConn, err = server.Accept(context.Background())
    86  		Expect(err).ToNot(HaveOccurred())
    87  		Expect(serverConn.ConnectionState().TLS.DidResume).To(BeTrue())
    88  		conn2.CloseWithError(0, "")
    89  	})
    90  
    91  	It("doesn't use session resumption, if the config disables it", func() {
    92  		sConf := getTLSConfig()
    93  		sConf.SessionTicketsDisabled = true
    94  		server, err := quic.ListenAddr("localhost:0", sConf, getQuicConfig(nil))
    95  		Expect(err).ToNot(HaveOccurred())
    96  		defer server.Close()
    97  
    98  		gets := make(chan string, 100)
    99  		puts := make(chan string, 100)
   100  		cache := newClientSessionCache(tls.NewLRUClientSessionCache(10), gets, puts)
   101  		tlsConf := getTLSClientConfig()
   102  		tlsConf.ClientSessionCache = cache
   103  		conn1, err := quic.DialAddr(
   104  			context.Background(),
   105  			fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
   106  			tlsConf,
   107  			getQuicConfig(nil),
   108  		)
   109  		Expect(err).ToNot(HaveOccurred())
   110  		defer conn1.CloseWithError(0, "")
   111  		Consistently(puts).ShouldNot(Receive())
   112  		Expect(conn1.ConnectionState().TLS.DidResume).To(BeFalse())
   113  
   114  		ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
   115  		defer cancel()
   116  		serverConn, err := server.Accept(ctx)
   117  		Expect(err).ToNot(HaveOccurred())
   118  		Expect(serverConn.ConnectionState().TLS.DidResume).To(BeFalse())
   119  
   120  		conn2, err := quic.DialAddr(
   121  			context.Background(),
   122  			fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
   123  			tlsConf,
   124  			getQuicConfig(nil),
   125  		)
   126  		Expect(err).ToNot(HaveOccurred())
   127  		Expect(conn2.ConnectionState().TLS.DidResume).To(BeFalse())
   128  		defer conn2.CloseWithError(0, "")
   129  
   130  		serverConn, err = server.Accept(context.Background())
   131  		Expect(err).ToNot(HaveOccurred())
   132  		Expect(serverConn.ConnectionState().TLS.DidResume).To(BeFalse())
   133  	})
   134  
   135  	It("doesn't use session resumption, if the config returned by GetConfigForClient disables it", func() {
   136  		sConf := &tls.Config{
   137  			GetConfigForClient: func(*tls.ClientHelloInfo) (*tls.Config, error) {
   138  				conf := getTLSConfig()
   139  				conf.SessionTicketsDisabled = true
   140  				return conf, nil
   141  			},
   142  		}
   143  
   144  		server, err := quic.ListenAddr("localhost:0", sConf, getQuicConfig(nil))
   145  		Expect(err).ToNot(HaveOccurred())
   146  		defer server.Close()
   147  
   148  		gets := make(chan string, 100)
   149  		puts := make(chan string, 100)
   150  		cache := newClientSessionCache(tls.NewLRUClientSessionCache(10), gets, puts)
   151  		tlsConf := getTLSClientConfig()
   152  		tlsConf.ClientSessionCache = cache
   153  		conn1, err := quic.DialAddr(
   154  			context.Background(),
   155  			fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
   156  			tlsConf,
   157  			getQuicConfig(nil),
   158  		)
   159  		Expect(err).ToNot(HaveOccurred())
   160  		Consistently(puts).ShouldNot(Receive())
   161  		Expect(conn1.ConnectionState().TLS.DidResume).To(BeFalse())
   162  		defer conn1.CloseWithError(0, "")
   163  
   164  		ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
   165  		defer cancel()
   166  		serverConn, err := server.Accept(ctx)
   167  		Expect(err).ToNot(HaveOccurred())
   168  		Expect(serverConn.ConnectionState().TLS.DidResume).To(BeFalse())
   169  
   170  		conn2, err := quic.DialAddr(
   171  			context.Background(),
   172  			fmt.Sprintf("localhost:%d", server.Addr().(*net.UDPAddr).Port),
   173  			tlsConf,
   174  			getQuicConfig(nil),
   175  		)
   176  		Expect(err).ToNot(HaveOccurred())
   177  		Expect(conn2.ConnectionState().TLS.DidResume).To(BeFalse())
   178  		defer conn2.CloseWithError(0, "")
   179  
   180  		serverConn, err = server.Accept(context.Background())
   181  		Expect(err).ToNot(HaveOccurred())
   182  		Expect(serverConn.ConnectionState().TLS.DidResume).To(BeFalse())
   183  	})
   184  })