github.com/igoogolx/clash@v1.19.8/listener/mixed/mixed.go (about)

     1  package mixed
     2  
     3  import (
     4  	"net"
     5  
     6  	"github.com/igoogolx/clash/common/cache"
     7  	N "github.com/igoogolx/clash/common/net"
     8  	C "github.com/igoogolx/clash/constant"
     9  	"github.com/igoogolx/clash/listener/http"
    10  	"github.com/igoogolx/clash/listener/socks"
    11  	"github.com/igoogolx/clash/transport/socks4"
    12  	"github.com/igoogolx/clash/transport/socks5"
    13  )
    14  
    15  type Listener struct {
    16  	listener net.Listener
    17  	addr     string
    18  	cache    *cache.LruCache
    19  	closed   bool
    20  }
    21  
    22  // RawAddress implements C.Listener
    23  func (l *Listener) RawAddress() string {
    24  	return l.addr
    25  }
    26  
    27  // Address implements C.Listener
    28  func (l *Listener) Address() string {
    29  	return l.listener.Addr().String()
    30  }
    31  
    32  // Close implements C.Listener
    33  func (l *Listener) Close() error {
    34  	l.closed = true
    35  	return l.listener.Close()
    36  }
    37  
    38  func New(addr string, in chan<- C.ConnContext) (C.Listener, error) {
    39  	l, err := net.Listen("tcp", addr)
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  
    44  	ml := &Listener{
    45  		listener: l,
    46  		addr:     addr,
    47  		cache:    cache.New(cache.WithAge(30)),
    48  	}
    49  	go func() {
    50  		for {
    51  			c, err := ml.listener.Accept()
    52  			if err != nil {
    53  				if ml.closed {
    54  					break
    55  				}
    56  				continue
    57  			}
    58  			go handleConn(c, in, ml.cache)
    59  		}
    60  	}()
    61  
    62  	return ml, nil
    63  }
    64  
    65  func handleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.LruCache) {
    66  	conn.(*net.TCPConn).SetKeepAlive(true)
    67  
    68  	bufConn := N.NewBufferedConn(conn)
    69  	head, err := bufConn.Peek(1)
    70  	if err != nil {
    71  		return
    72  	}
    73  
    74  	switch head[0] {
    75  	case socks4.Version:
    76  		socks.HandleSocks4(bufConn, in)
    77  	case socks5.Version:
    78  		socks.HandleSocks5(bufConn, in)
    79  	default:
    80  		http.HandleConn(bufConn, in, cache)
    81  	}
    82  }