mirror of
https://github.com/MetaCubeX/Clash.Meta.git
synced 2025-04-19 16:50:56 +00:00
chore: Support Duration format
This commit is contained in:
parent
c44949bc45
commit
fa46f066be
11 changed files with 106 additions and 40 deletions
|
@ -12,7 +12,6 @@ import (
|
|||
"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 +30,7 @@ type GroupBase struct {
|
|||
failedTesting atomic.Bool
|
||||
proxies [][]C.Proxy
|
||||
versions []atomic.Uint32
|
||||
TestTimeout int
|
||||
TestTimeout string
|
||||
maxFailedTimes int
|
||||
}
|
||||
|
||||
|
@ -40,7 +39,7 @@ type GroupBaseOption struct {
|
|||
filter string
|
||||
excludeFilter string
|
||||
excludeType string
|
||||
TestTimeout int
|
||||
TestTimeout string
|
||||
maxFailedTimes int
|
||||
providers []provider.ProxyProvider
|
||||
}
|
||||
|
@ -74,8 +73,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 +107,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 +243,11 @@ func (gb *GroupBase) onDialFailed(adapterType C.AdapterType, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
var timeout time.Duration
|
||||
if gb.TestTimeout != "" {
|
||||
timeout = utils.ParseDuration(gb.TestTimeout, "ms")
|
||||
}
|
||||
|
||||
go func() {
|
||||
gb.failedTestMux.Lock()
|
||||
defer gb.failedTestMux.Unlock()
|
||||
|
@ -253,7 +257,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
|
||||
}
|
||||
|
|
|
@ -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(utils.ParseDuration(groupOption.Interval, "s").Seconds())
|
||||
}
|
||||
if groupOption.TestTimeout != "" {
|
||||
timeout = uint(utils.ParseDuration(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 {
|
||||
|
|
|
@ -160,7 +160,7 @@ func NewRelay(option *GroupCommonOption, providers []provider.ProxyProvider) *Re
|
|||
"",
|
||||
"",
|
||||
"",
|
||||
5000,
|
||||
"5000",
|
||||
5,
|
||||
providers,
|
||||
}),
|
||||
|
|
|
@ -21,8 +21,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 +45,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 +73,27 @@ func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvide
|
|||
return nil, err
|
||||
}
|
||||
|
||||
var hcInterval uint
|
||||
if schema.HealthCheck.Enable {
|
||||
if schema.HealthCheck.Interval == 0 {
|
||||
schema.HealthCheck.Interval = 300
|
||||
}
|
||||
hcInterval = uint(schema.HealthCheck.Interval)
|
||||
var (
|
||||
interval time.Duration
|
||||
hcInterval uint
|
||||
timeout uint
|
||||
)
|
||||
if schema.Interval != "" {
|
||||
interval = utils.ParseDuration(schema.Interval, "s")
|
||||
}
|
||||
hc := NewHealthCheck([]C.Proxy{}, schema.HealthCheck.URL, uint(schema.HealthCheck.TestTimeout), hcInterval, schema.HealthCheck.Lazy, expectedStatus)
|
||||
if schema.HealthCheck.Enable {
|
||||
if schema.HealthCheck.Interval != "" {
|
||||
hcInterval = uint(utils.ParseDuration(schema.HealthCheck.Interval, "s").Seconds())
|
||||
}
|
||||
if hcInterval == 0 {
|
||||
hcInterval = 300
|
||||
}
|
||||
}
|
||||
if schema.HealthCheck.TestTimeout != "" {
|
||||
timeout = uint(utils.ParseDuration(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 +113,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
|
||||
|
|
|
@ -50,6 +50,7 @@ func SplitHostPort(s string) (host, port string, hasPort bool, err error) {
|
|||
|
||||
func TCPKeepAlive(c net.Conn) {
|
||||
if tcp, ok := c.(*net.TCPConn); ok {
|
||||
fmt.Println(KeepAliveInterval)
|
||||
_ = tcp.SetKeepAlive(true)
|
||||
_ = tcp.SetKeepAlivePeriod(KeepAliveInterval)
|
||||
}
|
||||
|
|
31
common/utils/time.go
Normal file
31
common/utils/time.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ParseDuration(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)
|
||||
case "h":
|
||||
_, err := strconv.Atoi(interval)
|
||||
if err == nil {
|
||||
interval += "h"
|
||||
}
|
||||
Duration, _ = time.ParseDuration(interval)
|
||||
}
|
||||
return Duration
|
||||
}
|
|
@ -15,7 +15,7 @@ import (
|
|||
var (
|
||||
geoMode bool
|
||||
AutoUpdate bool
|
||||
UpdateInterval int
|
||||
UpdateInterval string
|
||||
geoLoaderName = "memconservative"
|
||||
geoSiteMatcher = "succinct"
|
||||
)
|
||||
|
@ -30,7 +30,7 @@ func GeoAutoUpdate() bool {
|
|||
return AutoUpdate
|
||||
}
|
||||
|
||||
func GeoUpdateInterval() int {
|
||||
func GeoUpdateInterval() string {
|
||||
return UpdateInterval
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ func SetGeodataMode(newGeodataMode bool) {
|
|||
func SetGeoAutoUpdate(newAutoUpdate bool) {
|
||||
AutoUpdate = newAutoUpdate
|
||||
}
|
||||
func SetGeoUpdateInterval(newGeoUpdateInterval int) {
|
||||
func SetGeoUpdateInterval(newGeoUpdateInterval string) {
|
||||
UpdateInterval = newGeoUpdateInterval
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ func LoadGeoSiteMatcher(countryCode string) (router.DomainMatcher, int, error) {
|
|||
/**
|
||||
linear: linear algorithm
|
||||
matcher, err := router.NewDomainMatcher(domains)
|
||||
mph:minimal perfect hash algorithm
|
||||
mph: minimal perfect hash algorithm
|
||||
*/
|
||||
var matcher router.DomainMatcher
|
||||
if geoSiteMatcher == "mph" {
|
||||
|
|
|
@ -56,7 +56,7 @@ type General struct {
|
|||
RoutingMark int `json:"-"`
|
||||
GeoXUrl GeoXUrl `json:"geox-url"`
|
||||
GeoAutoUpdate bool `json:"geo-auto-update"`
|
||||
GeoUpdateInterval int `json:"geo-update-interval"`
|
||||
GeoUpdateInterval string `json:"geo-update-interval"`
|
||||
GeodataMode bool `json:"geodata-mode"`
|
||||
GeodataLoader string `json:"geodata-loader"`
|
||||
GeositeMatcher string `json:"geosite-matcher"`
|
||||
|
@ -313,7 +313,7 @@ type RawConfig struct {
|
|||
RoutingMark int `yaml:"routing-mark"`
|
||||
Tunnels []LC.Tunnel `yaml:"tunnels"`
|
||||
GeoAutoUpdate bool `yaml:"geo-auto-update" json:"geo-auto-update"`
|
||||
GeoUpdateInterval int `yaml:"geo-update-interval" json:"geo-update-interval"`
|
||||
GeoUpdateInterval string `yaml:"geo-update-interval" json:"geo-update-interval"`
|
||||
GeodataMode bool `yaml:"geodata-mode" json:"geodata-mode"`
|
||||
GeodataLoader string `yaml:"geodata-loader" json:"geodata-loader"`
|
||||
GeositeMatcher string `yaml:"geosite-matcher" json:"geosite-matcher"`
|
||||
|
@ -321,7 +321,7 @@ type RawConfig struct {
|
|||
FindProcessMode P.FindProcessMode `yaml:"find-process-mode" json:"find-process-mode"`
|
||||
GlobalClientFingerprint string `yaml:"global-client-fingerprint"`
|
||||
GlobalUA string `yaml:"global-ua"`
|
||||
KeepAliveInterval int `yaml:"keep-alive-interval"`
|
||||
KeepAliveInterval string `yaml:"keep-alive-interval"`
|
||||
|
||||
Sniffer RawSniffer `yaml:"sniffer" json:"sniffer"`
|
||||
ProxyProvider map[string]map[string]any `yaml:"proxy-providers"`
|
||||
|
@ -401,7 +401,7 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
|
|||
IPv6: true,
|
||||
Mode: T.Rule,
|
||||
GeoAutoUpdate: false,
|
||||
GeoUpdateInterval: 24,
|
||||
GeoUpdateInterval: "24h",
|
||||
GeodataMode: C.GeodataMode,
|
||||
GeodataLoader: "memconservative",
|
||||
UnifiedDelay: false,
|
||||
|
@ -631,8 +631,8 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
|
|||
C.ASNUrl = cfg.GeoXUrl.ASN
|
||||
C.GeodataMode = cfg.GeodataMode
|
||||
C.UA = cfg.GlobalUA
|
||||
if cfg.KeepAliveInterval != 0 {
|
||||
N.KeepAliveInterval = time.Duration(cfg.KeepAliveInterval) * time.Second
|
||||
if cfg.KeepAliveInterval != "" {
|
||||
N.KeepAliveInterval = utils.ParseDuration(cfg.KeepAliveInterval, "s")
|
||||
}
|
||||
|
||||
ExternalUIPath = cfg.ExternalUI
|
||||
|
|
|
@ -4,7 +4,7 @@ var (
|
|||
ASNEnable bool
|
||||
GeodataMode bool
|
||||
GeoAutoUpdate bool
|
||||
GeoUpdateInterval int
|
||||
GeoUpdateInterval string
|
||||
GeoIpUrl string
|
||||
MmdbUrl string
|
||||
GeoSiteUrl string
|
||||
|
|
5
main.go
5
main.go
|
@ -12,6 +12,7 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
"github.com/metacubex/mihomo/config"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/features"
|
||||
|
@ -111,9 +112,9 @@ func main() {
|
|||
}
|
||||
|
||||
if C.GeoAutoUpdate {
|
||||
ticker := time.NewTicker(time.Duration(C.GeoUpdateInterval) * time.Hour)
|
||||
ticker := time.NewTicker(utils.ParseDuration(C.GeoUpdateInterval, "h"))
|
||||
|
||||
log.Infoln("[GEO] Start update GEO database every %d hours", C.GeoUpdateInterval)
|
||||
log.Infoln("[GEO] Start update GEO database every %s", utils.ParseDuration(C.GeoUpdateInterval, "h"))
|
||||
go func() {
|
||||
for range ticker.C {
|
||||
updateGeoDatabases()
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/metacubex/mihomo/common/structure"
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
"github.com/metacubex/mihomo/component/resource"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/features"
|
||||
|
@ -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 = utils.ParseDuration(schema.Interval, "s")
|
||||
}
|
||||
|
||||
var vehicle P.Vehicle
|
||||
switch schema.Type {
|
||||
case "file":
|
||||
|
@ -74,5 +80,5 @@ func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(t
|
|||
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
|
||||
return NewRuleSetProvider(name, behavior, format, interval, vehicle, parse), nil
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue