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  }