Chore: cleanup code

This commit is contained in:
yaling888 2022-07-01 18:34:36 +08:00
parent e1fe8ce3b2
commit ae6cc1d67d
25 changed files with 159 additions and 189 deletions

View File

@ -30,10 +30,8 @@ type LoadBalance struct {
var errStrategy = errors.New("unsupported strategy") var errStrategy = errors.New("unsupported strategy")
func parseStrategy(config map[string]any) string { func parseStrategy(config map[string]any) string {
if elm, ok := config["strategy"]; ok { if strategy, ok := config["strategy"].(string); ok {
if strategy, ok := elm.(string); ok { return strategy
return strategy
}
} }
return "consistent-hashing" return "consistent-hashing"
} }

View File

@ -125,10 +125,8 @@ func parseURLTestOption(config map[string]any) []urlTestOption {
opts := []urlTestOption{} opts := []urlTestOption{}
// tolerance // tolerance
if elm, ok := config["tolerance"]; ok { if tolerance, ok := config["tolerance"].(int); ok {
if tolerance, ok := elm.(int); ok { opts = append(opts, urlTestWithTolerance(uint16(tolerance)))
opts = append(opts, urlTestWithTolerance(uint16(tolerance)))
}
} }
return opts return opts

View File

@ -10,7 +10,7 @@ import (
func ParseProxy(mapping map[string]any, forceCertVerify bool) (C.Proxy, error) { func ParseProxy(mapping map[string]any, forceCertVerify bool) (C.Proxy, error) {
decoder := structure.NewDecoder(structure.Option{TagName: "proxy", WeaklyTypedInput: true}) decoder := structure.NewDecoder(structure.Option{TagName: "proxy", WeaklyTypedInput: true})
proxyType, existType := mapping["type"] proxyType, existType := mapping["type"].(string)
if !existType { if !existType {
return nil, fmt.Errorf("missing type") return nil, fmt.Errorf("missing type")
} }
@ -19,7 +19,7 @@ func ParseProxy(mapping map[string]any, forceCertVerify bool) (C.Proxy, error) {
proxy C.ProxyAdapter proxy C.ProxyAdapter
err error err error
) )
switch proxyType.(string) { switch proxyType {
case "ss": case "ss":
ssOption := &outbound.ShadowSocksOption{} ssOption := &outbound.ShadowSocksOption{}
err = decoder.Decode(mapping, ssOption) err = decoder.Decode(mapping, ssOption)

View File

@ -5,6 +5,7 @@ import (
"crypto/md5" "crypto/md5"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"time" "time"
types "github.com/Dreamacro/clash/constant/provider" types "github.com/Dreamacro/clash/constant/provider"
@ -14,6 +15,8 @@ import (
var ( var (
fileMode os.FileMode = 0o666 fileMode os.FileMode = 0o666
dirMode os.FileMode = 0o755 dirMode os.FileMode = 0o755
commentRegx = regexp.MustCompile(`(.*#.*\n)`)
) )
type parser[V any] func([]byte) (V, error) type parser[V any] func([]byte) (V, error)
@ -168,6 +171,18 @@ func safeWrite(path string, buf []byte) error {
return os.WriteFile(path, buf, fileMode) return os.WriteFile(path, buf, fileMode)
} }
func removeComment(buf []byte) []byte {
arr := commentRegx.FindAllSubmatch(buf, -1)
for _, subs := range arr {
sub := subs[0]
if !bytes.HasPrefix(bytes.TrimLeft(sub, " "), []byte("#")) {
continue
}
buf = bytes.Replace(buf, sub, []byte(""), 1)
}
return buf
}
func newFetcher[V any](name string, interval time.Duration, vehicle types.Vehicle, parser parser[V], onUpdate func(V)) *fetcher[V] { func newFetcher[V any](name string, interval time.Duration, vehicle types.Vehicle, parser parser[V], onUpdate func(V)) *fetcher[V] {
var ticker *time.Ticker var ticker *time.Ticker
if interval != 0 { if interval != 0 {

View File

@ -321,12 +321,13 @@ func proxiesParseAndFilter(filter string, filterReg *regexp.Regexp, forceCertVer
proxies := []C.Proxy{} proxies := []C.Proxy{}
for idx, mapping := range schema.Proxies { for idx, mapping := range schema.Proxies {
if name, ok := mapping["name"]; ok && len(filter) > 0 && !filterReg.MatchString(name.(string)) { name, ok := mapping["name"].(string)
if ok && len(filter) > 0 && !filterReg.MatchString(name) {
continue continue
} }
if prefixName != "" { if prefixName != "" {
mapping["name"] = prefixName + mapping["name"].(string) mapping["name"] = prefixName + name
} }
proxy, err := adapter.ParseProxy(mapping, forceCertVerify) proxy, err := adapter.ParseProxy(mapping, forceCertVerify)

View File

@ -103,7 +103,7 @@ func (h *HTTPVehicle) Read() ([]byte, error) {
return nil, err return nil, err
} }
return buf, nil return removeComment(buf), nil
} }
func NewHTTPVehicle(url string, path string, header http.Header) *HTTPVehicle { func NewHTTPVehicle(url string, path string, header http.Header) *HTTPVehicle {

View File

@ -2,6 +2,7 @@ package cert
import ( import (
"crypto/tls" "crypto/tls"
"sync"
"github.com/Dreamacro/clash/component/trie" "github.com/Dreamacro/clash/component/trie"
) )
@ -9,10 +10,14 @@ import (
// DomainTrieCertsStorage cache wildcard certificates // DomainTrieCertsStorage cache wildcard certificates
type DomainTrieCertsStorage struct { type DomainTrieCertsStorage struct {
certsCache *trie.DomainTrie[*tls.Certificate] certsCache *trie.DomainTrie[*tls.Certificate]
lock sync.RWMutex
} }
// Get gets the certificate from the storage // Get gets the certificate from the storage
func (c *DomainTrieCertsStorage) Get(key string) (*tls.Certificate, bool) { func (c *DomainTrieCertsStorage) Get(key string) (*tls.Certificate, bool) {
c.lock.RLock()
defer c.lock.RUnlock()
ca := c.certsCache.Search(key) ca := c.certsCache.Search(key)
if ca == nil { if ca == nil {
return nil, false return nil, false
@ -22,7 +27,9 @@ func (c *DomainTrieCertsStorage) Get(key string) (*tls.Certificate, bool) {
// Set saves the certificate to the storage // Set saves the certificate to the storage
func (c *DomainTrieCertsStorage) Set(key string, cert *tls.Certificate) { func (c *DomainTrieCertsStorage) Set(key string, cert *tls.Certificate) {
c.lock.Lock()
_ = c.certsCache.Insert(key, cert) _ = c.certsCache.Insert(key, cert)
c.lock.Unlock()
} }
func NewDomainTrieCertsStorage() *DomainTrieCertsStorage { func NewDomainTrieCertsStorage() *DomainTrieCertsStorage {

View File

@ -29,13 +29,13 @@ func bindMarkToControl(mark int, chain controlFn) controlFn {
return return
} }
return c.Control(func(fd uintptr) { var innerErr error
switch network { err = c.Control(func(fd uintptr) {
case "tcp4", "udp4": innerErr = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
_ = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
case "tcp6", "udp6":
_ = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark)
}
}) })
if err == nil && innerErr != nil {
err = innerErr
}
return
} }
} }

View File

@ -2,11 +2,7 @@ package process
import ( import (
"errors" "errors"
"net"
"net/netip" "net/netip"
"github.com/Dreamacro/clash/common/nnip"
C "github.com/Dreamacro/clash/constant"
) )
var ( var (
@ -23,52 +19,3 @@ const (
func FindProcessName(network string, srcIP netip.Addr, srcPort int) (string, error) { func FindProcessName(network string, srcIP netip.Addr, srcPort int) (string, error) {
return findProcessName(network, srcIP, srcPort) return findProcessName(network, srcIP, srcPort)
} }
func ShouldFindProcess(metadata *C.Metadata) bool {
if metadata.Process != "" {
return false
}
if metadata.SrcIP.IsUnspecified() {
return true
}
for _, ip := range localIPs {
if ip == metadata.SrcIP {
return true
}
}
return false
}
func AppendLocalIPs(ip ...netip.Addr) {
localIPs = append(ip, localIPs...)
}
func getLocalIPs() []netip.Addr {
var ips []netip.Addr
netInterfaces, err := net.Interfaces()
if err != nil {
ips = append(ips, netip.AddrFrom4([4]byte{127, 0, 0, 1}), nnip.IpToAddr(net.IPv6loopback))
return ips
}
for i := 0; i < len(netInterfaces); i++ {
if (netInterfaces[i].Flags & net.FlagUp) != 0 {
adds, _ := netInterfaces[i].Addrs()
for _, address := range adds {
if ipNet, ok := address.(*net.IPNet); ok {
ips = append(ips, nnip.IpToAddr(ipNet.IP))
}
}
}
}
return ips
}
var localIPs []netip.Addr
func init() {
localIPs = getLocalIPs()
}

View File

@ -6,8 +6,6 @@ import (
"syscall" "syscall"
"unsafe" "unsafe"
"github.com/Dreamacro/clash/common/nnip"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -63,10 +61,10 @@ func findProcessName(network string, ip netip.Addr, port int) (string, error) {
switch { switch {
case flag&0x1 > 0 && isIPv4: case flag&0x1 > 0 && isIPv4:
// ipv4 // ipv4
srcIP = nnip.IpToAddr(buf[inp+76 : inp+80]) srcIP, _ = netip.AddrFromSlice(buf[inp+76 : inp+80])
case flag&0x2 > 0 && !isIPv4: case flag&0x2 > 0 && !isIPv4:
// ipv6 // ipv6
srcIP = nnip.IpToAddr(buf[inp+64 : inp+80]) srcIP, _ = netip.AddrFromSlice(buf[inp+64 : inp+80])
default: default:
continue continue
} }

View File

@ -10,7 +10,6 @@ import (
"syscall" "syscall"
"unsafe" "unsafe"
"github.com/Dreamacro/clash/common/nnip"
"github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/log"
) )
@ -135,10 +134,10 @@ func (s *searcher) Search(buf []byte, ip netip.Addr, port uint16, isTCP bool) (u
switch { switch {
case flag&0x1 > 0 && isIPv4: case flag&0x1 > 0 && isIPv4:
// ipv4 // ipv4
srcIP = nnip.IpToAddr(buf[inp+s.ip : inp+s.ip+4]) srcIP, _ = netip.AddrFromSlice(buf[inp+s.ip : inp+s.ip+4])
case flag&0x2 > 0 && !isIPv4: case flag&0x2 > 0 && !isIPv4:
// ipv6 // ipv6
srcIP = nnip.IpToAddr(buf[inp+s.ip-12 : inp+s.ip+4]) srcIP, _ = netip.AddrFromSlice(buf[inp+s.ip-12 : inp+s.ip+4])
default: default:
continue continue
} }

View File

@ -7,7 +7,6 @@ import (
"syscall" "syscall"
"unsafe" "unsafe"
"github.com/Dreamacro/clash/common/nnip"
"github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/log"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
@ -132,7 +131,7 @@ func (s *searcher) Search(b []byte, ip netip.Addr, port uint16) (uint32, error)
continue continue
} }
srcIP := nnip.IpToAddr(row[s.ip : s.ip+s.ipSize]) srcIP, _ := netip.AddrFromSlice(row[s.ip : s.ip+s.ipSize])
// windows binds an unbound udp socket to 0.0.0.0/[::] while first sendto // windows binds an unbound udp socket to 0.0.0.0/[::] while first sendto
if ip != srcIP && (!srcIP.IsUnspecified() || s.tcpState != -1) { if ip != srcIP && (!srcIP.IsUnspecified() || s.tcpState != -1) {
continue continue

View File

@ -99,12 +99,13 @@ type Profile struct {
// Tun config // Tun config
type Tun struct { type Tun struct {
Enable bool `yaml:"enable" json:"enable"` Enable bool `yaml:"enable" json:"enable"`
Device string `yaml:"device" json:"device"` Device string `yaml:"device" json:"device"`
Stack C.TUNStack `yaml:"stack" json:"stack"` Stack C.TUNStack `yaml:"stack" json:"stack"`
DNSHijack []C.DNSUrl `yaml:"dns-hijack" json:"dns-hijack"` DNSHijack []C.DNSUrl `yaml:"dns-hijack" json:"dns-hijack"`
AutoRoute bool `yaml:"auto-route" json:"auto-route"` AutoRoute bool `yaml:"auto-route" json:"auto-route"`
AutoDetectInterface bool `yaml:"auto-detect-interface" json:"auto-detect-interface"` AutoDetectInterface bool `yaml:"auto-detect-interface" json:"auto-detect-interface"`
TunAddressPrefix *netip.Prefix `yaml:"_" json:"_"`
} }
// IPTables config // IPTables config
@ -415,11 +416,11 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[
// keep the original order of ProxyGroups in config file // keep the original order of ProxyGroups in config file
for idx, mapping := range groupsConfig { for idx, mapping := range groupsConfig {
groupName, existName := mapping["name"] groupName, existName := mapping["name"].(string)
if !existName { if !existName {
return nil, nil, fmt.Errorf("proxy group %d: missing name", idx) return nil, nil, fmt.Errorf("proxy group %d: missing name", idx)
} }
proxyList = append(proxyList, groupName.(string)) proxyList = append(proxyList, groupName)
} }
// check if any loop exists and sort the ProxyGroups // check if any loop exists and sort the ProxyGroups

View File

@ -82,7 +82,7 @@ func ApplyConfig(cfg *config.Config, force bool) {
updateHosts(cfg.Hosts) updateHosts(cfg.Hosts)
updateMitm(cfg.Mitm) updateMitm(cfg.Mitm)
updateProfile(cfg) updateProfile(cfg)
updateDNS(cfg.DNS, cfg.General.Tun) updateDNS(cfg.DNS, &cfg.General.Tun)
updateGeneral(cfg.General, force) updateGeneral(cfg.General, force)
updateIPTables(cfg) updateIPTables(cfg)
updateExperimental(cfg) updateExperimental(cfg)
@ -121,7 +121,7 @@ func GetGeneral() *config.General {
func updateExperimental(_ *config.Config) {} func updateExperimental(_ *config.Config) {}
func updateDNS(c *config.DNS, t config.Tun) { func updateDNS(c *config.DNS, t *config.Tun) {
cfg := dns.Config{ cfg := dns.Config{
Main: c.NameServer, Main: c.NameServer,
Fallback: c.Fallback, Fallback: c.Fallback,
@ -179,7 +179,7 @@ func updateDNS(c *config.DNS, t config.Tun) {
} }
if cfg.Pool != nil { if cfg.Pool != nil {
P.SetTunAddressPrefix(cfg.Pool.IPNet()) t.TunAddressPrefix = cfg.Pool.IPNet()
} }
} }

View File

@ -31,11 +31,9 @@ import (
) )
var ( var (
allowLan = false allowLan = false
bindAddress = "*" bindAddress = "*"
lastTunConf *config.Tun lastTunConf *config.Tun
lastTunAddressPrefix *netip.Prefix
tunAddressPrefix *netip.Prefix
socksListener *socks.Listener socksListener *socks.Listener
socksUDPListener *socks.UDPListener socksUDPListener *socks.UDPListener
@ -109,10 +107,6 @@ func SetBindAddress(host string) {
bindAddress = host bindAddress = host
} }
func SetTunAddressPrefix(tunAddress *netip.Prefix) {
tunAddressPrefix = tunAddress
}
func ReCreateHTTP(port int, tcpIn chan<- C.ConnContext) { func ReCreateHTTP(port int, tcpIn chan<- C.ConnContext) {
httpMux.Lock() httpMux.Lock()
defer httpMux.Unlock() defer httpMux.Unlock()
@ -363,14 +357,10 @@ func ReCreateTun(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *
} }
}() }()
if tunAddressPrefix == nil {
tunAddressPrefix = lastTunAddressPrefix
}
tunConf.DNSHijack = C.RemoveDuplicateDNSUrl(tunConf.DNSHijack) tunConf.DNSHijack = C.RemoveDuplicateDNSUrl(tunConf.DNSHijack)
if tunStackListener != nil { if tunStackListener != nil {
if !hasTunConfigChange(tunConf, tunAddressPrefix) { if !hasTunConfigChange(tunConf) {
return return
} }
@ -379,7 +369,6 @@ func ReCreateTun(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *
} }
lastTunConf = tunConf lastTunConf = tunConf
lastTunAddressPrefix = tunAddressPrefix
if !tunConf.Enable { if !tunConf.Enable {
return return
@ -391,7 +380,7 @@ func ReCreateTun(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *
udpIn: udpIn, udpIn: udpIn,
} }
tunStackListener, err = tun.New(tunConf, tunAddressPrefix, tcpIn, udpIn, callback) tunStackListener, err = tun.New(tunConf, tcpIn, udpIn, callback)
if err != nil { if err != nil {
return return
} }
@ -535,7 +524,7 @@ func genAddr(host string, port int, allowLan bool) string {
return fmt.Sprintf("127.0.0.1:%d", port) return fmt.Sprintf("127.0.0.1:%d", port)
} }
func hasTunConfigChange(tunConf *config.Tun, tunAddressPrefix *netip.Prefix) bool { func hasTunConfigChange(tunConf *config.Tun) bool {
if lastTunConf == nil { if lastTunConf == nil {
return true return true
} }
@ -558,11 +547,11 @@ func hasTunConfigChange(tunConf *config.Tun, tunAddressPrefix *netip.Prefix) boo
return true return true
} }
if (tunAddressPrefix != nil && lastTunAddressPrefix == nil) || (tunAddressPrefix == nil && lastTunAddressPrefix != nil) { if (lastTunConf.TunAddressPrefix != nil && tunConf.TunAddressPrefix == nil) || (lastTunConf.TunAddressPrefix == nil && tunConf.TunAddressPrefix != nil) {
return true return true
} }
if tunAddressPrefix != nil && lastTunAddressPrefix != nil && *tunAddressPrefix != *lastTunAddressPrefix { if lastTunConf.TunAddressPrefix != nil && tunConf.TunAddressPrefix != nil && *lastTunConf.TunAddressPrefix != *tunConf.TunAddressPrefix {
return true return true
} }

View File

@ -72,6 +72,11 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error)
if err != nil { if err != nil {
continue continue
} }
if rAddr.Addr().Is4() {
// try to unmap 4in6 address
lAddr = netip.AddrPortFrom(lAddr.Addr().Unmap(), lAddr.Port())
}
handlePacketConn(in, buf[:n], lAddr, rAddr) handlePacketConn(in, buf[:n], lAddr, rAddr)
} }
}() }()

View File

@ -41,6 +41,10 @@ func (f *FD) Name() string {
return strconv.Itoa(f.fd) return strconv.Itoa(f.fd)
} }
func (f *FD) MTU() uint32 {
return f.mtu
}
func (f *FD) Close() error { func (f *FD) Close() error {
err := unix.Close(f.fd) err := unix.Close(f.fd)
if f.file != nil { if f.file != nil {

View File

@ -4,8 +4,48 @@ import (
"errors" "errors"
"github.com/Dreamacro/clash/listener/tun/device" "github.com/Dreamacro/clash/listener/tun/device"
"gvisor.dev/gvisor/pkg/tcpip/stack"
) )
func Open(name string, mtu uint32) (device.Device, error) { type FD struct {
stack.LinkEndpoint
}
func Open(_ string, _ uint32) (device.Device, error) {
return nil, errors.New("not supported") return nil, errors.New("not supported")
} }
func (f *FD) Name() string {
return ""
}
func (f *FD) Type() string {
return Driver
}
func (f *FD) Read(_ []byte) (int, error) {
return 0, nil
}
func (f *FD) Write(_ []byte) (int, error) {
return 0, nil
}
func (f *FD) Close() error {
return nil
}
func (f *FD) UseEndpoint() error {
return nil
}
func (f *FD) UseIOBased() error {
return nil
}
func (f *FD) MTU() uint32 {
return 0
}
var _ device.Device = (*FD)(nil)

View File

@ -59,10 +59,13 @@ func Open(name string, mtu uint32) (_ device.Device, err error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("get mtu: %w", err) return nil, fmt.Errorf("get mtu: %w", err)
} }
t.mtu = uint32(tunMTU)
if t.mtu == 0 {
t.mtu = uint32(tunMTU)
}
if t.offset > 0 { if t.offset > 0 {
t.cache = make([]byte, 65535) t.cache = make([]byte, int(t.mtu)+t.offset)
} }
return t, nil return t, nil
@ -108,6 +111,10 @@ func (t *TUN) Name() string {
return name return name
} }
func (t *TUN) MTU() uint32 {
return t.mtu
}
func (t *TUN) UseEndpoint() error { func (t *TUN) UseEndpoint() error {
ep, err := iobased.New(t, t.mtu, t.offset) ep, err := iobased.New(t, t.mtu, t.offset)
if err != nil { if err != nil {

View File

@ -5,8 +5,10 @@ import (
"net" "net"
"net/netip" "net/netip"
dev "github.com/Dreamacro/clash/listener/tun/device"
"github.com/Dreamacro/clash/listener/tun/device/fdbased"
"github.com/Dreamacro/clash/listener/tun/device/tun"
"github.com/Dreamacro/clash/listener/tun/ipstack/system/mars/tcpip" "github.com/Dreamacro/clash/listener/tun/ipstack/system/mars/tcpip"
"github.com/Dreamacro/clash/log"
) )
func Start(device io.ReadWriter, gateway, portal, broadcast netip.Addr) (*TCP, *UDP, error) { func Start(device io.ReadWriter, gateway, portal, broadcast netip.Addr) (*TCP, *UDP, error) {
@ -19,10 +21,27 @@ func Start(device io.ReadWriter, gateway, portal, broadcast netip.Addr) (*TCP, *
return nil, nil, err return nil, nil, err
} }
var (
t dev.Device
mtu uint32
ok bool
)
if t, ok = device.(*tun.TUN); ok {
mtu = t.MTU()
} else if t, ok = device.(*fdbased.FD); ok {
mtu = t.MTU()
}
bufferSize := int(mtu)
if bufferSize == 0 {
bufferSize = 64 * 1024
}
tab := newTable() tab := newTable()
udp := &UDP{ udp := &UDP{
device: device, device: device,
buf: [0xffff]byte{}, buf: make([]byte, bufferSize),
} }
tcp := &TCP{ tcp := &TCP{
listener: listener, listener: listener,
@ -38,7 +57,7 @@ func Start(device io.ReadWriter, gateway, portal, broadcast netip.Addr) (*TCP, *
_ = udp.Close() _ = udp.Close()
}() }()
buf := make([]byte, 0xffff) buf := make([]byte, bufferSize)
for { for {
n, err := device.Read(buf) n, err := device.Read(buf)
@ -133,11 +152,7 @@ func Start(device io.ReadWriter, gateway, portal, broadcast netip.Addr) (*TCP, *
continue continue
} }
port, err = tab.newConn(tup) port = tab.newConn(tup)
if err != nil {
log.Warnln("[STACK] drop tcp packet by system stack: %v", err)
continue
}
} }
ip.SetSourceIP(portal) ip.SetSourceIP(portal)
@ -156,7 +171,7 @@ func Start(device io.ReadWriter, gateway, portal, broadcast netip.Addr) (*TCP, *
continue continue
} }
go udp.handleUDPPacket(ip, u) udp.handleUDPPacket(ip, u)
case tcpip.ICMP: case tcpip.ICMP:
i := tcpip.ICMPPacket(ip.Payload()) i := tcpip.ICMPPacket(ip.Payload())

View File

@ -1,13 +1,9 @@
package nat package nat
import ( import (
"fmt"
"net/netip" "net/netip"
"sync"
"github.com/Dreamacro/clash/common/generics/list" "github.com/Dreamacro/clash/common/generics/list"
"golang.org/x/exp/maps"
) )
const ( const (
@ -31,8 +27,6 @@ type table struct {
tuples map[tuple]*list.Element[*binding] tuples map[tuple]*list.Element[*binding]
ports [portLength]*list.Element[*binding] ports [portLength]*list.Element[*binding]
available *list.List[*binding] available *list.List[*binding]
mux sync.Mutex
count uint16
} }
func (t *table) tupleOf(port uint16) tuple { func (t *table) tupleOf(port uint16) tuple {
@ -49,64 +43,27 @@ func (t *table) tupleOf(port uint16) tuple {
} }
func (t *table) portOf(tuple tuple) uint16 { func (t *table) portOf(tuple tuple) uint16 {
t.mux.Lock()
elm := t.tuples[tuple] elm := t.tuples[tuple]
if elm == nil { if elm == nil {
t.mux.Unlock()
return 0 return 0
} }
t.mux.Unlock()
t.available.MoveToFront(elm) t.available.MoveToFront(elm)
return portBegin + elm.Value.offset return portBegin + elm.Value.offset
} }
func (t *table) newConn(tuple tuple) (uint16, error) { func (t *table) newConn(tuple tuple) uint16 {
t.mux.Lock() elm := t.available.Back()
elm, err := t.availableConn() b := elm.Value
if err != nil {
t.mux.Unlock()
return 0, err
}
elm.Value.tuple = tuple delete(t.tuples, b.tuple)
t.tuples[tuple] = elm t.tuples[tuple] = elm
t.mux.Unlock() b.tuple = tuple
return portBegin + elm.Value.offset, nil t.available.MoveToFront(elm)
}
func (t *table) availableConn() (*list.Element[*binding], error) { return portBegin + b.offset
var elm *list.Element[*binding]
for i := 0; i < portLength; i++ {
elm = t.available.Back()
t.available.MoveToFront(elm)
offset := elm.Value.offset
tup := t.ports[offset].Value.tuple
if t.tuples[tup] != nil && tup.SourceAddr.IsValid() {
continue
}
if t.count == portLength { // resize
tuples := make(map[tuple]*list.Element[*binding], portLength)
maps.Copy(tuples, t.tuples)
t.tuples = tuples
t.count = 1
}
return elm, nil
}
return nil, fmt.Errorf("too many open files, limits [%d, %d]", portLength, len(t.tuples))
}
func (t *table) closeConn(tuple tuple) {
t.mux.Lock()
delete(t.tuples, tuple)
t.count++
t.mux.Unlock()
} }
func newTable() *table { func newTable() *table {
@ -114,7 +71,6 @@ func newTable() *table {
tuples: make(map[tuple]*list.Element[*binding], portLength), tuples: make(map[tuple]*list.Element[*binding], portLength),
ports: [portLength]*list.Element[*binding]{}, ports: [portLength]*list.Element[*binding]{},
available: list.New[*binding](), available: list.New[*binding](),
count: 1,
} }
for idx := range result.ports { for idx := range result.ports {

View File

@ -16,8 +16,6 @@ type conn struct {
net.Conn net.Conn
tuple tuple tuple tuple
close func()
} }
func (t *TCP) Accept() (net.Conn, error) { func (t *TCP) Accept() (net.Conn, error) {
@ -41,9 +39,6 @@ func (t *TCP) Accept() (net.Conn, error) {
return &conn{ return &conn{
Conn: c, Conn: c,
tuple: tup, tuple: tup,
close: func() {
t.table.closeConn(tup)
},
}, nil }, nil
} }
@ -60,7 +55,6 @@ func (t *TCP) SetDeadline(time time.Time) error {
} }
func (c *conn) Close() error { func (c *conn) Close() error {
c.close()
return c.Conn.Close() return c.Conn.Close()
} }

View File

@ -24,7 +24,7 @@ type UDP struct {
queueLock sync.Mutex queueLock sync.Mutex
queue []*call queue []*call
bufLock sync.Mutex bufLock sync.Mutex
buf [0xffff]byte buf []byte
} }
func (u *UDP) ReadFrom(buf []byte) (int, netip.AddrPort, netip.AddrPort, error) { func (u *UDP) ReadFrom(buf []byte) (int, netip.AddrPort, netip.AddrPort, error) {

View File

@ -9,7 +9,6 @@ import (
"github.com/Dreamacro/clash/adapter/inbound" "github.com/Dreamacro/clash/adapter/inbound"
"github.com/Dreamacro/clash/common/cmd" "github.com/Dreamacro/clash/common/cmd"
"github.com/Dreamacro/clash/component/process"
"github.com/Dreamacro/clash/config" "github.com/Dreamacro/clash/config"
C "github.com/Dreamacro/clash/constant" C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/listener/tun/device" "github.com/Dreamacro/clash/listener/tun/device"
@ -24,7 +23,7 @@ import (
) )
// New TunAdapter // New TunAdapter
func New(tunConf *config.Tun, tunAddressPrefix *netip.Prefix, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter, tunChangeCallback C.TUNChangeCallback) (ipstack.Stack, error) { func New(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter, tunChangeCallback C.TUNChangeCallback) (ipstack.Stack, error) {
var ( var (
tunAddress = netip.Prefix{} tunAddress = netip.Prefix{}
devName = tunConf.Device devName = tunConf.Device
@ -48,16 +47,14 @@ func New(tunConf *config.Tun, tunAddressPrefix *netip.Prefix, tcpIn chan<- C.Con
devName = generateDeviceName() devName = generateDeviceName()
} }
if tunAddressPrefix != nil { if tunConf.TunAddressPrefix != nil {
tunAddress = *tunAddressPrefix tunAddress = *tunConf.TunAddressPrefix
} }
if !tunAddress.IsValid() || !tunAddress.Addr().Is4() { if !tunAddress.IsValid() || !tunAddress.Addr().Is4() {
tunAddress = netip.MustParsePrefix("198.18.0.1/16") tunAddress = netip.MustParsePrefix("198.18.0.1/16")
} }
process.AppendLocalIPs(tunAddress.Masked().Addr().Next())
// open tun device // open tun device
tunDevice, err = parseDevice(devName, uint32(mtu)) tunDevice, err = parseDevice(devName, uint32(mtu))
if err != nil { if err != nil {

View File

@ -394,7 +394,7 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) {
resolved = true resolved = true
} }
if !processFound && rule.ShouldFindProcess() && P.ShouldFindProcess(metadata) { if !processFound && rule.ShouldFindProcess() {
processFound = true processFound = true
srcPort, err := strconv.ParseUint(metadata.SrcPort, 10, 16) srcPort, err := strconv.ParseUint(metadata.SrcPort, 10, 16)