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