github.com/v2fly/v2ray-core/v5@v5.16.2-0.20240507031116-8191faa6e095/transport/internet/grpc/hub.go (about) 1 //go:build !confonly 2 // +build !confonly 3 4 package grpc 5 6 import ( 7 "context" 8 9 "google.golang.org/grpc" 10 "google.golang.org/grpc/credentials" 11 12 "github.com/v2fly/v2ray-core/v5/common" 13 "github.com/v2fly/v2ray-core/v5/common/net" 14 "github.com/v2fly/v2ray-core/v5/common/session" 15 "github.com/v2fly/v2ray-core/v5/transport/internet" 16 "github.com/v2fly/v2ray-core/v5/transport/internet/grpc/encoding" 17 "github.com/v2fly/v2ray-core/v5/transport/internet/tls" 18 ) 19 20 type Listener struct { 21 encoding.UnimplementedGunServiceServer 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.GunService_TunServer) error { 31 tunCtx, cancel := context.WithCancel(l.ctx) 32 l.handler(encoding.NewGunConn(server, cancel)) 33 <-tunCtx.Done() 34 return nil 35 } 36 37 func (l Listener) Close() error { 38 l.s.Stop() 39 return nil 40 } 41 42 func (l Listener) Addr() net.Addr { 43 return l.local 44 } 45 46 func Listen(ctx context.Context, address net.Address, port net.Port, settings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) { 47 grpcSettings := settings.ProtocolSettings.(*Config) 48 var listener *Listener 49 if port == net.Port(0) { // unix 50 listener = &Listener{ 51 handler: handler, 52 local: &net.UnixAddr{ 53 Name: address.Domain(), 54 Net: "unix", 55 }, 56 config: grpcSettings, 57 } 58 } else { // tcp 59 listener = &Listener{ 60 handler: handler, 61 local: &net.TCPAddr{ 62 IP: address.IP(), 63 Port: int(port), 64 }, 65 config: grpcSettings, 66 } 67 } 68 69 listener.ctx = ctx 70 71 config := tls.ConfigFromStreamSettings(settings) 72 73 var s *grpc.Server 74 if config == nil { 75 s = grpc.NewServer() 76 } else { 77 // gRPC server may silently ignore TLS errors 78 s = grpc.NewServer(grpc.Creds(credentials.NewTLS(config.GetTLSConfig(tls.WithNextProto("h2"))))) 79 } 80 listener.s = s 81 82 if settings.SocketSettings != nil && settings.SocketSettings.AcceptProxyProtocol { 83 newError("accepting PROXY protocol").AtWarning().WriteToLog(session.ExportIDToError(ctx)) 84 } 85 86 go func() { 87 var streamListener net.Listener 88 var err error 89 if port == net.Port(0) { // unix 90 streamListener, err = internet.ListenSystem(ctx, &net.UnixAddr{ 91 Name: address.Domain(), 92 Net: "unix", 93 }, settings.SocketSettings) 94 if err != nil { 95 newError("failed to listen on ", address).Base(err).AtError().WriteToLog(session.ExportIDToError(ctx)) 96 return 97 } 98 } else { // tcp 99 streamListener, err = internet.ListenSystem(ctx, &net.TCPAddr{ 100 IP: address.IP(), 101 Port: int(port), 102 }, settings.SocketSettings) 103 if err != nil { 104 newError("failed to listen on ", address, ":", port).Base(err).AtError().WriteToLog(session.ExportIDToError(ctx)) 105 return 106 } 107 } 108 109 encoding.RegisterGunServiceServerX(s, listener, grpcSettings.ServiceName) 110 111 if err = s.Serve(streamListener); err != nil { 112 newError("Listener for grpc ended").Base(err).WriteToLog() 113 } 114 }() 115 116 return listener, nil 117 } 118 119 func init() { 120 common.Must(internet.RegisterTransportListener(protocolName, Listen)) 121 }