space.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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 event.Event = iota
  36. )
  37. type spaceImpl struct {
  38. event.Listener
  39. cache map[reflect.Type]Application
  40. initialized bool
  41. }
  42. func NewSpace() Space {
  43. return &spaceImpl{
  44. cache: make(map[reflect.Type]Application),
  45. }
  46. }
  47. func (s *spaceImpl) On(e event.Event, h event.Handler) {
  48. if e == SpaceInitializing && s.initialized {
  49. _ = h(nil) // Ignore error
  50. return
  51. }
  52. s.Listener.On(e, h)
  53. }
  54. func (s *spaceImpl) Initialize() error {
  55. if s.initialized {
  56. return nil
  57. }
  58. s.initialized = true
  59. return s.Fire(SpaceInitializing, nil)
  60. }
  61. func (s *spaceImpl) GetApplication(appInterface interface{}) Application {
  62. if s == nil {
  63. return nil
  64. }
  65. appType := reflect.TypeOf(appInterface)
  66. return s.cache[appType]
  67. }
  68. func (s *spaceImpl) AddApplication(app Application) error {
  69. if s == nil {
  70. return newError("nil space").AtError()
  71. }
  72. appType := reflect.TypeOf(app.Interface())
  73. s.cache[appType] = app
  74. return nil
  75. }
  76. func (s *spaceImpl) Start() error {
  77. for _, app := range s.cache {
  78. if err := app.Start(); err != nil {
  79. return err
  80. }
  81. }
  82. return nil
  83. }
  84. func (s *spaceImpl) Close() {
  85. for _, app := range s.cache {
  86. app.Close()
  87. }
  88. }
  89. type contextKey int
  90. const (
  91. spaceKey = contextKey(0)
  92. )
  93. func AddApplicationToSpace(ctx context.Context, appConfig interface{}) error {
  94. space := SpaceFromContext(ctx)
  95. if space == nil {
  96. return newError("no space in context").AtError()
  97. }
  98. application, err := CreateAppFromConfig(ctx, appConfig)
  99. if err != nil {
  100. return err
  101. }
  102. return space.AddApplication(application)
  103. }
  104. func SpaceFromContext(ctx context.Context) Space {
  105. return ctx.Value(spaceKey).(Space)
  106. }
  107. func ContextWithSpace(ctx context.Context, space Space) context.Context {
  108. return context.WithValue(ctx, spaceKey, space)
  109. }