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