Feature: add tolerance for url-test

This commit is contained in:
Dreamacro 2020-05-29 17:47:50 +08:00
parent 8d0c6c6e66
commit 5628f97da1
3 changed files with 45 additions and 3 deletions

View file

@ -293,6 +293,7 @@ proxy-groups:
- ss1
- ss2
- vmess1
# tolerance: 150
url: 'http://www.gstatic.com/generate_204'
interval: 300

View file

@ -101,7 +101,8 @@ func ParseProxyGroup(config map[string]interface{}, proxyMap map[string]C.Proxy,
var group C.ProxyAdapter
switch groupOption.Type {
case "url-test":
group = NewURLTest(groupName, providers)
opts := parseURLTestOption(config)
group = NewURLTest(groupName, providers, opts...)
case "select":
group = NewSelector(groupName, providers)
case "fallback":

View file

@ -11,8 +11,19 @@ import (
C "github.com/Dreamacro/clash/constant"
)
type urlTestOption func(*URLTest)
func urlTestWithTolerance(tolerance uint16) urlTestOption {
return func(u *URLTest) {
u.tolerance = tolerance
}
}
type URLTest struct {
*outbound.Base
tolerance uint16
lastDelay uint16
fastNode C.Proxy
single *singledo.Single
fastSingle *singledo.Single
providers []provider.ProxyProvider
@ -52,6 +63,13 @@ func (u *URLTest) proxies() []C.Proxy {
func (u *URLTest) fast() C.Proxy {
elm, _, _ := u.fastSingle.Do(func() (interface{}, error) {
// tolerance
if u.tolerance != 0 && u.fastNode != nil {
if u.fastNode.LastDelay() < u.lastDelay+u.tolerance {
return u.fastNode, nil
}
}
proxies := u.proxies()
fast := proxies[0]
min := fast.LastDelay()
@ -66,6 +84,9 @@ func (u *URLTest) fast() C.Proxy {
min = delay
}
}
u.fastNode = fast
u.lastDelay = fast.LastDelay()
return fast, nil
})
@ -88,11 +109,30 @@ func (u *URLTest) MarshalJSON() ([]byte, error) {
})
}
func NewURLTest(name string, providers []provider.ProxyProvider) *URLTest {
return &URLTest{
func parseURLTestOption(config map[string]interface{}) []urlTestOption {
opts := []urlTestOption{}
// tolerance
if elm, ok := config["tolerance"]; ok {
if tolerance, ok := elm.(int); ok {
opts = append(opts, urlTestWithTolerance(uint16(tolerance)))
}
}
return opts
}
func NewURLTest(name string, providers []provider.ProxyProvider, options ...urlTestOption) *URLTest {
urlTest := &URLTest{
Base: outbound.NewBase(name, "", C.URLTest, false),
single: singledo.NewSingle(defaultGetProxiesDuration),
fastSingle: singledo.NewSingle(time.Second * 10),
providers: providers,
}
for _, option := range options {
option(urlTest)
}
return urlTest
}