Change: proxy gruop strategy improvement

This commit is contained in:
Dreamacro
2019-12-10 15:04:22 +08:00
parent bd4302e096
commit 2334bafe68
7 changed files with 198 additions and 63 deletions

View File

@ -4,36 +4,35 @@ import (
"context"
"encoding/json"
"net"
"time"
"github.com/Dreamacro/clash/adapters/outbound"
"github.com/Dreamacro/clash/adapters/provider"
"github.com/Dreamacro/clash/common/singledo"
C "github.com/Dreamacro/clash/constant"
)
type URLTest struct {
*outbound.Base
fast C.Proxy
providers []provider.ProxyProvider
single *singledo.Single
fastSingle *singledo.Single
providers []provider.ProxyProvider
}
func (u *URLTest) Now() string {
return u.fast.Name()
return u.fast().Name()
}
func (u *URLTest) DialContext(ctx context.Context, metadata *C.Metadata) (c C.Conn, err error) {
for i := 0; i < 3; i++ {
c, err = u.fast.DialContext(ctx, metadata)
if err == nil {
c.AppendToChains(u)
return
}
u.fallback()
c, err = u.fast().DialContext(ctx, metadata)
if err == nil {
c.AppendToChains(u)
}
return
return c, err
}
func (u *URLTest) DialUDP(metadata *C.Metadata) (C.PacketConn, net.Addr, error) {
pc, addr, err := u.fast.DialUDP(metadata)
pc, addr, err := u.fast().DialUDP(metadata)
if err == nil {
pc.AppendToChains(u)
}
@ -41,15 +40,37 @@ func (u *URLTest) DialUDP(metadata *C.Metadata) (C.PacketConn, net.Addr, error)
}
func (u *URLTest) proxies() []C.Proxy {
proxies := []C.Proxy{}
for _, provider := range u.providers {
proxies = append(proxies, provider.Proxies()...)
}
return proxies
elm, _, _ := u.single.Do(func() (interface{}, error) {
return getProvidersProxies(u.providers), nil
})
return elm.([]C.Proxy)
}
func (u *URLTest) fast() C.Proxy {
elm, _, _ := u.fastSingle.Do(func() (interface{}, error) {
proxies := u.proxies()
fast := proxies[0]
min := fast.LastDelay()
for _, proxy := range proxies[1:] {
if !proxy.Alive() {
continue
}
delay := proxy.LastDelay()
if delay < min {
fast = proxy
min = delay
}
}
return fast, nil
})
return elm.(C.Proxy)
}
func (u *URLTest) SupportUDP() bool {
return u.fast.SupportUDP()
return u.fast().SupportUDP()
}
func (u *URLTest) MarshalJSON() ([]byte, error) {
@ -64,30 +85,11 @@ func (u *URLTest) MarshalJSON() ([]byte, error) {
})
}
func (u *URLTest) fallback() {
proxies := u.proxies()
fast := proxies[0]
min := fast.LastDelay()
for _, proxy := range proxies[1:] {
if !proxy.Alive() {
continue
}
delay := proxy.LastDelay()
if delay < min {
fast = proxy
min = delay
}
}
u.fast = fast
}
func NewURLTest(name string, providers []provider.ProxyProvider) *URLTest {
fast := providers[0].Proxies()[0]
return &URLTest{
Base: outbound.NewBase(name, C.URLTest, false),
fast: fast,
providers: providers,
Base: outbound.NewBase(name, C.URLTest, false),
single: singledo.NewSingle(defaultGetProxiesDuration),
fastSingle: singledo.NewSingle(time.Second * 10),
providers: providers,
}
}