github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/proxy/mixed/mixed.go (about)

     1  package mixed
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"net"
     7  
     8  	"github.com/Asutorufa/yuhaiin/pkg/log"
     9  	"github.com/Asutorufa/yuhaiin/pkg/net/netapi"
    10  	"github.com/Asutorufa/yuhaiin/pkg/net/proxy/http"
    11  	"github.com/Asutorufa/yuhaiin/pkg/net/proxy/socks4a"
    12  	"github.com/Asutorufa/yuhaiin/pkg/net/proxy/socks5"
    13  	"github.com/Asutorufa/yuhaiin/pkg/protos/config/listener"
    14  	"github.com/Asutorufa/yuhaiin/pkg/utils/pool"
    15  )
    16  
    17  type Mixed struct {
    18  	lis net.Listener
    19  
    20  	s5c *netapi.ChannelListener
    21  	s5  netapi.Accepter
    22  
    23  	s4c *netapi.ChannelListener
    24  	s4  netapi.Accepter
    25  
    26  	httpc *netapi.ChannelListener
    27  	http  netapi.Accepter
    28  
    29  	*netapi.ChannelServer
    30  }
    31  
    32  func init() {
    33  	listener.RegisterProtocol(NewServer)
    34  }
    35  
    36  func NewServer(o *listener.Inbound_Mix) func(lis netapi.Listener) (netapi.Accepter, error) {
    37  	return func(ii netapi.Listener) (netapi.Accepter, error) {
    38  		lis, err := ii.Stream(context.TODO())
    39  		if err != nil {
    40  			return nil, err
    41  		}
    42  
    43  		mix := &Mixed{
    44  			lis:           lis,
    45  			ChannelServer: netapi.NewChannelServer(),
    46  		}
    47  
    48  		mix.s5c = netapi.NewChannelListener(lis.Addr())
    49  		mix.s5, err = socks5.NewServer(&listener.Inbound_Socks5{
    50  			Socks5: &listener.Socks5{
    51  				Host:     o.Mix.Host,
    52  				Username: o.Mix.Username,
    53  				Password: o.Mix.Password,
    54  				Udp:      true,
    55  			},
    56  		})(netapi.PatchStream(mix.s5c, ii))
    57  		if err != nil {
    58  			mix.Close()
    59  			return nil, err
    60  		}
    61  		s5 := mix.s5.(*socks5.Server)
    62  		s5.ChannelServer.Close()
    63  		s5.ChannelServer = mix.ChannelServer
    64  
    65  		mix.s4c = netapi.NewChannelListener(lis.Addr())
    66  		mix.s4, err = socks4a.NewServer(&listener.Inbound_Socks4A{
    67  			Socks4A: &listener.Socks4A{
    68  				Host:     o.Mix.Host,
    69  				Username: o.Mix.Username,
    70  			},
    71  		})(netapi.PatchStream(mix.s4c, ii))
    72  		if err != nil {
    73  			mix.Close()
    74  			return nil, err
    75  		}
    76  		s4 := mix.s4.(*socks4a.Server)
    77  		s4.ChannelServer.Close()
    78  		s4.ChannelServer = mix.ChannelServer
    79  
    80  		mix.httpc = netapi.NewChannelListener(lis.Addr())
    81  		mix.http, err = http.NewServer(&listener.Inbound_Http{
    82  			Http: &listener.Http{
    83  				Host:     o.Mix.Host,
    84  				Username: o.Mix.Username,
    85  				Password: o.Mix.Password,
    86  			},
    87  		})(netapi.PatchStream(mix.httpc, ii))
    88  		if err != nil {
    89  			mix.Close()
    90  			return nil, err
    91  		}
    92  		http := mix.http.(*http.Server)
    93  		http.ChannelServer.Close()
    94  		http.ChannelServer = mix.ChannelServer
    95  
    96  		go func() {
    97  			defer mix.Close()
    98  			if err := mix.handle(); err != nil {
    99  				log.Debug("mixed handle failed", "err", err)
   100  			}
   101  		}()
   102  
   103  		return mix, nil
   104  	}
   105  }
   106  
   107  func (m *Mixed) Close() error {
   108  	m.ChannelServer.Close()
   109  	noneNilClose(m.s5c)
   110  	noneNilClose(m.s5)
   111  	noneNilClose(m.s4c)
   112  	noneNilClose(m.s4)
   113  	noneNilClose(m.httpc)
   114  	noneNilClose(m.http)
   115  	return m.lis.Close()
   116  }
   117  
   118  func noneNilClose(i io.Closer) {
   119  	if c, ok := i.(*netapi.ChannelListener); ok {
   120  		if c != nil {
   121  			_ = c.Close()
   122  		}
   123  
   124  		return
   125  	}
   126  
   127  	if i != nil {
   128  		_ = i.Close()
   129  	}
   130  }
   131  
   132  func (m *Mixed) handle() error {
   133  	for {
   134  		conn, err := m.lis.Accept()
   135  		if err != nil {
   136  			log.Error("mixed accept failed", "err", err)
   137  
   138  			if ne, ok := err.(net.Error); ok && ne.Temporary() {
   139  				continue
   140  			}
   141  			return err
   142  		}
   143  
   144  		go func() {
   145  			protocol := pool.GetBytesBuffer(pool.DefaultSize)
   146  
   147  			n, err := protocol.ReadFrom(conn)
   148  			if err != nil || n <= 0 {
   149  				conn.Close()
   150  				return
   151  			}
   152  
   153  			conn = netapi.NewPrefixBytesConn(conn, protocol)
   154  
   155  			switch protocol.Bytes()[0] {
   156  			case 0x05:
   157  				m.s5c.NewConn(conn)
   158  			case 0x04:
   159  				m.s4c.NewConn(conn)
   160  			default:
   161  				m.httpc.NewConn(conn)
   162  			}
   163  		}()
   164  	}
   165  }