mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-10-19 15:54:24 +00:00
Bind network reset dispatch to manager lifecycle
This commit is contained in:
+86
-74
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
"github.com/sagernet/sing/common/winpowrprof"
|
||||
"github.com/sagernet/sing/common/x/list"
|
||||
"github.com/sagernet/sing/service"
|
||||
"github.com/sagernet/sing/service/pause"
|
||||
|
||||
@@ -34,37 +35,39 @@ import (
|
||||
var _ adapter.NetworkManager = (*NetworkManager)(nil)
|
||||
|
||||
type NetworkManager struct {
|
||||
ctx context.Context
|
||||
logger logger.ContextLogger
|
||||
router adapter.Router
|
||||
interfaceFinder *control.DefaultInterfaceFinder
|
||||
networkInterfaces common.TypedValue[[]adapter.NetworkInterface]
|
||||
autoDetectInterface bool
|
||||
defaultOptions adapter.NetworkOptions
|
||||
autoRedirectOutputMark uint32
|
||||
networkMonitor tun.NetworkUpdateMonitor
|
||||
interfaceMonitor tun.DefaultInterfaceMonitor
|
||||
packageManager tun.PackageManager
|
||||
powerListener winpowrprof.EventListener
|
||||
pauseManager pause.Manager
|
||||
platformInterface adapter.PlatformInterface
|
||||
connectionManager adapter.ConnectionManager
|
||||
endpoint adapter.EndpointManager
|
||||
inbound adapter.InboundManager
|
||||
outbound adapter.OutboundManager
|
||||
needWIFIState bool
|
||||
wifiMonitor settings.WIFIMonitor
|
||||
wifiState adapter.WIFIState
|
||||
networkEnvironment uint64
|
||||
stateAccess sync.RWMutex
|
||||
environmentUpdateAccess sync.Mutex
|
||||
environmentUpdateTimer *time.Timer
|
||||
interfaceUpdateAccess sync.Mutex
|
||||
interfaceUpdateCancel context.CancelFunc
|
||||
interfaceUpdateRunAccess sync.Mutex
|
||||
powerUpdateAccess sync.Mutex
|
||||
powerUpdateCancel context.CancelFunc
|
||||
started bool
|
||||
ctx context.Context
|
||||
logger logger.ContextLogger
|
||||
router adapter.Router
|
||||
interfaceFinder *control.DefaultInterfaceFinder
|
||||
networkInterfaces common.TypedValue[[]adapter.NetworkInterface]
|
||||
autoDetectInterface bool
|
||||
defaultOptions adapter.NetworkOptions
|
||||
autoRedirectOutputMark uint32
|
||||
networkMonitor tun.NetworkUpdateMonitor
|
||||
interfaceMonitor tun.DefaultInterfaceMonitor
|
||||
packageManager tun.PackageManager
|
||||
powerListener winpowrprof.EventListener
|
||||
pauseManager pause.Manager
|
||||
platformInterface adapter.PlatformInterface
|
||||
connectionManager adapter.ConnectionManager
|
||||
endpoint adapter.EndpointManager
|
||||
inbound adapter.InboundManager
|
||||
outbound adapter.OutboundManager
|
||||
needWIFIState bool
|
||||
wifiMonitor settings.WIFIMonitor
|
||||
wifiState adapter.WIFIState
|
||||
networkEnvironment uint64
|
||||
stateAccess sync.RWMutex
|
||||
environmentUpdateAccess sync.Mutex
|
||||
environmentUpdateTimer *time.Timer
|
||||
startedCtx context.Context
|
||||
startedCancel context.CancelFunc
|
||||
interfaceUpdateElement *list.Element[tun.DefaultInterfaceUpdateCallback]
|
||||
interfaceUpdateAccess sync.Mutex
|
||||
interfaceUpdateCancel context.CancelFunc
|
||||
resetRunAccess sync.Mutex
|
||||
powerUpdateAccess sync.Mutex
|
||||
powerUpdateCancel context.CancelFunc
|
||||
}
|
||||
|
||||
func NewNetworkManager(ctx context.Context, logger logger.ContextLogger, options option.RouteOptions, dnsOptions option.DNSOptions) (*NetworkManager, error) {
|
||||
@@ -134,13 +137,10 @@ func NewNetworkManager(ctx context.Context, logger logger.ContextLogger, options
|
||||
if err != nil {
|
||||
return nil, E.New("auto_detect_interface unsupported on current platform")
|
||||
}
|
||||
interfaceMonitor.RegisterCallback(nm.notifyInterfaceUpdate)
|
||||
nm.interfaceMonitor = interfaceMonitor
|
||||
}
|
||||
} else {
|
||||
interfaceMonitor := nm.platformInterface.CreateDefaultInterfaceMonitor(logger)
|
||||
interfaceMonitor.RegisterCallback(nm.notifyInterfaceUpdate)
|
||||
nm.interfaceMonitor = interfaceMonitor
|
||||
nm.interfaceMonitor = nm.platformInterface.CreateDefaultInterfaceMonitor(logger)
|
||||
}
|
||||
return nm, nil
|
||||
}
|
||||
@@ -167,22 +167,6 @@ func (r *NetworkManager) Start(stage adapter.StartStage) error {
|
||||
}
|
||||
}
|
||||
case adapter.StartStateStart:
|
||||
if runtime.GOOS == "windows" {
|
||||
powerListener, err := winpowrprof.NewEventListener(r.notifyWindowsPowerEvent)
|
||||
if err == nil {
|
||||
r.powerListener = powerListener
|
||||
} else {
|
||||
r.logger.Warn("initialize power listener: ", err)
|
||||
}
|
||||
}
|
||||
if r.powerListener != nil {
|
||||
monitor.Start("start power listener")
|
||||
err := r.powerListener.Start()
|
||||
monitor.Finish()
|
||||
if err != nil {
|
||||
return E.Cause(err, "start power listener")
|
||||
}
|
||||
}
|
||||
if C.IsAndroid && r.platformInterface == nil {
|
||||
monitor.Start("initialize package manager")
|
||||
packageManager, err := tun.NewPackageManager(tun.PackageManagerOptions{
|
||||
@@ -217,7 +201,30 @@ func (r *NetworkManager) Start(stage adapter.StartStage) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
r.started = true
|
||||
r.startedCtx, r.startedCancel = context.WithCancel(r.ctx)
|
||||
if runtime.GOOS == "windows" {
|
||||
powerListener, err := winpowrprof.NewEventListener(r.notifyWindowsPowerEvent)
|
||||
if err == nil {
|
||||
r.powerListener = powerListener
|
||||
} else {
|
||||
r.logger.Warn("initialize power listener: ", err)
|
||||
}
|
||||
}
|
||||
if r.powerListener != nil {
|
||||
monitor.Start("start power listener")
|
||||
err := r.powerListener.Start()
|
||||
monitor.Finish()
|
||||
if err != nil {
|
||||
return E.Cause(err, "start power listener")
|
||||
}
|
||||
}
|
||||
if r.interfaceMonitor != nil {
|
||||
r.interfaceUpdateElement = r.interfaceMonitor.RegisterCallback(r.notifyInterfaceUpdate)
|
||||
// Every monitor implementation has already delivered the initial state when Start returned:
|
||||
// sing-tun checks routes synchronously, the Apple client blocks on the first NWPathMonitor update,
|
||||
// and the Android client resolves the active network before setListener returns.
|
||||
r.notifyInterfaceUpdate(r.interfaceMonitor.DefaultInterface(), 0)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -235,12 +242,9 @@ func (r *NetworkManager) Initialize(ruleSets []adapter.RuleSet) {
|
||||
func (r *NetworkManager) Close() error {
|
||||
monitor := taskmonitor.New(r.logger, C.StopTimeout)
|
||||
var err error
|
||||
if r.packageManager != nil {
|
||||
monitor.Start("close package manager")
|
||||
err = E.Append(err, r.packageManager.Close(), func(err error) error {
|
||||
return E.Cause(err, "close package manager")
|
||||
})
|
||||
monitor.Finish()
|
||||
if r.interfaceUpdateElement != nil {
|
||||
r.interfaceMonitor.UnregisterCallback(r.interfaceUpdateElement)
|
||||
r.interfaceUpdateElement = nil
|
||||
}
|
||||
if r.powerListener != nil {
|
||||
monitor.Start("close power listener")
|
||||
@@ -249,6 +253,20 @@ func (r *NetworkManager) Close() error {
|
||||
})
|
||||
monitor.Finish()
|
||||
}
|
||||
if r.startedCancel != nil {
|
||||
r.startedCancel()
|
||||
monitor.Start("wait network reset")
|
||||
r.resetRunAccess.Lock()
|
||||
monitor.Finish()
|
||||
defer r.resetRunAccess.Unlock()
|
||||
}
|
||||
if r.packageManager != nil {
|
||||
monitor.Start("close package manager")
|
||||
err = E.Append(err, r.packageManager.Close(), func(err error) error {
|
||||
return E.Cause(err, "close package manager")
|
||||
})
|
||||
monitor.Finish()
|
||||
}
|
||||
if r.interfaceMonitor != nil {
|
||||
monitor.Start("close interface monitor")
|
||||
err = E.Append(err, r.interfaceMonitor.Close(), func(err error) error {
|
||||
@@ -256,14 +274,6 @@ func (r *NetworkManager) Close() error {
|
||||
})
|
||||
monitor.Finish()
|
||||
}
|
||||
r.interfaceUpdateAccess.Lock()
|
||||
interfaceUpdateCancel := r.interfaceUpdateCancel
|
||||
r.interfaceUpdateCancel = nil
|
||||
r.interfaceUpdateAccess.Unlock()
|
||||
if interfaceUpdateCancel != nil {
|
||||
interfaceUpdateCancel()
|
||||
}
|
||||
r.cancelPowerUpdate()
|
||||
if r.networkMonitor != nil {
|
||||
monitor.Start("close network monitor")
|
||||
err = E.Append(err, r.networkMonitor.Close(), func(err error) error {
|
||||
@@ -516,7 +526,7 @@ func (r *NetworkManager) notifyInterfaceUpdate(defaultInterface *control.Interfa
|
||||
return
|
||||
}
|
||||
r.pauseManager.NetworkWake()
|
||||
updateContext, updateCancel := context.WithCancel(r.ctx)
|
||||
updateContext, updateCancel := context.WithCancel(r.startedCtx)
|
||||
r.interfaceUpdateAccess.Lock()
|
||||
previousCancel := r.interfaceUpdateCancel
|
||||
r.interfaceUpdateCancel = updateCancel
|
||||
@@ -531,8 +541,8 @@ func (r *NetworkManager) notifyInterfaceUpdate(defaultInterface *control.Interfa
|
||||
}
|
||||
|
||||
func (r *NetworkManager) updateInterface(ctx context.Context, defaultInterface *control.Interface) {
|
||||
r.interfaceUpdateRunAccess.Lock()
|
||||
defer r.interfaceUpdateRunAccess.Unlock()
|
||||
r.resetRunAccess.Lock()
|
||||
defer r.resetRunAccess.Unlock()
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
@@ -571,9 +581,6 @@ func (r *NetworkManager) updateInterface(ctx context.Context, defaultInterface *
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
if !r.started {
|
||||
return
|
||||
}
|
||||
r.ResetNetwork(ctx)
|
||||
}
|
||||
|
||||
@@ -582,7 +589,7 @@ func (r *NetworkManager) notifyWindowsPowerEvent(event int) {
|
||||
case winpowrprof.EVENT_SUSPEND:
|
||||
r.pauseManager.DevicePause()
|
||||
r.cancelPowerUpdate()
|
||||
r.ResetNetwork(r.ctx)
|
||||
r.ResetNetwork(r.startedCtx)
|
||||
case winpowrprof.EVENT_RESUME:
|
||||
if !r.pauseManager.IsDevicePaused() {
|
||||
return
|
||||
@@ -590,7 +597,7 @@ func (r *NetworkManager) notifyWindowsPowerEvent(event int) {
|
||||
fallthrough
|
||||
case winpowrprof.EVENT_RESUME_AUTOMATIC:
|
||||
r.pauseManager.DeviceWake()
|
||||
updateContext, updateCancel := context.WithCancel(r.ctx)
|
||||
updateContext, updateCancel := context.WithCancel(r.startedCtx)
|
||||
r.powerUpdateAccess.Lock()
|
||||
previousCancel := r.powerUpdateCancel
|
||||
r.powerUpdateCancel = updateCancel
|
||||
@@ -600,6 +607,11 @@ func (r *NetworkManager) notifyWindowsPowerEvent(event int) {
|
||||
}
|
||||
go func() {
|
||||
defer updateCancel()
|
||||
r.resetRunAccess.Lock()
|
||||
defer r.resetRunAccess.Unlock()
|
||||
if updateContext.Err() != nil {
|
||||
return
|
||||
}
|
||||
r.ResetNetwork(updateContext)
|
||||
}()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user