From f5834dd5e272d69a9f494ad318c8f3f6e5f34c1f Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Sat, 24 Aug 2024 13:25:23 +0800 Subject: [PATCH] chore: code cleanup --- common/nnip/netip.go | 20 +++++ hub/executor/executor.go | 10 +-- hub/route/configs.go | 15 +--- listener/config/tun.go | 147 ++++++++++++++++++++++++++++++++++- listener/listener.go | 161 ++++----------------------------------- 5 files changed, 185 insertions(+), 168 deletions(-) diff --git a/common/nnip/netip.go b/common/nnip/netip.go index e4566138..b987bb45 100644 --- a/common/nnip/netip.go +++ b/common/nnip/netip.go @@ -51,3 +51,23 @@ func UnMasked(p netip.Prefix) netip.Addr { } return addr } + +// PrefixCompare returns an integer comparing two prefixes. +// The result will be 0 if p == p2, -1 if p < p2, and +1 if p > p2. +// modify from https://github.com/golang/go/issues/61642#issuecomment-1848587909 +func PrefixCompare(p, p2 netip.Prefix) int { + // compare by validity, address family and prefix base address + if c := p.Masked().Addr().Compare(p2.Masked().Addr()); c != 0 { + return c + } + // compare by prefix length + f1, f2 := p.Bits(), p2.Bits() + if f1 < f2 { + return -1 + } + if f1 > f2 { + return 1 + } + // compare by prefix address + return p.Addr().Compare(p2.Addr()) +} diff --git a/hub/executor/executor.go b/hub/executor/executor.go index 89145241..8eb54ac4 100644 --- a/hub/executor/executor.go +++ b/hub/executor/executor.go @@ -90,6 +90,7 @@ func ApplyConfig(cfg *config.Config, force bool) { } } + updateExperimental(cfg) updateUsers(cfg.Users) updateProxies(cfg.Proxies, cfg.Providers) updateRules(cfg.Rules, cfg.SubRules, cfg.RuleProviders) @@ -100,8 +101,6 @@ func ApplyConfig(cfg *config.Config, force bool) { updateDNS(cfg.DNS, cfg.General.IPv6) updateListeners(cfg.General, cfg.Listeners, force) updateIPTables(cfg) - updateTun(cfg.General) - updateExperimental(cfg) updateTunnels(cfg.Tunnels) tunnel.OnInnerLoading() @@ -186,6 +185,7 @@ func updateListeners(general *config.General, listeners map[string]C.InboundList listener.ReCreateShadowSocks(general.ShadowSocksConfig, tunnel.Tunnel) listener.ReCreateVmess(general.VmessConfig, tunnel.Tunnel) listener.ReCreateTuic(general.TuicServer, tunnel.Tunnel) + listener.ReCreateTun(general.Tun, tunnel.Tunnel) } func updateExperimental(c *config.Config) { @@ -343,12 +343,6 @@ func hcCompatibleProvider(proxyProviders map[string]provider.ProxyProvider) { } } -func updateTun(general *config.General) { - if general == nil { - return - } - listener.ReCreateTun(general.Tun, tunnel.Tunnel) -} func updateSniffer(sniffer *config.Sniffer) { if sniffer.Enable { diff --git a/hub/route/configs.go b/hub/route/configs.go index c7b340c6..b31a607e 100644 --- a/hub/route/configs.go +++ b/hub/route/configs.go @@ -62,7 +62,6 @@ type tunSchema struct { DNSHijack *[]string `yaml:"dns-hijack" json:"dns-hijack"` AutoRoute *bool `yaml:"auto-route" json:"auto-route"` AutoDetectInterface *bool `yaml:"auto-detect-interface" json:"auto-detect-interface"` - //RedirectToTun []string `yaml:"-" json:"-"` MTU *uint32 `yaml:"mtu" json:"mtu,omitempty"` GSO *bool `yaml:"gso" json:"gso,omitempty"` @@ -118,21 +117,13 @@ func getConfigs(w http.ResponseWriter, r *http.Request) { render.JSON(w, r, general) } -func pointerOrDefault(p *int, def int) int { +func pointerOrDefault[T any](p *T, def T) T { if p != nil { return *p } return def } -func pointerOrDefaultString(p *string, def string) string { - if p != nil { - return *p - } - - return def -} - func pointerOrDefaultTun(p *tunSchema, def LC.Tun) LC.Tun { if p != nil { def.Enable = p.Enable @@ -336,8 +327,8 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) { P.ReCreateTProxy(pointerOrDefault(general.TProxyPort, ports.TProxyPort), tunnel.Tunnel) P.ReCreateMixed(pointerOrDefault(general.MixedPort, ports.MixedPort), tunnel.Tunnel) P.ReCreateTun(pointerOrDefaultTun(general.Tun, P.LastTunConf), tunnel.Tunnel) - P.ReCreateShadowSocks(pointerOrDefaultString(general.ShadowSocksConfig, ports.ShadowSocksConfig), tunnel.Tunnel) - P.ReCreateVmess(pointerOrDefaultString(general.VmessConfig, ports.VmessConfig), tunnel.Tunnel) + P.ReCreateShadowSocks(pointerOrDefault(general.ShadowSocksConfig, ports.ShadowSocksConfig), tunnel.Tunnel) + P.ReCreateVmess(pointerOrDefault(general.VmessConfig, ports.VmessConfig), tunnel.Tunnel) P.ReCreateTuic(pointerOrDefaultTuicServer(general.TuicServer, P.LastTuicConf), tunnel.Tunnel) if general.Mode != nil { diff --git a/listener/config/tun.go b/listener/config/tun.go index cea22bfd..06dc53ef 100644 --- a/listener/config/tun.go +++ b/listener/config/tun.go @@ -3,7 +3,10 @@ package config import ( "net/netip" + "github.com/metacubex/mihomo/common/nnip" C "github.com/metacubex/mihomo/constant" + + "golang.org/x/exp/slices" ) func StringSliceToNetipPrefixSlice(ss []string) ([]netip.Prefix, error) { @@ -25,7 +28,6 @@ type Tun struct { DNSHijack []string `yaml:"dns-hijack" json:"dns-hijack"` AutoRoute bool `yaml:"auto-route" json:"auto-route"` AutoDetectInterface bool `yaml:"auto-detect-interface" json:"auto-detect-interface"` - RedirectToTun []string `yaml:"-" json:"-"` MTU uint32 `yaml:"mtu" json:"mtu,omitempty"` GSO bool `yaml:"gso" json:"gso,omitempty"` @@ -60,3 +62,146 @@ type Tun struct { Inet4RouteExcludeAddress []netip.Prefix `yaml:"inet4-route-exclude-address" json:"inet4-route-exclude-address,omitempty"` Inet6RouteExcludeAddress []netip.Prefix `yaml:"inet6-route-exclude-address" json:"inet6-route-exclude-address,omitempty"` } + +func (t *Tun) Sort() { + slices.Sort(t.DNSHijack) + + slices.SortFunc(t.Inet4Address, nnip.PrefixCompare) + slices.SortFunc(t.Inet6Address, nnip.PrefixCompare) + slices.SortFunc(t.RouteAddress, nnip.PrefixCompare) + slices.Sort(t.RouteAddressSet) + slices.SortFunc(t.RouteExcludeAddress, nnip.PrefixCompare) + slices.Sort(t.RouteExcludeAddressSet) + slices.Sort(t.IncludeInterface) + slices.Sort(t.ExcludeInterface) + slices.Sort(t.IncludeUID) + slices.Sort(t.IncludeUIDRange) + slices.Sort(t.ExcludeUID) + slices.Sort(t.ExcludeUIDRange) + slices.Sort(t.IncludeAndroidUser) + slices.Sort(t.IncludePackage) + slices.Sort(t.ExcludePackage) + + slices.SortFunc(t.Inet4RouteAddress, nnip.PrefixCompare) + slices.SortFunc(t.Inet6RouteAddress, nnip.PrefixCompare) + slices.SortFunc(t.Inet4RouteExcludeAddress, nnip.PrefixCompare) + slices.SortFunc(t.Inet6RouteExcludeAddress, nnip.PrefixCompare) +} + +func (t *Tun) Equal(other Tun) bool { + if t.Enable != other.Enable { + return false + } + if t.Device != other.Device { + return false + } + if t.Stack != other.Stack { + return false + } + if !slices.Equal(t.DNSHijack, other.DNSHijack) { + return false + } + if t.AutoRoute != other.AutoRoute { + return false + } + if t.AutoDetectInterface != other.AutoDetectInterface { + return false + } + + if t.MTU != other.MTU { + return false + } + if t.GSO != other.GSO { + return false + } + if t.GSOMaxSize != other.GSOMaxSize { + return false + } + if !slices.Equal(t.Inet4Address, other.Inet4Address) { + return false + } + if !slices.Equal(t.Inet6Address, other.Inet6Address) { + return false + } + if t.IPRoute2TableIndex != other.IPRoute2TableIndex { + return false + } + if t.IPRoute2RuleIndex != other.IPRoute2RuleIndex { + return false + } + if t.AutoRedirect != other.AutoRedirect { + return false + } + if t.AutoRedirectInputMark != other.AutoRedirectInputMark { + return false + } + if t.AutoRedirectOutputMark != other.AutoRedirectOutputMark { + return false + } + if t.StrictRoute != other.StrictRoute { + return false + } + if !slices.Equal(t.RouteAddress, other.RouteAddress) { + return false + } + if !slices.Equal(t.RouteAddressSet, other.RouteAddressSet) { + return false + } + if !slices.Equal(t.RouteExcludeAddress, other.RouteExcludeAddress) { + return false + } + if !slices.Equal(t.RouteExcludeAddressSet, other.RouteExcludeAddressSet) { + return false + } + if !slices.Equal(t.IncludeInterface, other.IncludeInterface) { + return false + } + if !slices.Equal(t.ExcludeInterface, other.ExcludeInterface) { + return false + } + if !slices.Equal(t.IncludeUID, other.IncludeUID) { + return false + } + if !slices.Equal(t.IncludeUIDRange, other.IncludeUIDRange) { + return false + } + if !slices.Equal(t.ExcludeUID, other.ExcludeUID) { + return false + } + if !slices.Equal(t.ExcludeUIDRange, other.ExcludeUIDRange) { + return false + } + if !slices.Equal(t.IncludeAndroidUser, other.IncludeAndroidUser) { + return false + } + if !slices.Equal(t.IncludePackage, other.IncludePackage) { + return false + } + if !slices.Equal(t.ExcludePackage, other.ExcludePackage) { + return false + } + if t.EndpointIndependentNat != other.EndpointIndependentNat { + return false + } + if t.UDPTimeout != other.UDPTimeout { + return false + } + if t.FileDescriptor != other.FileDescriptor { + return false + } + + if !slices.Equal(t.Inet4RouteAddress, other.Inet4RouteAddress) { + return false + } + if !slices.Equal(t.Inet6RouteAddress, other.Inet6RouteAddress) { + return false + } + if !slices.Equal(t.Inet4RouteExcludeAddress, other.Inet4RouteExcludeAddress) { + return false + } + if !slices.Equal(t.Inet6RouteExcludeAddress, other.Inet6RouteExcludeAddress) { + return false + } + + return true +} diff --git a/listener/listener.go b/listener/listener.go index 4d106778..2e25c8b8 100644 --- a/listener/listener.go +++ b/listener/listener.go @@ -2,9 +2,7 @@ package listener import ( "fmt" - "golang.org/x/exp/slices" "net" - "sort" "strconv" "strings" "sync" @@ -49,19 +47,17 @@ var ( tuicListener *tuic.Listener // lock for recreate function - socksMux sync.Mutex - httpMux sync.Mutex - redirMux sync.Mutex - tproxyMux sync.Mutex - mixedMux sync.Mutex - tunnelMux sync.Mutex - inboundMux sync.Mutex - tunMux sync.Mutex - ssMux sync.Mutex - vmessMux sync.Mutex - tuicMux sync.Mutex - autoRedirMux sync.Mutex - tcMux sync.Mutex + socksMux sync.Mutex + httpMux sync.Mutex + redirMux sync.Mutex + tproxyMux sync.Mutex + mixedMux sync.Mutex + tunnelMux sync.Mutex + inboundMux sync.Mutex + tunMux sync.Mutex + ssMux sync.Mutex + vmessMux sync.Mutex + tuicMux sync.Mutex LastTunConf LC.Tun LastTuicConf LC.TuicServer @@ -499,6 +495,8 @@ func ReCreateMixed(port int, tunnel C.Tunnel) { } func ReCreateTun(tunConf LC.Tun, tunnel C.Tunnel) { + tunConf.Sort() + tunMux.Lock() defer func() { LastTunConf = tunConf @@ -513,7 +511,7 @@ func ReCreateTun(tunConf LC.Tun, tunnel C.Tunnel) { } }() - if !hasTunConfigChange(&tunConf) { + if tunConf.Equal(LastTunConf) { if tunLister != nil { tunLister.FlushDefaultInterface() } @@ -717,137 +715,6 @@ func genAddr(host string, port int, allowLan bool) string { return fmt.Sprintf("127.0.0.1:%d", port) } -func hasTunConfigChange(tunConf *LC.Tun) bool { - if LastTunConf.Enable != tunConf.Enable || - LastTunConf.Device != tunConf.Device || - LastTunConf.Stack != tunConf.Stack || - LastTunConf.AutoRoute != tunConf.AutoRoute || - LastTunConf.AutoDetectInterface != tunConf.AutoDetectInterface || - LastTunConf.MTU != tunConf.MTU || - LastTunConf.GSO != tunConf.GSO || - LastTunConf.GSOMaxSize != tunConf.GSOMaxSize || - LastTunConf.IPRoute2TableIndex != tunConf.IPRoute2TableIndex || - LastTunConf.IPRoute2RuleIndex != tunConf.IPRoute2RuleIndex || - LastTunConf.AutoRedirect != tunConf.AutoRedirect || - LastTunConf.AutoRedirectInputMark != tunConf.AutoRedirectInputMark || - LastTunConf.AutoRedirectOutputMark != tunConf.AutoRedirectOutputMark || - LastTunConf.StrictRoute != tunConf.StrictRoute || - LastTunConf.EndpointIndependentNat != tunConf.EndpointIndependentNat || - LastTunConf.UDPTimeout != tunConf.UDPTimeout || - LastTunConf.FileDescriptor != tunConf.FileDescriptor { - return true - } - - if len(LastTunConf.DNSHijack) != len(tunConf.DNSHijack) { - return true - } - - sort.Slice(tunConf.DNSHijack, func(i, j int) bool { - return tunConf.DNSHijack[i] < tunConf.DNSHijack[j] - }) - - sort.Slice(tunConf.RouteAddress, func(i, j int) bool { - return tunConf.RouteAddress[i].String() < tunConf.RouteAddress[j].String() - }) - - sort.Slice(tunConf.RouteAddressSet, func(i, j int) bool { - return tunConf.RouteAddressSet[i] < tunConf.RouteAddressSet[j] - }) - - sort.Slice(tunConf.RouteExcludeAddress, func(i, j int) bool { - return tunConf.RouteExcludeAddress[i].String() < tunConf.RouteExcludeAddress[j].String() - }) - - sort.Slice(tunConf.RouteExcludeAddressSet, func(i, j int) bool { - return tunConf.RouteExcludeAddressSet[i] < tunConf.RouteExcludeAddressSet[j] - }) - - sort.Slice(tunConf.Inet4Address, func(i, j int) bool { - return tunConf.Inet4Address[i].String() < tunConf.Inet4Address[j].String() - }) - - sort.Slice(tunConf.Inet6Address, func(i, j int) bool { - return tunConf.Inet6Address[i].String() < tunConf.Inet6Address[j].String() - }) - - sort.Slice(tunConf.Inet4RouteAddress, func(i, j int) bool { - return tunConf.Inet4RouteAddress[i].String() < tunConf.Inet4RouteAddress[j].String() - }) - - sort.Slice(tunConf.Inet6RouteAddress, func(i, j int) bool { - return tunConf.Inet6RouteAddress[i].String() < tunConf.Inet6RouteAddress[j].String() - }) - - sort.Slice(tunConf.Inet4RouteExcludeAddress, func(i, j int) bool { - return tunConf.Inet4RouteExcludeAddress[i].String() < tunConf.Inet4RouteExcludeAddress[j].String() - }) - - sort.Slice(tunConf.Inet6RouteExcludeAddress, func(i, j int) bool { - return tunConf.Inet6RouteExcludeAddress[i].String() < tunConf.Inet6RouteExcludeAddress[j].String() - }) - - sort.Slice(tunConf.IncludeInterface, func(i, j int) bool { - return tunConf.IncludeInterface[i] < tunConf.IncludeInterface[j] - }) - - sort.Slice(tunConf.ExcludeInterface, func(i, j int) bool { - return tunConf.ExcludeInterface[i] < tunConf.ExcludeInterface[j] - }) - - sort.Slice(tunConf.IncludeUID, func(i, j int) bool { - return tunConf.IncludeUID[i] < tunConf.IncludeUID[j] - }) - - sort.Slice(tunConf.IncludeUIDRange, func(i, j int) bool { - return tunConf.IncludeUIDRange[i] < tunConf.IncludeUIDRange[j] - }) - - sort.Slice(tunConf.ExcludeUID, func(i, j int) bool { - return tunConf.ExcludeUID[i] < tunConf.ExcludeUID[j] - }) - - sort.Slice(tunConf.ExcludeUIDRange, func(i, j int) bool { - return tunConf.ExcludeUIDRange[i] < tunConf.ExcludeUIDRange[j] - }) - - sort.Slice(tunConf.IncludeAndroidUser, func(i, j int) bool { - return tunConf.IncludeAndroidUser[i] < tunConf.IncludeAndroidUser[j] - }) - - sort.Slice(tunConf.IncludePackage, func(i, j int) bool { - return tunConf.IncludePackage[i] < tunConf.IncludePackage[j] - }) - - sort.Slice(tunConf.ExcludePackage, func(i, j int) bool { - return tunConf.ExcludePackage[i] < tunConf.ExcludePackage[j] - }) - - if !slices.Equal(tunConf.DNSHijack, LastTunConf.DNSHijack) || - !slices.Equal(tunConf.RouteAddress, LastTunConf.RouteAddress) || - !slices.Equal(tunConf.RouteAddressSet, LastTunConf.RouteAddressSet) || - !slices.Equal(tunConf.RouteExcludeAddress, LastTunConf.RouteExcludeAddress) || - !slices.Equal(tunConf.RouteExcludeAddressSet, LastTunConf.RouteExcludeAddressSet) || - !slices.Equal(tunConf.Inet4Address, LastTunConf.Inet4Address) || - !slices.Equal(tunConf.Inet6Address, LastTunConf.Inet6Address) || - !slices.Equal(tunConf.Inet4RouteAddress, LastTunConf.Inet4RouteAddress) || - !slices.Equal(tunConf.Inet6RouteAddress, LastTunConf.Inet6RouteAddress) || - !slices.Equal(tunConf.Inet4RouteExcludeAddress, LastTunConf.Inet4RouteExcludeAddress) || - !slices.Equal(tunConf.Inet6RouteExcludeAddress, LastTunConf.Inet6RouteExcludeAddress) || - !slices.Equal(tunConf.IncludeInterface, LastTunConf.IncludeInterface) || - !slices.Equal(tunConf.ExcludeInterface, LastTunConf.ExcludeInterface) || - !slices.Equal(tunConf.IncludeUID, LastTunConf.IncludeUID) || - !slices.Equal(tunConf.IncludeUIDRange, LastTunConf.IncludeUIDRange) || - !slices.Equal(tunConf.ExcludeUID, LastTunConf.ExcludeUID) || - !slices.Equal(tunConf.ExcludeUIDRange, LastTunConf.ExcludeUIDRange) || - !slices.Equal(tunConf.IncludeAndroidUser, LastTunConf.IncludeAndroidUser) || - !slices.Equal(tunConf.IncludePackage, LastTunConf.IncludePackage) || - !slices.Equal(tunConf.ExcludePackage, LastTunConf.ExcludePackage) { - return true - } - - return false -} - func closeTunListener() { if tunLister != nil { tunLister.Close()