From cbf6133145e2aa95714c75b23d3e0a003f9060bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sat, 8 Jul 2023 16:08:46 +0800 Subject: [PATCH] Fix async FakeIP save --- adapter/fakeip.go | 2 ++ experimental/clashapi/cachefile/cache.go | 14 ++++++++++--- experimental/clashapi/cachefile/fakeip.go | 24 +++++++++++++++++++++++ route/router.go | 2 +- transport/fakeip/memory.go | 5 +++++ transport/fakeip/store.go | 7 +------ 6 files changed, 44 insertions(+), 10 deletions(-) diff --git a/adapter/fakeip.go b/adapter/fakeip.go index 6854bebcd5..4ce2b28a0a 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 5d80505255..e2ef364d32 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 2c0965562a..14ba741798 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" ) @@ -14,6 +15,8 @@ var ( keyMetadata = []byte("metadata") ) +var _ adapter.ClashCacheFile = (*CacheFile)(nil) + func (c *CacheFile) FakeIPMetadata() *adapter.FakeIPMetadata { var metadata adapter.FakeIPMetadata err := c.DB.View(func(tx *bbolt.Tx) error { @@ -57,7 +60,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/route/router.go b/route/router.go index c23c8a458e..84a7050d46 100644 --- a/route/router.go +++ b/route/router.go @@ -252,7 +252,7 @@ func NewRouter( if fakeIPOptions.Inet6Range != nil { inet6Range = fakeIPOptions.Inet6Range.Build() } - router.fakeIPStore = fakeip.NewStore(router, router.logger, inet4Range, inet6Range) + router.fakeIPStore = fakeip.NewStore(router, inet4Range, inet6Range) } usePlatformDefaultInterfaceMonitor := platformInterface != nil && platformInterface.UsePlatformDefaultInterfaceMonitor() diff --git a/transport/fakeip/memory.go b/transport/fakeip/memory.go index 61674f4c0a..cb60d251fc 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 c731979ec3..973da60bec 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 }