世界 пре 2 година
родитељ
комит
120dae4eed

+ 2 - 1
adapter/fakeip.go

@@ -10,7 +10,7 @@ import (
 type FakeIPStore interface {
 	Service
 	Contains(address netip.Addr) bool
-	Create(domain string, strategy dns.DomainStrategy) (netip.Addr, error)
+	Create(domain string, isIPv6 bool) (netip.Addr, error)
 	Lookup(address netip.Addr) (string, bool)
 	Reset() error
 }
@@ -21,6 +21,7 @@ type FakeIPStorage interface {
 	FakeIPStore(address netip.Addr, domain string) error
 	FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger)
 	FakeIPLoad(address netip.Addr) (string, bool)
+	FakeIPLoadDomain(domain string, isIPv6 bool) (netip.Addr, bool)
 	FakeIPReset() error
 }
 

+ 45 - 4
experimental/clashapi/cachefile/fakeip.go

@@ -6,13 +6,16 @@ import (
 
 	"github.com/sagernet/sing-box/adapter"
 	"github.com/sagernet/sing/common/logger"
+	M "github.com/sagernet/sing/common/metadata"
 
 	"go.etcd.io/bbolt"
 )
 
 var (
-	bucketFakeIP = []byte("fakeip")
-	keyMetadata  = []byte("metadata")
+	bucketFakeIP        = []byte("fakeip")
+	bucketFakeIPDomain4 = []byte("fakeip_domain4")
+	bucketFakeIPDomain6 = []byte("fakeip_domain6")
+	keyMetadata         = []byte("metadata")
 )
 
 func (c *CacheFile) FakeIPMetadata() *adapter.FakeIPMetadata {
@@ -54,7 +57,19 @@ func (c *CacheFile) FakeIPStore(address netip.Addr, domain string) error {
 		if err != nil {
 			return err
 		}
-		return bucket.Put(address.AsSlice(), []byte(domain))
+		err = bucket.Put(address.AsSlice(), []byte(domain))
+		if err != nil {
+			return err
+		}
+		if address.Is4() {
+			bucket, err = tx.CreateBucketIfNotExists(bucketFakeIPDomain4)
+		} else {
+			bucket, err = tx.CreateBucketIfNotExists(bucketFakeIPDomain6)
+		}
+		if err != nil {
+			return err
+		}
+		return bucket.Put([]byte(domain), address.AsSlice())
 	})
 }
 
@@ -92,8 +107,34 @@ func (c *CacheFile) FakeIPLoad(address netip.Addr) (string, bool) {
 	return domain, domain != ""
 }
 
+func (c *CacheFile) FakeIPLoadDomain(domain string, isIPv6 bool) (netip.Addr, bool) {
+	var address netip.Addr
+	_ = c.DB.View(func(tx *bbolt.Tx) error {
+		var bucket *bbolt.Bucket
+		if isIPv6 {
+			bucket = tx.Bucket(bucketFakeIPDomain6)
+		} else {
+			bucket = tx.Bucket(bucketFakeIPDomain4)
+		}
+		if bucket == nil {
+			return nil
+		}
+		address = M.AddrFromIP(bucket.Get([]byte(domain)))
+		return nil
+	})
+	return address, address.IsValid()
+}
+
 func (c *CacheFile) FakeIPReset() error {
 	return c.DB.Batch(func(tx *bbolt.Tx) error {
-		return tx.DeleteBucket(bucketFakeIP)
+		err := tx.DeleteBucket(bucketFakeIP)
+		if err != nil {
+			return err
+		}
+		err = tx.DeleteBucket(bucketFakeIPDomain4)
+		if err != nil {
+			return err
+		}
+		return tx.DeleteBucket(bucketFakeIPDomain6)
 	})
 }

+ 40 - 10
transport/fakeip/memory.go

@@ -2,48 +2,78 @@ package fakeip
 
 import (
 	"net/netip"
+	"sync"
 
 	"github.com/sagernet/sing-box/adapter"
-	"github.com/sagernet/sing/common/cache"
 	"github.com/sagernet/sing/common/logger"
 )
 
 var _ adapter.FakeIPStorage = (*MemoryStorage)(nil)
 
 type MemoryStorage struct {
-	metadata    *adapter.FakeIPMetadata
-	domainCache *cache.LruCache[netip.Addr, string]
+	addressAccess sync.RWMutex
+	domainAccess  sync.RWMutex
+	addressCache  map[netip.Addr]string
+	domainCache4  map[string]netip.Addr
+	domainCache6  map[string]netip.Addr
 }
 
 func NewMemoryStorage() *MemoryStorage {
 	return &MemoryStorage{
-		domainCache: cache.New[netip.Addr, string](),
+		addressCache: make(map[netip.Addr]string),
+		domainCache4: make(map[string]netip.Addr),
+		domainCache6: make(map[string]netip.Addr),
 	}
 }
 
 func (s *MemoryStorage) FakeIPMetadata() *adapter.FakeIPMetadata {
-	return s.metadata
+	return nil
 }
 
 func (s *MemoryStorage) FakeIPSaveMetadata(metadata *adapter.FakeIPMetadata) error {
-	s.metadata = metadata
 	return nil
 }
 
 func (s *MemoryStorage) FakeIPStore(address netip.Addr, domain string) error {
-	s.domainCache.Store(address, domain)
+	s.addressAccess.Lock()
+	s.domainAccess.Lock()
+	s.addressCache[address] = domain
+	if address.Is4() {
+		s.domainCache4[domain] = address
+	} else {
+		s.domainCache6[domain] = address
+	}
+	s.domainAccess.Unlock()
+	s.addressAccess.Unlock()
 	return nil
 }
 
 func (s *MemoryStorage) FakeIPStoreAsync(address netip.Addr, domain string, logger logger.Logger) {
-	s.domainCache.Store(address, domain)
+	_ = s.FakeIPStore(address, domain)
 }
 
 func (s *MemoryStorage) FakeIPLoad(address netip.Addr) (string, bool) {
-	return s.domainCache.Load(address)
+	s.addressAccess.RLock()
+	defer s.addressAccess.RUnlock()
+	domain, loaded := s.addressCache[address]
+	return domain, loaded
+}
+
+func (s *MemoryStorage) FakeIPLoadDomain(domain string, isIPv6 bool) (netip.Addr, bool) {
+	s.domainAccess.RLock()
+	defer s.domainAccess.RUnlock()
+	if !isIPv6 {
+		address, loaded := s.domainCache4[domain]
+		return address, loaded
+	} else {
+		address, loaded := s.domainCache6[domain]
+		return address, loaded
+	}
 }
 
 func (s *MemoryStorage) FakeIPReset() error {
-	s.domainCache = cache.New[netip.Addr, string]()
+	s.addressCache = make(map[netip.Addr]string)
+	s.domainCache4 = make(map[string]netip.Addr)
+	s.domainCache6 = make(map[string]netip.Addr)
 	return nil
 }

+ 2 - 2
transport/fakeip/server.go

@@ -69,14 +69,14 @@ func (s *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg,
 func (s *Transport) Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error) {
 	var addresses []netip.Addr
 	if strategy != dns.DomainStrategyUseIPv6 {
-		inet4Address, err := s.store.Create(domain, dns.DomainStrategyUseIPv4)
+		inet4Address, err := s.store.Create(domain, false)
 		if err != nil {
 			return nil, err
 		}
 		addresses = append(addresses, inet4Address)
 	}
 	if strategy != dns.DomainStrategyUseIPv4 {
-		inet6Address, err := s.store.Create(domain, dns.DomainStrategyUseIPv6)
+		inet6Address, err := s.store.Create(domain, true)
 		if err != nil {
 			return nil, err
 		}

+ 5 - 3
transport/fakeip/store.go

@@ -4,7 +4,6 @@ import (
 	"net/netip"
 
 	"github.com/sagernet/sing-box/adapter"
-	"github.com/sagernet/sing-dns"
 	E "github.com/sagernet/sing/common/exceptions"
 	"github.com/sagernet/sing/common/logger"
 )
@@ -72,9 +71,12 @@ func (s *Store) Close() error {
 	})
 }
 
-func (s *Store) Create(domain string, strategy dns.DomainStrategy) (netip.Addr, error) {
+func (s *Store) Create(domain string, isIPv6 bool) (netip.Addr, error) {
+	if address, loaded := s.storage.FakeIPLoadDomain(domain, isIPv6); loaded {
+		return address, nil
+	}
 	var address netip.Addr
-	if strategy == dns.DomainStrategyUseIPv4 {
+	if !isIPv6 {
 		if !s.inet4Current.IsValid() {
 			return netip.Addr{}, E.New("missing IPv4 fakeip address range")
 		}