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  }