github.com/sagernet/quic-go@v0.43.1-beta.1/internal/qtls_ech/client_session_cache.go (about)

     1  //go:build go1.21
     2  
     3  package qtls
     4  
     5  import (
     6  	"sync"
     7  
     8  	"github.com/sagernet/cloudflare-tls"
     9  )
    10  
    11  type clientSessionCache struct {
    12  	mx      sync.Mutex
    13  	getData func(earlyData bool) []byte
    14  	setData func(data []byte, earlyData bool) (allowEarlyData bool)
    15  	wrapped tls.ClientSessionCache
    16  }
    17  
    18  var _ tls.ClientSessionCache = &clientSessionCache{}
    19  
    20  func (c *clientSessionCache) Put(key string, cs *tls.ClientSessionState) {
    21  	c.mx.Lock()
    22  	defer c.mx.Unlock()
    23  
    24  	if cs == nil {
    25  		c.wrapped.Put(key, nil)
    26  		return
    27  	}
    28  	ticket, state, err := cs.ResumptionState()
    29  	if err != nil || state == nil {
    30  		c.wrapped.Put(key, cs)
    31  		return
    32  	}
    33  	state.Extra = append(state.Extra, addExtraPrefix(c.getData(state.EarlyData)))
    34  	newCS, err := tls.NewResumptionState(ticket, state)
    35  	if err != nil {
    36  		// It's not clear why this would error. Just save the original state.
    37  		c.wrapped.Put(key, cs)
    38  		return
    39  	}
    40  	c.wrapped.Put(key, newCS)
    41  }
    42  
    43  func (c *clientSessionCache) Get(key string) (*tls.ClientSessionState, bool) {
    44  	c.mx.Lock()
    45  	defer c.mx.Unlock()
    46  
    47  	cs, ok := c.wrapped.Get(key)
    48  	if !ok || cs == nil {
    49  		return cs, ok
    50  	}
    51  	ticket, state, err := cs.ResumptionState()
    52  	if err != nil {
    53  		// It's not clear why this would error.
    54  		// Remove the ticket from the session cache, so we don't run into this error over and over again
    55  		c.wrapped.Put(key, nil)
    56  		return nil, false
    57  	}
    58  	// restore QUIC transport parameters and RTT stored in state.Extra
    59  	if extra := findExtraData(state.Extra); extra != nil {
    60  		earlyData := c.setData(extra, state.EarlyData)
    61  		if state.EarlyData {
    62  			state.EarlyData = earlyData
    63  		}
    64  	}
    65  	session, err := tls.NewResumptionState(ticket, state)
    66  	if err != nil {
    67  		// It's not clear why this would error.
    68  		// Remove the ticket from the session cache, so we don't run into this error over and over again
    69  		c.wrapped.Put(key, nil)
    70  		return nil, false
    71  	}
    72  	return session, true
    73  }