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