mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-04-06 05:17:37 +03:00
Fix local rule-set not updated
This commit is contained in:
parent
bab8dc0b82
commit
27c31eac5d
4 changed files with 62 additions and 49 deletions
|
@ -39,17 +39,17 @@ type CacheFile interface {
|
||||||
StoreSelected(group string, selected string) error
|
StoreSelected(group string, selected string) error
|
||||||
LoadGroupExpand(group string) (isExpand bool, loaded bool)
|
LoadGroupExpand(group string) (isExpand bool, loaded bool)
|
||||||
StoreGroupExpand(group string, expand bool) error
|
StoreGroupExpand(group string, expand bool) error
|
||||||
LoadRuleSet(tag string) *SavedRuleSet
|
LoadRuleSet(tag string) *SavedBinary
|
||||||
SaveRuleSet(tag string, set *SavedRuleSet) error
|
SaveRuleSet(tag string, set *SavedBinary) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type SavedRuleSet struct {
|
type SavedBinary struct {
|
||||||
Content []byte
|
Content []byte
|
||||||
LastUpdated time.Time
|
LastUpdated time.Time
|
||||||
LastEtag string
|
LastEtag string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SavedRuleSet) MarshalBinary() ([]byte, error) {
|
func (s *SavedBinary) MarshalBinary() ([]byte, error) {
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
err := binary.Write(&buffer, binary.BigEndian, uint8(1))
|
err := binary.Write(&buffer, binary.BigEndian, uint8(1))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -70,7 +70,7 @@ func (s *SavedRuleSet) MarshalBinary() ([]byte, error) {
|
||||||
return buffer.Bytes(), nil
|
return buffer.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SavedRuleSet) UnmarshalBinary(data []byte) error {
|
func (s *SavedBinary) UnmarshalBinary(data []byte) error {
|
||||||
reader := bytes.NewReader(data)
|
reader := bytes.NewReader(data)
|
||||||
var version uint8
|
var version uint8
|
||||||
err := binary.Read(reader, binary.BigEndian, &version)
|
err := binary.Read(reader, binary.BigEndian, &version)
|
||||||
|
|
|
@ -284,8 +284,8 @@ func (c *CacheFile) StoreGroupExpand(group string, isExpand bool) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheFile) LoadRuleSet(tag string) *adapter.SavedRuleSet {
|
func (c *CacheFile) LoadRuleSet(tag string) *adapter.SavedBinary {
|
||||||
var savedSet adapter.SavedRuleSet
|
var savedSet adapter.SavedBinary
|
||||||
err := c.DB.View(func(t *bbolt.Tx) error {
|
err := c.DB.View(func(t *bbolt.Tx) error {
|
||||||
bucket := c.bucket(t, bucketRuleSet)
|
bucket := c.bucket(t, bucketRuleSet)
|
||||||
if bucket == nil {
|
if bucket == nil {
|
||||||
|
@ -303,7 +303,7 @@ func (c *CacheFile) LoadRuleSet(tag string) *adapter.SavedRuleSet {
|
||||||
return &savedSet
|
return &savedSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheFile) SaveRuleSet(tag string, set *adapter.SavedRuleSet) error {
|
func (c *CacheFile) SaveRuleSet(tag string, set *adapter.SavedBinary) error {
|
||||||
return c.DB.Batch(func(t *bbolt.Tx) error {
|
return c.DB.Batch(func(t *bbolt.Tx) error {
|
||||||
bucket, err := c.createBucket(t, bucketRuleSet)
|
bucket, err := c.createBucket(t, bucketRuleSet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/sagernet/fswatch"
|
"github.com/sagernet/fswatch"
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
@ -33,6 +34,8 @@ type LocalRuleSet struct {
|
||||||
metadata adapter.RuleSetMetadata
|
metadata adapter.RuleSetMetadata
|
||||||
fileFormat string
|
fileFormat string
|
||||||
watcher *fswatch.Watcher
|
watcher *fswatch.Watcher
|
||||||
|
callbackAccess sync.Mutex
|
||||||
|
callbacks list.List[adapter.RuleSetUpdateCallback]
|
||||||
refs atomic.Int32
|
refs atomic.Int32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,13 +55,12 @@ func NewLocalRuleSet(ctx context.Context, logger logger.Logger, options option.R
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err := ruleSet.reloadFile(filemanager.BasePath(ctx, options.LocalOptions.Path))
|
filePath := filemanager.BasePath(ctx, options.LocalOptions.Path)
|
||||||
|
filePath, _ = filepath.Abs(options.LocalOptions.Path)
|
||||||
|
err := ruleSet.reloadFile(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if options.Type == C.RuleSetTypeLocal {
|
|
||||||
filePath, _ := filepath.Abs(options.LocalOptions.Path)
|
|
||||||
watcher, err := fswatch.NewWatcher(fswatch.Options{
|
watcher, err := fswatch.NewWatcher(fswatch.Options{
|
||||||
Path: []string{filePath},
|
Path: []string{filePath},
|
||||||
Callback: func(path string) {
|
Callback: func(path string) {
|
||||||
|
@ -141,6 +143,12 @@ func (s *LocalRuleSet) reloadRules(headlessRules []option.HeadlessRule) error {
|
||||||
metadata.ContainsIPCIDRRule = hasHeadlessRule(headlessRules, isIPCIDRHeadlessRule)
|
metadata.ContainsIPCIDRRule = hasHeadlessRule(headlessRules, isIPCIDRHeadlessRule)
|
||||||
s.rules = rules
|
s.rules = rules
|
||||||
s.metadata = metadata
|
s.metadata = metadata
|
||||||
|
s.callbackAccess.Lock()
|
||||||
|
callbacks := s.callbacks.Array()
|
||||||
|
s.callbackAccess.Unlock()
|
||||||
|
for _, callback := range callbacks {
|
||||||
|
callback(s)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,10 +181,15 @@ func (s *LocalRuleSet) Cleanup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LocalRuleSet) RegisterCallback(callback adapter.RuleSetUpdateCallback) *list.Element[adapter.RuleSetUpdateCallback] {
|
func (s *LocalRuleSet) RegisterCallback(callback adapter.RuleSetUpdateCallback) *list.Element[adapter.RuleSetUpdateCallback] {
|
||||||
return nil
|
s.callbackAccess.Lock()
|
||||||
|
defer s.callbackAccess.Unlock()
|
||||||
|
return s.callbacks.PushBack(callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LocalRuleSet) UnregisterCallback(element *list.Element[adapter.RuleSetUpdateCallback]) {
|
func (s *LocalRuleSet) UnregisterCallback(element *list.Element[adapter.RuleSetUpdateCallback]) {
|
||||||
|
s.callbackAccess.Lock()
|
||||||
|
defer s.callbackAccess.Unlock()
|
||||||
|
s.callbacks.Remove(element)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LocalRuleSet) Close() error {
|
func (s *LocalRuleSet) Close() error {
|
||||||
|
|
|
@ -35,8 +35,8 @@ var _ adapter.RuleSet = (*RemoteRuleSet)(nil)
|
||||||
type RemoteRuleSet struct {
|
type RemoteRuleSet struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
outboundManager adapter.OutboundManager
|
|
||||||
logger logger.ContextLogger
|
logger logger.ContextLogger
|
||||||
|
outbound adapter.OutboundManager
|
||||||
options option.RuleSet
|
options option.RuleSet
|
||||||
metadata adapter.RuleSetMetadata
|
metadata adapter.RuleSetMetadata
|
||||||
updateInterval time.Duration
|
updateInterval time.Duration
|
||||||
|
@ -63,7 +63,7 @@ func NewRemoteRuleSet(ctx context.Context, logger logger.ContextLogger, options
|
||||||
return &RemoteRuleSet{
|
return &RemoteRuleSet{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
outboundManager: service.FromContext[adapter.OutboundManager](ctx),
|
outbound: service.FromContext[adapter.OutboundManager](ctx),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
options: options,
|
options: options,
|
||||||
updateInterval: updateInterval,
|
updateInterval: updateInterval,
|
||||||
|
@ -83,13 +83,13 @@ func (s *RemoteRuleSet) StartContext(ctx context.Context, startContext *adapter.
|
||||||
s.cacheFile = service.FromContext[adapter.CacheFile](s.ctx)
|
s.cacheFile = service.FromContext[adapter.CacheFile](s.ctx)
|
||||||
var dialer N.Dialer
|
var dialer N.Dialer
|
||||||
if s.options.RemoteOptions.DownloadDetour != "" {
|
if s.options.RemoteOptions.DownloadDetour != "" {
|
||||||
outbound, loaded := s.outboundManager.Outbound(s.options.RemoteOptions.DownloadDetour)
|
outbound, loaded := s.outbound.Outbound(s.options.RemoteOptions.DownloadDetour)
|
||||||
if !loaded {
|
if !loaded {
|
||||||
return E.New("download_detour not found: ", s.options.RemoteOptions.DownloadDetour)
|
return E.New("download detour not found: ", s.options.RemoteOptions.DownloadDetour)
|
||||||
}
|
}
|
||||||
dialer = outbound
|
dialer = outbound
|
||||||
} else {
|
} else {
|
||||||
dialer = s.outboundManager.Default()
|
dialer = s.outbound.Default()
|
||||||
}
|
}
|
||||||
s.dialer = dialer
|
s.dialer = dialer
|
||||||
if s.cacheFile != nil {
|
if s.cacheFile != nil {
|
||||||
|
@ -286,7 +286,7 @@ func (s *RemoteRuleSet) fetchOnce(ctx context.Context, startContext *adapter.HTT
|
||||||
}
|
}
|
||||||
s.lastUpdated = time.Now()
|
s.lastUpdated = time.Now()
|
||||||
if s.cacheFile != nil {
|
if s.cacheFile != nil {
|
||||||
err = s.cacheFile.SaveRuleSet(s.options.Tag, &adapter.SavedRuleSet{
|
err = s.cacheFile.SaveRuleSet(s.options.Tag, &adapter.SavedBinary{
|
||||||
LastUpdated: s.lastUpdated,
|
LastUpdated: s.lastUpdated,
|
||||||
Content: content,
|
Content: content,
|
||||||
LastEtag: s.lastEtag,
|
LastEtag: s.lastEtag,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue