github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/app/commander/commander.go (about) 1 // +build !confonly 2 3 package commander 4 5 //go:generate go run v2ray.com/core/common/errors/errorgen 6 7 import ( 8 "context" 9 "net" 10 "sync" 11 12 "google.golang.org/grpc" 13 14 "v2ray.com/core" 15 "v2ray.com/core/common" 16 "v2ray.com/core/common/signal/done" 17 "v2ray.com/core/features/outbound" 18 ) 19 20 // Commander is a V2Ray feature that provides gRPC methods to external clients. 21 type Commander struct { 22 sync.Mutex 23 server *grpc.Server 24 services []Service 25 ohm outbound.Manager 26 tag string 27 } 28 29 // NewCommander creates a new Commander based on the given config. 30 func NewCommander(ctx context.Context, config *Config) (*Commander, error) { 31 c := &Commander{ 32 tag: config.Tag, 33 } 34 35 common.Must(core.RequireFeatures(ctx, func(om outbound.Manager) { 36 c.ohm = om 37 })) 38 39 for _, rawConfig := range config.Service { 40 config, err := rawConfig.GetInstance() 41 if err != nil { 42 return nil, err 43 } 44 rawService, err := common.CreateObject(ctx, config) 45 if err != nil { 46 return nil, err 47 } 48 service, ok := rawService.(Service) 49 if !ok { 50 return nil, newError("not a Service.") 51 } 52 c.services = append(c.services, service) 53 } 54 55 return c, nil 56 } 57 58 // Type implements common.HasType. 59 func (c *Commander) Type() interface{} { 60 return (*Commander)(nil) 61 } 62 63 // Start implements common.Runnable. 64 func (c *Commander) Start() error { 65 c.Lock() 66 c.server = grpc.NewServer() 67 for _, service := range c.services { 68 service.Register(c.server) 69 } 70 c.Unlock() 71 72 listener := &OutboundListener{ 73 buffer: make(chan net.Conn, 4), 74 done: done.New(), 75 } 76 77 go func() { 78 if err := c.server.Serve(listener); err != nil { 79 newError("failed to start grpc server").Base(err).AtError().WriteToLog() 80 } 81 }() 82 83 if err := c.ohm.RemoveHandler(context.Background(), c.tag); err != nil { 84 newError("failed to remove existing handler").WriteToLog() 85 } 86 87 return c.ohm.AddHandler(context.Background(), &Outbound{ 88 tag: c.tag, 89 listener: listener, 90 }) 91 } 92 93 // Close implements common.Closable. 94 func (c *Commander) Close() error { 95 c.Lock() 96 defer c.Unlock() 97 98 if c.server != nil { 99 c.server.Stop() 100 c.server = nil 101 } 102 103 return nil 104 } 105 106 func init() { 107 common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) { 108 return NewCommander(ctx, cfg.(*Config)) 109 })) 110 }