mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-12-12 16:18:50 +00:00
119 lines
3 KiB
Go
119 lines
3 KiB
Go
package fakeip
|
|
|
|
import (
|
|
"context"
|
|
"net/netip"
|
|
|
|
"github.com/sagernet/sing-box/adapter"
|
|
E "github.com/sagernet/sing/common/exceptions"
|
|
"github.com/sagernet/sing/common/logger"
|
|
"github.com/sagernet/sing/service"
|
|
)
|
|
|
|
var _ adapter.FakeIPStore = (*Store)(nil)
|
|
|
|
type Store struct {
|
|
ctx context.Context
|
|
logger logger.Logger
|
|
inet4Range netip.Prefix
|
|
inet6Range netip.Prefix
|
|
storage adapter.FakeIPStorage
|
|
inet4Current netip.Addr
|
|
inet6Current netip.Addr
|
|
}
|
|
|
|
func NewStore(ctx context.Context, logger logger.Logger, inet4Range netip.Prefix, inet6Range netip.Prefix) *Store {
|
|
return &Store{
|
|
ctx: ctx,
|
|
logger: logger,
|
|
inet4Range: inet4Range,
|
|
inet6Range: inet6Range,
|
|
}
|
|
}
|
|
|
|
func (s *Store) Start() error {
|
|
var storage adapter.FakeIPStorage
|
|
cacheFile := service.FromContext[adapter.CacheFile](s.ctx)
|
|
if cacheFile != nil && cacheFile.StoreFakeIP() {
|
|
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()
|
|
}
|
|
_ = storage.FakeIPReset()
|
|
}
|
|
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, isIPv6 bool) (netip.Addr, error) {
|
|
if address, loaded := s.storage.FakeIPLoadDomain(domain, isIPv6); loaded {
|
|
return address, nil
|
|
}
|
|
var address netip.Addr
|
|
if !isIPv6 {
|
|
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
|
|
}
|
|
s.storage.FakeIPStoreAsync(address, domain, s.logger)
|
|
s.storage.FakeIPSaveMetadataAsync(&adapter.FakeIPMetadata{
|
|
Inet4Range: s.inet4Range,
|
|
Inet6Range: s.inet6Range,
|
|
Inet4Current: s.inet4Current,
|
|
Inet6Current: s.inet6Current,
|
|
})
|
|
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()
|
|
}
|