| // Copyright 2022 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package tls |
| |
| import ( |
| "crypto/x509" |
| "runtime" |
| "sync" |
| "weak" |
| ) |
| |
| // weakCertCache provides a cache of *x509.Certificates, allowing multiple |
| // connections to reuse parsed certificates, instead of re-parsing the |
| // certificate for every connection, which is an expensive operation. |
| type weakCertCache struct{ sync.Map } |
| |
| func (wcc *weakCertCache) newCert(der []byte) (*x509.Certificate, error) { |
| if entry, ok := wcc.Load(string(der)); ok { |
| if v := entry.(weak.Pointer[x509.Certificate]).Value(); v != nil { |
| return v, nil |
| } |
| } |
| |
| cert, err := x509.ParseCertificate(der) |
| if err != nil { |
| return nil, err |
| } |
| |
| wp := weak.Make(cert) |
| if entry, loaded := wcc.LoadOrStore(string(der), wp); !loaded { |
| runtime.AddCleanup(cert, func(_ any) { wcc.CompareAndDelete(string(der), entry) }, any(string(der))) |
| } else if v := entry.(weak.Pointer[x509.Certificate]).Value(); v != nil { |
| return v, nil |
| } else { |
| if wcc.CompareAndSwap(string(der), entry, wp) { |
| runtime.AddCleanup(cert, func(_ any) { wcc.CompareAndDelete(string(der), wp) }, any(string(der))) |
| } |
| } |
| return cert, nil |
| } |
| |
| var globalCertCache = new(weakCertCache) |