mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-25 10:01:30 +00:00
Add idle_timeout
for URLTest outbound
This commit is contained in:
parent
a99deb2cb5
commit
f1e3a59db3
|
@ -3,11 +3,12 @@ package constant
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TCPTimeout = 5 * time.Second
|
TCPTimeout = 5 * time.Second
|
||||||
ReadPayloadTimeout = 300 * time.Millisecond
|
ReadPayloadTimeout = 300 * time.Millisecond
|
||||||
DNSTimeout = 10 * time.Second
|
DNSTimeout = 10 * time.Second
|
||||||
QUICTimeout = 30 * time.Second
|
QUICTimeout = 30 * time.Second
|
||||||
STUNTimeout = 15 * time.Second
|
STUNTimeout = 15 * time.Second
|
||||||
UDPTimeout = 5 * time.Minute
|
UDPTimeout = 5 * time.Minute
|
||||||
DefaultURLTestInterval = 1 * time.Minute
|
DefaultURLTestInterval = 3 * time.Minute
|
||||||
|
DefaultURLTestIdleTimeout = 30 * time.Minute
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,9 +10,10 @@
|
||||||
"proxy-b",
|
"proxy-b",
|
||||||
"proxy-c"
|
"proxy-c"
|
||||||
],
|
],
|
||||||
"url": "https://www.gstatic.com/generate_204",
|
"url": "",
|
||||||
"interval": "1m",
|
"interval": "",
|
||||||
"tolerance": 50,
|
"tolerance": 0,
|
||||||
|
"idle_timeout": "",
|
||||||
"interrupt_exist_connections": false
|
"interrupt_exist_connections": false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -31,12 +32,16 @@ The URL to test. `https://www.gstatic.com/generate_204` will be used if empty.
|
||||||
|
|
||||||
#### interval
|
#### interval
|
||||||
|
|
||||||
The test interval. `1m` will be used if empty.
|
The test interval. `3m` will be used if empty.
|
||||||
|
|
||||||
#### tolerance
|
#### tolerance
|
||||||
|
|
||||||
The test tolerance in milliseconds. `50` will be used if empty.
|
The test tolerance in milliseconds. `50` will be used if empty.
|
||||||
|
|
||||||
|
#### idle_timeout
|
||||||
|
|
||||||
|
The idle timeout. `30m` will be used if empty.
|
||||||
|
|
||||||
#### interrupt_exist_connections
|
#### interrupt_exist_connections
|
||||||
|
|
||||||
Interrupt existing connections when the selected outbound has changed.
|
Interrupt existing connections when the selected outbound has changed.
|
||||||
|
|
|
@ -10,9 +10,10 @@
|
||||||
"proxy-b",
|
"proxy-b",
|
||||||
"proxy-c"
|
"proxy-c"
|
||||||
],
|
],
|
||||||
"url": "https://www.gstatic.com/generate_204",
|
"url": "",
|
||||||
"interval": "1m",
|
"interval": "",
|
||||||
"tolerance": 50,
|
"tolerance": 50,
|
||||||
|
"idle_timeout": "",
|
||||||
"interrupt_exist_connections": false
|
"interrupt_exist_connections": false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -31,12 +32,16 @@
|
||||||
|
|
||||||
#### interval
|
#### interval
|
||||||
|
|
||||||
测试间隔。 默认使用 `1m`。
|
测试间隔。 默认使用 `3m`。
|
||||||
|
|
||||||
#### tolerance
|
#### tolerance
|
||||||
|
|
||||||
以毫秒为单位的测试容差。 默认使用 `50`。
|
以毫秒为单位的测试容差。 默认使用 `50`。
|
||||||
|
|
||||||
|
#### idle_timeout
|
||||||
|
|
||||||
|
空闲超时。默认使用 `30m`。
|
||||||
|
|
||||||
#### interrupt_exist_connections
|
#### interrupt_exist_connections
|
||||||
|
|
||||||
当选定的出站发生更改时,中断现有连接。
|
当选定的出站发生更改时,中断现有连接。
|
||||||
|
|
|
@ -11,5 +11,6 @@ type URLTestOutboundOptions struct {
|
||||||
URL string `json:"url,omitempty"`
|
URL string `json:"url,omitempty"`
|
||||||
Interval Duration `json:"interval,omitempty"`
|
Interval Duration `json:"interval,omitempty"`
|
||||||
Tolerance uint16 `json:"tolerance,omitempty"`
|
Tolerance uint16 `json:"tolerance,omitempty"`
|
||||||
|
IdleTimeout Duration `json:"idle_timeout,omitempty"`
|
||||||
InterruptExistConnections bool `json:"interrupt_exist_connections,omitempty"`
|
InterruptExistConnections bool `json:"interrupt_exist_connections,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ type URLTest struct {
|
||||||
link string
|
link string
|
||||||
interval time.Duration
|
interval time.Duration
|
||||||
tolerance uint16
|
tolerance uint16
|
||||||
|
idleTimeout time.Duration
|
||||||
group *URLTestGroup
|
group *URLTestGroup
|
||||||
interruptExternalConnections bool
|
interruptExternalConnections bool
|
||||||
}
|
}
|
||||||
|
@ -54,6 +55,7 @@ func NewURLTest(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||||
link: options.URL,
|
link: options.URL,
|
||||||
interval: time.Duration(options.Interval),
|
interval: time.Duration(options.Interval),
|
||||||
tolerance: options.Tolerance,
|
tolerance: options.Tolerance,
|
||||||
|
idleTimeout: time.Duration(options.IdleTimeout),
|
||||||
interruptExternalConnections: options.InterruptExistConnections,
|
interruptExternalConnections: options.InterruptExistConnections,
|
||||||
}
|
}
|
||||||
if len(outbound.tags) == 0 {
|
if len(outbound.tags) == 0 {
|
||||||
|
@ -71,7 +73,21 @@ func (s *URLTest) Start() error {
|
||||||
}
|
}
|
||||||
outbounds = append(outbounds, detour)
|
outbounds = append(outbounds, detour)
|
||||||
}
|
}
|
||||||
s.group = NewURLTestGroup(s.ctx, s.router, s.logger, outbounds, s.link, s.interval, s.tolerance, s.interruptExternalConnections)
|
group, err := NewURLTestGroup(
|
||||||
|
s.ctx,
|
||||||
|
s.router,
|
||||||
|
s.logger,
|
||||||
|
outbounds,
|
||||||
|
s.link,
|
||||||
|
s.interval,
|
||||||
|
s.tolerance,
|
||||||
|
s.idleTimeout,
|
||||||
|
s.interruptExternalConnections,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.group = group
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,6 +176,7 @@ type URLTestGroup struct {
|
||||||
link string
|
link string
|
||||||
interval time.Duration
|
interval time.Duration
|
||||||
tolerance uint16
|
tolerance uint16
|
||||||
|
idleTimeout time.Duration
|
||||||
history *urltest.HistoryStorage
|
history *urltest.HistoryStorage
|
||||||
checking atomic.Bool
|
checking atomic.Bool
|
||||||
pauseManager pause.Manager
|
pauseManager pause.Manager
|
||||||
|
@ -183,14 +200,21 @@ func NewURLTestGroup(
|
||||||
link string,
|
link string,
|
||||||
interval time.Duration,
|
interval time.Duration,
|
||||||
tolerance uint16,
|
tolerance uint16,
|
||||||
|
idleTimeout time.Duration,
|
||||||
interruptExternalConnections bool,
|
interruptExternalConnections bool,
|
||||||
) *URLTestGroup {
|
) (*URLTestGroup, error) {
|
||||||
if interval == 0 {
|
if interval == 0 {
|
||||||
interval = C.DefaultURLTestInterval
|
interval = C.DefaultURLTestInterval
|
||||||
}
|
}
|
||||||
if tolerance == 0 {
|
if tolerance == 0 {
|
||||||
tolerance = 50
|
tolerance = 50
|
||||||
}
|
}
|
||||||
|
if idleTimeout == 0 {
|
||||||
|
idleTimeout = C.DefaultURLTestIdleTimeout
|
||||||
|
}
|
||||||
|
if interval > idleTimeout {
|
||||||
|
return nil, E.New("interval must be less or equal than idle_timeout")
|
||||||
|
}
|
||||||
var history *urltest.HistoryStorage
|
var history *urltest.HistoryStorage
|
||||||
if history = service.PtrFromContext[urltest.HistoryStorage](ctx); history != nil {
|
if history = service.PtrFromContext[urltest.HistoryStorage](ctx); history != nil {
|
||||||
} else if clashServer := router.ClashServer(); clashServer != nil {
|
} else if clashServer := router.ClashServer(); clashServer != nil {
|
||||||
|
@ -206,12 +230,13 @@ func NewURLTestGroup(
|
||||||
link: link,
|
link: link,
|
||||||
interval: interval,
|
interval: interval,
|
||||||
tolerance: tolerance,
|
tolerance: tolerance,
|
||||||
|
idleTimeout: idleTimeout,
|
||||||
history: history,
|
history: history,
|
||||||
close: make(chan struct{}),
|
close: make(chan struct{}),
|
||||||
pauseManager: pause.ManagerFromContext(ctx),
|
pauseManager: pause.ManagerFromContext(ctx),
|
||||||
interruptGroup: interrupt.NewGroup(),
|
interruptGroup: interrupt.NewGroup(),
|
||||||
interruptExternalConnections: interruptExternalConnections,
|
interruptExternalConnections: interruptExternalConnections,
|
||||||
}
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *URLTestGroup) PostStart() {
|
func (g *URLTestGroup) PostStart() {
|
||||||
|
@ -278,6 +303,7 @@ func (g *URLTestGroup) Select(network string) adapter.Outbound {
|
||||||
|
|
||||||
func (g *URLTestGroup) loopCheck() {
|
func (g *URLTestGroup) loopCheck() {
|
||||||
if time.Now().Sub(g.lastActive.Load()) > g.interval {
|
if time.Now().Sub(g.lastActive.Load()) > g.interval {
|
||||||
|
g.lastActive.Store(time.Now())
|
||||||
g.CheckOutbounds(false)
|
g.CheckOutbounds(false)
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
|
@ -286,6 +312,13 @@ func (g *URLTestGroup) loopCheck() {
|
||||||
return
|
return
|
||||||
case <-g.ticker.C:
|
case <-g.ticker.C:
|
||||||
}
|
}
|
||||||
|
if time.Now().Sub(g.lastActive.Load()) > g.idleTimeout {
|
||||||
|
g.access.Lock()
|
||||||
|
g.ticker.Stop()
|
||||||
|
g.ticker = nil
|
||||||
|
g.access.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
g.pauseManager.WaitActive()
|
g.pauseManager.WaitActive()
|
||||||
g.CheckOutbounds(false)
|
g.CheckOutbounds(false)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue