space.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. package app
  2. type ID int
  3. // Context of a function call from proxy to app.
  4. type Context interface {
  5. CallerTag() string
  6. }
  7. // A Space contains all apps that may be available in a V2Ray runtime.
  8. // Caller must check the availability of an app by calling HasXXX before getting its instance.
  9. type Space interface {
  10. HasApp(ID) bool
  11. GetApp(ID) interface{}
  12. }
  13. type ForContextCreator func(Context, interface{}) interface{}
  14. var (
  15. metadataCache = make(map[ID]ForContextCreator)
  16. )
  17. func Register(id ID, creator ForContextCreator) {
  18. // TODO: check id
  19. metadataCache[id] = creator
  20. }
  21. type contextImpl struct {
  22. callerTag string
  23. }
  24. func (this *contextImpl) CallerTag() string {
  25. return this.callerTag
  26. }
  27. type spaceImpl struct {
  28. cache map[ID]interface{}
  29. tag string
  30. }
  31. func newSpaceImpl(tag string, cache map[ID]interface{}) *spaceImpl {
  32. space := &spaceImpl{
  33. tag: tag,
  34. cache: make(map[ID]interface{}),
  35. }
  36. context := &contextImpl{
  37. callerTag: tag,
  38. }
  39. for id, object := range cache {
  40. creator, found := metadataCache[id]
  41. if found {
  42. space.cache[id] = creator(context, object)
  43. }
  44. }
  45. return space
  46. }
  47. func (this *spaceImpl) HasApp(id ID) bool {
  48. _, found := this.cache[id]
  49. return found
  50. }
  51. func (this *spaceImpl) GetApp(id ID) interface{} {
  52. obj, found := this.cache[id]
  53. if !found {
  54. return nil
  55. }
  56. return obj
  57. }
  58. // A SpaceController is supposed to be used by a shell to create Spaces. It should not be used
  59. // directly by proxies.
  60. type SpaceController struct {
  61. objectCache map[ID]interface{}
  62. }
  63. func NewController() *SpaceController {
  64. return &SpaceController{
  65. objectCache: make(map[ID]interface{}),
  66. }
  67. }
  68. func (this *SpaceController) Bind(id ID, object interface{}) {
  69. this.objectCache[id] = object
  70. }
  71. func (this *SpaceController) ForContext(tag string) Space {
  72. return newSpaceImpl(tag, this.objectCache)
  73. }