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