github.com/metacubex/mihomo@v1.18.5/listener/shadowsocks/tcp.go (about)

     1  package shadowsocks
     2  
     3  import (
     4  	"net"
     5  	"strings"
     6  
     7  	"github.com/metacubex/mihomo/adapter/inbound"
     8  	N "github.com/metacubex/mihomo/common/net"
     9  	C "github.com/metacubex/mihomo/constant"
    10  	LC "github.com/metacubex/mihomo/listener/config"
    11  	"github.com/metacubex/mihomo/transport/shadowsocks/core"
    12  	"github.com/metacubex/mihomo/transport/socks5"
    13  )
    14  
    15  type Listener struct {
    16  	closed       bool
    17  	config       LC.ShadowsocksServer
    18  	listeners    []net.Listener
    19  	udpListeners []*UDPListener
    20  	pickCipher   core.Cipher
    21  }
    22  
    23  var _listener *Listener
    24  
    25  func New(config LC.ShadowsocksServer, tunnel C.Tunnel) (*Listener, error) {
    26  	pickCipher, err := core.PickCipher(config.Cipher, nil, config.Password)
    27  	if err != nil {
    28  		return nil, err
    29  	}
    30  
    31  	sl := &Listener{false, config, nil, nil, pickCipher}
    32  	_listener = sl
    33  
    34  	for _, addr := range strings.Split(config.Listen, ",") {
    35  		addr := addr
    36  
    37  		if config.Udp {
    38  			//UDP
    39  			ul, err := NewUDP(addr, pickCipher, tunnel)
    40  			if err != nil {
    41  				return nil, err
    42  			}
    43  			sl.udpListeners = append(sl.udpListeners, ul)
    44  		}
    45  
    46  		//TCP
    47  		l, err := inbound.Listen("tcp", addr)
    48  		if err != nil {
    49  			return nil, err
    50  		}
    51  		sl.listeners = append(sl.listeners, l)
    52  
    53  		go func() {
    54  			for {
    55  				c, err := l.Accept()
    56  				if err != nil {
    57  					if sl.closed {
    58  						break
    59  					}
    60  					continue
    61  				}
    62  				N.TCPKeepAlive(c)
    63  				go sl.HandleConn(c, tunnel)
    64  			}
    65  		}()
    66  	}
    67  
    68  	return sl, nil
    69  }
    70  
    71  func (l *Listener) Close() error {
    72  	var retErr error
    73  	for _, lis := range l.listeners {
    74  		err := lis.Close()
    75  		if err != nil {
    76  			retErr = err
    77  		}
    78  	}
    79  	for _, lis := range l.udpListeners {
    80  		err := lis.Close()
    81  		if err != nil {
    82  			retErr = err
    83  		}
    84  	}
    85  	return retErr
    86  }
    87  
    88  func (l *Listener) Config() string {
    89  	return l.config.String()
    90  }
    91  
    92  func (l *Listener) AddrList() (addrList []net.Addr) {
    93  	for _, lis := range l.listeners {
    94  		addrList = append(addrList, lis.Addr())
    95  	}
    96  	for _, lis := range l.udpListeners {
    97  		addrList = append(addrList, lis.LocalAddr())
    98  	}
    99  	return
   100  }
   101  
   102  func (l *Listener) HandleConn(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) {
   103  	conn = l.pickCipher.StreamConn(conn)
   104  	conn = N.NewDeadlineConn(conn) // embed ss can't handle readDeadline correctly
   105  
   106  	target, err := socks5.ReadAddr0(conn)
   107  	if err != nil {
   108  		_ = conn.Close()
   109  		return
   110  	}
   111  	tunnel.HandleTCPConn(inbound.NewSocket(target, conn, C.SHADOWSOCKS, additions...))
   112  }
   113  
   114  func HandleShadowSocks(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) bool {
   115  	if _listener != nil && _listener.pickCipher != nil {
   116  		go _listener.HandleConn(conn, tunnel, additions...)
   117  		return true
   118  	}
   119  	return false
   120  }