sing-box/transport/fakeip/store.go

109 lines
2.7 KiB
Go

package fakeip
import (
"net/netip"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-dns"
E "github.com/sagernet/sing/common/exceptions"
)
var _ adapter.FakeIPStore = (*Store)(nil)
type Store struct {
router adapter.Router
inet4Range netip.Prefix
inet6Range netip.Prefix
storage adapter.FakeIPStorage
inet4Current netip.Addr
inet6Current netip.Addr
}
func NewStore(router adapter.Router, inet4Range netip.Prefix, inet6Range netip.Prefix) *Store {
return &Store{
router: router,
inet4Range: inet4Range,
inet6Range: inet6Range,
}
}
func (s *Store) Start() error {
var storage adapter.FakeIPStorage
if clashServer := s.router.ClashServer(); clashServer != nil && clashServer.StoreFakeIP() {
if cacheFile := clashServer.CacheFile(); cacheFile != nil {
storage = cacheFile
}
}
if storage == nil {
storage = NewMemoryStorage()
}
metadata := storage.FakeIPMetadata()
if metadata != nil && metadata.Inet4Range == s.inet4Range && metadata.Inet6Range == s.inet6Range {
s.inet4Current = metadata.Inet4Current
s.inet6Current = metadata.Inet6Current
} else {
if s.inet4Range.IsValid() {
s.inet4Current = s.inet4Range.Addr().Next().Next()
}
if s.inet6Range.IsValid() {
s.inet6Current = s.inet6Range.Addr().Next().Next()
}
}
s.storage = storage
return nil
}
func (s *Store) Contains(address netip.Addr) bool {
return s.inet4Range.Contains(address) || s.inet6Range.Contains(address)
}
func (s *Store) Close() error {
if s.storage == nil {
return nil
}
return s.storage.FakeIPSaveMetadata(&adapter.FakeIPMetadata{
Inet4Range: s.inet4Range,
Inet6Range: s.inet6Range,
Inet4Current: s.inet4Current,
Inet6Current: s.inet6Current,
})
}
func (s *Store) Create(domain string, strategy dns.DomainStrategy) (netip.Addr, error) {
var address netip.Addr
if strategy == dns.DomainStrategyUseIPv4 {
if !s.inet4Current.IsValid() {
return netip.Addr{}, E.New("missing IPv4 fakeip address range")
}
nextAddress := s.inet4Current.Next()
if !s.inet4Range.Contains(nextAddress) {
nextAddress = s.inet4Range.Addr().Next().Next()
}
s.inet4Current = nextAddress
address = nextAddress
} else {
if !s.inet6Current.IsValid() {
return netip.Addr{}, E.New("missing IPv6 fakeip address range")
}
nextAddress := s.inet6Current.Next()
if !s.inet6Range.Contains(nextAddress) {
nextAddress = s.inet6Range.Addr().Next().Next()
}
s.inet6Current = nextAddress
address = nextAddress
}
err := s.storage.FakeIPStore(address, domain)
if err != nil {
return netip.Addr{}, err
}
return address, nil
}
func (s *Store) Lookup(address netip.Addr) (string, bool) {
return s.storage.FakeIPLoad(address)
}
func (s *Store) Reset() error {
return s.storage.FakeIPReset()
}