-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathport_manager.go
More file actions
72 lines (60 loc) · 1.57 KB
/
port_manager.go
File metadata and controls
72 lines (60 loc) · 1.57 KB
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
61
62
63
64
65
66
67
68
69
70
71
72
package dmsg
import (
"math/rand"
"sync"
"time"
"github.com/SkycoinProject/dmsg/cipher"
)
const (
firstEphemeralPort = 49152
lastEphemeralPort = 65535
)
// PortManager manages ports of nodes.
type PortManager struct {
mu sync.RWMutex
rand *rand.Rand
listeners map[uint16]*Listener
}
func newPortManager() *PortManager {
return &PortManager{
rand: rand.New(rand.NewSource(time.Now().UnixNano())),
listeners: make(map[uint16]*Listener),
}
}
// Listener returns a listener assigned to a given port.
func (pm *PortManager) Listener(port uint16) (*Listener, bool) {
pm.mu.RLock()
defer pm.mu.RUnlock()
l, ok := pm.listeners[port]
return l, ok
}
// NewListener assigns listener to port if port is available.
func (pm *PortManager) NewListener(pk cipher.PubKey, port uint16) (*Listener, bool) {
pm.mu.Lock()
defer pm.mu.Unlock()
if _, ok := pm.listeners[port]; ok {
return nil, false
}
l := newListener(pk, port)
pm.listeners[port] = l
return l, true
}
// RemoveListener removes listener assigned to port.
func (pm *PortManager) RemoveListener(port uint16) {
pm.mu.Lock()
defer pm.mu.Unlock()
delete(pm.listeners, port)
}
// NextEmptyEphemeralPort returns next random ephemeral port.
// It has a value between firstEphemeralPort and lastEphemeralPort.
func (pm *PortManager) NextEmptyEphemeralPort() uint16 {
for {
port := pm.randomEphemeralPort()
if _, ok := pm.Listener(port); !ok {
return port
}
}
}
func (pm *PortManager) randomEphemeralPort() uint16 {
return uint16(firstEphemeralPort + pm.rand.Intn(lastEphemeralPort-firstEphemeralPort))
}