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  }