Change: proxy gruop strategy improvement
This commit is contained in:
20
adapters/outboundgroup/common.go
Normal file
20
adapters/outboundgroup/common.go
Normal file
@ -0,0 +1,20 @@
|
||||
package outboundgroup
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/Dreamacro/clash/adapters/provider"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultGetProxiesDuration = time.Second * 5
|
||||
)
|
||||
|
||||
func getProvidersProxies(providers []provider.ProxyProvider) []C.Proxy {
|
||||
proxies := []C.Proxy{}
|
||||
for _, provider := range providers {
|
||||
proxies = append(proxies, provider.Proxies()...)
|
||||
}
|
||||
return proxies
|
||||
}
|
@ -7,11 +7,13 @@ import (
|
||||
|
||||
"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 Fallback struct {
|
||||
*outbound.Base
|
||||
single *singledo.Single
|
||||
providers []provider.ProxyProvider
|
||||
}
|
||||
|
||||
@ -56,29 +58,28 @@ func (f *Fallback) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (f *Fallback) proxies() []C.Proxy {
|
||||
proxies := []C.Proxy{}
|
||||
for _, provider := range f.providers {
|
||||
proxies = append(proxies, provider.Proxies()...)
|
||||
}
|
||||
return proxies
|
||||
elm, _, _ := f.single.Do(func() (interface{}, error) {
|
||||
return getProvidersProxies(f.providers), nil
|
||||
})
|
||||
|
||||
return elm.([]C.Proxy)
|
||||
}
|
||||
|
||||
func (f *Fallback) findAliveProxy() C.Proxy {
|
||||
for _, provider := range f.providers {
|
||||
proxies := provider.Proxies()
|
||||
for _, proxy := range proxies {
|
||||
if proxy.Alive() {
|
||||
return proxy
|
||||
}
|
||||
proxies := f.proxies()
|
||||
for _, proxy := range proxies {
|
||||
if proxy.Alive() {
|
||||
return proxy
|
||||
}
|
||||
}
|
||||
|
||||
return f.providers[0].Proxies()[0]
|
||||
return f.proxies()[0]
|
||||
}
|
||||
|
||||
func NewFallback(name string, providers []provider.ProxyProvider) *Fallback {
|
||||
return &Fallback{
|
||||
Base: outbound.NewBase(name, C.Fallback, false),
|
||||
single: singledo.NewSingle(defaultGetProxiesDuration),
|
||||
providers: providers,
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/Dreamacro/clash/adapters/outbound"
|
||||
"github.com/Dreamacro/clash/adapters/provider"
|
||||
"github.com/Dreamacro/clash/common/murmur3"
|
||||
"github.com/Dreamacro/clash/common/singledo"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
|
||||
"golang.org/x/net/publicsuffix"
|
||||
@ -15,6 +16,7 @@ import (
|
||||
|
||||
type LoadBalance struct {
|
||||
*outbound.Base
|
||||
single *singledo.Single
|
||||
maxRetry int
|
||||
providers []provider.ProxyProvider
|
||||
}
|
||||
@ -98,11 +100,11 @@ func (lb *LoadBalance) SupportUDP() bool {
|
||||
}
|
||||
|
||||
func (lb *LoadBalance) proxies() []C.Proxy {
|
||||
proxies := []C.Proxy{}
|
||||
for _, provider := range lb.providers {
|
||||
proxies = append(proxies, provider.Proxies()...)
|
||||
}
|
||||
return proxies
|
||||
elm, _, _ := lb.single.Do(func() (interface{}, error) {
|
||||
return getProvidersProxies(lb.providers), nil
|
||||
})
|
||||
|
||||
return elm.([]C.Proxy)
|
||||
}
|
||||
|
||||
func (lb *LoadBalance) MarshalJSON() ([]byte, error) {
|
||||
@ -119,6 +121,7 @@ func (lb *LoadBalance) MarshalJSON() ([]byte, error) {
|
||||
func NewLoadBalance(name string, providers []provider.ProxyProvider) *LoadBalance {
|
||||
return &LoadBalance{
|
||||
Base: outbound.NewBase(name, C.LoadBalance, false),
|
||||
single: singledo.NewSingle(defaultGetProxiesDuration),
|
||||
maxRetry: 3,
|
||||
providers: providers,
|
||||
}
|
||||
|
@ -8,11 +8,13 @@ import (
|
||||
|
||||
"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 Selector struct {
|
||||
*outbound.Base
|
||||
single *singledo.Single
|
||||
selected C.Proxy
|
||||
providers []provider.ProxyProvider
|
||||
}
|
||||
@ -66,17 +68,18 @@ func (s *Selector) Set(name string) error {
|
||||
}
|
||||
|
||||
func (s *Selector) proxies() []C.Proxy {
|
||||
proxies := []C.Proxy{}
|
||||
for _, provider := range s.providers {
|
||||
proxies = append(proxies, provider.Proxies()...)
|
||||
}
|
||||
return proxies
|
||||
elm, _, _ := s.single.Do(func() (interface{}, error) {
|
||||
return getProvidersProxies(s.providers), nil
|
||||
})
|
||||
|
||||
return elm.([]C.Proxy)
|
||||
}
|
||||
|
||||
func NewSelector(name string, providers []provider.ProxyProvider) *Selector {
|
||||
selected := providers[0].Proxies()[0]
|
||||
return &Selector{
|
||||
Base: outbound.NewBase(name, C.Selector, false),
|
||||
single: singledo.NewSingle(defaultGetProxiesDuration),
|
||||
providers: providers,
|
||||
selected: selected,
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user