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

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