github.com/igoogolx/clash@v1.19.8/hub/executor/executor.go (about) 1 package executor 2 3 import ( 4 "fmt" 5 "os" 6 "sync" 7 8 "github.com/igoogolx/clash/adapter" 9 "github.com/igoogolx/clash/adapter/outboundgroup" 10 "github.com/igoogolx/clash/component/auth" 11 "github.com/igoogolx/clash/component/dialer" 12 "github.com/igoogolx/clash/component/iface" 13 "github.com/igoogolx/clash/component/profile" 14 "github.com/igoogolx/clash/component/profile/cachefile" 15 "github.com/igoogolx/clash/component/resolver" 16 "github.com/igoogolx/clash/component/trie" 17 "github.com/igoogolx/clash/config" 18 C "github.com/igoogolx/clash/constant" 19 "github.com/igoogolx/clash/constant/provider" 20 "github.com/igoogolx/clash/dns" 21 "github.com/igoogolx/clash/listener" 22 authStore "github.com/igoogolx/clash/listener/auth" 23 "github.com/igoogolx/clash/log" 24 "github.com/igoogolx/clash/tunnel" 25 ) 26 27 var mux sync.Mutex 28 29 func readConfig(path string) ([]byte, error) { 30 if _, err := os.Stat(path); os.IsNotExist(err) { 31 return nil, err 32 } 33 data, err := os.ReadFile(path) 34 if err != nil { 35 return nil, err 36 } 37 38 if len(data) == 0 { 39 return nil, fmt.Errorf("configuration file %s is empty", path) 40 } 41 42 return data, err 43 } 44 45 // Parse config with default config path 46 func Parse() (*config.Config, error) { 47 return ParseWithPath(C.Path.Config()) 48 } 49 50 // ParseWithPath parse config with custom config path 51 func ParseWithPath(path string) (*config.Config, error) { 52 buf, err := readConfig(path) 53 if err != nil { 54 return nil, err 55 } 56 57 return ParseWithBytes(buf) 58 } 59 60 // ParseWithBytes config with buffer 61 func ParseWithBytes(buf []byte) (*config.Config, error) { 62 return config.Parse(buf) 63 } 64 65 // ApplyConfig dispatch configure to all parts 66 func ApplyConfig(cfg *config.Config, force bool) { 67 mux.Lock() 68 defer mux.Unlock() 69 70 updateUsers(cfg.Users) 71 updateProxies(cfg.Proxies, cfg.Providers) 72 updateRules(cfg.Rules) 73 updateHosts(cfg.Hosts) 74 updateProfile(cfg) 75 updateGeneral(cfg.General, force) 76 updateInbounds(cfg.Inbounds, force) 77 updateDNS(cfg.DNS) 78 updateExperimental(cfg) 79 updateTunnels(cfg.Tunnels) 80 } 81 82 func GetGeneral() *config.General { 83 ports := listener.GetPorts() 84 authenticator := []string{} 85 if auth := authStore.Authenticator(); auth != nil { 86 authenticator = auth.Users() 87 } 88 89 general := &config.General{ 90 LegacyInbound: config.LegacyInbound{ 91 Port: ports.Port, 92 SocksPort: ports.SocksPort, 93 RedirPort: ports.RedirPort, 94 TProxyPort: ports.TProxyPort, 95 MixedPort: ports.MixedPort, 96 AllowLan: listener.AllowLan(), 97 BindAddress: listener.BindAddress(), 98 }, 99 Authentication: authenticator, 100 Mode: tunnel.Mode(), 101 LogLevel: log.Level(), 102 IPv6: !resolver.DisableIPv6, 103 } 104 105 return general 106 } 107 108 func updateExperimental(c *config.Config) { 109 tunnel.UDPFallbackMatch.Store(c.Experimental.UDPFallbackMatch) 110 } 111 112 func updateDNS(c *config.DNS) { 113 if !c.Enable { 114 resolver.DefaultResolver = nil 115 resolver.DefaultHostMapper = nil 116 dns.ReCreateServer("", nil, nil) 117 return 118 } 119 120 cfg := dns.Config{ 121 Main: c.NameServer, 122 Fallback: c.Fallback, 123 IPv6: c.IPv6, 124 EnhancedMode: c.EnhancedMode, 125 Pool: c.FakeIPRange, 126 Hosts: c.Hosts, 127 FallbackFilter: dns.FallbackFilter{ 128 GeoIP: c.FallbackFilter.GeoIP, 129 GeoIPCode: c.FallbackFilter.GeoIPCode, 130 IPCIDR: c.FallbackFilter.IPCIDR, 131 Domain: c.FallbackFilter.Domain, 132 }, 133 Default: c.DefaultNameserver, 134 Policy: c.NameServerPolicy, 135 SearchDomains: c.SearchDomains, 136 } 137 138 r := dns.NewResolver(cfg) 139 m := dns.NewEnhancer(cfg) 140 141 // reuse cache of old host mapper 142 if old := resolver.DefaultHostMapper; old != nil { 143 m.PatchFrom(old.(*dns.ResolverEnhancer)) 144 } 145 146 resolver.DefaultResolver = r 147 resolver.DefaultHostMapper = m 148 149 dns.ReCreateServer(c.Listen, r, m) 150 } 151 152 func updateHosts(tree *trie.DomainTrie) { 153 resolver.DefaultHosts = tree 154 } 155 156 func updateProxies(proxies map[string]C.Proxy, providers map[string]provider.ProxyProvider) { 157 tunnel.UpdateProxies(proxies, providers) 158 } 159 160 func updateRules(rules []C.Rule) { 161 tunnel.UpdateRules(rules) 162 } 163 164 func updateTunnels(tunnels []config.Tunnel) { 165 listener.PatchTunnel(tunnels, tunnel.TCPIn(), tunnel.UDPIn()) 166 } 167 168 func updateInbounds(inbounds []C.Inbound, force bool) { 169 if !force { 170 return 171 } 172 tcpIn := tunnel.TCPIn() 173 udpIn := tunnel.UDPIn() 174 175 listener.ReCreateListeners(inbounds, tcpIn, udpIn) 176 } 177 178 func updateGeneral(general *config.General, force bool) { 179 log.SetLevel(general.LogLevel) 180 tunnel.SetMode(general.Mode) 181 resolver.DisableIPv6 = !general.IPv6 182 183 dialer.DefaultInterface.Store(general.Interface) 184 dialer.DefaultRoutingMark.Store(int32(general.RoutingMark)) 185 186 iface.FlushCache() 187 188 if !force { 189 return 190 } 191 192 allowLan := general.AllowLan 193 listener.SetAllowLan(allowLan) 194 195 bindAddress := general.BindAddress 196 listener.SetBindAddress(bindAddress) 197 198 ports := listener.Ports{ 199 Port: general.Port, 200 SocksPort: general.SocksPort, 201 RedirPort: general.RedirPort, 202 TProxyPort: general.TProxyPort, 203 MixedPort: general.MixedPort, 204 } 205 listener.ReCreatePortsListeners(ports, tunnel.TCPIn(), tunnel.UDPIn()) 206 } 207 208 func updateUsers(users []auth.AuthUser) { 209 authenticator := auth.NewAuthenticator(users) 210 authStore.SetAuthenticator(authenticator) 211 if authenticator != nil { 212 log.Infoln("Authentication of local server updated") 213 } 214 } 215 216 func updateProfile(cfg *config.Config) { 217 profileCfg := cfg.Profile 218 219 profile.StoreSelected.Store(profileCfg.StoreSelected) 220 if profileCfg.StoreSelected { 221 patchSelectGroup(cfg.Proxies) 222 } 223 } 224 225 func patchSelectGroup(proxies map[string]C.Proxy) { 226 mapping := cachefile.Cache().SelectedMap() 227 if mapping == nil { 228 return 229 } 230 231 for name, proxy := range proxies { 232 outbound, ok := proxy.(*adapter.Proxy) 233 if !ok { 234 continue 235 } 236 237 selector, ok := outbound.ProxyAdapter.(*outboundgroup.Selector) 238 if !ok { 239 continue 240 } 241 242 selected, exist := mapping[name] 243 if !exist { 244 continue 245 } 246 247 selector.Set(selected) 248 } 249 }