router.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package core
  2. import (
  3. "context"
  4. "sync"
  5. "v2ray.com/core/common"
  6. "v2ray.com/core/common/errors"
  7. "v2ray.com/core/common/net"
  8. "v2ray.com/core/transport/ray"
  9. )
  10. // Dispatcher is a feature that dispatches inbound requests to outbound handlers based on rules.
  11. // Dispatcher is required to be registered in a V2Ray instance to make V2Ray function properly.
  12. type Dispatcher interface {
  13. Feature
  14. // Dispatch returns a Ray for transporting data for the given request.
  15. Dispatch(ctx context.Context, dest net.Destination) (ray.InboundRay, error)
  16. }
  17. type syncDispatcher struct {
  18. sync.RWMutex
  19. Dispatcher
  20. }
  21. func (d *syncDispatcher) Dispatch(ctx context.Context, dest net.Destination) (ray.InboundRay, error) {
  22. d.RLock()
  23. defer d.RUnlock()
  24. if d.Dispatcher == nil {
  25. return nil, newError("Dispatcher not set.").AtError()
  26. }
  27. return d.Dispatcher.Dispatch(ctx, dest)
  28. }
  29. func (d *syncDispatcher) Start() error {
  30. d.RLock()
  31. defer d.RUnlock()
  32. if d.Dispatcher == nil {
  33. return newError("Dispatcher not set.").AtError()
  34. }
  35. return d.Dispatcher.Start()
  36. }
  37. func (d *syncDispatcher) Close() error {
  38. d.RLock()
  39. defer d.RUnlock()
  40. return common.Close(d.Dispatcher)
  41. }
  42. func (d *syncDispatcher) Set(disp Dispatcher) {
  43. if disp == nil {
  44. return
  45. }
  46. d.Lock()
  47. defer d.Unlock()
  48. common.Close(d.Dispatcher)
  49. d.Dispatcher = disp
  50. }
  51. var (
  52. // ErrNoClue is for the situation that existing information is not enough to make a decision. For example, Router may return this error when there is no suitable route.
  53. ErrNoClue = errors.New("not enough information for making a decision")
  54. )
  55. // Router is a feature to choose a outbound tag for the given request.
  56. type Router interface {
  57. Feature
  58. // PickRoute returns a tag of an OutboundHandler based on the given context.
  59. PickRoute(ctx context.Context) (string, error)
  60. }
  61. type syncRouter struct {
  62. sync.RWMutex
  63. Router
  64. }
  65. func (r *syncRouter) PickRoute(ctx context.Context) (string, error) {
  66. r.RLock()
  67. defer r.RUnlock()
  68. if r.Router == nil {
  69. return "", ErrNoClue
  70. }
  71. return r.Router.PickRoute(ctx)
  72. }
  73. func (r *syncRouter) Start() error {
  74. r.RLock()
  75. defer r.RUnlock()
  76. if r.Router == nil {
  77. return nil
  78. }
  79. return r.Router.Start()
  80. }
  81. func (r *syncRouter) Close() error {
  82. r.RLock()
  83. defer r.RUnlock()
  84. return common.Close(r.Router)
  85. }
  86. func (r *syncRouter) Set(router Router) {
  87. if router == nil {
  88. return
  89. }
  90. r.Lock()
  91. defer r.Unlock()
  92. common.Close(r.Router)
  93. r.Router = router
  94. }