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