mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2025-02-23 12:42:27 +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
|
# skip-cert-verify: true
|
||||||
|
|
||||||
proxy-groups:
|
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
|
# Traffic: clash <-> http <-> vmess <-> ss1 <-> ss2 <-> Internet
|
||||||
- name: "relay"
|
- name: "relay"
|
||||||
type: relay
|
type: relay
|
||||||
|
@ -53,6 +53,10 @@ func (b *Base) Addr() string {
|
|||||||
return b.addr
|
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 {
|
func NewBase(name string, addr string, tp C.AdapterType, udp bool) *Base {
|
||||||
return &Base{name, addr, tp, udp}
|
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 {
|
func (f *Fallback) proxies() []C.Proxy {
|
||||||
elm, _, _ := f.single.Do(func() (interface{}, error) {
|
elm, _, _ := f.single.Do(func() (interface{}, error) {
|
||||||
return getProvidersProxies(f.providers), nil
|
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))))
|
proxy := lb.Unwrap(metadata)
|
||||||
proxies := lb.proxies()
|
|
||||||
buckets := int32(len(proxies))
|
c, err = proxy.DialContext(ctx, metadata)
|
||||||
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)
|
|
||||||
return
|
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))))
|
key := uint64(murmur3.Sum32([]byte(getKey(metadata))))
|
||||||
proxies := lb.proxies()
|
proxies := lb.proxies()
|
||||||
buckets := int32(len(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)
|
idx := jumpHash(key, buckets)
|
||||||
proxy := proxies[idx]
|
proxy := proxies[idx]
|
||||||
if proxy.Alive() {
|
if proxy.Alive() {
|
||||||
return proxy.DialUDP(metadata)
|
return proxy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return proxies[0].DialUDP(metadata)
|
return proxies[0]
|
||||||
}
|
|
||||||
|
|
||||||
func (lb *LoadBalance) SupportUDP() bool {
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lb *LoadBalance) proxies() []C.Proxy {
|
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) {
|
func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata) (C.Conn, error) {
|
||||||
proxies := r.proxies()
|
proxies := r.proxies(metadata)
|
||||||
if len(proxies) == 0 {
|
if len(proxies) == 0 {
|
||||||
return nil, errors.New("Proxy does not exist")
|
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) {
|
func (r *Relay) MarshalJSON() ([]byte, error) {
|
||||||
var all []string
|
var all []string
|
||||||
for _, proxy := range r.proxies() {
|
for _, proxy := range r.rawProxies() {
|
||||||
all = append(all, proxy.Name())
|
all = append(all, proxy.Name())
|
||||||
}
|
}
|
||||||
return json.Marshal(map[string]interface{}{
|
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) {
|
elm, _, _ := r.single.Do(func() (interface{}, error) {
|
||||||
return getProvidersProxies(r.providers), nil
|
return getProvidersProxies(r.providers), nil
|
||||||
})
|
})
|
||||||
@ -75,6 +75,20 @@ func (r *Relay) proxies() []C.Proxy {
|
|||||||
return elm.([]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 {
|
func NewRelay(name string, providers []provider.ProxyProvider) *Relay {
|
||||||
return &Relay{
|
return &Relay{
|
||||||
Base: outbound.NewBase(name, "", C.Relay, false),
|
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")
|
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 {
|
func (s *Selector) selectedProxy() C.Proxy {
|
||||||
elm, _, _ := s.single.Do(func() (interface{}, error) {
|
elm, _, _ := s.single.Do(func() (interface{}, error) {
|
||||||
proxies := getProvidersProxies(s.providers)
|
proxies := getProvidersProxies(s.providers)
|
||||||
|
@ -38,6 +38,10 @@ func (u *URLTest) DialUDP(metadata *C.Metadata) (C.PacketConn, error) {
|
|||||||
return pc, err
|
return pc, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *URLTest) Unwrap(metadata *C.Metadata) C.Proxy {
|
||||||
|
return u.fast()
|
||||||
|
}
|
||||||
|
|
||||||
func (u *URLTest) proxies() []C.Proxy {
|
func (u *URLTest) proxies() []C.Proxy {
|
||||||
elm, _, _ := u.single.Do(func() (interface{}, error) {
|
elm, _, _ := u.single.Do(func() (interface{}, error) {
|
||||||
return getProvidersProxies(u.providers), nil
|
return getProvidersProxies(u.providers), nil
|
||||||
|
@ -69,6 +69,8 @@ type ProxyAdapter interface {
|
|||||||
SupportUDP() bool
|
SupportUDP() bool
|
||||||
MarshalJSON() ([]byte, error)
|
MarshalJSON() ([]byte, error)
|
||||||
Addr() string
|
Addr() string
|
||||||
|
// Unwrap extracts the proxy from a proxy-group. It returns nil when nothing to extract.
|
||||||
|
Unwrap(metadata *Metadata) Proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
type DelayHistory struct {
|
type DelayHistory struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user