Handle network update callbacks in background

This commit is contained in:
世界
2026-08-30 17:41:46 +08:00
parent cfddedb3da
commit 6720a27109
46 changed files with 382 additions and 134 deletions
+1 -1
View File
@@ -77,7 +77,7 @@ func (i *Inbound) Start(stage adapter.StartStage) error {
return i.listener.Start()
}
func (i *Inbound) InterfaceUpdated() {
func (i *Inbound) InterfaceUpdated(ctx context.Context) {
i.udpNat.Purge()
}
+1 -1
View File
@@ -121,7 +121,7 @@ func (h *Outbound) fetchMyAddresses() {
h.myAddresses.Store(myAddresses)
}
func (h *Outbound) InterfaceUpdated() {
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
h.fetchMyAddresses()
if h.icmpPort != nil {
h.icmpPort.Close()
+17 -9
View File
@@ -45,6 +45,7 @@ type URLTest struct {
tolerance uint16
idleTimeout time.Duration
group *URLTestGroup
checkAccess sync.Mutex
interruptExternalConnections bool
}
@@ -114,14 +115,14 @@ func (s *URLTest) URLTest(ctx context.Context) (map[string]uint16, error) {
}
func (s *URLTest) CheckOutbounds() {
s.group.CheckOutbounds(true)
s.group.CheckOutbounds(s.ctx, true)
}
func (s *URLTest) PerformUpdateCheck() {
s.group.performUpdateCheck()
}
func (s *URLTest) InterfaceUpdated() {
func (s *URLTest) InterfaceUpdated(ctx context.Context) {
group := s.group
if group == nil {
return
@@ -129,7 +130,14 @@ func (s *URLTest) InterfaceUpdated() {
if group.pause.IsDevicePaused() || group.pause.IsNetworkPaused() {
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) {
@@ -250,7 +258,7 @@ func (g *URLTestGroup) PostStart() {
defer g.access.Unlock()
g.started = true
g.lastActive.Store(time.Now())
go g.CheckOutbounds(false)
go g.CheckOutbounds(g.ctx, false)
}
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{}) {
if time.Since(g.lastActive.Load()) > g.interval {
g.lastActive.Store(time.Now())
g.CheckOutbounds(false)
g.CheckOutbounds(g.ctx, false)
}
for {
select {
@@ -349,12 +357,12 @@ func (g *URLTestGroup) loopCheck(ticker *time.Ticker, closeChan <-chan struct{})
g.access.Unlock()
return
}
g.CheckOutbounds(false)
g.CheckOutbounds(g.ctx, false)
}
}
func (g *URLTestGroup) CheckOutbounds(force bool) {
_, _ = g.urlTest(g.ctx, force)
func (g *URLTestGroup) CheckOutbounds(ctx context.Context, force bool) {
_, _ = g.urlTest(ctx, force)
}
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
}
b.Go(realTag, func() (any, error) {
testCtx, cancel := context.WithTimeout(g.ctx, C.TCPTimeout)
testCtx, cancel := context.WithTimeout(ctx, C.TCPTimeout)
defer cancel()
testChan := make(chan urlTestResult, 1)
go func() {
+1 -1
View File
@@ -115,7 +115,7 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
return h.client.ListenPacket(ctx, destination)
}
func (h *Outbound) InterfaceUpdated() {
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
h.client.CloseWithError(E.New("network changed"))
}
+1 -1
View File
@@ -281,7 +281,7 @@ func (h *Inbound) Start(stage adapter.StartStage) error {
return h.service.Start(packetConn)
}
func (h *Inbound) InterfaceUpdated() {
func (h *Inbound) InterfaceUpdated(ctx context.Context) {
h.service.Reset()
}
+1 -1
View File
@@ -203,7 +203,7 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
return h.client.ListenPacket(ctx)
}
func (h *Outbound) InterfaceUpdated() {
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
h.client.CloseWithError(E.New("network changed"))
}
+1 -1
View File
@@ -254,7 +254,7 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
return h.uotClient.ListenPacket(ctx, destination)
}
func (h *Outbound) InterfaceUpdated() {
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
h.client.Engine().CloseAllConnections()
}
+1 -1
View File
@@ -486,7 +486,7 @@ func (e *Endpoint) Close() error {
return err
}
func (e *Endpoint) InterfaceUpdated() {
func (e *Endpoint) InterfaceUpdated(ctx context.Context) {
e.client.RestartSession()
}
+1 -1
View File
@@ -658,7 +658,7 @@ func (c *ClientEndpoint) Close() error {
return err
}
func (c *ClientEndpoint) InterfaceUpdated() {
func (c *ClientEndpoint) InterfaceUpdated(ctx context.Context) {
c.client.RestartSession()
}
+1 -1
View File
@@ -85,7 +85,7 @@ func (t *TProxy) Start(stage adapter.StartStage) error {
return err
}
func (t *TProxy) InterfaceUpdated() {
func (t *TProxy) InterfaceUpdated(ctx context.Context) {
t.udpNat.Purge()
}
+1 -1
View File
@@ -130,7 +130,7 @@ func (h *Outbound) MultiplexEnabled() bool {
return h.multiplexDialer != nil
}
func (h *Outbound) InterfaceUpdated() {
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
if h.multiplexDialer != nil {
h.multiplexDialer.Reset()
}
+1 -1
View File
@@ -139,7 +139,7 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n
return packetConn, nil
}
func (h *Outbound) InterfaceUpdated() {
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
h.client.Reset()
}
+1 -1
View File
@@ -206,7 +206,7 @@ func (s *Outbound) connect(ctx context.Context) (client *ssh.Client, err error)
return client, nil
}
func (s *Outbound) InterfaceUpdated() {
func (s *Outbound) InterfaceUpdated(ctx context.Context) {
common.Close(s.clientConn)
}
+1 -1
View File
@@ -740,7 +740,7 @@ func (t *Endpoint) Close() error {
return err
}
func (t *Endpoint) InterfaceUpdated() {
func (t *Endpoint) InterfaceUpdated(ctx context.Context) {
if !t.started.Load() {
return
}
+1 -1
View File
@@ -113,7 +113,7 @@ func (h *Outbound) MultiplexEnabled() bool {
return h.multiplexDialer != nil
}
func (h *Outbound) InterfaceUpdated() {
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
if h.transport != nil {
h.transport.Close()
}
+1 -1
View File
@@ -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"))
}
+1 -1
View File
@@ -505,7 +505,7 @@ func (t *Inbound) updateRouteAddressSet(it adapter.RuleSet) {
t.routeExcludeAddressSet = nil
}
func (t *Inbound) InterfaceUpdated() {
func (t *Inbound) InterfaceUpdated(ctx context.Context) {
tunStack := t.tunStack
if tunStack != nil {
tunStack.ResetNetwork()
+1 -1
View File
@@ -133,7 +133,7 @@ func (h *Outbound) MultiplexEnabled() bool {
return h.multiplexDialer != nil
}
func (h *Outbound) InterfaceUpdated() {
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
if h.transport != nil {
h.transport.Close()
}
+1 -1
View File
@@ -111,7 +111,7 @@ func (h *Outbound) MultiplexEnabled() bool {
return h.multiplexDialer != nil
}
func (h *Outbound) InterfaceUpdated() {
func (h *Outbound) InterfaceUpdated(ctx context.Context) {
if h.transport != nil {
h.transport.Close()
}
+14 -1
View File
@@ -4,6 +4,7 @@ import (
"context"
"net"
"net/netip"
"sync"
"sync/atomic"
"time"
@@ -42,6 +43,7 @@ type Endpoint struct {
logger logger.ContextLogger
localAddresses []netip.Prefix
endpoint *wireguard.Endpoint
bindAccess sync.Mutex
started atomic.Bool
}
@@ -145,14 +147,25 @@ func (w *Endpoint) Start(stage adapter.StartStage) error {
}
func (w *Endpoint) Close() error {
w.bindAccess.Lock()
w.started.Store(false)
w.bindAccess.Unlock()
return w.endpoint.Close()
}
func (w *Endpoint) InterfaceUpdated() {
func (w *Endpoint) InterfaceUpdated(ctx context.Context) {
if !w.started.Load() {
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()
if err != nil {
w.logger.Error(E.Cause(err, "update bind"))