-
Notifications
You must be signed in to change notification settings - Fork 5
/
util.go
60 lines (49 loc) · 1.08 KB
/
util.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
50
51
52
53
54
55
56
57
58
59
60
package session
import (
"encoding/hex"
"errors"
"fmt"
"net"
"strconv"
"sync"
"time"
)
var (
zeroTime time.Time
)
func sessionKey(remoteAddr string, sessionID []byte) string {
return remoteAddr + ":" + hex.EncodeToString(sessionID)
}
func connID(i int) string {
return strconv.Itoa(i)
}
// Get free port start from parameter `port`
// If paramenter `port` is 0, return system available port
// The returned port is free in both TCP and UDP
var lock sync.Mutex
func GetFreePort(port int) (int, error) {
// to avoid race condition
lock.Lock()
defer lock.Unlock()
for i := 0; i < 100; i++ {
addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:%d", port))
if err != nil {
return 0, err
}
l, err := net.ListenTCP("tcp", addr)
if err != nil {
return 0, err
}
defer l.Close()
port = l.Addr().(*net.TCPAddr).Port
u, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.ParseIP("127.0.0.1"), Port: port})
if err != nil {
l.Close()
port++
continue
}
u.Close()
return port, nil
}
return 0, errors.New("failed to find free port after 100 tries")
}