router.go 2.3 KB

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