mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-07-04 02:38:42 +00:00
86 lines
2.1 KiB
Go
86 lines
2.1 KiB
Go
package tls
|
|
|
|
import (
|
|
"context"
|
|
"slices"
|
|
"sync"
|
|
"time"
|
|
"unsafe"
|
|
|
|
"github.com/xtls/xray-core/common/errors"
|
|
"github.com/xtls/xray-core/common/ocsp"
|
|
"github.com/xtls/xray-core/common/platform/filesystem"
|
|
"github.com/xtls/xray-core/common/utils"
|
|
)
|
|
|
|
var certsCache = utils.NewWeakCacheMap[uintptr, Certificate]()
|
|
|
|
var startHotReload sync.Once
|
|
|
|
func setupHotReload(entry *Certificate) {
|
|
startHotReload.Do(func() {
|
|
go handleHotReload()
|
|
})
|
|
// ensure the cache before use
|
|
entry.getX509KeyPair()
|
|
if entry.OneTimeLoading {
|
|
return
|
|
}
|
|
uptr := uintptr(unsafe.Pointer(entry))
|
|
if _, ok := certsCache.Load(uptr); !ok {
|
|
certsCache.Store(uptr, entry)
|
|
}
|
|
}
|
|
|
|
func handleHotReload() {
|
|
// should be enough?
|
|
t := time.NewTicker(600 * time.Second)
|
|
for {
|
|
certsCache.Range(updateCert)
|
|
<-t.C
|
|
}
|
|
}
|
|
|
|
func updateCert(_ uintptr, entry *Certificate) bool {
|
|
extraData := entry.extraData()
|
|
reloadInterval := int64(entry.OcspStapling)
|
|
if reloadInterval <= 0 {
|
|
reloadInterval = 3600
|
|
}
|
|
if extraData.lastReload+reloadInterval >= time.Now().Unix() {
|
|
return true
|
|
} else {
|
|
extraData.lastReload = time.Now().Unix()
|
|
}
|
|
if entry.CertificatePath != "" && entry.KeyPath != "" {
|
|
newCert, err := filesystem.ReadCert(entry.CertificatePath)
|
|
if err != nil {
|
|
errors.LogErrorInner(context.Background(), err, "failed to parse certificate")
|
|
return true
|
|
}
|
|
newKey, err := filesystem.ReadCert(entry.KeyPath)
|
|
if err != nil {
|
|
errors.LogErrorInner(context.Background(), err, "failed to parse key")
|
|
return true
|
|
}
|
|
if string(newCert) != string(entry.Certificate) || string(newKey) != string(entry.Key) {
|
|
entry.Certificate = newCert
|
|
entry.Key = newKey
|
|
}
|
|
}
|
|
entry.parseX509KeyPair()
|
|
if entry.OcspStapling > 0 {
|
|
keyPair := entry.getX509KeyPair()
|
|
if keyPair == nil {
|
|
return true
|
|
}
|
|
if newOCSPData, err := ocsp.GetOCSPForCert(keyPair.Certificate); err != nil {
|
|
errors.LogWarningInner(context.Background(), err, "ignoring invalid OCSP")
|
|
} else if OCSPData := extraData.ocspData.Load(); OCSPData == nil || !slices.Equal(newOCSPData, *OCSPData) {
|
|
extraData.ocspData.Store(&newOCSPData)
|
|
}
|
|
entry.parseX509KeyPair()
|
|
}
|
|
return true
|
|
}
|