inbound_detour_dynamic.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. package point
  2. import (
  3. "sync"
  4. "time"
  5. "github.com/v2ray/v2ray-core/app"
  6. "github.com/v2ray/v2ray-core/common/dice"
  7. "github.com/v2ray/v2ray-core/common/log"
  8. v2net "github.com/v2ray/v2ray-core/common/net"
  9. "github.com/v2ray/v2ray-core/proxy"
  10. proxyrepo "github.com/v2ray/v2ray-core/proxy/repo"
  11. )
  12. type InboundDetourHandlerDynamic struct {
  13. sync.RWMutex
  14. space app.Space
  15. config *InboundDetourConfig
  16. portsInUse map[v2net.Port]bool
  17. ichs []proxy.InboundHandler
  18. lastRefresh time.Time
  19. }
  20. func NewInboundDetourHandlerDynamic(space app.Space, config *InboundDetourConfig) (*InboundDetourHandlerDynamic, error) {
  21. handler := &InboundDetourHandlerDynamic{
  22. space: space,
  23. config: config,
  24. portsInUse: make(map[v2net.Port]bool),
  25. }
  26. handler.ichs = make([]proxy.InboundHandler, config.Allocation.Concurrency)
  27. // To test configuration
  28. ich, err := proxyrepo.CreateInboundHandler(config.Protocol, space, config.Settings, config.ListenOn, 0)
  29. if err != nil {
  30. log.Error("Point: Failed to create inbound connection handler: ", err)
  31. return nil, err
  32. }
  33. ich.Close()
  34. return handler, nil
  35. }
  36. func (this *InboundDetourHandlerDynamic) pickUnusedPort() v2net.Port {
  37. delta := int(this.config.PortRange.To) - int(this.config.PortRange.From) + 1
  38. for {
  39. r := dice.Roll(delta)
  40. port := this.config.PortRange.From + v2net.Port(r)
  41. _, used := this.portsInUse[port]
  42. if !used {
  43. return port
  44. }
  45. }
  46. }
  47. func (this *InboundDetourHandlerDynamic) GetConnectionHandler() (proxy.InboundHandler, int) {
  48. this.RLock()
  49. defer this.RUnlock()
  50. ich := this.ichs[dice.Roll(len(this.ichs))]
  51. until := this.config.Allocation.Refresh - int((time.Now().Unix()-this.lastRefresh.Unix())/60/1000)
  52. if until < 0 {
  53. until = 0
  54. }
  55. return ich, int(until)
  56. }
  57. func (this *InboundDetourHandlerDynamic) Close() {
  58. this.Lock()
  59. defer this.Unlock()
  60. for _, ich := range this.ichs {
  61. ich.Close()
  62. }
  63. }
  64. func (this *InboundDetourHandlerDynamic) refresh() error {
  65. this.lastRefresh = time.Now()
  66. config := this.config
  67. ich2Recycle := this.ichs
  68. newIchs := make([]proxy.InboundHandler, config.Allocation.Concurrency)
  69. for idx, _ := range newIchs {
  70. port := this.pickUnusedPort()
  71. ich, err := proxyrepo.CreateInboundHandler(config.Protocol, this.space, config.Settings, config.ListenOn, port)
  72. if err != nil {
  73. log.Error("Point: Failed to create inbound connection handler: ", err)
  74. return err
  75. }
  76. err = ich.Start()
  77. if err != nil {
  78. log.Error("Point: Failed to start inbound connection handler: ", err)
  79. return err
  80. }
  81. this.portsInUse[port] = true
  82. newIchs[idx] = ich
  83. }
  84. this.Lock()
  85. this.ichs = newIchs
  86. this.Unlock()
  87. go func() {
  88. time.Sleep(time.Minute)
  89. for _, ich := range ich2Recycle {
  90. if ich == nil {
  91. continue
  92. }
  93. port := ich.Port()
  94. ich.Close()
  95. delete(this.portsInUse, port)
  96. }
  97. ich2Recycle = nil
  98. }()
  99. return nil
  100. }
  101. func (this *InboundDetourHandlerDynamic) Start() error {
  102. err := this.refresh()
  103. if err != nil {
  104. log.Error("Point: Failed to refresh dynamic allocations: ", err)
  105. return err
  106. }
  107. go func() {
  108. for {
  109. time.Sleep(time.Duration(this.config.Allocation.Refresh) * time.Minute)
  110. err := this.refresh()
  111. if err != nil {
  112. log.Error("Point: Failed to refresh dynamic allocations: ", err)
  113. }
  114. }
  115. }()
  116. return nil
  117. }