From c25af47daa77927ebe7459f6a49d89db6239f103 Mon Sep 17 00:00:00 2001
From: gVisor bot <gvisor-bot@google.com>
Date: Fri, 17 Nov 2023 00:37:54 +0800
Subject: [PATCH] feat: add `override` to proxy-providers

Co-authored-by: xishang0128 <xishang02@gmail.com>
---
 adapter/provider/parser.go    | 31 +++++++++++++++++++++----------
 adapter/provider/provider.go  | 25 ++++++++++++++++++++++---
 component/resource/fetcher.go |  2 +-
 3 files changed, 44 insertions(+), 14 deletions(-)

diff --git a/adapter/provider/parser.go b/adapter/provider/parser.go
index 321380ed..966d33d6 100644
--- a/adapter/provider/parser.go
+++ b/adapter/provider/parser.go
@@ -25,16 +25,26 @@ type healthCheckSchema struct {
 	ExpectedStatus string `provider:"expected-status,omitempty"`
 }
 
+type OverrideSchema struct {
+	UDP            *bool   `proxy:"udp,omitempty"`
+	Up             *string `proxy:"up,omitempty"`
+	Down           *string `proxy:"down,omitempty"`
+	DialerProxy    *string `provider:"dialer-proxy,omitempty"`
+	SkipCertVerify *bool   `proxy:"skip-cert-verify,omitempty"`
+}
+
 type proxyProviderSchema struct {
-	Type          string            `provider:"type"`
-	Path          string            `provider:"path,omitempty"`
-	URL           string            `provider:"url,omitempty"`
-	Interval      int               `provider:"interval,omitempty"`
-	Filter        string            `provider:"filter,omitempty"`
-	ExcludeFilter string            `provider:"exclude-filter,omitempty"`
-	ExcludeType   string            `provider:"exclude-type,omitempty"`
-	DialerProxy   string            `provider:"dialer-proxy,omitempty"`
-	HealthCheck   healthCheckSchema `provider:"health-check,omitempty"`
+	Type          string `provider:"type"`
+	Path          string `provider:"path,omitempty"`
+	URL           string `provider:"url,omitempty"`
+	Interval      int    `provider:"interval,omitempty"`
+	Filter        string `provider:"filter,omitempty"`
+	ExcludeFilter string `provider:"exclude-filter,omitempty"`
+	ExcludeType   string `provider:"exclude-type,omitempty"`
+	DialerProxy   string `provider:"dialer-proxy,omitempty"`
+
+	HealthCheck healthCheckSchema `provider:"health-check,omitempty"`
+	Override    OverrideSchema    `provider:"override,omitempty"`
 }
 
 func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvider, error) {
@@ -85,6 +95,7 @@ func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvide
 	excludeFilter := schema.ExcludeFilter
 	excludeType := schema.ExcludeType
 	dialerProxy := schema.DialerProxy
+	override := schema.Override
 
-	return NewProxySetProvider(name, interval, filter, excludeFilter, excludeType, dialerProxy, vehicle, hc)
+	return NewProxySetProvider(name, interval, filter, excludeFilter, excludeType, dialerProxy, override, vehicle, hc)
 }
diff --git a/adapter/provider/provider.go b/adapter/provider/provider.go
index 5c1b0f76..cd8b0e90 100644
--- a/adapter/provider/provider.go
+++ b/adapter/provider/provider.go
@@ -165,7 +165,7 @@ func stopProxyProvider(pd *ProxySetProvider) {
 	_ = pd.Fetcher.Destroy()
 }
 
-func NewProxySetProvider(name string, interval time.Duration, filter string, excludeFilter string, excludeType string, dialerProxy string, vehicle types.Vehicle, hc *HealthCheck) (*ProxySetProvider, error) {
+func NewProxySetProvider(name string, interval time.Duration, filter string, excludeFilter string, excludeType string, dialerProxy string, override OverrideSchema, vehicle types.Vehicle, hc *HealthCheck) (*ProxySetProvider, error) {
 	excludeFilterReg, err := regexp2.Compile(excludeFilter, 0)
 	if err != nil {
 		return nil, fmt.Errorf("invalid excludeFilter regex: %w", err)
@@ -193,7 +193,7 @@ func NewProxySetProvider(name string, interval time.Duration, filter string, exc
 		healthCheck: hc,
 	}
 
-	fetcher := resource.NewFetcher[[]C.Proxy](name, interval, vehicle, proxiesParseAndFilter(filter, excludeFilter, excludeTypeArray, filterRegs, excludeFilterReg, dialerProxy), proxiesOnUpdate(pd))
+	fetcher := resource.NewFetcher[[]C.Proxy](name, interval, vehicle, proxiesParseAndFilter(filter, excludeFilter, excludeTypeArray, filterRegs, excludeFilterReg, dialerProxy, override), proxiesOnUpdate(pd))
 	pd.Fetcher = fetcher
 	ProxyProviderName[name] = struct{}{}
 	wrapper := &ProxySetProvider{pd}
@@ -295,7 +295,7 @@ func proxiesOnUpdate(pd *proxySetProvider) func([]C.Proxy) {
 	}
 }
 
-func proxiesParseAndFilter(filter string, excludeFilter string, excludeTypeArray []string, filterRegs []*regexp2.Regexp, excludeFilterReg *regexp2.Regexp, dialerProxy string) resource.Parser[[]C.Proxy] {
+func proxiesParseAndFilter(filter string, excludeFilter string, excludeTypeArray []string, filterRegs []*regexp2.Regexp, excludeFilterReg *regexp2.Regexp, dialerProxy string, override OverrideSchema) resource.Parser[[]C.Proxy] {
 	return func(buf []byte) ([]C.Proxy, error) {
 		schema := &ProxySchema{}
 
@@ -358,13 +358,32 @@ func proxiesParseAndFilter(filter string, excludeFilter string, excludeTypeArray
 				if _, ok := proxiesSet[name]; ok {
 					continue
 				}
+
 				if len(dialerProxy) > 0 {
 					mapping["dialer-proxy"] = dialerProxy
 				}
+
+				if override.UDP != nil {
+					mapping["udp"] = *override.UDP
+				}
+				if override.Up != nil {
+					mapping["up"] = *override.Up
+				}
+				if override.Down != nil {
+					mapping["down"] = *override.Down
+				}
+				if override.DialerProxy != nil {
+					mapping["dialer-proxy"] = *override.DialerProxy
+				}
+				if override.SkipCertVerify != nil {
+					mapping["skip-cert-verify"] = *override.SkipCertVerify
+				}
+
 				proxy, err := adapter.ParseProxy(mapping)
 				if err != nil {
 					return nil, fmt.Errorf("proxy %d error: %w", idx, err)
 				}
+
 				proxiesSet[name] = struct{}{}
 				proxies = append(proxies, proxy)
 			}
diff --git a/component/resource/fetcher.go b/component/resource/fetcher.go
index 31dc5c08..3d749645 100644
--- a/component/resource/fetcher.go
+++ b/component/resource/fetcher.go
@@ -59,7 +59,7 @@ func (f *Fetcher[V]) Initial() (V, error) {
 		f.UpdatedAt = &modTime
 		isLocal = true
 		if f.interval != 0 && modTime.Add(f.interval).Before(time.Now()) {
-			log.Warnln("[Provider] %s not updated for a long time, force refresh", f.Name())
+			log.Warnln("[Provider] %s not updated for %s, force update", f.Name(), time.Now().Sub(modTime))
 			forceUpdate = true
 		}
 	} else {