2024-04-30 23:38:49 +08:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import "C"
|
|
|
|
|
import (
|
2024-06-13 23:43:42 +08:00
|
|
|
"github.com/metacubex/mihomo/adapter"
|
2024-04-30 23:38:49 +08:00
|
|
|
"github.com/metacubex/mihomo/adapter/inbound"
|
2024-07-02 08:08:31 +08:00
|
|
|
"github.com/metacubex/mihomo/adapter/outboundgroup"
|
2024-05-10 10:11:27 +08:00
|
|
|
ap "github.com/metacubex/mihomo/adapter/provider"
|
2024-04-30 23:38:49 +08:00
|
|
|
"github.com/metacubex/mihomo/component/dialer"
|
|
|
|
|
"github.com/metacubex/mihomo/component/resolver"
|
|
|
|
|
"github.com/metacubex/mihomo/config"
|
2024-06-13 23:43:42 +08:00
|
|
|
"github.com/metacubex/mihomo/constant"
|
2024-06-12 19:28:58 +08:00
|
|
|
"github.com/metacubex/mihomo/hub"
|
2024-04-30 23:38:49 +08:00
|
|
|
"github.com/metacubex/mihomo/hub/executor"
|
2024-06-13 19:17:14 +08:00
|
|
|
"github.com/metacubex/mihomo/hub/route"
|
2024-04-30 23:38:49 +08:00
|
|
|
"github.com/metacubex/mihomo/listener"
|
|
|
|
|
"github.com/metacubex/mihomo/log"
|
|
|
|
|
"github.com/metacubex/mihomo/tunnel"
|
|
|
|
|
"os"
|
|
|
|
|
"os/exec"
|
2024-05-10 10:11:27 +08:00
|
|
|
"path/filepath"
|
2024-04-30 23:38:49 +08:00
|
|
|
"runtime"
|
2024-05-07 13:50:00 +08:00
|
|
|
"strings"
|
2024-07-07 10:02:10 +08:00
|
|
|
"sync"
|
2024-04-30 23:38:49 +08:00
|
|
|
"syscall"
|
2024-06-03 18:02:05 +08:00
|
|
|
"time"
|
2024-04-30 23:38:49 +08:00
|
|
|
)
|
|
|
|
|
|
2024-05-10 10:11:27 +08:00
|
|
|
type healthCheckSchema struct {
|
|
|
|
|
Enable bool `provider:"enable"`
|
|
|
|
|
URL string `provider:"url"`
|
|
|
|
|
Interval int `provider:"interval"`
|
|
|
|
|
TestTimeout int `provider:"timeout,omitempty"`
|
|
|
|
|
Lazy bool `provider:"lazy,omitempty"`
|
|
|
|
|
ExpectedStatus string `provider:"expected-status,omitempty"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type proxyProviderSchema struct {
|
|
|
|
|
Type string `provider:"type"`
|
|
|
|
|
Path string `provider:"path,omitempty"`
|
|
|
|
|
URL string `provider:"url,omitempty"`
|
|
|
|
|
Proxy string `provider:"proxy,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 ap.OverrideSchema `provider:"override,omitempty"`
|
|
|
|
|
Header map[string][]string `provider:"header,omitempty"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ruleProviderSchema struct {
|
|
|
|
|
Type string `provider:"type"`
|
|
|
|
|
Behavior string `provider:"behavior"`
|
|
|
|
|
Path string `provider:"path,omitempty"`
|
|
|
|
|
URL string `provider:"url,omitempty"`
|
|
|
|
|
Proxy string `provider:"proxy,omitempty"`
|
|
|
|
|
Format string `provider:"format,omitempty"`
|
|
|
|
|
Interval int `provider:"interval,omitempty"`
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-02 08:08:31 +08:00
|
|
|
type ConfigExtendedParams struct {
|
|
|
|
|
IsPatch bool `json:"is-patch"`
|
|
|
|
|
IsCompatible bool `json:"is-compatible"`
|
|
|
|
|
SelectedMap map[string]string `json:"selected-map"`
|
|
|
|
|
TestURL *string `json:"test-url"`
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-30 23:38:49 +08:00
|
|
|
type GenerateConfigParams struct {
|
2024-07-02 08:08:31 +08:00
|
|
|
ProfilePath *string `json:"profile-path"`
|
|
|
|
|
Config config.RawConfig `json:"config" `
|
|
|
|
|
Params ConfigExtendedParams `json:"params"`
|
2024-04-30 23:38:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ChangeProxyParams struct {
|
|
|
|
|
GroupName *string `json:"group-name"`
|
|
|
|
|
ProxyName *string `json:"proxy-name"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type TestDelayParams struct {
|
|
|
|
|
ProxyName string `json:"proxy-name"`
|
|
|
|
|
Timeout int64 `json:"timeout"`
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-13 23:43:42 +08:00
|
|
|
type ProcessMapItem struct {
|
2024-06-16 19:04:33 +08:00
|
|
|
Id int64 `json:"id"`
|
|
|
|
|
Value string `json:"value"`
|
2024-04-30 23:38:49 +08:00
|
|
|
}
|
|
|
|
|
|
2024-06-03 18:02:05 +08:00
|
|
|
type ExternalProvider struct {
|
|
|
|
|
Name string `json:"name"`
|
|
|
|
|
Type string `json:"type"`
|
|
|
|
|
VehicleType string `json:"vehicle-type"`
|
|
|
|
|
UpdateAt time.Time `json:"update-at"`
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-30 23:38:49 +08:00
|
|
|
func restartExecutable(execPath string) {
|
|
|
|
|
var err error
|
|
|
|
|
executor.Shutdown()
|
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
|
cmd := exec.Command(execPath, os.Args[1:]...)
|
|
|
|
|
log.Infoln("restarting: %q %q", execPath, os.Args[1:])
|
|
|
|
|
cmd.Stdin = os.Stdin
|
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
err = cmd.Start()
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalln("restarting: %s", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
os.Exit(0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log.Infoln("restarting: %q %q", execPath, os.Args[1:])
|
|
|
|
|
err = syscall.Exec(execPath, os.Args, os.Environ())
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalln("restarting: %s", err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func readFile(path string) ([]byte, error) {
|
|
|
|
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
data, err := os.ReadFile(path)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return data, err
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-10 10:11:27 +08:00
|
|
|
func removeFile(path string) error {
|
|
|
|
|
absPath, err := filepath.Abs(path)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
err = os.Remove(absPath)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-30 23:38:49 +08:00
|
|
|
func getRawConfigWithPath(path *string) *config.RawConfig {
|
|
|
|
|
if path == nil {
|
|
|
|
|
return config.DefaultRawConfig()
|
|
|
|
|
} else {
|
|
|
|
|
bytes, err := readFile(*path)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("getProfile readFile error %v", err)
|
|
|
|
|
return config.DefaultRawConfig()
|
|
|
|
|
}
|
|
|
|
|
prof, err := config.UnmarshalRawConfig(bytes)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Errorln("getProfile UnmarshalRawConfig error %v", err)
|
|
|
|
|
return config.DefaultRawConfig()
|
|
|
|
|
}
|
|
|
|
|
return prof
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-02 08:08:31 +08:00
|
|
|
func decorationConfig(profilePath *string, cfg config.RawConfig) *config.RawConfig {
|
2024-04-30 23:38:49 +08:00
|
|
|
prof := getRawConfigWithPath(profilePath)
|
2024-07-02 08:08:31 +08:00
|
|
|
overwriteConfig(prof, cfg)
|
2024-04-30 23:38:49 +08:00
|
|
|
return prof
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-07 13:50:00 +08:00
|
|
|
func Reduce[T any, U any](s []T, initVal U, f func(U, T) U) U {
|
|
|
|
|
for _, v := range s {
|
|
|
|
|
initVal = f(initVal, v)
|
|
|
|
|
}
|
|
|
|
|
return initVal
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Map[T, U any](slice []T, fn func(T) U) []U {
|
|
|
|
|
result := make([]U, len(slice))
|
|
|
|
|
for i, v := range slice {
|
|
|
|
|
result[i] = fn(v)
|
|
|
|
|
}
|
|
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func replaceFromMap(s string, m map[string]string) string {
|
|
|
|
|
for k, v := range m {
|
|
|
|
|
s = strings.ReplaceAll(s, k, v)
|
|
|
|
|
}
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func removeDuplicateFromSlice[T any](slice []T) []T {
|
|
|
|
|
result := make([]T, 0)
|
|
|
|
|
seen := make(map[any]struct{})
|
|
|
|
|
for _, value := range slice {
|
|
|
|
|
if _, ok := seen[value]; !ok {
|
|
|
|
|
result = append(result, value)
|
|
|
|
|
seen[value] = struct{}{}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func generateProxyGroupAndRule(proxyGroup *[]map[string]any, rule *[]string) {
|
|
|
|
|
var replacements = map[string]string{}
|
|
|
|
|
var selectArr []map[string]any
|
|
|
|
|
var urlTestArr []map[string]any
|
|
|
|
|
var fallbackArr []map[string]any
|
|
|
|
|
for _, group := range *proxyGroup {
|
|
|
|
|
switch group["type"] {
|
|
|
|
|
case "select":
|
|
|
|
|
selectArr = append(selectArr, group)
|
|
|
|
|
replacements[group["name"].(string)] = "Proxy"
|
|
|
|
|
break
|
|
|
|
|
case "url-test":
|
|
|
|
|
urlTestArr = append(urlTestArr, group)
|
|
|
|
|
replacements[group["name"].(string)] = "Auto"
|
|
|
|
|
break
|
|
|
|
|
case "fallback":
|
|
|
|
|
fallbackArr = append(fallbackArr, group)
|
|
|
|
|
replacements[group["name"].(string)] = "Fallback"
|
|
|
|
|
break
|
|
|
|
|
default:
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ProxyProxies := Reduce(selectArr, []string{}, func(res []string, cur map[string]any) []string {
|
|
|
|
|
if cur["proxies"] == nil {
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
for _, proxyName := range cur["proxies"].([]interface{}) {
|
|
|
|
|
if str, ok := proxyName.(string); ok {
|
|
|
|
|
str = replaceFromMap(str, replacements)
|
|
|
|
|
if str != "Proxy" {
|
|
|
|
|
res = append(res, str)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return res
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
ProxyProxies = removeDuplicateFromSlice(ProxyProxies)
|
|
|
|
|
|
|
|
|
|
AutoProxies := Reduce(urlTestArr, []string{}, func(res []string, cur map[string]any) []string {
|
|
|
|
|
if cur["proxies"] == nil {
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
for _, proxyName := range cur["proxies"].([]interface{}) {
|
|
|
|
|
if str, ok := proxyName.(string); ok {
|
|
|
|
|
str = replaceFromMap(str, replacements)
|
|
|
|
|
if str != "Auto" {
|
|
|
|
|
res = append(res, str)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return res
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
AutoProxies = removeDuplicateFromSlice(AutoProxies)
|
|
|
|
|
|
|
|
|
|
FallbackProxies := Reduce(fallbackArr, []string{}, func(res []string, cur map[string]any) []string {
|
|
|
|
|
if cur["proxies"] == nil {
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
for _, proxyName := range cur["proxies"].([]interface{}) {
|
|
|
|
|
if str, ok := proxyName.(string); ok {
|
|
|
|
|
str = replaceFromMap(str, replacements)
|
|
|
|
|
if str != "Fallback" {
|
|
|
|
|
res = append(res, str)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return res
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
FallbackProxies = removeDuplicateFromSlice(FallbackProxies)
|
|
|
|
|
|
|
|
|
|
var computedProxyGroup []map[string]any
|
|
|
|
|
|
|
|
|
|
if len(ProxyProxies) > 0 {
|
|
|
|
|
computedProxyGroup = append(computedProxyGroup,
|
|
|
|
|
map[string]any{
|
|
|
|
|
"name": "Proxy",
|
|
|
|
|
"type": "select",
|
|
|
|
|
"proxies": ProxyProxies,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(AutoProxies) > 0 {
|
|
|
|
|
computedProxyGroup = append(computedProxyGroup,
|
|
|
|
|
map[string]any{
|
|
|
|
|
"name": "Auto",
|
|
|
|
|
"type": "url-test",
|
|
|
|
|
"proxies": AutoProxies,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(FallbackProxies) > 0 {
|
|
|
|
|
computedProxyGroup = append(computedProxyGroup,
|
|
|
|
|
map[string]any{
|
|
|
|
|
"name": "Fallback",
|
|
|
|
|
"type": "fallback",
|
|
|
|
|
"proxies": FallbackProxies,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
computedRule := Map(*rule, func(value string) string {
|
|
|
|
|
return replaceFromMap(value, replacements)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
*proxyGroup = computedProxyGroup
|
|
|
|
|
*rule = computedRule
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-02 08:08:31 +08:00
|
|
|
func overwriteConfig(targetConfig *config.RawConfig, patchConfig config.RawConfig) {
|
2024-06-11 20:50:57 +08:00
|
|
|
targetConfig.ExternalController = patchConfig.ExternalController
|
2024-04-30 23:38:49 +08:00
|
|
|
targetConfig.ExternalUI = ""
|
|
|
|
|
targetConfig.Interface = ""
|
|
|
|
|
targetConfig.ExternalUIURL = ""
|
2024-06-12 19:28:58 +08:00
|
|
|
targetConfig.TCPConcurrent = patchConfig.TCPConcurrent
|
|
|
|
|
targetConfig.UnifiedDelay = patchConfig.UnifiedDelay
|
2024-07-08 17:34:14 +08:00
|
|
|
//targetConfig.GeodataMode = false
|
2024-06-11 20:50:57 +08:00
|
|
|
targetConfig.IPv6 = patchConfig.IPv6
|
2024-04-30 23:38:49 +08:00
|
|
|
targetConfig.LogLevel = patchConfig.LogLevel
|
2024-07-15 13:47:06 +08:00
|
|
|
targetConfig.Port = 0
|
|
|
|
|
targetConfig.SocksPort = 0
|
2024-06-06 10:13:03 +08:00
|
|
|
targetConfig.MixedPort = patchConfig.MixedPort
|
2024-06-13 23:43:42 +08:00
|
|
|
targetConfig.FindProcessMode = patchConfig.FindProcessMode
|
2024-04-30 23:38:49 +08:00
|
|
|
targetConfig.AllowLan = patchConfig.AllowLan
|
|
|
|
|
targetConfig.Mode = patchConfig.Mode
|
|
|
|
|
targetConfig.Tun.Enable = patchConfig.Tun.Enable
|
|
|
|
|
targetConfig.Tun.Device = patchConfig.Tun.Device
|
2024-06-29 21:42:00 +08:00
|
|
|
targetConfig.Tun.DNSHijack = patchConfig.Tun.DNSHijack
|
|
|
|
|
targetConfig.Tun.Stack = patchConfig.Tun.Stack
|
2024-06-12 19:28:58 +08:00
|
|
|
targetConfig.GeodataLoader = patchConfig.GeodataLoader
|
2024-05-05 16:12:00 +08:00
|
|
|
targetConfig.Profile.StoreSelected = false
|
2024-07-13 16:36:08 +08:00
|
|
|
targetConfig.GeoXUrl = patchConfig.GeoXUrl
|
|
|
|
|
targetConfig.GlobalUA = patchConfig.GlobalUA
|
2024-04-30 23:38:49 +08:00
|
|
|
if targetConfig.DNS.Enable == false {
|
|
|
|
|
targetConfig.DNS = patchConfig.DNS
|
|
|
|
|
}
|
2024-06-13 23:43:42 +08:00
|
|
|
//if runtime.GOOS == "android" {
|
|
|
|
|
// targetConfig.DNS.NameServer = append(targetConfig.DNS.NameServer, "dhcp://"+dns.SystemDNSPlaceholder)
|
|
|
|
|
//} else if runtime.GOOS == "windows" {
|
|
|
|
|
// targetConfig.DNS.NameServer = append(targetConfig.DNS.NameServer, dns.SystemDNSPlaceholder)
|
|
|
|
|
//}
|
2024-07-02 08:08:31 +08:00
|
|
|
if configParams.IsCompatible == false {
|
2024-05-10 10:11:27 +08:00
|
|
|
targetConfig.ProxyProvider = make(map[string]map[string]any)
|
|
|
|
|
targetConfig.RuleProvider = make(map[string]map[string]any)
|
|
|
|
|
generateProxyGroupAndRule(&targetConfig.ProxyGroup, &targetConfig.Rule)
|
|
|
|
|
}
|
2024-04-30 23:38:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func patchConfig(general *config.General) {
|
|
|
|
|
log.Infoln("[Apply] patch")
|
2024-06-13 19:17:14 +08:00
|
|
|
route.ReStartServer(general.ExternalController)
|
2024-04-30 23:38:49 +08:00
|
|
|
listener.SetAllowLan(general.AllowLan)
|
|
|
|
|
inbound.SetSkipAuthPrefixes(general.SkipAuthPrefixes)
|
|
|
|
|
inbound.SetAllowedIPs(general.LanAllowedIPs)
|
|
|
|
|
inbound.SetDisAllowedIPs(general.LanDisAllowedIPs)
|
|
|
|
|
listener.SetBindAddress(general.BindAddress)
|
|
|
|
|
tunnel.SetSniffing(general.Sniffing)
|
2024-06-13 23:43:42 +08:00
|
|
|
tunnel.SetFindProcessMode(general.FindProcessMode)
|
2024-04-30 23:38:49 +08:00
|
|
|
dialer.SetTcpConcurrent(general.TCPConcurrent)
|
|
|
|
|
dialer.DefaultInterface.Store(general.Interface)
|
2024-06-13 23:43:42 +08:00
|
|
|
adapter.UnifiedDelay.Store(general.UnifiedDelay)
|
2024-04-30 23:38:49 +08:00
|
|
|
listener.ReCreateHTTP(general.Port, tunnel.Tunnel)
|
|
|
|
|
listener.ReCreateSocks(general.SocksPort, tunnel.Tunnel)
|
|
|
|
|
listener.ReCreateRedir(general.RedirPort, tunnel.Tunnel)
|
|
|
|
|
listener.ReCreateAutoRedir(general.EBpf.AutoRedir, tunnel.Tunnel)
|
|
|
|
|
listener.ReCreateTProxy(general.TProxyPort, tunnel.Tunnel)
|
|
|
|
|
listener.ReCreateTun(general.Tun, tunnel.Tunnel)
|
|
|
|
|
listener.ReCreateMixed(general.MixedPort, tunnel.Tunnel)
|
|
|
|
|
listener.ReCreateShadowSocks(general.ShadowSocksConfig, tunnel.Tunnel)
|
|
|
|
|
listener.ReCreateVmess(general.VmessConfig, tunnel.Tunnel)
|
|
|
|
|
listener.ReCreateTuic(general.TuicServer, tunnel.Tunnel)
|
|
|
|
|
tunnel.SetMode(general.Mode)
|
|
|
|
|
log.SetLevel(general.LogLevel)
|
|
|
|
|
|
2024-06-13 19:17:14 +08:00
|
|
|
resolver.DisableIPv6 = !general.IPv6
|
2024-05-06 16:57:53 +08:00
|
|
|
}
|
2024-05-06 10:32:39 +08:00
|
|
|
|
2024-07-02 08:08:31 +08:00
|
|
|
func patchSelectGroup() {
|
|
|
|
|
mapping := configParams.SelectedMap
|
|
|
|
|
if mapping == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
for name, proxy := range tunnel.ProxiesWithProviders() {
|
|
|
|
|
outbound, ok := proxy.(*adapter.Proxy)
|
|
|
|
|
if !ok {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
selector, ok := outbound.ProxyAdapter.(outboundgroup.SelectAble)
|
|
|
|
|
if !ok {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
selected, exist := mapping[name]
|
|
|
|
|
if !exist {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
selector.ForceSet(selected)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-07 10:02:10 +08:00
|
|
|
var applyLock sync.Mutex
|
|
|
|
|
|
2024-07-26 08:05:22 +08:00
|
|
|
func applyConfig() error {
|
2024-07-07 10:02:10 +08:00
|
|
|
applyLock.Lock()
|
|
|
|
|
defer applyLock.Unlock()
|
2024-04-30 23:38:49 +08:00
|
|
|
cfg, err := config.ParseRawConfig(currentConfig)
|
|
|
|
|
if err != nil {
|
|
|
|
|
cfg, _ = config.ParseRawConfig(config.DefaultRawConfig())
|
|
|
|
|
}
|
2024-07-02 08:08:31 +08:00
|
|
|
if configParams.TestURL != nil {
|
|
|
|
|
constant.DefaultTestURL = *configParams.TestURL
|
|
|
|
|
}
|
|
|
|
|
if configParams.IsPatch {
|
2024-04-30 23:38:49 +08:00
|
|
|
patchConfig(cfg.General)
|
|
|
|
|
} else {
|
2024-07-24 01:27:49 +08:00
|
|
|
closeConnections()
|
2024-06-19 13:13:31 +08:00
|
|
|
runtime.GC()
|
2024-06-12 19:28:58 +08:00
|
|
|
hub.UltraApplyConfig(cfg, true)
|
2024-07-02 08:08:31 +08:00
|
|
|
patchSelectGroup()
|
2024-04-30 23:38:49 +08:00
|
|
|
}
|
2024-07-26 08:05:22 +08:00
|
|
|
return err
|
2024-04-30 23:38:49 +08:00
|
|
|
}
|