github.com/EagleQL/Xray-core@v1.4.3/transport/internet/grpc/hub.go (about)

     1  package grpc
     2  
     3  import (
     4  	"context"
     5  
     6  	"google.golang.org/grpc"
     7  	"google.golang.org/grpc/credentials"
     8  
     9  	"github.com/xtls/xray-core/common"
    10  	"github.com/xtls/xray-core/common/net"
    11  	"github.com/xtls/xray-core/common/session"
    12  	"github.com/xtls/xray-core/transport/internet"
    13  	"github.com/xtls/xray-core/transport/internet/grpc/encoding"
    14  	"github.com/xtls/xray-core/transport/internet/tls"
    15  )
    16  
    17  type Listener struct {
    18  	encoding.UnimplementedGRPCServiceServer
    19  	ctx     context.Context
    20  	handler internet.ConnHandler
    21  	local   net.Addr
    22  	config  *Config
    23  	locker  *internet.FileLocker // for unix domain socket
    24  
    25  	s *grpc.Server
    26  }
    27  
    28  func (l Listener) Tun(server encoding.GRPCService_TunServer) error {
    29  	tunCtx, cancel := context.WithCancel(l.ctx)
    30  	l.handler(encoding.NewHunkConn(server, cancel))
    31  	<-tunCtx.Done()
    32  	return nil
    33  }
    34  
    35  func (l Listener) TunMulti(server encoding.GRPCService_TunMultiServer) error {
    36  	tunCtx, cancel := context.WithCancel(l.ctx)
    37  	l.handler(encoding.NewMultiHunkConn(server, cancel))
    38  	<-tunCtx.Done()
    39  	return nil
    40  }
    41  
    42  func (l Listener) Close() error {
    43  	l.s.Stop()
    44  	return nil
    45  }
    46  
    47  func (l Listener) Addr() net.Addr {
    48  	return l.local
    49  }
    50  
    51  func Listen(ctx context.Context, address net.Address, port net.Port, settings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) {
    52  	grpcSettings := settings.ProtocolSettings.(*Config)
    53  	var listener *Listener
    54  	if port == net.Port(0) { // unix
    55  		listener = &Listener{
    56  			handler: handler,
    57  			local: &net.UnixAddr{
    58  				Name: address.Domain(),
    59  				Net:  "unix",
    60  			},
    61  			config: grpcSettings,
    62  		}
    63  	} else { // tcp
    64  		listener = &Listener{
    65  			handler: handler,
    66  			local: &net.TCPAddr{
    67  				IP:   address.IP(),
    68  				Port: int(port),
    69  			},
    70  			config: grpcSettings,
    71  		}
    72  	}
    73  
    74  	listener.ctx = ctx
    75  
    76  	config := tls.ConfigFromStreamSettings(settings)
    77  
    78  	var s *grpc.Server
    79  	if config == nil {
    80  		s = grpc.NewServer()
    81  	} else {
    82  		s = grpc.NewServer(grpc.Creds(credentials.NewTLS(config.GetTLSConfig(tls.WithNextProto("h2")))))
    83  	}
    84  	listener.s = s
    85  
    86  	if settings.SocketSettings != nil && settings.SocketSettings.AcceptProxyProtocol {
    87  		newError("accepting PROXY protocol").AtWarning().WriteToLog(session.ExportIDToError(ctx))
    88  	}
    89  
    90  	go func() {
    91  		var streamListener net.Listener
    92  		var err error
    93  		if port == net.Port(0) { // unix
    94  			streamListener, err = internet.ListenSystem(ctx, &net.UnixAddr{
    95  				Name: address.Domain(),
    96  				Net:  "unix",
    97  			}, settings.SocketSettings)
    98  			if err != nil {
    99  				newError("failed to listen on ", address).Base(err).AtError().WriteToLog(session.ExportIDToError(ctx))
   100  				return
   101  			}
   102  			locker := ctx.Value(address.Domain())
   103  			if locker != nil {
   104  				listener.locker = locker.(*internet.FileLocker)
   105  			}
   106  		} else { // tcp
   107  			streamListener, err = internet.ListenSystem(ctx, &net.TCPAddr{
   108  				IP:   address.IP(),
   109  				Port: int(port),
   110  			}, settings.SocketSettings)
   111  			if err != nil {
   112  				newError("failed to listen on ", address, ":", port).Base(err).AtError().WriteToLog(session.ExportIDToError(ctx))
   113  				return
   114  			}
   115  		}
   116  
   117  		encoding.RegisterGRPCServiceServerX(s, listener, grpcSettings.ServiceName)
   118  
   119  		if err = s.Serve(streamListener); err != nil {
   120  			newError("Listener for gRPC ended").Base(err).WriteToLog()
   121  		}
   122  	}()
   123  
   124  	return listener, nil
   125  }
   126  
   127  func init() {
   128  	common.Must(internet.RegisterTransportListener(protocolName, Listen))
   129  }