diff --git a/component/updater/update_ui.go b/component/updater/update_ui.go index 29081761a..bd2a58815 100644 --- a/component/updater/update_ui.go +++ b/component/updater/update_ui.go @@ -14,24 +14,69 @@ import ( "github.com/metacubex/mihomo/log" ) -var ( - ExternalUIURL string - ExternalUIPath string - AutoDownloadUI bool -) +type UIUpdater struct { + externalUIURL string + externalUIPath string + autoDownloadUI bool + + mutex sync.Mutex +} -var xdMutex sync.Mutex +var DefaultUiUpdater = &UIUpdater{} + +func NewUiUpdater(externalUI, externalUIURL, externalUIName string) *UIUpdater { + updater := &UIUpdater{} + // checkout externalUI exist + if externalUI != "" { + updater.autoDownloadUI = true + updater.externalUIPath = C.Path.Resolve(externalUI) + } else { + // default externalUI path + updater.externalUIPath = path.Join(C.Path.HomeDir(), "ui") + } -func DownloadUI() error { - xdMutex.Lock() - defer xdMutex.Unlock() + // checkout UIpath/name exist + if externalUIName != "" { + updater.autoDownloadUI = true + updater.externalUIPath = path.Join(updater.externalUIPath, externalUIName) + } + + if externalUIURL != "" { + updater.externalUIURL = externalUIURL + } + return updater +} + +func (u *UIUpdater) AutoDownloadUI() { + u.mutex.Lock() + defer u.mutex.Unlock() + if u.autoDownloadUI { + dirEntries, _ := os.ReadDir(u.externalUIPath) + if len(dirEntries) > 0 { + log.Infoln("UI already exists, skip downloading") + } else { + log.Infoln("External UI downloading ...") + err := u.downloadUI() + if err != nil { + log.Errorln("Error downloading UI: %s", err) + } + } + } +} + +func (u *UIUpdater) DownloadUI() error { + u.mutex.Lock() + defer u.mutex.Unlock() + return u.downloadUI() +} - err := prepareUIPath() +func (u *UIUpdater) downloadUI() error { + err := u.prepareUIPath() if err != nil { return fmt.Errorf("prepare UI path failed: %w", err) } - data, err := downloadForBytes(ExternalUIURL) + data, err := downloadForBytes(u.externalUIURL) if err != nil { return fmt.Errorf("can't download file: %w", err) } @@ -42,7 +87,7 @@ func DownloadUI() error { } defer os.Remove(saved) - err = cleanup(ExternalUIPath) + err = cleanup(u.externalUIPath) if err != nil { if !os.IsNotExist(err) { return fmt.Errorf("cleanup exist file error: %w", err) @@ -54,18 +99,18 @@ func DownloadUI() error { return fmt.Errorf("can't extract zip file: %w", err) } - err = os.Rename(unzipFolder, ExternalUIPath) + err = os.Rename(unzipFolder, u.externalUIPath) if err != nil { return fmt.Errorf("rename UI folder failed: %w", err) } return nil } -func prepareUIPath() error { - if _, err := os.Stat(ExternalUIPath); os.IsNotExist(err) { - log.Infoln("dir %s does not exist, creating", ExternalUIPath) - if err := os.MkdirAll(ExternalUIPath, os.ModePerm); err != nil { - log.Warnln("create dir %s error: %s", ExternalUIPath, err) +func (u *UIUpdater) prepareUIPath() error { + if _, err := os.Stat(u.externalUIPath); os.IsNotExist(err) { + log.Infoln("dir %s does not exist, creating", u.externalUIPath) + if err := os.MkdirAll(u.externalUIPath, os.ModePerm); err != nil { + log.Warnln("create dir %s error: %s", u.externalUIPath, err) } } return nil diff --git a/config/config.go b/config/config.go index 3ca57a459..69957cee9 100644 --- a/config/config.go +++ b/config/config.go @@ -7,7 +7,6 @@ import ( "net" "net/netip" "net/url" - "path" "strings" "time" @@ -21,14 +20,12 @@ import ( "github.com/metacubex/mihomo/component/fakeip" "github.com/metacubex/mihomo/component/geodata" mihomoHttp "github.com/metacubex/mihomo/component/http" - "github.com/metacubex/mihomo/component/keepalive" P "github.com/metacubex/mihomo/component/process" "github.com/metacubex/mihomo/component/resolver" "github.com/metacubex/mihomo/component/resource" "github.com/metacubex/mihomo/component/sniffer" tlsC "github.com/metacubex/mihomo/component/tls" "github.com/metacubex/mihomo/component/trie" - "github.com/metacubex/mihomo/component/updater" C "github.com/metacubex/mihomo/constant" providerTypes "github.com/metacubex/mihomo/constant/provider" snifferTypes "github.com/metacubex/mihomo/constant/sniffer" @@ -67,6 +64,9 @@ type General struct { GlobalClientFingerprint string `json:"global-client-fingerprint"` GlobalUA string `json:"global-ua"` ETagSupport bool `json:"etag-support"` + KeepAliveIdle int `json:"keep-alive-idle"` + KeepAliveInterval int `json:"keep-alive-interval"` + DisableKeepAlive bool `json:"disable-keep-alive"` } // Inbound config @@ -105,6 +105,8 @@ type Controller struct { ExternalControllerUnix string ExternalControllerPipe string ExternalUI string + ExternalUIURL string + ExternalUIName string ExternalDohServer string Secret string Cors Cors @@ -706,8 +708,6 @@ func ParseRawConfig(rawCfg *RawConfig) (*Config, error) { } func parseGeneral(cfg *RawConfig) (*General, error) { - updater.SetGeoAutoUpdate(cfg.GeoAutoUpdate) - updater.SetGeoUpdateInterval(cfg.GeoUpdateInterval) geodata.SetGeodataMode(cfg.GeodataMode) geodata.SetLoader(cfg.GeodataLoader) geodata.SetSiteMatcher(cfg.GeositeMatcher) @@ -718,33 +718,6 @@ func parseGeneral(cfg *RawConfig) (*General, error) { mihomoHttp.SetUA(cfg.GlobalUA) resource.SetETag(cfg.ETagSupport) - if cfg.KeepAliveIdle != 0 { - keepalive.SetKeepAliveIdle(time.Duration(cfg.KeepAliveIdle) * time.Second) - } - if cfg.KeepAliveInterval != 0 { - keepalive.SetKeepAliveInterval(time.Duration(cfg.KeepAliveInterval) * time.Second) - } - keepalive.SetDisableKeepAlive(cfg.DisableKeepAlive) - - // checkout externalUI exist - if cfg.ExternalUI != "" { - updater.AutoDownloadUI = true - updater.ExternalUIPath = C.Path.Resolve(cfg.ExternalUI) - } else { - // default externalUI path - updater.ExternalUIPath = path.Join(C.Path.HomeDir(), "ui") - } - - // checkout UIpath/name exist - if cfg.ExternalUIName != "" { - updater.AutoDownloadUI = true - updater.ExternalUIPath = path.Join(updater.ExternalUIPath, cfg.ExternalUIName) - } - - if cfg.ExternalUIURL != "" { - updater.ExternalUIURL = cfg.ExternalUIURL - } - return &General{ Inbound: Inbound{ Port: cfg.Port, @@ -783,6 +756,9 @@ func parseGeneral(cfg *RawConfig) (*General, error) { GlobalClientFingerprint: cfg.GlobalClientFingerprint, GlobalUA: cfg.GlobalUA, ETagSupport: cfg.ETagSupport, + KeepAliveIdle: cfg.KeepAliveIdle, + KeepAliveInterval: cfg.KeepAliveInterval, + DisableKeepAlive: cfg.DisableKeepAlive, }, nil } @@ -790,6 +766,8 @@ func parseController(cfg *RawConfig) (*Controller, error) { return &Controller{ ExternalController: cfg.ExternalController, ExternalUI: cfg.ExternalUI, + ExternalUIURL: cfg.ExternalUIURL, + ExternalUIName: cfg.ExternalUIName, Secret: cfg.Secret, ExternalControllerPipe: cfg.ExternalControllerPipe, ExternalControllerUnix: cfg.ExternalControllerUnix, diff --git a/dns/system.go b/dns/system.go index 9fb803ddc..ab6c01002 100644 --- a/dns/system.go +++ b/dns/system.go @@ -31,12 +31,12 @@ type systemClient struct { func (c *systemClient) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) { dnsClients, err := c.getDnsClients() + if len(dnsClients) == 0 && len(c.defaultNS) > 0 { + dnsClients = c.defaultNS + err = nil + } if err != nil { - if len(c.defaultNS) > 0 { - dnsClients = c.defaultNS - } else { - return - } + return } msg, _, err = batchExchange(ctx, dnsClients, m) return @@ -45,11 +45,16 @@ func (c *systemClient) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Ms // Address implements dnsClient func (c *systemClient) Address() string { dnsClients, _ := c.getDnsClients() + isDefault := "" + if len(dnsClients) == 0 && len(c.defaultNS) > 0 { + dnsClients = c.defaultNS + isDefault = "[defaultNS]" + } addrs := make([]string, 0, len(dnsClients)) for _, c := range dnsClients { addrs = append(addrs, c.Address()) } - return fmt.Sprintf("system(%s)", strings.Join(addrs, ",")) + return fmt.Sprintf("system%s(%s)", isDefault, strings.Join(addrs, ",")) } var _ dnsClient = (*systemClient)(nil) diff --git a/hub/executor/executor.go b/hub/executor/executor.go index b8d9cddb9..199790635 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -19,6 +19,7 @@ import ( G "github.com/metacubex/mihomo/component/geodata" mihomoHttp "github.com/metacubex/mihomo/component/http" "github.com/metacubex/mihomo/component/iface" + "github.com/metacubex/mihomo/component/keepalive" "github.com/metacubex/mihomo/component/profile" "github.com/metacubex/mihomo/component/profile/cachefile" "github.com/metacubex/mihomo/component/resolver" @@ -117,7 +118,7 @@ func ApplyConfig(cfg *config.Config, force bool) { runtime.GC() tunnel.OnRunning() hcCompatibleProvider(cfg.Providers) - initExternalUI() + updateUpdater(cfg) resolver.ResetConnection() } @@ -176,6 +177,9 @@ func GetGeneral() *config.General { GlobalClientFingerprint: tlsC.GetGlobalFingerprint(), GlobalUA: mihomoHttp.UA(), ETagSupport: resource.ETag(), + KeepAliveInterval: int(keepalive.KeepAliveInterval() / time.Second), + KeepAliveIdle: int(keepalive.KeepAliveIdle() / time.Second), + DisableKeepAlive: keepalive.DisableKeepAlive(), } return general @@ -394,16 +398,14 @@ func updateTunnels(tunnels []LC.Tunnel) { listener.PatchTunnel(tunnels, tunnel.Tunnel) } -func initExternalUI() { - if updater.AutoDownloadUI { - dirEntries, _ := os.ReadDir(updater.ExternalUIPath) - if len(dirEntries) > 0 { - log.Infoln("UI already exists, skip downloading") - } else { - log.Infoln("External UI downloading ...") - updater.DownloadUI() - } - } +func updateUpdater(cfg *config.Config) { + general := cfg.General + updater.SetGeoAutoUpdate(general.GeoAutoUpdate) + updater.SetGeoUpdateInterval(general.GeoUpdateInterval) + + controller := cfg.Controller + updater.DefaultUiUpdater = updater.NewUiUpdater(controller.ExternalUI, controller.ExternalUIURL, controller.ExternalUIName) + updater.DefaultUiUpdater.AutoDownloadUI() } func updateGeneral(general *config.General) { @@ -419,6 +421,10 @@ func updateGeneral(general *config.General) { inbound.SetTfo(general.InboundTfo) inbound.SetMPTCP(general.InboundMPTCP) + keepalive.SetKeepAliveIdle(time.Duration(general.KeepAliveIdle) * time.Second) + keepalive.SetKeepAliveInterval(time.Duration(general.KeepAliveInterval) * time.Second) + keepalive.SetDisableKeepAlive(general.DisableKeepAlive) + adapter.UnifiedDelay.Store(general.UnifiedDelay) dialer.DefaultInterface.Store(general.Interface) diff --git a/hub/route/upgrade.go b/hub/route/upgrade.go index 25c326ddd..2fed3f676 100644 --- a/hub/route/upgrade.go +++ b/hub/route/upgrade.go @@ -47,7 +47,7 @@ func upgradeCore(w http.ResponseWriter, r *http.Request) { } func updateUI(w http.ResponseWriter, r *http.Request) { - err := updater.DownloadUI() + err := updater.DefaultUiUpdater.DownloadUI() if err != nil { log.Warnln("%s", err) render.Status(r, http.StatusInternalServerError)