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 }