mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-06-04 18:27:30 +03:00
Fix URLTest outbound
This commit is contained in:
@@ -3,7 +3,6 @@ package outbound
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -38,7 +37,6 @@ type URLTest struct {
|
||||
tolerance uint16
|
||||
group *URLTestGroup
|
||||
interruptExternalConnections bool
|
||||
started bool
|
||||
}
|
||||
|
||||
func NewURLTest(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.URLTestOutboundOptions) (*URLTest, error) {
|
||||
@@ -84,8 +82,7 @@ func (s *URLTest) Start() error {
|
||||
}
|
||||
|
||||
func (s *URLTest) PostStart() error {
|
||||
s.started = true
|
||||
go s.CheckOutbounds()
|
||||
s.group.PostStart()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -103,8 +100,8 @@ func (s *URLTest) All() []string {
|
||||
return s.tags
|
||||
}
|
||||
|
||||
func (s *URLTest) URLTest(ctx context.Context, link string) (map[string]uint16, error) {
|
||||
return s.group.URLTest(ctx, link)
|
||||
func (s *URLTest) URLTest(ctx context.Context) (map[string]uint16, error) {
|
||||
return s.group.URLTest(ctx)
|
||||
}
|
||||
|
||||
func (s *URLTest) CheckOutbounds() {
|
||||
@@ -112,9 +109,7 @@ func (s *URLTest) CheckOutbounds() {
|
||||
}
|
||||
|
||||
func (s *URLTest) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
if s.started {
|
||||
s.group.Start()
|
||||
}
|
||||
s.group.Touch()
|
||||
outbound := s.group.Select(network)
|
||||
conn, err := outbound.DialContext(ctx, network, destination)
|
||||
if err == nil {
|
||||
@@ -126,9 +121,7 @@ func (s *URLTest) DialContext(ctx context.Context, network string, destination M
|
||||
}
|
||||
|
||||
func (s *URLTest) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||
if s.started {
|
||||
s.group.Start()
|
||||
}
|
||||
s.group.Touch()
|
||||
outbound := s.group.Select(N.NetworkUDP)
|
||||
conn, err := outbound.ListenPacket(ctx, destination)
|
||||
if err == nil {
|
||||
@@ -170,9 +163,11 @@ type URLTestGroup struct {
|
||||
interruptGroup *interrupt.Group
|
||||
interruptExternalConnections bool
|
||||
|
||||
access sync.Mutex
|
||||
ticker *time.Ticker
|
||||
close chan struct{}
|
||||
access sync.Mutex
|
||||
ticker *time.Ticker
|
||||
close chan struct{}
|
||||
started bool
|
||||
lastActive atomic.TypedValue[time.Time]
|
||||
}
|
||||
|
||||
func NewURLTestGroup(
|
||||
@@ -214,8 +209,18 @@ func NewURLTestGroup(
|
||||
}
|
||||
}
|
||||
|
||||
func (g *URLTestGroup) Start() {
|
||||
func (g *URLTestGroup) PostStart() {
|
||||
g.started = true
|
||||
g.lastActive.Store(time.Now())
|
||||
go g.CheckOutbounds(false)
|
||||
}
|
||||
|
||||
func (g *URLTestGroup) Touch() {
|
||||
if !g.started {
|
||||
return
|
||||
}
|
||||
if g.ticker != nil {
|
||||
g.lastActive.Store(time.Now())
|
||||
return
|
||||
}
|
||||
g.access.Lock()
|
||||
@@ -266,51 +271,30 @@ func (g *URLTestGroup) Select(network string) adapter.Outbound {
|
||||
return minOutbound
|
||||
}
|
||||
|
||||
func (g *URLTestGroup) Fallback(used adapter.Outbound) []adapter.Outbound {
|
||||
outbounds := make([]adapter.Outbound, 0, len(g.outbounds)-1)
|
||||
for _, detour := range g.outbounds {
|
||||
if detour != used {
|
||||
outbounds = append(outbounds, detour)
|
||||
}
|
||||
}
|
||||
sort.SliceStable(outbounds, func(i, j int) bool {
|
||||
oi := outbounds[i]
|
||||
oj := outbounds[j]
|
||||
hi := g.history.LoadURLTestHistory(RealTag(oi))
|
||||
if hi == nil {
|
||||
return false
|
||||
}
|
||||
hj := g.history.LoadURLTestHistory(RealTag(oj))
|
||||
if hj == nil {
|
||||
return false
|
||||
}
|
||||
return hi.Delay < hj.Delay
|
||||
})
|
||||
return outbounds
|
||||
}
|
||||
|
||||
func (g *URLTestGroup) loopCheck() {
|
||||
go g.CheckOutbounds(true)
|
||||
if time.Now().Sub(g.lastActive.Load()) > g.interval {
|
||||
g.CheckOutbounds(false)
|
||||
}
|
||||
for {
|
||||
g.pauseManager.WaitActive()
|
||||
select {
|
||||
case <-g.close:
|
||||
return
|
||||
case <-g.ticker.C:
|
||||
g.CheckOutbounds(false)
|
||||
}
|
||||
g.pauseManager.WaitActive()
|
||||
g.CheckOutbounds(false)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *URLTestGroup) CheckOutbounds(force bool) {
|
||||
_, _ = g.urlTest(g.ctx, g.link, force)
|
||||
_, _ = g.urlTest(g.ctx, force)
|
||||
}
|
||||
|
||||
func (g *URLTestGroup) URLTest(ctx context.Context, link string) (map[string]uint16, error) {
|
||||
return g.urlTest(ctx, link, false)
|
||||
func (g *URLTestGroup) URLTest(ctx context.Context) (map[string]uint16, error) {
|
||||
return g.urlTest(ctx, false)
|
||||
}
|
||||
|
||||
func (g *URLTestGroup) urlTest(ctx context.Context, link string, force bool) (map[string]uint16, error) {
|
||||
func (g *URLTestGroup) urlTest(ctx context.Context, force bool) (map[string]uint16, error) {
|
||||
result := make(map[string]uint16)
|
||||
if g.checking.Swap(true) {
|
||||
return result, nil
|
||||
@@ -337,7 +321,7 @@ func (g *URLTestGroup) urlTest(ctx context.Context, link string, force bool) (ma
|
||||
b.Go(realTag, func() (any, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), C.TCPTimeout)
|
||||
defer cancel()
|
||||
t, err := urltest.URLTest(ctx, link, p)
|
||||
t, err := urltest.URLTest(ctx, g.link, p)
|
||||
if err != nil {
|
||||
g.logger.Debug("outbound ", tag, " unavailable: ", err)
|
||||
g.history.DeleteURLTestHistory(realTag)
|
||||
|
||||
Reference in New Issue
Block a user