github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/transport/fakeip/store.go (about)

     1  package fakeip
     2  
     3  import (
     4  	"net/netip"
     5  
     6  	"github.com/inazumav/sing-box/adapter"
     7  	E "github.com/sagernet/sing/common/exceptions"
     8  	"github.com/sagernet/sing/common/logger"
     9  )
    10  
    11  var _ adapter.FakeIPStore = (*Store)(nil)
    12  
    13  type Store struct {
    14  	router       adapter.Router
    15  	logger       logger.Logger
    16  	inet4Range   netip.Prefix
    17  	inet6Range   netip.Prefix
    18  	storage      adapter.FakeIPStorage
    19  	inet4Current netip.Addr
    20  	inet6Current netip.Addr
    21  }
    22  
    23  func NewStore(router adapter.Router, logger logger.Logger, inet4Range netip.Prefix, inet6Range netip.Prefix) *Store {
    24  	return &Store{
    25  		router:     router,
    26  		logger:     logger,
    27  		inet4Range: inet4Range,
    28  		inet6Range: inet6Range,
    29  	}
    30  }
    31  
    32  func (s *Store) Start() error {
    33  	var storage adapter.FakeIPStorage
    34  	if clashServer := s.router.ClashServer(); clashServer != nil && clashServer.StoreFakeIP() {
    35  		if cacheFile := clashServer.CacheFile(); cacheFile != nil {
    36  			storage = cacheFile
    37  		}
    38  	}
    39  	if storage == nil {
    40  		storage = NewMemoryStorage()
    41  	}
    42  	metadata := storage.FakeIPMetadata()
    43  	if metadata != nil && metadata.Inet4Range == s.inet4Range && metadata.Inet6Range == s.inet6Range {
    44  		s.inet4Current = metadata.Inet4Current
    45  		s.inet6Current = metadata.Inet6Current
    46  	} else {
    47  		if s.inet4Range.IsValid() {
    48  			s.inet4Current = s.inet4Range.Addr().Next().Next()
    49  		}
    50  		if s.inet6Range.IsValid() {
    51  			s.inet6Current = s.inet6Range.Addr().Next().Next()
    52  		}
    53  		_ = storage.FakeIPReset()
    54  	}
    55  	s.storage = storage
    56  	return nil
    57  }
    58  
    59  func (s *Store) Contains(address netip.Addr) bool {
    60  	return s.inet4Range.Contains(address) || s.inet6Range.Contains(address)
    61  }
    62  
    63  func (s *Store) Close() error {
    64  	if s.storage == nil {
    65  		return nil
    66  	}
    67  	return s.storage.FakeIPSaveMetadata(&adapter.FakeIPMetadata{
    68  		Inet4Range:   s.inet4Range,
    69  		Inet6Range:   s.inet6Range,
    70  		Inet4Current: s.inet4Current,
    71  		Inet6Current: s.inet6Current,
    72  	})
    73  }
    74  
    75  func (s *Store) Create(domain string, isIPv6 bool) (netip.Addr, error) {
    76  	if address, loaded := s.storage.FakeIPLoadDomain(domain, isIPv6); loaded {
    77  		return address, nil
    78  	}
    79  	var address netip.Addr
    80  	if !isIPv6 {
    81  		if !s.inet4Current.IsValid() {
    82  			return netip.Addr{}, E.New("missing IPv4 fakeip address range")
    83  		}
    84  		nextAddress := s.inet4Current.Next()
    85  		if !s.inet4Range.Contains(nextAddress) {
    86  			nextAddress = s.inet4Range.Addr().Next().Next()
    87  		}
    88  		s.inet4Current = nextAddress
    89  		address = nextAddress
    90  	} else {
    91  		if !s.inet6Current.IsValid() {
    92  			return netip.Addr{}, E.New("missing IPv6 fakeip address range")
    93  		}
    94  		nextAddress := s.inet6Current.Next()
    95  		if !s.inet6Range.Contains(nextAddress) {
    96  			nextAddress = s.inet6Range.Addr().Next().Next()
    97  		}
    98  		s.inet6Current = nextAddress
    99  		address = nextAddress
   100  	}
   101  	s.storage.FakeIPStoreAsync(address, domain, s.logger)
   102  	s.storage.FakeIPSaveMetadataAsync(&adapter.FakeIPMetadata{
   103  		Inet4Range:   s.inet4Range,
   104  		Inet6Range:   s.inet6Range,
   105  		Inet4Current: s.inet4Current,
   106  		Inet6Current: s.inet6Current,
   107  	})
   108  	return address, nil
   109  }
   110  
   111  func (s *Store) Lookup(address netip.Addr) (string, bool) {
   112  	return s.storage.FakeIPLoad(address)
   113  }
   114  
   115  func (s *Store) Reset() error {
   116  	return s.storage.FakeIPReset()
   117  }