space.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package app
  2. import (
  3. "context"
  4. "reflect"
  5. "v2ray.com/core/common"
  6. "v2ray.com/core/common/event"
  7. )
  8. type Application interface {
  9. Interface() interface{}
  10. Start() error
  11. Close()
  12. }
  13. func CreateAppFromConfig(ctx context.Context, config interface{}) (Application, error) {
  14. application, err := common.CreateObject(ctx, config)
  15. if err != nil {
  16. return nil, err
  17. }
  18. switch a := application.(type) {
  19. case Application:
  20. return a, nil
  21. default:
  22. return nil, newError("not an application")
  23. }
  24. }
  25. // A Space contains all apps that may be available in a V2Ray runtime.
  26. type Space interface {
  27. event.Registry
  28. GetApplication(appInterface interface{}) Application
  29. AddApplication(application Application) error
  30. Initialize() error
  31. Start() error
  32. Close()
  33. }
  34. const (
  35. // SpaceInitializing is an event to be fired when Space is being initialized.
  36. SpaceInitializing event.Event = iota
  37. )
  38. type spaceImpl struct {
  39. event.Listener
  40. cache map[reflect.Type]Application
  41. initialized bool
  42. }
  43. // NewSpace creates a new Space.
  44. func NewSpace() Space {
  45. return &spaceImpl{
  46. cache: make(map[reflect.Type]Application),
  47. }
  48. }
  49. func (s *spaceImpl) On(e event.Event, h event.Handler) {
  50. if e == SpaceInitializing && s.initialized {
  51. _ = h(nil) // Ignore error
  52. return
  53. }
  54. s.Listener.On(e, h)
  55. }
  56. func (s *spaceImpl) Initialize() error {
  57. if s.initialized {
  58. return nil
  59. }
  60. s.initialized = true
  61. return s.Fire(SpaceInitializing, nil)
  62. }
  63. func (s *spaceImpl) GetApplication(appInterface interface{}) Application {
  64. if s == nil {
  65. return nil
  66. }
  67. appType := reflect.TypeOf(appInterface)
  68. return s.cache[appType]
  69. }
  70. func (s *spaceImpl) AddApplication(app Application) error {
  71. if s == nil {
  72. return newError("nil space").AtError()
  73. }
  74. appType := reflect.TypeOf(app.Interface())
  75. s.cache[appType] = app
  76. return nil
  77. }
  78. func (s *spaceImpl) Start() error {
  79. for _, app := range s.cache {
  80. if err := app.Start(); err != nil {
  81. return err
  82. }
  83. }
  84. return nil
  85. }
  86. func (s *spaceImpl) Close() {
  87. for _, app := range s.cache {
  88. app.Close()
  89. }
  90. }
  91. type contextKey int
  92. const (
  93. spaceKey = contextKey(0)
  94. )
  95. func AddApplicationToSpace(ctx context.Context, appConfig interface{}) error {
  96. space := SpaceFromContext(ctx)
  97. if space == nil {
  98. return newError("no space in context").AtError()
  99. }
  100. application, err := CreateAppFromConfig(ctx, appConfig)
  101. if err != nil {
  102. return err
  103. }
  104. return space.AddApplication(application)
  105. }
  106. func SpaceFromContext(ctx context.Context) Space {
  107. return ctx.Value(spaceKey).(Space)
  108. }
  109. func ContextWithSpace(ctx context.Context, space Space) context.Context {
  110. return context.WithValue(ctx, spaceKey, space)
  111. }