github.com/yaling888/clash@v1.53.0/listener/autoredir/tcp.go (about) 1 package autoredir 2 3 import ( 4 "net" 5 "net/netip" 6 7 "github.com/phuslu/log" 8 9 "github.com/yaling888/clash/adapter/inbound" 10 C "github.com/yaling888/clash/constant" 11 "github.com/yaling888/clash/transport/socks5" 12 ) 13 14 type Listener struct { 15 listener net.Listener 16 addr string 17 closed bool 18 lookupFunc func(netip.AddrPort) (socks5.Addr, error) 19 } 20 21 // RawAddress implements C.Listener 22 func (l *Listener) RawAddress() string { 23 return l.addr 24 } 25 26 // Address implements C.Listener 27 func (l *Listener) Address() string { 28 return l.listener.Addr().String() 29 } 30 31 // Close implements C.Listener 32 func (l *Listener) Close() error { 33 l.closed = true 34 return l.listener.Close() 35 } 36 37 func (l *Listener) TCPAddr() netip.AddrPort { 38 return l.listener.Addr().(*net.TCPAddr).AddrPort() 39 } 40 41 func (l *Listener) SetLookupFunc(lookupFunc func(netip.AddrPort) (socks5.Addr, error)) { 42 l.lookupFunc = lookupFunc 43 } 44 45 func (l *Listener) handleRedir(conn net.Conn, in chan<- C.ConnContext) { 46 if l.lookupFunc == nil { 47 log.Error().Msg("[Auto Redirect] lookup function is nil") 48 return 49 } 50 51 target, err := l.lookupFunc(conn.RemoteAddr().(*net.TCPAddr).AddrPort()) 52 if err != nil { 53 log.Warn().Err(err).Msg("[Auto Redirect]") 54 _ = conn.Close() 55 return 56 } 57 58 _ = conn.(*net.TCPConn).SetKeepAlive(true) 59 60 in <- inbound.NewSocket(target, conn, C.REDIR) 61 } 62 63 func New(addr string, in chan<- C.ConnContext) (*Listener, error) { 64 l, err := net.Listen("tcp", addr) 65 if err != nil { 66 return nil, err 67 } 68 al := &Listener{ 69 listener: l, 70 addr: addr, 71 } 72 73 go func() { 74 for { 75 c, err := l.Accept() 76 if err != nil { 77 if al.closed { 78 break 79 } 80 continue 81 } 82 go al.handleRedir(c, in) 83 } 84 }() 85 86 return al, nil 87 }