package corebin import ( "os" "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 } // 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). func Invalidate() { mu.Lock() cache = map[string]string{} mu.Unlock() } // Resolve caches the result of fn under key. Stale paths (missing on disk) are refreshed. func Resolve(key string, fn func() (string, error)) (string, error) { if path, ok := Get(key); ok { if _, err := os.Stat(path); err == nil { return path, nil } mu.Lock() delete(cache, key) mu.Unlock() } 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" } }