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 }