github.com/yaling888/clash@v1.53.0/listener/redir/tcp.go (about)

     1  package redir
     2  
     3  import (
     4  	"net"
     5  
     6  	"github.com/phuslu/log"
     7  
     8  	"github.com/yaling888/clash/adapter/inbound"
     9  	C "github.com/yaling888/clash/constant"
    10  )
    11  
    12  type Listener struct {
    13  	listener net.Listener
    14  	addr     string
    15  	closed   bool
    16  }
    17  
    18  // RawAddress implements C.Listener
    19  func (l *Listener) RawAddress() string {
    20  	return l.addr
    21  }
    22  
    23  // Address implements C.Listener
    24  func (l *Listener) Address() string {
    25  	return l.listener.Addr().String()
    26  }
    27  
    28  // Close implements C.Listener
    29  func (l *Listener) Close() error {
    30  	l.closed = true
    31  	return l.listener.Close()
    32  }
    33  
    34  func New(addr string, in chan<- C.ConnContext) (C.Listener, error) {
    35  	l, err := net.Listen("tcp", addr)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	rl := &Listener{
    40  		listener: l,
    41  		addr:     addr,
    42  	}
    43  
    44  	go func() {
    45  		for {
    46  			c, err := l.Accept()
    47  			if err != nil {
    48  				if rl.closed {
    49  					break
    50  				}
    51  				continue
    52  			}
    53  			go handleRedir(c, in)
    54  		}
    55  	}()
    56  
    57  	return rl, nil
    58  }
    59  
    60  func handleRedir(conn net.Conn, in chan<- C.ConnContext) {
    61  	target, err := parserPacket(conn)
    62  	if err != nil {
    63  		_ = conn.Close()
    64  		log.Warn().Err(err).Msg("[Redir] handle redirect")
    65  		return
    66  	}
    67  	_ = conn.(*net.TCPConn).SetKeepAlive(true)
    68  	in <- inbound.NewSocket(target, conn, C.REDIR)
    69  }