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