GetRandomPorts returns available random ports, previously allocated ports will be ignored.
(bindAddr string, minPort, maxPort, count int)
| 105 | |
| 106 | // GetRandomPorts returns available random ports, previously allocated ports will be ignored. |
| 107 | func GetRandomPorts(bindAddr string, minPort, maxPort, count int) (ports []int, err error) { |
| 108 | allocateLock.Lock() |
| 109 | defer allocateLock.Unlock() |
| 110 | |
| 111 | ports = make([]int, 0, count) |
| 112 | |
| 113 | defer func() { |
| 114 | // save the allocated ports |
| 115 | if err == nil { |
| 116 | for _, port := range ports { |
| 117 | addr := net.JoinHostPort(bindAddr, fmt.Sprint(port)) |
| 118 | allocatedPorts.Store(addr, true) |
| 119 | addr = net.JoinHostPort("0.0.0.0", fmt.Sprint(port)) |
| 120 | allocatedPorts.Store(addr, true) |
| 121 | } |
| 122 | } |
| 123 | }() |
| 124 | |
| 125 | if count == 0 { |
| 126 | return |
| 127 | } |
| 128 | |
| 129 | if minPort == 0 { |
| 130 | minPort = 1 |
| 131 | } |
| 132 | |
| 133 | if minPort > maxPort { |
| 134 | err = ErrNotEnoughPorts |
| 135 | return |
| 136 | } |
| 137 | |
| 138 | pivotPort := minPort |
| 139 | if maxPort != minPort { |
| 140 | pivotPort = rand.Intn(maxPort-minPort) + minPort |
| 141 | } |
| 142 | |
| 143 | for i := pivotPort; i <= maxPort; i++ { |
| 144 | if testPort(bindAddr, i, true) { |
| 145 | ports = append(ports, i) |
| 146 | } |
| 147 | |
| 148 | if len(ports) == count { |
| 149 | return |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | for i := minPort; i < pivotPort; i++ { |
| 154 | if testPort(bindAddr, i, true) { |
| 155 | ports = append(ports, i) |
| 156 | } |
| 157 | |
| 158 | if len(ports) == count { |
| 159 | return |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | err = ErrNotEnoughPorts |
| 164 |