generated from TBD54566975/tbd-project-template
-
Notifications
You must be signed in to change notification settings - Fork 7
/
bind_allocator.go
49 lines (40 loc) · 895 Bytes
/
bind_allocator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package bind
import (
"net"
"net/url"
"strconv"
"github.com/alecthomas/atomic"
)
type BindAllocator struct {
baseURL *url.URL
port atomic.Int32
}
func NewBindAllocator(url *url.URL) (*BindAllocator, error) {
_, portStr, err := net.SplitHostPort(url.Host)
if err != nil {
return nil, err
}
port, err := strconv.Atoi(portStr)
if err != nil {
return nil, err
}
return &BindAllocator{
baseURL: url,
port: atomic.NewInt32(int32(port) - 1), //nolint:gosec
}, nil
}
func (b *BindAllocator) Next() *url.URL {
var l *net.TCPListener
var err error
for {
b.port.Add(1)
l, err = net.ListenTCP("tcp", &net.TCPAddr{IP: net.ParseIP(b.baseURL.Hostname()), Port: int(b.port.Load())})
if err != nil {
continue
}
_ = l.Close()
newURL := *b.baseURL
newURL.Host = net.JoinHostPort(b.baseURL.Hostname(), strconv.Itoa(int(b.port.Load())))
return &newURL
}
}