Skip to content

Commit

Permalink
chore: Support Duration format
Browse files Browse the repository at this point in the history
  • Loading branch information
xishang0128 committed Apr 7, 2024
1 parent c44949b commit fa46f06
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 38 deletions.
18 changes: 11 additions & 7 deletions adapter/outboundgroup/groupbase.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -31,7 +30,7 @@ type GroupBase struct {
failedTesting atomic.Bool
proxies [][]C.Proxy
versions []atomic.Uint32
TestTimeout int
TestTimeout string
maxFailedTimes int
}

Expand All @@ -40,7 +39,7 @@ type GroupBaseOption struct {
filter string
excludeFilter string
excludeType string
TestTimeout int
TestTimeout string
maxFailedTimes int
providers []provider.ProxyProvider
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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
}
Expand Down
23 changes: 17 additions & 6 deletions adapter/outboundgroup/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down Expand Up @@ -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 {
Expand All @@ -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...)
}
Expand All @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion adapter/outboundgroup/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func NewRelay(option *GroupCommonOption, providers []provider.ProxyProvider) *Re
"",
"",
"",
5000,
"5000",
5,
providers,
}),
Expand Down
30 changes: 21 additions & 9 deletions adapter/provider/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}
Expand All @@ -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"`
Expand Down Expand Up @@ -73,14 +73,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 = utils.ParseDuration(schema.Interval, "s")
}
if schema.HealthCheck.Enable {
if schema.HealthCheck.Interval == 0 {
schema.HealthCheck.Interval = 300
if schema.HealthCheck.Interval != "" {
hcInterval = uint(utils.ParseDuration(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(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 {
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions common/net/tcpip.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
31 changes: 31 additions & 0 deletions common/utils/time.go
Original file line number Diff line number Diff line change
@@ -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
}
8 changes: 4 additions & 4 deletions component/geodata/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
var (
geoMode bool
AutoUpdate bool
UpdateInterval int
UpdateInterval string
geoLoaderName = "memconservative"
geoSiteMatcher = "succinct"
)
Expand All @@ -30,7 +30,7 @@ func GeoAutoUpdate() bool {
return AutoUpdate
}

func GeoUpdateInterval() int {
func GeoUpdateInterval() string {
return UpdateInterval
}

Expand All @@ -48,7 +48,7 @@ func SetGeodataMode(newGeodataMode bool) {
func SetGeoAutoUpdate(newAutoUpdate bool) {
AutoUpdate = newAutoUpdate
}
func SetGeoUpdateInterval(newGeoUpdateInterval int) {
func SetGeoUpdateInterval(newGeoUpdateInterval string) {
UpdateInterval = newGeoUpdateInterval
}

Expand Down Expand Up @@ -144,7 +144,7 @@ func LoadGeoSiteMatcher(countryCode string) (router.DomainMatcher, int, error) {
/**
linear: linear algorithm
matcher, err := router.NewDomainMatcher(domains)
mphminimal perfect hash algorithm
mph: minimal perfect hash algorithm
*/
var matcher router.DomainMatcher
if geoSiteMatcher == "mph" {
Expand Down
12 changes: 6 additions & 6 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down Expand Up @@ -313,15 +313,15 @@ 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"`
TCPConcurrent bool `yaml:"tcp-concurrent" json:"tcp-concurrent"`
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"`
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion constant/geodata.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var (
ASNEnable bool
GeodataMode bool
GeoAutoUpdate bool
GeoUpdateInterval int
GeoUpdateInterval string
GeoIpUrl string
MmdbUrl string
GeoSiteUrl string
Expand Down
5 changes: 3 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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()
Expand Down
10 changes: 8 additions & 2 deletions rules/provider/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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) {
Expand Down Expand Up @@ -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":
Expand All @@ -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
}

0 comments on commit fa46f06

Please sign in to comment.