Trust corebin cache without Stat; batch networksetup; ActiveProxyURI instead of Config.Clone. Co-authored-by: Cursor <cursoragent@cursor.com>
76 lines
1.6 KiB
Go
76 lines
1.6 KiB
Go
package corebin
|
|
|
|
import (
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
var (
|
|
mu sync.Mutex
|
|
cache = map[string]string{}
|
|
)
|
|
|
|
// CacheKey identifies a resolved core binary for a binDir + protocol.
|
|
func CacheKey(binDir, proto string) string {
|
|
return binDir + "\x00" + proto
|
|
}
|
|
|
|
// VirtualPath reports paths that are not on-disk binaries (e.g. embedded AWG).
|
|
func VirtualPath(path string) bool {
|
|
return strings.HasPrefix(path, "embedded-")
|
|
}
|
|
|
|
// Get returns a cached absolute path if present.
|
|
func Get(key string) (string, bool) {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
p, ok := cache[key]
|
|
return p, ok
|
|
}
|
|
|
|
// Set stores a resolved path.
|
|
func Set(key, path string) {
|
|
if key == "" || path == "" {
|
|
return
|
|
}
|
|
mu.Lock()
|
|
cache[key] = path
|
|
mu.Unlock()
|
|
}
|
|
|
|
// Invalidate clears all cached paths (call after EnsureCore / binDir change / failed Start).
|
|
func Invalidate() {
|
|
mu.Lock()
|
|
cache = map[string]string{}
|
|
mu.Unlock()
|
|
}
|
|
|
|
// Resolve caches the result of fn under key.
|
|
// Hot-path polls trust the cache until Invalidate (no per-poll os.Stat).
|
|
// Embedded/virtual paths never touch the filesystem.
|
|
func Resolve(key string, fn func() (string, error)) (string, error) {
|
|
if path, ok := Get(key); ok {
|
|
return path, nil
|
|
}
|
|
path, err := fn()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
Set(key, path)
|
|
return path, nil
|
|
}
|
|
|
|
// ProtoKey normalizes protocol to the shared binary cache key (xray covers vless/vmess/trojan).
|
|
func ProtoKey(proto string) string {
|
|
switch proto {
|
|
case "hysteria2":
|
|
return "hysteria2"
|
|
case "awg":
|
|
return "awg"
|
|
case "vless", "vmess", "trojan", "xray":
|
|
return "xray"
|
|
default:
|
|
return "naive"
|
|
}
|
|
}
|