mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-07-05 09:34:14 +00:00
Fix nil panic
This commit is contained in:
parent
16450c57b5
commit
69cff7027e
1 changed files with 13 additions and 11 deletions
|
@ -77,8 +77,9 @@ func ApplyECH(c *Config, config *tls.Config) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ECHConfigCache struct {
|
type ECHConfigCache struct {
|
||||||
echConfig atomic.Pointer[[]byte]
|
echConfig atomic.Pointer[[]byte]
|
||||||
expire *time.Time
|
expire atomic.Pointer[time.Time]
|
||||||
|
// updateLock is not for preventing concurrent read/write, but for preventing concurrent update
|
||||||
updateLock sync.Mutex
|
updateLock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +87,7 @@ func (c *ECHConfigCache) update(domain string, server string) ([]byte, error) {
|
||||||
c.updateLock.Lock()
|
c.updateLock.Lock()
|
||||||
defer c.updateLock.Unlock()
|
defer c.updateLock.Unlock()
|
||||||
// Double check cache after acquiring lock
|
// Double check cache after acquiring lock
|
||||||
if c.expire.After(time.Now()) {
|
if c.expire.Load().After(time.Now()) {
|
||||||
errors.LogDebug(context.Background(), "Cache hit for domain after double check: ", domain)
|
errors.LogDebug(context.Background(), "Cache hit for domain after double check: ", domain)
|
||||||
return *c.echConfig.Load(), nil
|
return *c.echConfig.Load(), nil
|
||||||
}
|
}
|
||||||
|
@ -98,7 +99,7 @@ func (c *ECHConfigCache) update(domain string, server string) ([]byte, error) {
|
||||||
}
|
}
|
||||||
c.echConfig.Store(&echConfig)
|
c.echConfig.Store(&echConfig)
|
||||||
expire := time.Now().Add(time.Duration(ttl) * time.Second)
|
expire := time.Now().Add(time.Duration(ttl) * time.Second)
|
||||||
c.expire = &expire
|
c.expire.Store(&expire)
|
||||||
return *c.echConfig.Load(), nil
|
return *c.echConfig.Load(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,20 +118,21 @@ func QueryRecord(domain string, server string) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
echConfigCache := GlobalECHConfigCache[domain]
|
echConfigCache := GlobalECHConfigCache[domain]
|
||||||
if echConfigCache != nil && echConfigCache.expire.After(time.Now()) {
|
if echConfigCache == nil {
|
||||||
|
echConfigCache = &ECHConfigCache{}
|
||||||
|
echConfigCache.expire.Store(&time.Time{}) // zero value means initial state
|
||||||
|
GlobalECHConfigCache[domain] = echConfigCache
|
||||||
|
}
|
||||||
|
if echConfigCache != nil && echConfigCache.expire.Load().After(time.Now()) {
|
||||||
errors.LogDebug(context.Background(), "Cache hit for domain: ", domain)
|
errors.LogDebug(context.Background(), "Cache hit for domain: ", domain)
|
||||||
GlobalECHConfigCacheAccess.Unlock()
|
GlobalECHConfigCacheAccess.Unlock()
|
||||||
return *echConfigCache.echConfig.Load(), nil
|
return *echConfigCache.echConfig.Load(), nil
|
||||||
}
|
}
|
||||||
if echConfigCache == nil {
|
|
||||||
echConfigCache = &ECHConfigCache{}
|
|
||||||
GlobalECHConfigCache[domain] = echConfigCache
|
|
||||||
}
|
|
||||||
GlobalECHConfigCacheAccess.Unlock()
|
GlobalECHConfigCacheAccess.Unlock()
|
||||||
|
|
||||||
// If expire is nil, it means we are in initial state, wait for the query to finish
|
// If expire is zero value, it means we are in initial state, wait for the query to finish
|
||||||
// otherwise return old value immediately and update in a goroutine
|
// otherwise return old value immediately and update in a goroutine
|
||||||
if echConfigCache.expire == nil {
|
if *echConfigCache.expire.Load() == (time.Time{}) {
|
||||||
return echConfigCache.update(domain, server)
|
return echConfigCache.update(domain, server)
|
||||||
} else {
|
} else {
|
||||||
// If someone already acquired the lock, it means it is updating, do not start another update goroutine
|
// If someone already acquired the lock, it means it is updating, do not start another update goroutine
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue