space.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package app
  2. import (
  3. "github.com/golang/protobuf/proto"
  4. "v2ray.com/core/common/errors"
  5. "v2ray.com/core/common/log"
  6. "v2ray.com/core/common/serial"
  7. )
  8. type Application interface {
  9. }
  10. type InitializationCallback func() error
  11. type ApplicationFactory interface {
  12. Create(space Space, config interface{}) (Application, error)
  13. }
  14. type AppGetter interface {
  15. GetApp(name string) Application
  16. }
  17. var (
  18. applicationFactoryCache = make(map[string]ApplicationFactory)
  19. )
  20. func RegisterApplicationFactory(defaultConfig proto.Message, factory ApplicationFactory) error {
  21. if defaultConfig == nil {
  22. return errors.New("Space: config is nil.")
  23. }
  24. name := serial.GetMessageType(defaultConfig)
  25. if len(name) == 0 {
  26. return errors.New("Space: cannot get config type.")
  27. }
  28. applicationFactoryCache[name] = factory
  29. return nil
  30. }
  31. // A Space contains all apps that may be available in a V2Ray runtime.
  32. // Caller must check the availability of an app by calling HasXXX before getting its instance.
  33. type Space interface {
  34. AddApp(config proto.Message) error
  35. AddAppLegacy(name string, app Application)
  36. Initialize() error
  37. OnInitialize(InitializationCallback)
  38. }
  39. type spaceImpl struct {
  40. initialized bool
  41. cache map[string]Application
  42. appInit []InitializationCallback
  43. }
  44. func NewSpace() Space {
  45. return &spaceImpl{
  46. cache: make(map[string]Application),
  47. appInit: make([]InitializationCallback, 0, 32),
  48. }
  49. }
  50. func (v *spaceImpl) OnInitialize(f InitializationCallback) {
  51. if v.initialized {
  52. if err := f(); err != nil {
  53. log.Error("Space: error after space initialization: ", err)
  54. }
  55. } else {
  56. v.appInit = append(v.appInit, f)
  57. }
  58. }
  59. func (v *spaceImpl) Initialize() error {
  60. for _, f := range v.appInit {
  61. if err := f(); err != nil {
  62. return err
  63. }
  64. }
  65. v.initialized = true
  66. return nil
  67. }
  68. func (v *spaceImpl) GetApp(configType string) Application {
  69. obj, found := v.cache[configType]
  70. if !found {
  71. return nil
  72. }
  73. return obj
  74. }
  75. func (v *spaceImpl) AddApp(config proto.Message) error {
  76. configName := serial.GetMessageType(config)
  77. factory, found := applicationFactoryCache[configName]
  78. if !found {
  79. return errors.New("Space: app not registered: ", configName)
  80. }
  81. app, err := factory.Create(v, config)
  82. if err != nil {
  83. return err
  84. }
  85. v.cache[configName] = app
  86. return nil
  87. }
  88. func (v *spaceImpl) AddAppLegacy(name string, application Application) {
  89. v.cache[name] = application
  90. }