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  }