github.com/igoogolx/clash@v1.19.8/listener/tunnel/tcp.go (about) 1 package tunnel 2 3 import ( 4 "fmt" 5 "net" 6 7 "github.com/igoogolx/clash/adapter/inbound" 8 C "github.com/igoogolx/clash/constant" 9 "github.com/igoogolx/clash/transport/socks5" 10 ) 11 12 type Listener struct { 13 listener net.Listener 14 addr string 15 target socks5.Addr 16 proxy string 17 closed bool 18 } 19 20 // RawAddress implements C.Listener 21 func (l *Listener) RawAddress() string { 22 return l.addr 23 } 24 25 // Address implements C.Listener 26 func (l *Listener) Address() string { 27 return l.listener.Addr().String() 28 } 29 30 // Close implements C.Listener 31 func (l *Listener) Close() error { 32 l.closed = true 33 return l.listener.Close() 34 } 35 36 func (l *Listener) handleTCP(conn net.Conn, in chan<- C.ConnContext) { 37 conn.(*net.TCPConn).SetKeepAlive(true) 38 ctx := inbound.NewSocket(l.target, conn, C.TUNNEL) 39 ctx.Metadata().SpecialProxy = l.proxy 40 in <- ctx 41 } 42 43 func New(addr, target, proxy string, in chan<- C.ConnContext) (*Listener, error) { 44 l, err := net.Listen("tcp", addr) 45 if err != nil { 46 return nil, err 47 } 48 49 targetAddr := socks5.ParseAddr(target) 50 if targetAddr == nil { 51 return nil, fmt.Errorf("invalid target address %s", target) 52 } 53 54 rl := &Listener{ 55 listener: l, 56 target: targetAddr, 57 proxy: proxy, 58 addr: addr, 59 } 60 61 go func() { 62 for { 63 c, err := l.Accept() 64 if err != nil { 65 if rl.closed { 66 break 67 } 68 continue 69 } 70 go rl.handleTCP(c, in) 71 } 72 }() 73 74 return rl, nil 75 }