package utils import ( "crypto/tls" "sync" "time" ) type CertCache struct { syncLock *sync.RWMutex certs map[string]*certCacheItem } func NewCertCache() *CertCache { return &CertCache{&sync.RWMutex{}, make(map[string]*certCacheItem)} } func (cc *CertCache) Put(domain string, cert *tls.Certificate) { cc.syncLock.Lock() a, ok := cc.certs[domain] if ok { a.tick.Stop() close(a.end) delete(cc.certs, domain) } // Set up a ticker and timeout value i := &certCacheItem{cert, time.NewTicker(time.Minute * 10), make(chan struct{})} go cc.internalItemTick(domain, i) cc.certs[domain] = i cc.syncLock.Unlock() } func (cc *CertCache) Get(domain string) (*tls.Certificate, bool) { cc.syncLock.RLock() c, ok := cc.certs[domain] cc.syncLock.RUnlock() if ok { return c.cert, ok } return nil, false } func (cc *CertCache) Del(domain string) { cc.syncLock.Lock() a, ok := cc.certs[domain] if ok { a.tick.Stop() close(a.end) } delete(cc.certs, domain) cc.syncLock.Unlock() } func (cc *CertCache) internalItemTick(domain string, item *certCacheItem) { select { case <-item.tick.C: cc.Del(domain) case <-item.end: } } type certCacheItem struct { cert *tls.Certificate tick *time.Ticker end chan struct{} }