platform: Add sleep support for NetworkExtension

This commit is contained in:
世界 2023-08-01 16:40:11 +08:00
parent 8d629ef323
commit 1983f54907
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
3 changed files with 87 additions and 24 deletions

43
common/sleep/manager.go Normal file
View file

@ -0,0 +1,43 @@
package sleep
import (
"sync"
)
type Manager struct {
access sync.Mutex
done chan struct{}
}
func NewManager() *Manager {
closedChan := make(chan struct{})
close(closedChan)
return &Manager{
done: closedChan,
}
}
func (m *Manager) Sleep() {
m.access.Lock()
defer m.access.Unlock()
select {
case <-m.done:
default:
return
}
m.done = make(chan struct{})
}
func (m *Manager) Wake() {
m.access.Lock()
defer m.access.Unlock()
select {
case <-m.done:
default:
close(m.done)
}
}
func (m *Manager) Active() <-chan struct{} {
return m.done
}

View file

@ -8,6 +8,7 @@ import (
"github.com/sagernet/sing-box"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/process"
"github.com/sagernet/sing-box/common/sleep"
"github.com/sagernet/sing-box/common/urltest"
"github.com/sagernet/sing-box/experimental/libbox/internal/procfs"
"github.com/sagernet/sing-box/experimental/libbox/platform"
@ -22,9 +23,10 @@ import (
)
type BoxService struct {
ctx context.Context
cancel context.CancelFunc
instance *box.Box
ctx context.Context
cancel context.CancelFunc
instance *box.Box
sleepManager *sleep.Manager
}
func NewService(configContent string, platformInterface PlatformInterface) (*BoxService, error) {
@ -35,6 +37,8 @@ func NewService(configContent string, platformInterface PlatformInterface) (*Box
ctx, cancel := context.WithCancel(context.Background())
ctx = filemanager.WithDefault(ctx, sWorkingPath, sTempPath, sUserID, sGroupID)
ctx = service.ContextWithPtr(ctx, urltest.NewHistoryStorage())
sleepManager := sleep.NewManager()
ctx = service.ContextWithPtr(ctx, sleepManager)
instance, err := box.New(box.Options{
Context: ctx,
Options: options,
@ -45,9 +49,10 @@ func NewService(configContent string, platformInterface PlatformInterface) (*Box
return nil, E.Cause(err, "create service")
}
return &BoxService{
ctx: ctx,
cancel: cancel,
instance: instance,
ctx: ctx,
cancel: cancel,
instance: instance,
sleepManager: sleepManager,
}, nil
}
@ -60,6 +65,15 @@ func (s *BoxService) Close() error {
return s.instance.Close()
}
func (s *BoxService) Sleep() {
s.sleepManager.Sleep()
_ = s.instance.Router().ResetNetwork()
}
func (s *BoxService) Wake() {
s.sleepManager.Wake()
}
var _ platform.Interface = (*platformInterfaceWrapper)(nil)
type platformInterfaceWrapper struct {

View file

@ -8,6 +8,7 @@ import (
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/sleep"
"github.com/sagernet/sing-box/common/urltest"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
@ -143,15 +144,16 @@ func (s *URLTest) InterfaceUpdated() error {
}
type URLTestGroup struct {
ctx context.Context
router adapter.Router
logger log.Logger
outbounds []adapter.Outbound
link string
interval time.Duration
tolerance uint16
history *urltest.HistoryStorage
checking atomic.Bool
ctx context.Context
router adapter.Router
logger log.Logger
outbounds []adapter.Outbound
link string
interval time.Duration
tolerance uint16
history *urltest.HistoryStorage
checking atomic.Bool
sleepManager *sleep.Manager
access sync.Mutex
ticker *time.Ticker
@ -173,15 +175,16 @@ func NewURLTestGroup(ctx context.Context, router adapter.Router, logger log.Logg
history = urltest.NewHistoryStorage()
}
return &URLTestGroup{
ctx: ctx,
router: router,
logger: logger,
outbounds: outbounds,
link: link,
interval: interval,
tolerance: tolerance,
history: history,
close: make(chan struct{}),
ctx: ctx,
router: router,
logger: logger,
outbounds: outbounds,
link: link,
interval: interval,
tolerance: tolerance,
history: history,
close: make(chan struct{}),
sleepManager: service.PtrFromContext[sleep.Manager](ctx),
}
}
@ -263,6 +266,9 @@ func (g *URLTestGroup) Fallback(used adapter.Outbound) []adapter.Outbound {
func (g *URLTestGroup) loopCheck() {
go g.CheckOutbounds(true)
for {
if g.sleepManager != nil {
<-g.sleepManager.Active()
}
select {
case <-g.close:
return