mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2024-11-14 21:31:16 +08:00
Feature: support proxy-group in relay (#597)
This commit is contained in:
parent
b979ff0bc2
commit
752f87a8dc
@ -273,7 +273,7 @@ proxies:
|
||||
# skip-cert-verify: true
|
||||
|
||||
proxy-groups:
|
||||
# relay chains the proxies. proxies shall not contain a proxy-group. No UDP support.
|
||||
# relay chains the proxies. proxies shall not contain a relay. No UDP support.
|
||||
# Traffic: clash <-> http <-> vmess <-> ss1 <-> ss2 <-> Internet
|
||||
- name: "relay"
|
||||
type: relay
|
||||
|
@ -53,6 +53,10 @@ func (b *Base) Addr() string {
|
||||
return b.addr
|
||||
}
|
||||
|
||||
func (b *Base) Unwrap(metadata *C.Metadata) C.Proxy {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewBase(name string, addr string, tp C.AdapterType, udp bool) *Base {
|
||||
return &Base{name, addr, tp, udp}
|
||||
}
|
||||
|
@ -56,6 +56,11 @@ func (f *Fallback) MarshalJSON() ([]byte, error) {
|
||||
})
|
||||
}
|
||||
|
||||
func (f *Fallback) Unwrap(metadata *C.Metadata) C.Proxy {
|
||||
proxy := f.findAliveProxy()
|
||||
return proxy
|
||||
}
|
||||
|
||||
func (f *Fallback) proxies() []C.Proxy {
|
||||
elm, _, _ := f.single.Do(func() (interface{}, error) {
|
||||
return getProvidersProxies(f.providers), nil
|
||||
|
@ -59,18 +59,9 @@ func (lb *LoadBalance) DialContext(ctx context.Context, metadata *C.Metadata) (c
|
||||
}
|
||||
}()
|
||||
|
||||
key := uint64(murmur3.Sum32([]byte(getKey(metadata))))
|
||||
proxies := lb.proxies()
|
||||
buckets := int32(len(proxies))
|
||||
for i := 0; i < lb.maxRetry; i, key = i+1, key+1 {
|
||||
idx := jumpHash(key, buckets)
|
||||
proxy := proxies[idx]
|
||||
if proxy.Alive() {
|
||||
c, err = proxy.DialContext(ctx, metadata)
|
||||
return
|
||||
}
|
||||
}
|
||||
c, err = proxies[0].DialContext(ctx, metadata)
|
||||
proxy := lb.Unwrap(metadata)
|
||||
|
||||
c, err = proxy.DialContext(ctx, metadata)
|
||||
return
|
||||
}
|
||||
|
||||
@ -81,6 +72,16 @@ func (lb *LoadBalance) DialUDP(metadata *C.Metadata) (pc C.PacketConn, err error
|
||||
}
|
||||
}()
|
||||
|
||||
proxy := lb.Unwrap(metadata)
|
||||
|
||||
return proxy.DialUDP(metadata)
|
||||
}
|
||||
|
||||
func (lb *LoadBalance) SupportUDP() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (lb *LoadBalance) Unwrap(metadata *C.Metadata) C.Proxy {
|
||||
key := uint64(murmur3.Sum32([]byte(getKey(metadata))))
|
||||
proxies := lb.proxies()
|
||||
buckets := int32(len(proxies))
|
||||
@ -88,15 +89,11 @@ func (lb *LoadBalance) DialUDP(metadata *C.Metadata) (pc C.PacketConn, err error
|
||||
idx := jumpHash(key, buckets)
|
||||
proxy := proxies[idx]
|
||||
if proxy.Alive() {
|
||||
return proxy.DialUDP(metadata)
|
||||
return proxy
|
||||
}
|
||||
}
|
||||
|
||||
return proxies[0].DialUDP(metadata)
|
||||
}
|
||||
|
||||
func (lb *LoadBalance) SupportUDP() bool {
|
||||
return true
|
||||
return proxies[0]
|
||||
}
|
||||
|
||||
func (lb *LoadBalance) proxies() []C.Proxy {
|
||||
|
@ -20,7 +20,7 @@ type Relay struct {
|
||||
}
|
||||
|
||||
func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) {
|
||||
proxies := r.proxies()
|
||||
proxies := r.proxies(metadata)
|
||||
if len(proxies) == 0 {
|
||||
return nil, errors.New("Proxy does not exist")
|
||||
}
|
||||
@ -58,7 +58,7 @@ func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn,
|
||||
|
||||
func (r *Relay) MarshalJSON() ([]byte, error) {
|
||||
var all []string
|
||||
for _, proxy := range r.proxies() {
|
||||
for _, proxy := range r.rawProxies() {
|
||||
all = append(all, proxy.Name())
|
||||
}
|
||||
return json.Marshal(map[string]interface{}{
|
||||
@ -67,7 +67,7 @@ func (r *Relay) MarshalJSON() ([]byte, error) {
|
||||
})
|
||||
}
|
||||
|
||||
func (r *Relay) proxies() []C.Proxy {
|
||||
func (r *Relay) rawProxies() []C.Proxy {
|
||||
elm, _, _ := r.single.Do(func() (interface{}, error) {
|
||||
return getProvidersProxies(r.providers), nil
|
||||
})
|
||||
@ -75,6 +75,20 @@ func (r *Relay) proxies() []C.Proxy {
|
||||
return elm.([]C.Proxy)
|
||||
}
|
||||
|
||||
func (r *Relay) proxies(metadata *C.Metadata) []C.Proxy {
|
||||
proxies := r.rawProxies()
|
||||
|
||||
for n, proxy := range proxies {
|
||||
subproxy := proxy.Unwrap(metadata)
|
||||
for subproxy != nil {
|
||||
proxies[n] = subproxy
|
||||
subproxy = subproxy.Unwrap(metadata)
|
||||
}
|
||||
}
|
||||
|
||||
return proxies
|
||||
}
|
||||
|
||||
func NewRelay(name string, providers []provider.ProxyProvider) *Relay {
|
||||
return &Relay{
|
||||
Base: outbound.NewBase(name, "", C.Relay, false),
|
||||
|
@ -67,6 +67,10 @@ func (s *Selector) Set(name string) error {
|
||||
return errors.New("Proxy does not exist")
|
||||
}
|
||||
|
||||
func (s *Selector) Unwrap(metadata *C.Metadata) C.Proxy {
|
||||
return s.selectedProxy()
|
||||
}
|
||||
|
||||
func (s *Selector) selectedProxy() C.Proxy {
|
||||
elm, _, _ := s.single.Do(func() (interface{}, error) {
|
||||
proxies := getProvidersProxies(s.providers)
|
||||
|
@ -38,6 +38,10 @@ func (u *URLTest) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
|
||||
return pc, err
|
||||
}
|
||||
|
||||
func (u *URLTest) Unwrap(metadata *C.Metadata) C.Proxy {
|
||||
return u.fast()
|
||||
}
|
||||
|
||||
func (u *URLTest) proxies() []C.Proxy {
|
||||
elm, _, _ := u.single.Do(func() (interface{}, error) {
|
||||
return getProvidersProxies(u.providers), nil
|
||||
|
@ -69,6 +69,8 @@ type ProxyAdapter interface {
|
||||
SupportUDP() bool
|
||||
MarshalJSON() ([]byte, error)
|
||||
Addr() string
|
||||
// Unwrap extracts the proxy from a proxy-group. It returns nil when nothing to extract.
|
||||
Unwrap(metadata *Metadata) Proxy
|
||||
}
|
||||
|
||||
type DelayHistory struct {
|
||||
|
Loading…
Reference in New Issue
Block a user