diff --git a/adapter/outboundgroup/groupbase.go b/adapter/outboundgroup/groupbase.go index b39ee3a659..96591014c7 100644 --- a/adapter/outboundgroup/groupbase.go +++ b/adapter/outboundgroup/groupbase.go @@ -8,11 +8,11 @@ import ( "time" "github.com/metacubex/mihomo/adapter/outbound" + AP "github.com/metacubex/mihomo/adapter/provider" "github.com/metacubex/mihomo/common/atomic" "github.com/metacubex/mihomo/common/utils" C "github.com/metacubex/mihomo/constant" "github.com/metacubex/mihomo/constant/provider" - types "github.com/metacubex/mihomo/constant/provider" "github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/tunnel" @@ -31,7 +31,7 @@ type GroupBase struct { failedTesting atomic.Bool proxies [][]C.Proxy versions []atomic.Uint32 - TestTimeout int + TestTimeout string maxFailedTimes int } @@ -40,7 +40,7 @@ type GroupBaseOption struct { filter string excludeFilter string excludeType string - TestTimeout int + TestTimeout string maxFailedTimes int providers []provider.ProxyProvider } @@ -74,8 +74,8 @@ func NewGroupBase(opt GroupBaseOption) *GroupBase { maxFailedTimes: opt.maxFailedTimes, } - if gb.TestTimeout == 0 { - gb.TestTimeout = 5000 + if gb.TestTimeout == "" { + gb.TestTimeout = "5000" } if gb.maxFailedTimes == 0 { gb.maxFailedTimes = 5 @@ -108,7 +108,7 @@ func (gb *GroupBase) GetProxies(touch bool) []C.Proxy { pd.Touch() } - if pd.VehicleType() == types.Compatible { + if pd.VehicleType() == provider.Compatible { gb.versions[i].Store(pd.Version()) gb.proxies[i] = pd.Proxies() continue @@ -244,6 +244,11 @@ func (gb *GroupBase) onDialFailed(adapterType C.AdapterType, err error) { return } + var timeout time.Duration + if gb.TestTimeout != "" { + timeout = AP.ParsedDuration(gb.TestTimeout, "ms") + } + go func() { gb.failedTestMux.Lock() defer gb.failedTestMux.Unlock() @@ -253,7 +258,7 @@ func (gb *GroupBase) onDialFailed(adapterType C.AdapterType, err error) { log.Debugln("ProxyGroup: %s first failed", gb.Name()) gb.failedTime = time.Now() } else { - if time.Since(gb.failedTime) > time.Duration(gb.TestTimeout)*time.Millisecond { + if time.Since(gb.failedTime) > timeout { gb.failedTimes = 0 return } diff --git a/adapter/outboundgroup/parser.go b/adapter/outboundgroup/parser.go index 876c92fa32..32c1e2ca89 100644 --- a/adapter/outboundgroup/parser.go +++ b/adapter/outboundgroup/parser.go @@ -27,8 +27,8 @@ type GroupCommonOption struct { Proxies []string `group:"proxies,omitempty"` Use []string `group:"use,omitempty"` URL string `group:"url,omitempty"` - Interval int `group:"interval,omitempty"` - TestTimeout int `group:"timeout,omitempty"` + Interval string `group:"interval,omitempty"` + TestTimeout string `group:"timeout,omitempty"` MaxFailedTimes int `group:"max-failed-times,omitempty"` Lazy bool `group:"lazy,omitempty"` DisableUDP bool `group:"disable-udp,omitempty"` @@ -88,6 +88,17 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide } groupOption.ExpectedStatus = status + var ( + interval uint + timeout uint + ) + if groupOption.Interval != "" { + interval = uint(provider.ParsedDuration(groupOption.Interval, "s").Seconds()) + } + if groupOption.TestTimeout != "" { + timeout = uint(provider.ParsedDuration(groupOption.TestTimeout, "ms").Milliseconds()) + } + if len(groupOption.Use) != 0 { PDs, err := getProviders(providersMap, groupOption.Use) if err != nil { @@ -106,7 +117,7 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide groupOption.URL = C.DefaultTestURL } } else { - addTestUrlToProviders(PDs, groupOption.URL, expectedStatus, groupOption.Filter, uint(groupOption.Interval)) + addTestUrlToProviders(PDs, groupOption.URL, expectedStatus, groupOption.Filter, interval) } providers = append(providers, PDs...) } @@ -127,12 +138,12 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide // select don't need auto health check if groupOption.Type != "select" && groupOption.Type != "relay" { - if groupOption.Interval == 0 { - groupOption.Interval = 300 + if interval == 0 { + interval = 300 } } - hc := provider.NewHealthCheck(ps, groupOption.URL, uint(groupOption.TestTimeout), uint(groupOption.Interval), groupOption.Lazy, expectedStatus) + hc := provider.NewHealthCheck(ps, groupOption.URL, timeout, interval, groupOption.Lazy, expectedStatus) pd, err := provider.NewCompatibleProvider(groupName, ps, hc) if err != nil { diff --git a/adapter/outboundgroup/relay.go b/adapter/outboundgroup/relay.go index 07fbcd9588..4128a4b309 100644 --- a/adapter/outboundgroup/relay.go +++ b/adapter/outboundgroup/relay.go @@ -160,7 +160,7 @@ func NewRelay(option *GroupCommonOption, providers []provider.ProxyProvider) *Re "", "", "", - 5000, + "5000", 5, providers, }), diff --git a/adapter/provider/parser.go b/adapter/provider/parser.go index 1094668d46..d26fcea809 100644 --- a/adapter/provider/parser.go +++ b/adapter/provider/parser.go @@ -3,6 +3,7 @@ package provider import ( "errors" "fmt" + "strconv" "time" "github.com/metacubex/mihomo/common/structure" @@ -21,8 +22,8 @@ var ( type healthCheckSchema struct { Enable bool `provider:"enable"` URL string `provider:"url"` - Interval int `provider:"interval"` - TestTimeout int `provider:"timeout,omitempty"` + Interval string `provider:"interval"` + TestTimeout string `provider:"timeout,omitempty"` Lazy bool `provider:"lazy,omitempty"` ExpectedStatus string `provider:"expected-status,omitempty"` } @@ -45,7 +46,7 @@ type proxyProviderSchema struct { Path string `provider:"path,omitempty"` URL string `provider:"url,omitempty"` Proxy string `provider:"proxy,omitempty"` - Interval int `provider:"interval,omitempty"` + Interval string `provider:"interval,omitempty"` Filter string `provider:"filter,omitempty"` ExcludeFilter string `provider:"exclude-filter,omitempty"` ExcludeType string `provider:"exclude-type,omitempty"` @@ -73,14 +74,27 @@ func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvide return nil, err } - var hcInterval uint + var ( + interval time.Duration + hcInterval uint + timeout uint + ) + if schema.Interval != "" { + interval = ParsedDuration(schema.Interval, "s") + } if schema.HealthCheck.Enable { - if schema.HealthCheck.Interval == 0 { - schema.HealthCheck.Interval = 300 + if schema.HealthCheck.Interval != "" { + hcInterval = uint(ParsedDuration(schema.HealthCheck.Interval, "s").Seconds()) + } + if hcInterval == 0 { + hcInterval = 300 } - hcInterval = uint(schema.HealthCheck.Interval) } - hc := NewHealthCheck([]C.Proxy{}, schema.HealthCheck.URL, uint(schema.HealthCheck.TestTimeout), hcInterval, schema.HealthCheck.Lazy, expectedStatus) + if schema.HealthCheck.TestTimeout != "" { + timeout = uint(ParsedDuration(schema.HealthCheck.TestTimeout, "ms").Milliseconds()) + } + + hc := NewHealthCheck([]C.Proxy{}, schema.HealthCheck.URL, timeout, hcInterval, schema.HealthCheck.Lazy, expectedStatus) var vehicle types.Vehicle switch schema.Type { @@ -100,7 +114,6 @@ func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvide return nil, fmt.Errorf("%w: %s", errVehicleType, schema.Type) } - interval := time.Duration(uint(schema.Interval)) * time.Second filter := schema.Filter excludeFilter := schema.ExcludeFilter excludeType := schema.ExcludeType @@ -109,3 +122,22 @@ func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvide return NewProxySetProvider(name, interval, filter, excludeFilter, excludeType, dialerProxy, override, vehicle, hc) } + +func ParsedDuration(interval string, unit string) time.Duration { + var Duration time.Duration + switch unit { + case "ms": + _, err := strconv.Atoi(interval) + if err == nil { + interval += "ms" + } + Duration, _ = time.ParseDuration(interval) + case "s": + _, err := strconv.Atoi(interval) + if err == nil { + interval += "s" + } + Duration, _ = time.ParseDuration(interval) + } + return Duration +} diff --git a/rules/provider/parse.go b/rules/provider/parse.go index a20da28d5c..d85f00505d 100644 --- a/rules/provider/parse.go +++ b/rules/provider/parse.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + AP "github.com/metacubex/mihomo/adapter/provider" "github.com/metacubex/mihomo/common/structure" "github.com/metacubex/mihomo/component/resource" C "github.com/metacubex/mihomo/constant" @@ -23,7 +24,7 @@ type ruleProviderSchema struct { URL string `provider:"url,omitempty"` Proxy string `provider:"proxy,omitempty"` Format string `provider:"format,omitempty"` - Interval int `provider:"interval,omitempty"` + Interval string `provider:"interval,omitempty"` } func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (parsed C.Rule, parseErr error)) (P.RuleProvider, error) { @@ -56,6 +57,11 @@ func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(t return nil, fmt.Errorf("unsupported format type: %s", schema.Format) } + var interval time.Duration + if schema.Interval != "" { + interval = AP.ParsedDuration(schema.Interval, "s") + } + var vehicle P.Vehicle switch schema.Type { case "file": @@ -73,6 +79,6 @@ func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(t default: return nil, fmt.Errorf("unsupported vehicle type: %s", schema.Type) } - - return NewRuleSetProvider(name, behavior, format, time.Duration(uint(schema.Interval))*time.Second, vehicle, parse), nil + fmt.Println(interval) + return NewRuleSetProvider(name, behavior, format, interval, vehicle, parse), nil }