github.com/metacubex/mihomo@v1.18.5/listener/tunnel/tcp.go (about) 1 package tunnel 2 3 import ( 4 "fmt" 5 "net" 6 7 "github.com/metacubex/mihomo/adapter/inbound" 8 N "github.com/metacubex/mihomo/common/net" 9 C "github.com/metacubex/mihomo/constant" 10 "github.com/metacubex/mihomo/transport/socks5" 11 ) 12 13 type Listener struct { 14 listener net.Listener 15 addr string 16 target socks5.Addr 17 proxy string 18 closed bool 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) handleTCP(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) { 38 N.TCPKeepAlive(conn) 39 tunnel.HandleTCPConn(inbound.NewSocket(l.target, conn, C.TUNNEL, additions...)) 40 } 41 42 func New(addr, target, proxy string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener, error) { 43 l, err := inbound.Listen("tcp", addr) 44 if err != nil { 45 return nil, err 46 } 47 48 targetAddr := socks5.ParseAddr(target) 49 if targetAddr == nil { 50 return nil, fmt.Errorf("invalid target address %s", target) 51 } 52 53 rl := &Listener{ 54 listener: l, 55 target: targetAddr, 56 proxy: proxy, 57 addr: addr, 58 } 59 60 if proxy != "" { 61 additions = append([]inbound.Addition{inbound.WithSpecialProxy(proxy)}, additions...) 62 } 63 64 go func() { 65 for { 66 c, err := l.Accept() 67 if err != nil { 68 if rl.closed { 69 break 70 } 71 continue 72 } 73 go rl.handleTCP(c, tunnel, additions...) 74 } 75 }() 76 77 return rl, nil 78 }