diff --git a/adapter/fakeip.go b/adapter/fakeip.go index 6854bebc..4ce2b28a 100644 --- a/adapter/fakeip.go +++ b/adapter/fakeip.go @@ -4,6 +4,7 @@ import ( "net/netip" "github.com/sagernet/sing-dns" + "github.com/sagernet/sing/common/logger" ) type FakeIPStore interface { @@ -18,6 +19,7 @@ type FakeIPStorage interface { FakeIPMetadata() *FakeIPMetadata FakeIPSaveMetadata(metadata *FakeIPMetadata) error FakeIPStore(address netip.Addr, domain string) error + FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger) FakeIPLoad(address netip.Addr) (string, bool) FakeIPReset() error } diff --git a/experimental/clashapi/cachefile/cache.go b/experimental/clashapi/cachefile/cache.go index 5d805052..e2ef364d 100644 --- a/experimental/clashapi/cachefile/cache.go +++ b/experimental/clashapi/cachefile/cache.go @@ -1,7 +1,9 @@ package cachefile import ( + "net/netip" "os" + "sync" "time" "github.com/sagernet/sing-box/adapter" @@ -14,8 +16,10 @@ var bucketSelected = []byte("selected") var _ adapter.ClashCacheFile = (*CacheFile)(nil) type CacheFile struct { - DB *bbolt.DB - cacheID []byte + DB *bbolt.DB + cacheID []byte + saveAccess sync.RWMutex + saveCache map[netip.Addr]string } func Open(path string, cacheID string) (*CacheFile, error) { @@ -36,7 +40,11 @@ func Open(path string, cacheID string) (*CacheFile, error) { if cacheID != "" { cacheIDBytes = append([]byte{0}, []byte(cacheID)...) } - return &CacheFile{db, cacheIDBytes}, nil + return &CacheFile{ + DB: db, + cacheID: cacheIDBytes, + saveCache: make(map[netip.Addr]string), + }, nil } func (c *CacheFile) bucket(t *bbolt.Tx, key []byte) *bbolt.Bucket { diff --git a/experimental/clashapi/cachefile/fakeip.go b/experimental/clashapi/cachefile/fakeip.go index 2c096556..7d455ccb 100644 --- a/experimental/clashapi/cachefile/fakeip.go +++ b/experimental/clashapi/cachefile/fakeip.go @@ -5,6 +5,7 @@ import ( "os" "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing/common/logger" "go.etcd.io/bbolt" ) @@ -57,7 +58,28 @@ func (c *CacheFile) FakeIPStore(address netip.Addr, domain string) error { }) } +func (c *CacheFile) FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger) { + c.saveAccess.Lock() + c.saveCache[address] = domain + c.saveAccess.Unlock() + go func() { + err := c.FakeIPStore(address, domain) + if err != nil { + logger.Warn("save FakeIP address pair: ", err) + } + c.saveAccess.Lock() + delete(c.saveCache, address) + c.saveAccess.Unlock() + }() +} + func (c *CacheFile) FakeIPLoad(address netip.Addr) (string, bool) { + c.saveAccess.RLock() + cachedDomain, cached := c.saveCache[address] + c.saveAccess.RUnlock() + if cached { + return cachedDomain, true + } var domain string _ = c.DB.View(func(tx *bbolt.Tx) error { bucket := tx.Bucket(bucketFakeIP) diff --git a/transport/fakeip/memory.go b/transport/fakeip/memory.go index 61674f4c..cb60d251 100644 --- a/transport/fakeip/memory.go +++ b/transport/fakeip/memory.go @@ -5,6 +5,7 @@ import ( "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing/common/cache" + "github.com/sagernet/sing/common/logger" ) var _ adapter.FakeIPStorage = (*MemoryStorage)(nil) @@ -34,6 +35,10 @@ func (s *MemoryStorage) FakeIPStore(address netip.Addr, domain string) error { return nil } +func (s *MemoryStorage) FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger) { + s.domainCache.Store(address, domain) +} + func (s *MemoryStorage) FakeIPLoad(address netip.Addr) (string, bool) { return s.domainCache.Load(address) } diff --git a/transport/fakeip/store.go b/transport/fakeip/store.go index c731979e..973da60b 100644 --- a/transport/fakeip/store.go +++ b/transport/fakeip/store.go @@ -95,12 +95,7 @@ func (s *Store) Create(domain string, strategy dns.DomainStrategy) (netip.Addr, s.inet6Current = nextAddress address = nextAddress } - go func() { - err := s.storage.FakeIPStore(address, domain) - if err != nil { - s.logger.Warn("save FakeIP address pair: ", err) - } - }() + s.storage.FakeIPStoreAsync(address, domain, s.logger) return address, nil }