1
0

ports.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. package server
  2. import (
  3. "errors"
  4. "fmt"
  5. "net"
  6. "sync"
  7. "time"
  8. )
  9. const (
  10. MinPort = 1
  11. MaxPort = 65535
  12. MaxPortReservedDuration = time.Duration(24) * time.Hour
  13. CleanReservedPortsInterval = time.Hour
  14. )
  15. var (
  16. ErrPortAlreadyUsed = errors.New("port already used")
  17. ErrPortNotAllowed = errors.New("port not allowed")
  18. ErrPortUnAvailable = errors.New("port unavailable")
  19. ErrNoAvailablePort = errors.New("no available port")
  20. )
  21. type PortCtx struct {
  22. ProxyName string
  23. Port int
  24. Closed bool
  25. UpdateTime time.Time
  26. }
  27. type PortManager struct {
  28. reservedPorts map[string]*PortCtx
  29. usedPorts map[int]*PortCtx
  30. freePorts map[int]struct{}
  31. bindAddr string
  32. netType string
  33. mu sync.Mutex
  34. }
  35. func NewPortManager(netType string, bindAddr string, allowPorts map[int]struct{}) *PortManager {
  36. pm := &PortManager{
  37. reservedPorts: make(map[string]*PortCtx),
  38. usedPorts: make(map[int]*PortCtx),
  39. freePorts: make(map[int]struct{}),
  40. bindAddr: bindAddr,
  41. netType: netType,
  42. }
  43. if len(allowPorts) > 0 {
  44. for port, _ := range allowPorts {
  45. pm.freePorts[port] = struct{}{}
  46. }
  47. } else {
  48. for i := MinPort; i <= MaxPort; i++ {
  49. pm.freePorts[i] = struct{}{}
  50. }
  51. }
  52. go pm.cleanReservedPortsWorker()
  53. return pm
  54. }
  55. func (pm *PortManager) Acquire(name string, port int) (realPort int, err error) {
  56. portCtx := &PortCtx{
  57. ProxyName: name,
  58. Closed: false,
  59. UpdateTime: time.Now(),
  60. }
  61. var ok bool
  62. pm.mu.Lock()
  63. defer func() {
  64. if err == nil {
  65. portCtx.Port = realPort
  66. }
  67. pm.mu.Unlock()
  68. }()
  69. // check reserved ports first
  70. if port == 0 {
  71. if ctx, ok := pm.reservedPorts[name]; ok {
  72. if pm.isPortAvailable(ctx.Port) {
  73. realPort = ctx.Port
  74. pm.usedPorts[realPort] = portCtx
  75. pm.reservedPorts[name] = portCtx
  76. delete(pm.freePorts, realPort)
  77. return
  78. }
  79. }
  80. }
  81. if port == 0 {
  82. // get random port
  83. count := 0
  84. maxTryTimes := 5
  85. for k, _ := range pm.freePorts {
  86. count++
  87. if count > maxTryTimes {
  88. break
  89. }
  90. if pm.isPortAvailable(k) {
  91. realPort = k
  92. pm.usedPorts[realPort] = portCtx
  93. pm.reservedPorts[name] = portCtx
  94. delete(pm.freePorts, realPort)
  95. break
  96. }
  97. }
  98. if realPort == 0 {
  99. err = ErrNoAvailablePort
  100. }
  101. } else {
  102. // specified port
  103. if _, ok = pm.freePorts[port]; ok {
  104. if pm.isPortAvailable(port) {
  105. realPort = port
  106. pm.usedPorts[realPort] = portCtx
  107. pm.reservedPorts[name] = portCtx
  108. delete(pm.freePorts, realPort)
  109. } else {
  110. err = ErrPortUnAvailable
  111. }
  112. } else {
  113. if _, ok = pm.usedPorts[port]; ok {
  114. err = ErrPortAlreadyUsed
  115. } else {
  116. err = ErrPortNotAllowed
  117. }
  118. }
  119. }
  120. return
  121. }
  122. func (pm *PortManager) isPortAvailable(port int) bool {
  123. if pm.netType == "udp" {
  124. addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", pm.bindAddr, port))
  125. if err != nil {
  126. return false
  127. }
  128. l, err := net.ListenUDP("udp", addr)
  129. if err != nil {
  130. return false
  131. }
  132. l.Close()
  133. return true
  134. } else {
  135. l, err := net.Listen(pm.netType, fmt.Sprintf("%s:%d", pm.bindAddr, port))
  136. if err != nil {
  137. return false
  138. }
  139. l.Close()
  140. return true
  141. }
  142. }
  143. func (pm *PortManager) Release(port int) {
  144. pm.mu.Lock()
  145. defer pm.mu.Unlock()
  146. if ctx, ok := pm.usedPorts[port]; ok {
  147. pm.freePorts[port] = struct{}{}
  148. delete(pm.usedPorts, port)
  149. ctx.Closed = true
  150. ctx.UpdateTime = time.Now()
  151. }
  152. }
  153. // Release reserved port if it isn't used in last 24 hours.
  154. func (pm *PortManager) cleanReservedPortsWorker() {
  155. for {
  156. time.Sleep(CleanReservedPortsInterval)
  157. pm.mu.Lock()
  158. for name, ctx := range pm.reservedPorts {
  159. if ctx.Closed && time.Since(ctx.UpdateTime) > MaxPortReservedDuration {
  160. delete(pm.reservedPorts, name)
  161. }
  162. }
  163. pm.mu.Unlock()
  164. }
  165. }