diff --git a/commander.go b/commander.go new file mode 100644 index 000000000..f65f0072f --- /dev/null +++ b/commander.go @@ -0,0 +1,63 @@ +package core + +import ( + "sync" + + "google.golang.org/grpc" +) + +// ServiceRegistryCallback is a callback function for registering services. +type ServiceRegistryCallback func(s *grpc.Server) + +// Commander is a feature that accepts commands from external source. +type Commander interface { + Feature + + // RegisterService registers a service into this Commander. + RegisterService(ServiceRegistryCallback) +} + +type syncCommander struct { + sync.RWMutex + Commander +} + +func (c *syncCommander) RegisterService(callback ServiceRegistryCallback) { + c.RLock() + defer c.RUnlock() + + if c.Commander == nil { + return + } + + c.Commander.RegisterService(callback) +} + +func (c *syncCommander) Start() error { + c.RLock() + defer c.RUnlock() + + if c.Commander == nil { + return nil + } + + return c.Commander.Start() +} + +func (c *syncCommander) Close() { + c.RLock() + defer c.RUnlock() + + if c.Commander == nil { + return + } + + c.Commander.Close() +} + +func (c *syncCommander) Set(commander Commander) { + c.Lock() + defer c.Unlock() + + c.Commander = commander +} diff --git a/v2ray.go b/v2ray.go index b6a0de9d4..542deef8a 100644 --- a/v2ray.go +++ b/v2ray.go @@ -28,6 +28,7 @@ type Instance struct { ihm syncInboundHandlerManager ohm syncOutboundHandlerManager clock syncClock + cmd syncCommander features []Feature id uuid.UUID @@ -130,6 +131,10 @@ func (s *Instance) RegisterFeature(feature interface{}, instance Feature) error s.ihm.Set(instance.(InboundHandlerManager)) case OutboundHandlerManager, *OutboundHandlerManager: s.ohm.Set(instance.(OutboundHandlerManager)) + case Clock, *Clock: + s.clock.Set(instance.(Clock)) + case Commander, *Commander: + s.cmd.Set(instance.(Commander)) } s.features = append(s.features, instance) return nil @@ -169,3 +174,8 @@ func (s *Instance) OutboundHandlerManager() OutboundHandlerManager { func (s *Instance) Clock() Clock { return &(s.clock) } + +// Commander returns the Commander used by this Instance. The returned Commander is always functional. +func (s *Instance) Commander() Commander { + return &(s.cmd) +}