github.com/metacubex/mihomo@v1.18.5/listener/mixed/mixed.go (about) 1 package mixed 2 3 import ( 4 "net" 5 6 "github.com/metacubex/mihomo/adapter/inbound" 7 "github.com/metacubex/mihomo/common/lru" 8 N "github.com/metacubex/mihomo/common/net" 9 C "github.com/metacubex/mihomo/constant" 10 "github.com/metacubex/mihomo/listener/http" 11 "github.com/metacubex/mihomo/listener/socks" 12 "github.com/metacubex/mihomo/transport/socks4" 13 "github.com/metacubex/mihomo/transport/socks5" 14 ) 15 16 type Listener struct { 17 listener net.Listener 18 addr string 19 cache *lru.LruCache[string, bool] 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, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener, error) { 40 isDefault := false 41 if len(additions) == 0 { 42 isDefault = true 43 additions = []inbound.Addition{ 44 inbound.WithInName("DEFAULT-MIXED"), 45 inbound.WithSpecialRules(""), 46 } 47 } 48 l, err := inbound.Listen("tcp", addr) 49 if err != nil { 50 return nil, err 51 } 52 53 ml := &Listener{ 54 listener: l, 55 addr: addr, 56 cache: lru.New[string, bool](lru.WithAge[string, bool](30)), 57 } 58 go func() { 59 for { 60 c, err := ml.listener.Accept() 61 if err != nil { 62 if ml.closed { 63 break 64 } 65 continue 66 } 67 if isDefault { // only apply on default listener 68 if !inbound.IsRemoteAddrDisAllowed(c.RemoteAddr()) { 69 _ = c.Close() 70 continue 71 } 72 } 73 go handleConn(c, tunnel, ml.cache, additions...) 74 } 75 }() 76 77 return ml, nil 78 } 79 80 func handleConn(conn net.Conn, tunnel C.Tunnel, cache *lru.LruCache[string, bool], additions ...inbound.Addition) { 81 N.TCPKeepAlive(conn) 82 83 bufConn := N.NewBufferedConn(conn) 84 head, err := bufConn.Peek(1) 85 if err != nil { 86 return 87 } 88 89 switch head[0] { 90 case socks4.Version: 91 socks.HandleSocks4(bufConn, tunnel, additions...) 92 case socks5.Version: 93 socks.HandleSocks5(bufConn, tunnel, additions...) 94 default: 95 http.HandleConn(bufConn, tunnel, cache, additions...) 96 } 97 }