mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-09-15 21:00:27 +00:00
Handle network update callbacks in background
This commit is contained in:
+4
-3
@@ -1,6 +1,7 @@
|
|||||||
package adapter
|
package adapter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
@@ -32,8 +33,8 @@ type NetworkManager interface {
|
|||||||
PackageManager() tun.PackageManager
|
PackageManager() tun.PackageManager
|
||||||
NeedWIFIState() bool
|
NeedWIFIState() bool
|
||||||
WIFIState() WIFIState
|
WIFIState() WIFIState
|
||||||
UpdateWIFIState()
|
UpdateWIFIState(ctx context.Context)
|
||||||
ResetNetwork()
|
ResetNetwork(ctx context.Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
type NetworkOptions struct {
|
type NetworkOptions struct {
|
||||||
@@ -48,7 +49,7 @@ type NetworkOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type InterfaceUpdateListener interface {
|
type InterfaceUpdateListener interface {
|
||||||
InterfaceUpdated()
|
InterfaceUpdated(ctx context.Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
type WIFIState struct {
|
type WIFIState struct {
|
||||||
|
|||||||
+2
-1
@@ -1,6 +1,7 @@
|
|||||||
package adapter
|
package adapter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
@@ -29,7 +30,7 @@ type PlatformInterface interface {
|
|||||||
|
|
||||||
ClearDNSCache()
|
ClearDNSCache()
|
||||||
RequestPermissionForWIFIState() error
|
RequestPermissionForWIFIState() error
|
||||||
ReadWIFIState() WIFIState
|
ReadWIFIState(ctx context.Context) WIFIState
|
||||||
|
|
||||||
UsePlatformConnectionOwnerFinder() bool
|
UsePlatformConnectionOwnerFinder() bool
|
||||||
FindConnectionOwner(request *FindConnectionOwnerRequest) (*ConnectionOwner, error)
|
FindConnectionOwner(request *FindConnectionOwnerRequest) (*ConnectionOwner, error)
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ func (l *Listener) Start() error {
|
|||||||
}
|
}
|
||||||
err = systemProxy.Enable()
|
err = systemProxy.Enable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "set system proxy")
|
return E.Errors(E.Cause(err, "set system proxy"), systemProxy.Close())
|
||||||
}
|
}
|
||||||
l.systemProxy = systemProxy
|
l.systemProxy = systemProxy
|
||||||
}
|
}
|
||||||
@@ -123,8 +123,11 @@ func (l *Listener) Start() error {
|
|||||||
func (l *Listener) Close() error {
|
func (l *Listener) Close() error {
|
||||||
l.shutdown.Store(true)
|
l.shutdown.Store(true)
|
||||||
var err error
|
var err error
|
||||||
if l.systemProxy != nil && l.systemProxy.IsEnabled() {
|
if l.systemProxy != nil {
|
||||||
err = l.systemProxy.Disable()
|
if l.systemProxy.IsEnabled() {
|
||||||
|
err = l.systemProxy.Disable()
|
||||||
|
}
|
||||||
|
err = E.Errors(err, l.systemProxy.Close())
|
||||||
}
|
}
|
||||||
return E.Errors(err, common.Close(
|
return E.Errors(err, common.Close(
|
||||||
l.tcpListener,
|
l.tcpListener,
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ func (p *AndroidSystemProxy) Enable() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *AndroidSystemProxy) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *AndroidSystemProxy) Disable() error {
|
func (p *AndroidSystemProxy) Disable() error {
|
||||||
err := p.runAndroidShell("settings", "put", "global", "http_proxy", ":0")
|
err := p.runAndroidShell("settings", "put", "global", "http_proxy", ":0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-tun"
|
"github.com/sagernet/sing-tun"
|
||||||
@@ -16,11 +17,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type DarwinSystemProxy struct {
|
type DarwinSystemProxy struct {
|
||||||
|
ctx context.Context
|
||||||
monitor tun.DefaultInterfaceMonitor
|
monitor tun.DefaultInterfaceMonitor
|
||||||
interfaceName string
|
interfaceName string
|
||||||
element *list.Element[tun.DefaultInterfaceUpdateCallback]
|
element *list.Element[tun.DefaultInterfaceUpdateCallback]
|
||||||
serverAddr M.Socksaddr
|
serverAddr M.Socksaddr
|
||||||
supportSOCKS bool
|
supportSOCKS bool
|
||||||
|
access sync.Mutex
|
||||||
|
updateCancel context.CancelFunc
|
||||||
isEnabled bool
|
isEnabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,6 +34,7 @@ func NewSystemProxy(ctx context.Context, serverAddr M.Socksaddr, supportSOCKS bo
|
|||||||
return nil, E.New("missing interface monitor")
|
return nil, E.New("missing interface monitor")
|
||||||
}
|
}
|
||||||
proxy := &DarwinSystemProxy{
|
proxy := &DarwinSystemProxy{
|
||||||
|
ctx: ctx,
|
||||||
monitor: interfaceMonitor,
|
monitor: interfaceMonitor,
|
||||||
serverAddr: serverAddr,
|
serverAddr: serverAddr,
|
||||||
supportSOCKS: supportSOCKS,
|
supportSOCKS: supportSOCKS,
|
||||||
@@ -39,14 +44,36 @@ func NewSystemProxy(ctx context.Context, serverAddr M.Socksaddr, supportSOCKS bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *DarwinSystemProxy) IsEnabled() bool {
|
func (p *DarwinSystemProxy) IsEnabled() bool {
|
||||||
|
p.access.Lock()
|
||||||
|
defer p.access.Unlock()
|
||||||
return p.isEnabled
|
return p.isEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *DarwinSystemProxy) Enable() error {
|
func (p *DarwinSystemProxy) Enable() error {
|
||||||
return p.update0()
|
p.access.Lock()
|
||||||
|
defer p.access.Unlock()
|
||||||
|
return p.updateLocked(p.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *DarwinSystemProxy) Disable() error {
|
func (p *DarwinSystemProxy) Disable() error {
|
||||||
|
p.access.Lock()
|
||||||
|
defer p.access.Unlock()
|
||||||
|
return p.disableLocked()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *DarwinSystemProxy) Close() error {
|
||||||
|
p.access.Lock()
|
||||||
|
updateCancel := p.updateCancel
|
||||||
|
p.updateCancel = nil
|
||||||
|
p.access.Unlock()
|
||||||
|
if updateCancel != nil {
|
||||||
|
updateCancel()
|
||||||
|
}
|
||||||
|
p.monitor.UnregisterCallback(p.element)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *DarwinSystemProxy) disableLocked() error {
|
||||||
interfaceDisplayName, err := getInterfaceDisplayName(p.interfaceName)
|
interfaceDisplayName, err := getInterfaceDisplayName(p.interfaceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -67,19 +94,35 @@ func (p *DarwinSystemProxy) Disable() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *DarwinSystemProxy) routeUpdate(defaultInterface *control.Interface, flags int) {
|
func (p *DarwinSystemProxy) routeUpdate(defaultInterface *control.Interface, flags int) {
|
||||||
if !p.isEnabled || defaultInterface == nil {
|
if defaultInterface == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = p.update0()
|
updateContext, updateCancel := context.WithCancel(p.ctx)
|
||||||
|
p.access.Lock()
|
||||||
|
previousCancel := p.updateCancel
|
||||||
|
p.updateCancel = updateCancel
|
||||||
|
p.access.Unlock()
|
||||||
|
if previousCancel != nil {
|
||||||
|
previousCancel()
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
defer updateCancel()
|
||||||
|
p.access.Lock()
|
||||||
|
defer p.access.Unlock()
|
||||||
|
if !p.isEnabled || updateContext.Err() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_ = p.updateLocked(updateContext)
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *DarwinSystemProxy) update0() error {
|
func (p *DarwinSystemProxy) updateLocked(ctx context.Context) error {
|
||||||
newInterface := p.monitor.DefaultInterface()
|
newInterface := p.monitor.DefaultInterface()
|
||||||
if p.interfaceName == newInterface.Name {
|
if newInterface == nil || p.interfaceName == newInterface.Name {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if p.interfaceName != "" {
|
if p.interfaceName != "" {
|
||||||
_ = p.Disable()
|
_ = p.disableLocked()
|
||||||
}
|
}
|
||||||
p.interfaceName = newInterface.Name
|
p.interfaceName = newInterface.Name
|
||||||
interfaceDisplayName, err := getInterfaceDisplayName(p.interfaceName)
|
interfaceDisplayName, err := getInterfaceDisplayName(p.interfaceName)
|
||||||
@@ -87,15 +130,27 @@ func (p *DarwinSystemProxy) update0() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if p.supportSOCKS {
|
if p.supportSOCKS {
|
||||||
|
err = ctx.Err()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
err = shell.Exec("networksetup", "-setsocksfirewallproxy", interfaceDisplayName, p.serverAddr.AddrString(), strconv.Itoa(int(p.serverAddr.Port))).Attach().Run()
|
err = shell.Exec("networksetup", "-setsocksfirewallproxy", interfaceDisplayName, p.serverAddr.AddrString(), strconv.Itoa(int(p.serverAddr.Port))).Attach().Run()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = ctx.Err()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
err = shell.Exec("networksetup", "-setwebproxy", interfaceDisplayName, p.serverAddr.AddrString(), strconv.Itoa(int(p.serverAddr.Port))).Attach().Run()
|
err = shell.Exec("networksetup", "-setwebproxy", interfaceDisplayName, p.serverAddr.AddrString(), strconv.Itoa(int(p.serverAddr.Port))).Attach().Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = ctx.Err()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
err = shell.Exec("networksetup", "-setsecurewebproxy", interfaceDisplayName, p.serverAddr.AddrString(), strconv.Itoa(int(p.serverAddr.Port))).Attach().Run()
|
err = shell.Exec("networksetup", "-setsecurewebproxy", interfaceDisplayName, p.serverAddr.AddrString(), strconv.Itoa(int(p.serverAddr.Port))).Attach().Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -118,6 +118,10 @@ func (p *LinuxSystemProxy) Enable() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *LinuxSystemProxy) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *LinuxSystemProxy) Disable() error {
|
func (p *LinuxSystemProxy) Disable() error {
|
||||||
if p.hasGSettings {
|
if p.hasGSettings {
|
||||||
err := p.execute("gsettings", "set", "org.gnome.system.proxy", "mode", "none")
|
err := p.execute("gsettings", "set", "org.gnome.system.proxy", "mode", "none")
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ func (p *WindowsSystemProxy) Enable() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *WindowsSystemProxy) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *WindowsSystemProxy) Disable() error {
|
func (p *WindowsSystemProxy) Disable() error {
|
||||||
err := wininet.ClearSystemProxy()
|
err := wininet.ClearSystemProxy()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ type SystemProxy interface {
|
|||||||
IsEnabled() bool
|
IsEnabled() bool
|
||||||
Enable() error
|
Enable() error
|
||||||
Disable() error
|
Disable() error
|
||||||
|
Close() error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package settings
|
package settings
|
||||||
|
|
||||||
import "github.com/sagernet/sing-box/adapter"
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
)
|
||||||
|
|
||||||
type WIFIMonitor interface {
|
type WIFIMonitor interface {
|
||||||
ReadWIFIState() adapter.WIFIState
|
ReadWIFIState(ctx context.Context) adapter.WIFIState
|
||||||
Start() error
|
Start() error
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package settings
|
package settings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
)
|
)
|
||||||
@@ -27,8 +29,8 @@ func NewWIFIMonitor(callback func(adapter.WIFIState)) (WIFIMonitor, error) {
|
|||||||
return nil, E.Cause(E.Errors(errors...), "no supported WIFI manager found")
|
return nil, E.Cause(E.Errors(errors...), "no supported WIFI manager found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *LinuxWIFIMonitor) ReadWIFIState() adapter.WIFIState {
|
func (m *LinuxWIFIMonitor) ReadWIFIState(ctx context.Context) adapter.WIFIState {
|
||||||
return m.monitor.ReadWIFIState()
|
return m.monitor.ReadWIFIState(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *LinuxWIFIMonitor) Start() error {
|
func (m *LinuxWIFIMonitor) Start() error {
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ func newConnManMonitor(callback func(adapter.WIFIState)) (WIFIMonitor, error) {
|
|||||||
return &connmanMonitor{conn: conn, callback: callback}, nil
|
return &connmanMonitor{conn: conn, callback: callback}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *connmanMonitor) ReadWIFIState() adapter.WIFIState {
|
func (m *connmanMonitor) ReadWIFIState(ctx context.Context) adapter.WIFIState {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
cmObj := m.conn.Object("net.connman", "/")
|
cmObj := m.conn.Object("net.connman", "/")
|
||||||
@@ -120,7 +120,7 @@ func (m *connmanMonitor) Start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
state := m.ReadWIFIState()
|
state := m.ReadWIFIState(ctx)
|
||||||
go m.monitorSignals(ctx, m.signalChan, state)
|
go m.monitorSignals(ctx, m.signalChan, state)
|
||||||
m.callback(state)
|
m.callback(state)
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ func (m *connmanMonitor) monitorSignals(ctx context.Context, signalChan chan *db
|
|||||||
// godbus Signal.Name uses "interface.member" format (e.g. "net.connman.Service.PropertyChanged"),
|
// godbus Signal.Name uses "interface.member" format (e.g. "net.connman.Service.PropertyChanged"),
|
||||||
// not just the member name. This differs from the D-Bus signal member in the match rule.
|
// not just the member name. This differs from the D-Bus signal member in the match rule.
|
||||||
if signal.Name == "net.connman.Service.PropertyChanged" {
|
if signal.Name == "net.connman.Service.PropertyChanged" {
|
||||||
state := m.ReadWIFIState()
|
state := m.ReadWIFIState(ctx)
|
||||||
if state != lastState {
|
if state != lastState {
|
||||||
lastState = state
|
lastState = state
|
||||||
m.callback(state)
|
m.callback(state)
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ func newIWDMonitor(callback func(adapter.WIFIState)) (WIFIMonitor, error) {
|
|||||||
return &iwdMonitor{conn: conn, callback: callback}, nil
|
return &iwdMonitor{conn: conn, callback: callback}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *iwdMonitor) ReadWIFIState() adapter.WIFIState {
|
func (m *iwdMonitor) ReadWIFIState(ctx context.Context) adapter.WIFIState {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
iwdObj := m.conn.Object("net.connman.iwd", "/")
|
iwdObj := m.conn.Object("net.connman.iwd", "/")
|
||||||
@@ -144,7 +144,7 @@ func (m *iwdMonitor) Start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
state := m.ReadWIFIState()
|
state := m.ReadWIFIState(ctx)
|
||||||
go m.monitorSignals(ctx, m.signalChan, state)
|
go m.monitorSignals(ctx, m.signalChan, state)
|
||||||
m.callback(state)
|
m.callback(state)
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ func (m *iwdMonitor) monitorSignals(ctx context.Context, signalChan chan *dbus.S
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if signal.Name == "org.freedesktop.DBus.Properties.PropertiesChanged" {
|
if signal.Name == "org.freedesktop.DBus.Properties.PropertiesChanged" {
|
||||||
state := m.ReadWIFIState()
|
state := m.ReadWIFIState(ctx)
|
||||||
if state != lastState {
|
if state != lastState {
|
||||||
lastState = state
|
lastState = state
|
||||||
m.callback(state)
|
m.callback(state)
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ func newNetworkManagerMonitor(callback func(adapter.WIFIState)) (WIFIMonitor, er
|
|||||||
return &networkManagerMonitor{conn: conn, callback: callback}, nil
|
return &networkManagerMonitor{conn: conn, callback: callback}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *networkManagerMonitor) ReadWIFIState() adapter.WIFIState {
|
func (m *networkManagerMonitor) ReadWIFIState(ctx context.Context) adapter.WIFIState {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
nmObj := m.conn.Object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager")
|
nmObj := m.conn.Object("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager")
|
||||||
@@ -119,7 +119,7 @@ func (m *networkManagerMonitor) Start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
state := m.ReadWIFIState()
|
state := m.ReadWIFIState(ctx)
|
||||||
go m.monitorSignals(ctx, m.signalChan, state)
|
go m.monitorSignals(ctx, m.signalChan, state)
|
||||||
m.callback(state)
|
m.callback(state)
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ func (m *networkManagerMonitor) monitorSignals(ctx context.Context, signalChan c
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if signal.Name == "org.freedesktop.DBus.Properties.PropertiesChanged" {
|
if signal.Name == "org.freedesktop.DBus.Properties.PropertiesChanged" {
|
||||||
state := m.ReadWIFIState()
|
state := m.ReadWIFIState(ctx)
|
||||||
if state != lastState {
|
if state != lastState {
|
||||||
lastState = state
|
lastState = state
|
||||||
m.callback(state)
|
m.callback(state)
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func newWpaSupplicantMonitor(callback func(adapter.WIFIState)) (WIFIMonitor, err
|
|||||||
return nil, os.ErrNotExist
|
return nil, os.ErrNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *wpaSupplicantMonitor) ReadWIFIState() adapter.WIFIState {
|
func (m *wpaSupplicantMonitor) ReadWIFIState(ctx context.Context) adapter.WIFIState {
|
||||||
id := wpaSocketCounter.Add(1)
|
id := wpaSocketCounter.Add(1)
|
||||||
localAddr := &net.UnixAddr{Name: fmt.Sprintf("@sing-box-wpa-%d-%d", os.Getpid(), id), Net: "unixgram"}
|
localAddr := &net.UnixAddr{Name: fmt.Sprintf("@sing-box-wpa-%d-%d", os.Getpid(), id), Net: "unixgram"}
|
||||||
remoteAddr := &net.UnixAddr{Name: m.socketPath, Net: "unixgram"}
|
remoteAddr := &net.UnixAddr{Name: m.socketPath, Net: "unixgram"}
|
||||||
@@ -63,6 +63,15 @@ func (m *wpaSupplicantMonitor) ReadWIFIState() adapter.WIFIState {
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
conn.SetDeadline(time.Now().Add(3 * time.Second))
|
conn.SetDeadline(time.Now().Add(3 * time.Second))
|
||||||
|
done := make(chan struct{})
|
||||||
|
defer close(done)
|
||||||
|
go func() {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
conn.SetDeadline(time.Now())
|
||||||
|
case <-done:
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
status, err := m.sendCommand(conn, "STATUS")
|
status, err := m.sendCommand(conn, "STATUS")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -124,7 +133,7 @@ func (m *wpaSupplicantMonitor) Start() error {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
m.cancel = cancel
|
m.cancel = cancel
|
||||||
|
|
||||||
state := m.ReadWIFIState()
|
state := m.ReadWIFIState(ctx)
|
||||||
go m.monitorEvents(ctx, state)
|
go m.monitorEvents(ctx, state)
|
||||||
m.callback(state)
|
m.callback(state)
|
||||||
|
|
||||||
@@ -202,7 +211,7 @@ func (m *wpaSupplicantMonitor) monitorEvents(ctx context.Context, lastState adap
|
|||||||
debounceTimer.Stop()
|
debounceTimer.Stop()
|
||||||
}
|
}
|
||||||
debounceTimer = time.AfterFunc(500*time.Millisecond, func() {
|
debounceTimer = time.AfterFunc(500*time.Millisecond, func() {
|
||||||
state := m.ReadWIFIState()
|
state := m.ReadWIFIState(ctx)
|
||||||
if state != lastState {
|
if state != lastState {
|
||||||
lastState = state
|
lastState = state
|
||||||
m.callback(state)
|
m.callback(state)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package settings
|
package settings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
@@ -15,7 +16,7 @@ func NewWIFIMonitor(callback func(adapter.WIFIState)) (WIFIMonitor, error) {
|
|||||||
return nil, os.ErrInvalid
|
return nil, os.ErrInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *stubWIFIMonitor) ReadWIFIState() adapter.WIFIState {
|
func (m *stubWIFIMonitor) ReadWIFIState(ctx context.Context) adapter.WIFIState {
|
||||||
return adapter.WIFIState{}
|
return adapter.WIFIState{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func NewWIFIMonitor(callback func(adapter.WIFIState)) (WIFIMonitor, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *windowsWIFIMonitor) ReadWIFIState() adapter.WIFIState {
|
func (m *windowsWIFIMonitor) ReadWIFIState(ctx context.Context) adapter.WIFIState {
|
||||||
interfaces, err := winwlanapi.EnumInterfaces(m.handle)
|
interfaces, err := winwlanapi.EnumInterfaces(m.handle)
|
||||||
if err != nil || len(interfaces) == 0 {
|
if err != nil || len(interfaces) == 0 {
|
||||||
return adapter.WIFIState{}
|
return adapter.WIFIState{}
|
||||||
@@ -92,7 +92,7 @@ func (m *windowsWIFIMonitor) Start() error {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
m.cancel = cancel
|
m.cancel = cancel
|
||||||
|
|
||||||
m.lastState = m.ReadWIFIState()
|
m.lastState = m.ReadWIFIState(ctx)
|
||||||
|
|
||||||
callbackFunc := func(data *winwlanapi.NotificationData, callbackContext uintptr) uintptr {
|
callbackFunc := func(data *winwlanapi.NotificationData, callbackContext uintptr) uintptr {
|
||||||
if data.NotificationSource != winwlanapi.NotificationSourceACM {
|
if data.NotificationSource != winwlanapi.NotificationSourceACM {
|
||||||
@@ -126,7 +126,7 @@ func (m *windowsWIFIMonitor) checkAndNotify() {
|
|||||||
m.mutex.Lock()
|
m.mutex.Lock()
|
||||||
defer m.mutex.Unlock()
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
state := m.ReadWIFIState()
|
state := m.ReadWIFIState(context.Background())
|
||||||
if state != m.lastState {
|
if state != m.lastState {
|
||||||
m.lastState = state
|
m.lastState = state
|
||||||
if m.callback != nil {
|
if m.callback != nil {
|
||||||
|
|||||||
+39
-11
@@ -55,6 +55,8 @@ type Transport struct {
|
|||||||
platformInterface adapter.PlatformInterface
|
platformInterface adapter.PlatformInterface
|
||||||
interfaceName string
|
interfaceName string
|
||||||
interfaceCallback *list.Element[tun.DefaultInterfaceUpdateCallback]
|
interfaceCallback *list.Element[tun.DefaultInterfaceUpdateCallback]
|
||||||
|
updateAccess sync.Mutex
|
||||||
|
updateCancel context.CancelFunc
|
||||||
refreshAccess sync.Mutex
|
refreshAccess sync.Mutex
|
||||||
savedState atomic.Pointer[transportState]
|
savedState atomic.Pointer[transportState]
|
||||||
ndots int
|
ndots int
|
||||||
@@ -126,6 +128,13 @@ func (t *Transport) Close() error {
|
|||||||
if t.interfaceCallback != nil {
|
if t.interfaceCallback != nil {
|
||||||
t.networkManager.InterfaceMonitor().UnregisterCallback(t.interfaceCallback)
|
t.networkManager.InterfaceMonitor().UnregisterCallback(t.interfaceCallback)
|
||||||
}
|
}
|
||||||
|
t.updateAccess.Lock()
|
||||||
|
updateCancel := t.updateCancel
|
||||||
|
t.updateCancel = nil
|
||||||
|
t.updateAccess.Unlock()
|
||||||
|
if updateCancel != nil {
|
||||||
|
updateCancel()
|
||||||
|
}
|
||||||
t.refreshAccess.Lock()
|
t.refreshAccess.Lock()
|
||||||
defer t.refreshAccess.Unlock()
|
defer t.refreshAccess.Unlock()
|
||||||
state := t.savedState.Swap(nil)
|
state := t.savedState.Swap(nil)
|
||||||
@@ -243,7 +252,7 @@ func (t *Transport) fetch() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t.updateServersLocked()
|
return t.updateServersLocked(t.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) startRefresh() {
|
func (t *Transport) startRefresh() {
|
||||||
@@ -256,7 +265,7 @@ func (t *Transport) startRefresh() {
|
|||||||
if state != nil && time.Since(state.updatedAt) < C.DHCPTTL {
|
if state != nil && time.Since(state.updatedAt) < C.DHCPTTL {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := t.updateServersLocked()
|
err := t.updateServersLocked(t.ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, errInterfaceIsCellular) && t.optional {
|
if errors.Is(err, errInterfaceIsCellular) && t.optional {
|
||||||
t.logger.Debug(E.Cause(err, "dhcp: refresh DNS servers"))
|
t.logger.Debug(E.Cause(err, "dhcp: refresh DNS servers"))
|
||||||
@@ -293,17 +302,20 @@ func (t *Transport) fetchInterface() (*control.Interface, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) updateServersLocked() error {
|
func (t *Transport) updateServersLocked(ctx context.Context) error {
|
||||||
iface, err := t.fetchInterface()
|
iface, err := t.fetchInterface()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.storeFailureLocked(err)
|
t.storeFailureLocked(err)
|
||||||
return E.Cause(err, "prepare interface")
|
return E.Cause(err, "prepare interface")
|
||||||
}
|
}
|
||||||
t.logger.Info("dhcp: query DNS servers on ", iface.Name)
|
t.logger.Info("dhcp: query DNS servers on ", iface.Name)
|
||||||
fetchCtx, cancel := context.WithTimeout(t.ctx, C.DHCPTimeout)
|
fetchCtx, cancel := context.WithTimeout(ctx, C.DHCPTimeout)
|
||||||
err = t.fetchServers0(fetchCtx, iface)
|
err = t.fetchServers0(fetchCtx, iface)
|
||||||
cancel()
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
t.storeFailureLocked(err)
|
t.storeFailureLocked(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -331,16 +343,28 @@ func (t *Transport) storeFailureLocked(err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) interfaceUpdated(defaultInterface *control.Interface, flags int) {
|
func (t *Transport) interfaceUpdated(defaultInterface *control.Interface, flags int) {
|
||||||
t.refreshAccess.Lock()
|
updateContext, updateCancel := context.WithCancel(t.ctx)
|
||||||
err := t.updateServersLocked()
|
t.updateAccess.Lock()
|
||||||
t.refreshAccess.Unlock()
|
previousCancel := t.updateCancel
|
||||||
if err != nil {
|
t.updateCancel = updateCancel
|
||||||
|
t.updateAccess.Unlock()
|
||||||
|
if previousCancel != nil {
|
||||||
|
previousCancel()
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
defer updateCancel()
|
||||||
|
t.refreshAccess.Lock()
|
||||||
|
err := t.updateServersLocked(updateContext)
|
||||||
|
t.refreshAccess.Unlock()
|
||||||
|
if err == nil || updateContext.Err() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
if errors.Is(err, errInterfaceIsCellular) && t.optional {
|
if errors.Is(err, errInterfaceIsCellular) && t.optional {
|
||||||
t.logger.Debug(E.Cause(errInterfaceIsCellular, "dhcp: update DNS servers"))
|
t.logger.Debug(E.Cause(errInterfaceIsCellular, "dhcp: update DNS servers"))
|
||||||
} else {
|
} else {
|
||||||
t.logger.Error("dhcp: update DNS servers: ", err)
|
t.logger.Error("dhcp: update DNS servers: ", err)
|
||||||
}
|
}
|
||||||
}
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Transport) fetchServers0(ctx context.Context, iface *control.Interface) error {
|
func (t *Transport) fetchServers0(ctx context.Context, iface *control.Interface) error {
|
||||||
@@ -356,11 +380,15 @@ func (t *Transport) fetchServers0(ctx context.Context, iface *control.Interface)
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
for range 5 {
|
for range 5 {
|
||||||
packetConn, err = listener.ListenPacket(t.ctx, "udp4", listenAddr)
|
packetConn, err = listener.ListenPacket(ctx, "udp4", listenAddr)
|
||||||
if err == nil || !errors.Is(err, syscall.EADDRINUSE) {
|
if err == nil || !errors.Is(err, syscall.EADDRINUSE) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second)
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
case <-time.After(time.Second):
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -58,6 +58,10 @@ type DBusResolvedResolver struct {
|
|||||||
interfaceCallback *list.Element[tun.DefaultInterfaceUpdateCallback]
|
interfaceCallback *list.Element[tun.DefaultInterfaceUpdateCallback]
|
||||||
systemBus *dbus.Conn
|
systemBus *dbus.Conn
|
||||||
savedServerSet atomic.Pointer[resolvedServerSet]
|
savedServerSet atomic.Pointer[resolvedServerSet]
|
||||||
|
updateAccess sync.Mutex
|
||||||
|
updateCancel context.CancelFunc
|
||||||
|
updateRunAccess sync.Mutex
|
||||||
|
closed bool
|
||||||
closeOnce sync.Once
|
closeOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +99,7 @@ func NewResolvedResolver(ctx context.Context, logger logger.ContextLogger) (Reso
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *DBusResolvedResolver) Start() error {
|
func (t *DBusResolvedResolver) Start() error {
|
||||||
t.updateStatus()
|
t.updateStatus(t.ctx)
|
||||||
t.interfaceCallback = t.interfaceMonitor.RegisterCallback(t.updateDefaultInterface)
|
t.interfaceCallback = t.interfaceMonitor.RegisterCallback(t.updateDefaultInterface)
|
||||||
err := t.systemBus.BusObject().AddMatchSignal(
|
err := t.systemBus.BusObject().AddMatchSignal(
|
||||||
"org.freedesktop.DBus",
|
"org.freedesktop.DBus",
|
||||||
@@ -122,7 +126,17 @@ func (t *DBusResolvedResolver) Start() error {
|
|||||||
func (t *DBusResolvedResolver) Close() error {
|
func (t *DBusResolvedResolver) Close() error {
|
||||||
var closeErr error
|
var closeErr error
|
||||||
t.closeOnce.Do(func() {
|
t.closeOnce.Do(func() {
|
||||||
|
t.updateAccess.Lock()
|
||||||
|
updateCancel := t.updateCancel
|
||||||
|
t.updateCancel = nil
|
||||||
|
t.updateAccess.Unlock()
|
||||||
|
if updateCancel != nil {
|
||||||
|
updateCancel()
|
||||||
|
}
|
||||||
|
t.updateRunAccess.Lock()
|
||||||
|
t.closed = true
|
||||||
serverSet := t.savedServerSet.Swap(nil)
|
serverSet := t.savedServerSet.Swap(nil)
|
||||||
|
t.updateRunAccess.Unlock()
|
||||||
if serverSet != nil {
|
if serverSet != nil {
|
||||||
closeErr = serverSet.Close()
|
closeErr = serverSet.Close()
|
||||||
}
|
}
|
||||||
@@ -174,7 +188,7 @@ func (t *DBusResolvedResolver) Exchange(ctx context.Context, message *mDNS.Msg)
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
t.updateStatus()
|
t.updateStatus(t.ctx)
|
||||||
refreshedServerSet := t.savedServerSet.Load()
|
refreshedServerSet := t.savedServerSet.Load()
|
||||||
if refreshedServerSet == nil || refreshedServerSet == serverSet {
|
if refreshedServerSet == nil || refreshedServerSet == serverSet {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -196,7 +210,7 @@ func (t *DBusResolvedResolver) ExchangeAsync(ctx context.Context, message *mDNS.
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
t.updateStatus()
|
t.updateStatus(t.ctx)
|
||||||
refreshedServerSet := t.savedServerSet.Load()
|
refreshedServerSet := t.savedServerSet.Load()
|
||||||
if refreshedServerSet == nil || refreshedServerSet == serverSet {
|
if refreshedServerSet == nil || refreshedServerSet == serverSet {
|
||||||
callback(nil, err)
|
callback(nil, err)
|
||||||
@@ -240,18 +254,44 @@ func (t *DBusResolvedResolver) loopUpdateStatus() {
|
|||||||
if !loaded || newOwner == "" {
|
if !loaded || newOwner == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
t.updateStatus()
|
t.postUpdateStatus()
|
||||||
case "org.freedesktop.DBus.Properties.PropertiesChanged":
|
case "org.freedesktop.DBus.Properties.PropertiesChanged":
|
||||||
if !shouldUpdateResolvedServerSet(signal) {
|
if !shouldUpdateResolvedServerSet(signal) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
t.updateStatus()
|
t.postUpdateStatus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *DBusResolvedResolver) updateStatus() {
|
func (t *DBusResolvedResolver) postUpdateStatus() {
|
||||||
serverSet, err := t.checkResolved(context.Background())
|
updateContext, updateCancel := context.WithCancel(t.ctx)
|
||||||
|
t.updateAccess.Lock()
|
||||||
|
previousCancel := t.updateCancel
|
||||||
|
t.updateCancel = updateCancel
|
||||||
|
t.updateAccess.Unlock()
|
||||||
|
if previousCancel != nil {
|
||||||
|
previousCancel()
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
defer updateCancel()
|
||||||
|
t.updateStatus(updateContext)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *DBusResolvedResolver) updateStatus(ctx context.Context) {
|
||||||
|
t.updateRunAccess.Lock()
|
||||||
|
defer t.updateRunAccess.Unlock()
|
||||||
|
if t.closed || ctx.Err() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
serverSet, err := t.checkResolved(ctx)
|
||||||
|
if t.closed || ctx.Err() != nil {
|
||||||
|
if serverSet != nil {
|
||||||
|
_ = serverSet.Close()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
oldServerSet := t.savedServerSet.Swap(serverSet)
|
oldServerSet := t.savedServerSet.Swap(serverSet)
|
||||||
if oldServerSet != nil {
|
if oldServerSet != nil {
|
||||||
_ = oldServerSet.Close()
|
_ = oldServerSet.Close()
|
||||||
@@ -291,7 +331,7 @@ func (t *DBusResolvedResolver) exchangeServerSet(ctx context.Context, message *m
|
|||||||
|
|
||||||
func (t *DBusResolvedResolver) checkResolved(ctx context.Context) (*resolvedServerSet, error) {
|
func (t *DBusResolvedResolver) checkResolved(ctx context.Context) (*resolvedServerSet, error) {
|
||||||
dbusObject := t.systemBus.Object("org.freedesktop.resolve1", "/org/freedesktop/resolve1")
|
dbusObject := t.systemBus.Object("org.freedesktop.resolve1", "/org/freedesktop/resolve1")
|
||||||
err := dbusObject.Call("org.freedesktop.DBus.Peer.Ping", 0).Err
|
err := dbusObject.(*dbus.Object).CallWithContext(ctx, "org.freedesktop.DBus.Peer.Ping", 0).Err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -321,10 +361,18 @@ func (t *DBusResolvedResolver) checkResolved(ctx context.Context) (*resolvedServ
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
err = ctx.Err()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
linkDNSEx, err := loadResolvedLinkDNSEx(linkObject)
|
linkDNSEx, err := loadResolvedLinkDNSEx(linkObject)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
err = ctx.Err()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
linkDNS, err := loadResolvedLinkDNS(linkObject)
|
linkDNS, err := loadResolvedLinkDNS(linkObject)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -570,5 +618,5 @@ func shouldUpdateResolvedServerSet(signal *dbus.Signal) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *DBusResolvedResolver) updateDefaultInterface(defaultInterface *control.Interface, flags int) {
|
func (t *DBusResolvedResolver) updateDefaultInterface(defaultInterface *control.Interface, flags int) {
|
||||||
t.updateStatus()
|
t.postUpdateStatus()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -120,7 +121,7 @@ func (p *linuxPlatformInterface) RequestPermissionForWIFIState() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *linuxPlatformInterface) ReadWIFIState() adapter.WIFIState {
|
func (p *linuxPlatformInterface) ReadWIFIState(ctx context.Context) adapter.WIFIState {
|
||||||
return adapter.WIFIState{}
|
return adapter.WIFIState{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ func (p *windowsPlatformInterface) RequestPermissionForWIFIState() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *windowsPlatformInterface) ReadWIFIState() adapter.WIFIState {
|
func (p *windowsPlatformInterface) ReadWIFIState(ctx context.Context) adapter.WIFIState {
|
||||||
return adapter.WIFIState{}
|
return adapter.WIFIState{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import (
|
|||||||
func connectionRouter(ctx context.Context, network adapter.NetworkManager, trafficManager *trafficcontrol.Manager) http.Handler {
|
func connectionRouter(ctx context.Context, network adapter.NetworkManager, trafficManager *trafficcontrol.Manager) http.Handler {
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.Get("/", getConnections(ctx, trafficManager))
|
r.Get("/", getConnections(ctx, trafficManager))
|
||||||
r.Delete("/", closeAllConnections(network, trafficManager))
|
r.Delete("/", closeAllConnections(ctx, network, trafficManager))
|
||||||
r.Delete("/{id}", closeConnection(trafficManager))
|
r.Delete("/{id}", closeConnection(trafficManager))
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@@ -170,10 +170,10 @@ func closeConnection(trafficManager *trafficcontrol.Manager) func(w http.Respons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func closeAllConnections(network adapter.NetworkManager, trafficManager *trafficcontrol.Manager) func(w http.ResponseWriter, r *http.Request) {
|
func closeAllConnections(ctx context.Context, network adapter.NetworkManager, trafficManager *trafficcontrol.Manager) func(w http.ResponseWriter, r *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
trafficManager.CloseAllConnections()
|
trafficManager.CloseAllConnections()
|
||||||
network.ResetNetwork()
|
network.ResetNetwork(ctx)
|
||||||
render.NoContent(w, r)
|
render.NoContent(w, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ func (s *CommandServer) ResetNetwork() {
|
|||||||
if instance == nil || instance.Box() == nil {
|
if instance == nil || instance.Box() == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
instance.Box().Network().ResetNetwork()
|
instance.Box().Network().ResetNetwork(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *CommandServer) UpdateWIFIState() {
|
func (s *CommandServer) UpdateWIFIState() {
|
||||||
@@ -270,7 +270,7 @@ func (s *CommandServer) UpdateWIFIState() {
|
|||||||
if instance == nil || instance.Box() == nil {
|
if instance == nil || instance.Box() == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
instance.Box().Network().UpdateWIFIState()
|
instance.Box().Network().UpdateWIFIState(context.Background())
|
||||||
}
|
}
|
||||||
|
|
||||||
type platformHandler CommandServer
|
type platformHandler CommandServer
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ func (s *platformInterfaceStub) UsePlatformWIFIMonitor() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *platformInterfaceStub) ReadWIFIState() adapter.WIFIState {
|
func (s *platformInterfaceStub) ReadWIFIState(ctx context.Context) adapter.WIFIState {
|
||||||
return adapter.WIFIState{}
|
return adapter.WIFIState{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package libbox
|
package libbox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
@@ -175,7 +176,7 @@ func (w *platformInterfaceWrapper) UsePlatformWIFIMonitor() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *platformInterfaceWrapper) ReadWIFIState() adapter.WIFIState {
|
func (w *platformInterfaceWrapper) ReadWIFIState(ctx context.Context) adapter.WIFIState {
|
||||||
wifiState := w.iif.ReadWIFIState()
|
wifiState := w.iif.ReadWIFIState()
|
||||||
if wifiState == nil {
|
if wifiState == nil {
|
||||||
return adapter.WIFIState{}
|
return adapter.WIFIState{}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ func (i *Inbound) Start(stage adapter.StartStage) error {
|
|||||||
return i.listener.Start()
|
return i.listener.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Inbound) InterfaceUpdated() {
|
func (i *Inbound) InterfaceUpdated(ctx context.Context) {
|
||||||
i.udpNat.Purge()
|
i.udpNat.Purge()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ func (h *Outbound) fetchMyAddresses() {
|
|||||||
h.myAddresses.Store(myAddresses)
|
h.myAddresses.Store(myAddresses)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) InterfaceUpdated() {
|
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
|
||||||
h.fetchMyAddresses()
|
h.fetchMyAddresses()
|
||||||
if h.icmpPort != nil {
|
if h.icmpPort != nil {
|
||||||
h.icmpPort.Close()
|
h.icmpPort.Close()
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ type URLTest struct {
|
|||||||
tolerance uint16
|
tolerance uint16
|
||||||
idleTimeout time.Duration
|
idleTimeout time.Duration
|
||||||
group *URLTestGroup
|
group *URLTestGroup
|
||||||
|
checkAccess sync.Mutex
|
||||||
interruptExternalConnections bool
|
interruptExternalConnections bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,14 +115,14 @@ func (s *URLTest) URLTest(ctx context.Context) (map[string]uint16, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *URLTest) CheckOutbounds() {
|
func (s *URLTest) CheckOutbounds() {
|
||||||
s.group.CheckOutbounds(true)
|
s.group.CheckOutbounds(s.ctx, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *URLTest) PerformUpdateCheck() {
|
func (s *URLTest) PerformUpdateCheck() {
|
||||||
s.group.performUpdateCheck()
|
s.group.performUpdateCheck()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *URLTest) InterfaceUpdated() {
|
func (s *URLTest) InterfaceUpdated(ctx context.Context) {
|
||||||
group := s.group
|
group := s.group
|
||||||
if group == nil {
|
if group == nil {
|
||||||
return
|
return
|
||||||
@@ -129,7 +130,14 @@ func (s *URLTest) InterfaceUpdated() {
|
|||||||
if group.pause.IsDevicePaused() || group.pause.IsNetworkPaused() {
|
if group.pause.IsDevicePaused() || group.pause.IsNetworkPaused() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go group.CheckOutbounds(true)
|
go func() {
|
||||||
|
s.checkAccess.Lock()
|
||||||
|
defer s.checkAccess.Unlock()
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
group.CheckOutbounds(ctx, true)
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *URLTest) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (s *URLTest) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
@@ -250,7 +258,7 @@ func (g *URLTestGroup) PostStart() {
|
|||||||
defer g.access.Unlock()
|
defer g.access.Unlock()
|
||||||
g.started = true
|
g.started = true
|
||||||
g.lastActive.Store(time.Now())
|
g.lastActive.Store(time.Now())
|
||||||
go g.CheckOutbounds(false)
|
go g.CheckOutbounds(g.ctx, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) Touch() {
|
func (g *URLTestGroup) Touch() {
|
||||||
@@ -330,7 +338,7 @@ func (g *URLTestGroup) Select(network string) (adapter.Outbound, bool) {
|
|||||||
func (g *URLTestGroup) loopCheck(ticker *time.Ticker, closeChan <-chan struct{}) {
|
func (g *URLTestGroup) loopCheck(ticker *time.Ticker, closeChan <-chan struct{}) {
|
||||||
if time.Since(g.lastActive.Load()) > g.interval {
|
if time.Since(g.lastActive.Load()) > g.interval {
|
||||||
g.lastActive.Store(time.Now())
|
g.lastActive.Store(time.Now())
|
||||||
g.CheckOutbounds(false)
|
g.CheckOutbounds(g.ctx, false)
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@@ -349,12 +357,12 @@ func (g *URLTestGroup) loopCheck(ticker *time.Ticker, closeChan <-chan struct{})
|
|||||||
g.access.Unlock()
|
g.access.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.CheckOutbounds(false)
|
g.CheckOutbounds(g.ctx, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) CheckOutbounds(force bool) {
|
func (g *URLTestGroup) CheckOutbounds(ctx context.Context, force bool) {
|
||||||
_, _ = g.urlTest(g.ctx, force)
|
_, _ = g.urlTest(ctx, force)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) URLTest(ctx context.Context) (map[string]uint16, error) {
|
func (g *URLTestGroup) URLTest(ctx context.Context) (map[string]uint16, error) {
|
||||||
@@ -391,7 +399,7 @@ func (g *URLTestGroup) urlTest(ctx context.Context, force bool) (map[string]uint
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
b.Go(realTag, func() (any, error) {
|
b.Go(realTag, func() (any, error) {
|
||||||
testCtx, cancel := context.WithTimeout(g.ctx, C.TCPTimeout)
|
testCtx, cancel := context.WithTimeout(ctx, C.TCPTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
testChan := make(chan urlTestResult, 1)
|
testChan := make(chan urlTestResult, 1)
|
||||||
go func() {
|
go func() {
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
|
|||||||
return h.client.ListenPacket(ctx, destination)
|
return h.client.ListenPacket(ctx, destination)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) InterfaceUpdated() {
|
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
|
||||||
h.client.CloseWithError(E.New("network changed"))
|
h.client.CloseWithError(E.New("network changed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ func (h *Inbound) Start(stage adapter.StartStage) error {
|
|||||||
return h.service.Start(packetConn)
|
return h.service.Start(packetConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Inbound) InterfaceUpdated() {
|
func (h *Inbound) InterfaceUpdated(ctx context.Context) {
|
||||||
h.service.Reset()
|
h.service.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
|
|||||||
return h.client.ListenPacket(ctx)
|
return h.client.ListenPacket(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) InterfaceUpdated() {
|
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
|
||||||
h.client.CloseWithError(E.New("network changed"))
|
h.client.CloseWithError(E.New("network changed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
|
|||||||
return h.uotClient.ListenPacket(ctx, destination)
|
return h.uotClient.ListenPacket(ctx, destination)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) InterfaceUpdated() {
|
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
|
||||||
h.client.Engine().CloseAllConnections()
|
h.client.Engine().CloseAllConnections()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -486,7 +486,7 @@ func (e *Endpoint) Close() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Endpoint) InterfaceUpdated() {
|
func (e *Endpoint) InterfaceUpdated(ctx context.Context) {
|
||||||
e.client.RestartSession()
|
e.client.RestartSession()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -658,7 +658,7 @@ func (c *ClientEndpoint) Close() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClientEndpoint) InterfaceUpdated() {
|
func (c *ClientEndpoint) InterfaceUpdated(ctx context.Context) {
|
||||||
c.client.RestartSession()
|
c.client.RestartSession()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ func (t *TProxy) Start(stage adapter.StartStage) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TProxy) InterfaceUpdated() {
|
func (t *TProxy) InterfaceUpdated(ctx context.Context) {
|
||||||
t.udpNat.Purge()
|
t.udpNat.Purge()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ func (h *Outbound) MultiplexEnabled() bool {
|
|||||||
return h.multiplexDialer != nil
|
return h.multiplexDialer != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) InterfaceUpdated() {
|
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
|
||||||
if h.multiplexDialer != nil {
|
if h.multiplexDialer != nil {
|
||||||
h.multiplexDialer.Reset()
|
h.multiplexDialer.Reset()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
|
|||||||
return packetConn, nil
|
return packetConn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) InterfaceUpdated() {
|
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
|
||||||
h.client.Reset()
|
h.client.Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ func (s *Outbound) connect(ctx context.Context) (client *ssh.Client, err error)
|
|||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Outbound) InterfaceUpdated() {
|
func (s *Outbound) InterfaceUpdated(ctx context.Context) {
|
||||||
common.Close(s.clientConn)
|
common.Close(s.clientConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -740,7 +740,7 @@ func (t *Endpoint) Close() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Endpoint) InterfaceUpdated() {
|
func (t *Endpoint) InterfaceUpdated(ctx context.Context) {
|
||||||
if !t.started.Load() {
|
if !t.started.Load() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ func (h *Outbound) MultiplexEnabled() bool {
|
|||||||
return h.multiplexDialer != nil
|
return h.multiplexDialer != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) InterfaceUpdated() {
|
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
|
||||||
if h.transport != nil {
|
if h.transport != nil {
|
||||||
h.transport.Close()
|
h.transport.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) InterfaceUpdated() {
|
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
|
||||||
_ = h.client.CloseWithError(E.New("network changed"))
|
_ = h.client.CloseWithError(E.New("network changed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -505,7 +505,7 @@ func (t *Inbound) updateRouteAddressSet(it adapter.RuleSet) {
|
|||||||
t.routeExcludeAddressSet = nil
|
t.routeExcludeAddressSet = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Inbound) InterfaceUpdated() {
|
func (t *Inbound) InterfaceUpdated(ctx context.Context) {
|
||||||
tunStack := t.tunStack
|
tunStack := t.tunStack
|
||||||
if tunStack != nil {
|
if tunStack != nil {
|
||||||
tunStack.ResetNetwork()
|
tunStack.ResetNetwork()
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ func (h *Outbound) MultiplexEnabled() bool {
|
|||||||
return h.multiplexDialer != nil
|
return h.multiplexDialer != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) InterfaceUpdated() {
|
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
|
||||||
if h.transport != nil {
|
if h.transport != nil {
|
||||||
h.transport.Close()
|
h.transport.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ func (h *Outbound) MultiplexEnabled() bool {
|
|||||||
return h.multiplexDialer != nil
|
return h.multiplexDialer != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) InterfaceUpdated() {
|
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
|
||||||
if h.transport != nil {
|
if h.transport != nil {
|
||||||
h.transport.Close()
|
h.transport.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ type Endpoint struct {
|
|||||||
logger logger.ContextLogger
|
logger logger.ContextLogger
|
||||||
localAddresses []netip.Prefix
|
localAddresses []netip.Prefix
|
||||||
endpoint *wireguard.Endpoint
|
endpoint *wireguard.Endpoint
|
||||||
|
bindAccess sync.Mutex
|
||||||
started atomic.Bool
|
started atomic.Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,14 +147,25 @@ func (w *Endpoint) Start(stage adapter.StartStage) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *Endpoint) Close() error {
|
func (w *Endpoint) Close() error {
|
||||||
|
w.bindAccess.Lock()
|
||||||
w.started.Store(false)
|
w.started.Store(false)
|
||||||
|
w.bindAccess.Unlock()
|
||||||
return w.endpoint.Close()
|
return w.endpoint.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Endpoint) InterfaceUpdated() {
|
func (w *Endpoint) InterfaceUpdated(ctx context.Context) {
|
||||||
if !w.started.Load() {
|
if !w.started.Load() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
go w.updateBind(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Endpoint) updateBind(ctx context.Context) {
|
||||||
|
w.bindAccess.Lock()
|
||||||
|
defer w.bindAccess.Unlock()
|
||||||
|
if ctx.Err() != nil || !w.started.Load() {
|
||||||
|
return
|
||||||
|
}
|
||||||
err := w.endpoint.BindUpdate()
|
err := w.endpoint.BindUpdate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.logger.Error(E.Cause(err, "update bind"))
|
w.logger.Error(E.Cause(err, "update bind"))
|
||||||
|
|||||||
+98
-39
@@ -34,32 +34,37 @@ import (
|
|||||||
var _ adapter.NetworkManager = (*NetworkManager)(nil)
|
var _ adapter.NetworkManager = (*NetworkManager)(nil)
|
||||||
|
|
||||||
type NetworkManager struct {
|
type NetworkManager struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
logger logger.ContextLogger
|
logger logger.ContextLogger
|
||||||
router adapter.Router
|
router adapter.Router
|
||||||
interfaceFinder *control.DefaultInterfaceFinder
|
interfaceFinder *control.DefaultInterfaceFinder
|
||||||
networkInterfaces common.TypedValue[[]adapter.NetworkInterface]
|
networkInterfaces common.TypedValue[[]adapter.NetworkInterface]
|
||||||
autoDetectInterface bool
|
autoDetectInterface bool
|
||||||
defaultOptions adapter.NetworkOptions
|
defaultOptions adapter.NetworkOptions
|
||||||
autoRedirectOutputMark uint32
|
autoRedirectOutputMark uint32
|
||||||
networkMonitor tun.NetworkUpdateMonitor
|
networkMonitor tun.NetworkUpdateMonitor
|
||||||
interfaceMonitor tun.DefaultInterfaceMonitor
|
interfaceMonitor tun.DefaultInterfaceMonitor
|
||||||
packageManager tun.PackageManager
|
packageManager tun.PackageManager
|
||||||
powerListener winpowrprof.EventListener
|
powerListener winpowrprof.EventListener
|
||||||
pauseManager pause.Manager
|
pauseManager pause.Manager
|
||||||
platformInterface adapter.PlatformInterface
|
platformInterface adapter.PlatformInterface
|
||||||
connectionManager adapter.ConnectionManager
|
connectionManager adapter.ConnectionManager
|
||||||
endpoint adapter.EndpointManager
|
endpoint adapter.EndpointManager
|
||||||
inbound adapter.InboundManager
|
inbound adapter.InboundManager
|
||||||
outbound adapter.OutboundManager
|
outbound adapter.OutboundManager
|
||||||
needWIFIState bool
|
needWIFIState bool
|
||||||
wifiMonitor settings.WIFIMonitor
|
wifiMonitor settings.WIFIMonitor
|
||||||
wifiState adapter.WIFIState
|
wifiState adapter.WIFIState
|
||||||
networkEnvironment uint64
|
networkEnvironment uint64
|
||||||
stateAccess sync.RWMutex
|
stateAccess sync.RWMutex
|
||||||
environmentUpdateAccess sync.Mutex
|
environmentUpdateAccess sync.Mutex
|
||||||
environmentUpdateTimer *time.Timer
|
environmentUpdateTimer *time.Timer
|
||||||
started bool
|
interfaceUpdateAccess sync.Mutex
|
||||||
|
interfaceUpdateCancel context.CancelFunc
|
||||||
|
interfaceUpdateRunAccess sync.Mutex
|
||||||
|
powerUpdateAccess sync.Mutex
|
||||||
|
powerUpdateCancel context.CancelFunc
|
||||||
|
started bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNetworkManager(ctx context.Context, logger logger.ContextLogger, options option.RouteOptions, dnsOptions option.DNSOptions) (*NetworkManager, error) {
|
func NewNetworkManager(ctx context.Context, logger logger.ContextLogger, options option.RouteOptions, dnsOptions option.DNSOptions) (*NetworkManager, error) {
|
||||||
@@ -251,6 +256,14 @@ func (r *NetworkManager) Close() error {
|
|||||||
})
|
})
|
||||||
monitor.Finish()
|
monitor.Finish()
|
||||||
}
|
}
|
||||||
|
r.interfaceUpdateAccess.Lock()
|
||||||
|
interfaceUpdateCancel := r.interfaceUpdateCancel
|
||||||
|
r.interfaceUpdateCancel = nil
|
||||||
|
r.interfaceUpdateAccess.Unlock()
|
||||||
|
if interfaceUpdateCancel != nil {
|
||||||
|
interfaceUpdateCancel()
|
||||||
|
}
|
||||||
|
r.cancelPowerUpdate()
|
||||||
if r.networkMonitor != nil {
|
if r.networkMonitor != nil {
|
||||||
monitor.Start("close network monitor")
|
monitor.Start("close network monitor")
|
||||||
err = E.Append(err, r.networkMonitor.Close(), func(err error) error {
|
err = E.Append(err, r.networkMonitor.Close(), func(err error) error {
|
||||||
@@ -455,19 +468,19 @@ func (r *NetworkManager) onWIFIStateChanged(state adapter.WIFIState) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *NetworkManager) UpdateWIFIState() {
|
func (r *NetworkManager) UpdateWIFIState(ctx context.Context) {
|
||||||
var state adapter.WIFIState
|
var state adapter.WIFIState
|
||||||
if r.wifiMonitor != nil {
|
if r.wifiMonitor != nil {
|
||||||
state = r.wifiMonitor.ReadWIFIState()
|
state = r.wifiMonitor.ReadWIFIState(ctx)
|
||||||
} else if r.platformInterface != nil && r.platformInterface.UsePlatformWIFIMonitor() {
|
} else if r.platformInterface != nil && r.platformInterface.UsePlatformWIFIMonitor() {
|
||||||
state = r.platformInterface.ReadWIFIState()
|
state = r.platformInterface.ReadWIFIState(ctx)
|
||||||
} else {
|
} else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r.onWIFIStateChanged(state)
|
r.onWIFIStateChanged(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *NetworkManager) ResetNetwork() {
|
func (r *NetworkManager) ResetNetwork(ctx context.Context) {
|
||||||
if r.connectionManager != nil {
|
if r.connectionManager != nil {
|
||||||
r.connectionManager.CloseAll()
|
r.connectionManager.CloseAll()
|
||||||
}
|
}
|
||||||
@@ -475,21 +488,21 @@ func (r *NetworkManager) ResetNetwork() {
|
|||||||
for _, endpoint := range r.endpoint.Endpoints() {
|
for _, endpoint := range r.endpoint.Endpoints() {
|
||||||
listener, isListener := endpoint.(adapter.InterfaceUpdateListener)
|
listener, isListener := endpoint.(adapter.InterfaceUpdateListener)
|
||||||
if isListener {
|
if isListener {
|
||||||
listener.InterfaceUpdated()
|
listener.InterfaceUpdated(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, inbound := range r.inbound.Inbounds() {
|
for _, inbound := range r.inbound.Inbounds() {
|
||||||
listener, isListener := inbound.(adapter.InterfaceUpdateListener)
|
listener, isListener := inbound.(adapter.InterfaceUpdateListener)
|
||||||
if isListener {
|
if isListener {
|
||||||
listener.InterfaceUpdated()
|
listener.InterfaceUpdated(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, outbound := range r.outbound.Outbounds() {
|
for _, outbound := range r.outbound.Outbounds() {
|
||||||
listener, isListener := outbound.(adapter.InterfaceUpdateListener)
|
listener, isListener := outbound.(adapter.InterfaceUpdateListener)
|
||||||
if isListener {
|
if isListener {
|
||||||
listener.InterfaceUpdated()
|
listener.InterfaceUpdated(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,8 +515,27 @@ func (r *NetworkManager) notifyInterfaceUpdate(defaultInterface *control.Interfa
|
|||||||
r.logger.Error("missing default interface")
|
r.logger.Error("missing default interface")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
r.pauseManager.NetworkWake()
|
r.pauseManager.NetworkWake()
|
||||||
|
updateContext, updateCancel := context.WithCancel(r.ctx)
|
||||||
|
r.interfaceUpdateAccess.Lock()
|
||||||
|
previousCancel := r.interfaceUpdateCancel
|
||||||
|
r.interfaceUpdateCancel = updateCancel
|
||||||
|
r.interfaceUpdateAccess.Unlock()
|
||||||
|
if previousCancel != nil {
|
||||||
|
previousCancel()
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
defer updateCancel()
|
||||||
|
r.updateInterface(updateContext, defaultInterface)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) updateInterface(ctx context.Context, defaultInterface *control.Interface) {
|
||||||
|
r.interfaceUpdateRunAccess.Lock()
|
||||||
|
defer r.interfaceUpdateRunAccess.Unlock()
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
var options []string
|
var options []string
|
||||||
options = append(options, F.ToString("index ", defaultInterface.Index))
|
options = append(options, F.ToString("index ", defaultInterface.Index))
|
||||||
if C.IsAndroid && r.platformInterface == nil {
|
if C.IsAndroid && r.platformInterface == nil {
|
||||||
@@ -531,20 +563,26 @@ func (r *NetworkManager) notifyInterfaceUpdate(defaultInterface *control.Interfa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.logger.Info("updated default interface ", defaultInterface.Name, ", ", strings.Join(options, ", "))
|
r.logger.Info("updated default interface ", defaultInterface.Name, ", ", strings.Join(options, ", "))
|
||||||
r.UpdateWIFIState()
|
r.UpdateWIFIState(ctx)
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
r.updateNetworkEnvironment()
|
r.updateNetworkEnvironment()
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
if !r.started {
|
if !r.started {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r.ResetNetwork()
|
r.ResetNetwork(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *NetworkManager) notifyWindowsPowerEvent(event int) {
|
func (r *NetworkManager) notifyWindowsPowerEvent(event int) {
|
||||||
switch event {
|
switch event {
|
||||||
case winpowrprof.EVENT_SUSPEND:
|
case winpowrprof.EVENT_SUSPEND:
|
||||||
r.pauseManager.DevicePause()
|
r.pauseManager.DevicePause()
|
||||||
r.ResetNetwork()
|
r.cancelPowerUpdate()
|
||||||
|
r.ResetNetwork(r.ctx)
|
||||||
case winpowrprof.EVENT_RESUME:
|
case winpowrprof.EVENT_RESUME:
|
||||||
if !r.pauseManager.IsDevicePaused() {
|
if !r.pauseManager.IsDevicePaused() {
|
||||||
return
|
return
|
||||||
@@ -552,7 +590,28 @@ func (r *NetworkManager) notifyWindowsPowerEvent(event int) {
|
|||||||
fallthrough
|
fallthrough
|
||||||
case winpowrprof.EVENT_RESUME_AUTOMATIC:
|
case winpowrprof.EVENT_RESUME_AUTOMATIC:
|
||||||
r.pauseManager.DeviceWake()
|
r.pauseManager.DeviceWake()
|
||||||
r.ResetNetwork()
|
updateContext, updateCancel := context.WithCancel(r.ctx)
|
||||||
|
r.powerUpdateAccess.Lock()
|
||||||
|
previousCancel := r.powerUpdateCancel
|
||||||
|
r.powerUpdateCancel = updateCancel
|
||||||
|
r.powerUpdateAccess.Unlock()
|
||||||
|
if previousCancel != nil {
|
||||||
|
previousCancel()
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
defer updateCancel()
|
||||||
|
r.ResetNetwork(updateContext)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *NetworkManager) cancelPowerUpdate() {
|
||||||
|
r.powerUpdateAccess.Lock()
|
||||||
|
previousCancel := r.powerUpdateCancel
|
||||||
|
r.powerUpdateCancel = nil
|
||||||
|
r.powerUpdateAccess.Unlock()
|
||||||
|
if previousCancel != nil {
|
||||||
|
previousCancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package oomkiller
|
package oomkiller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
runtimeDebug "runtime/debug"
|
runtimeDebug "runtime/debug"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -203,14 +204,14 @@ func (t *adaptiveTimer) poll() {
|
|||||||
t.logger.Warn("memory growth rate critical (report only), usage: ", byteformats.FormatMemoryBytes(sample.usage), t.logDetails(sample))
|
t.logger.Warn("memory growth rate critical (report only), usage: ", byteformats.FormatMemoryBytes(sample.usage), t.logDetails(sample))
|
||||||
} else {
|
} else {
|
||||||
t.logger.Error("memory growth rate critical, usage: ", byteformats.FormatMemoryBytes(sample.usage), t.logDetails(sample), ", resetting network")
|
t.logger.Error("memory growth rate critical, usage: ", byteformats.FormatMemoryBytes(sample.usage), t.logDetails(sample), ", resetting network")
|
||||||
t.network.ResetNetwork()
|
t.network.ResetNetwork(context.Background())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if t.killerDisabled {
|
if t.killerDisabled {
|
||||||
t.logger.Warn("memory threshold reached (report only), usage: ", byteformats.FormatMemoryBytes(sample.usage), t.logDetails(sample))
|
t.logger.Warn("memory threshold reached (report only), usage: ", byteformats.FormatMemoryBytes(sample.usage), t.logDetails(sample))
|
||||||
} else {
|
} else {
|
||||||
t.logger.Error("memory threshold reached, usage: ", byteformats.FormatMemoryBytes(sample.usage), t.logDetails(sample), ", resetting network")
|
t.logger.Error("memory threshold reached, usage: ", byteformats.FormatMemoryBytes(sample.usage), t.logDetails(sample), ", resetting network")
|
||||||
t.network.ResetNetwork()
|
t.network.ResetNetwork(context.Background())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
badCleanup()
|
badCleanup()
|
||||||
|
|||||||
Reference in New Issue
Block a user