Merge pull request #4628 from kippandrew/port-allocator

Fix port collision with dynamically allocated ports
This commit is contained in:
Victor Vieux 2014-03-25 14:30:10 -07:00
Родитель 6643cc20fe 555416fd02
Коммит abef5cb0fc
2 изменённых файлов: 42 добавлений и 7 удалений

Просмотреть файл

@ -100,22 +100,30 @@ func ReleaseAll() error {
} }
func registerDynamicPort(ip net.IP, proto string) (int, error) { func registerDynamicPort(ip net.IP, proto string) (int, error) {
allocated := defaultAllocatedPorts[proto]
port := nextPort(proto)
if port > EndPortRange {
return 0, ErrPortExceedsRange
}
if !equalsDefault(ip) { if !equalsDefault(ip) {
registerIP(ip) registerIP(ip)
ipAllocated := otherAllocatedPorts[ip.String()][proto] ipAllocated := otherAllocatedPorts[ip.String()][proto]
ipAllocated.Push(port)
} else { port, err := findNextPort(proto, ipAllocated)
allocated.Push(port) if err != nil {
return 0, err
} }
ipAllocated.Push(port)
return port, nil return port, nil
} else {
allocated := defaultAllocatedPorts[proto]
port, err := findNextPort(proto, allocated)
if err != nil {
return 0, err
}
allocated.Push(port)
return port, nil
}
} }
func registerSetPort(ip net.IP, proto string, port int) error { func registerSetPort(ip net.IP, proto string, port int) error {
@ -142,6 +150,17 @@ func equalsDefault(ip net.IP) bool {
return ip == nil || ip.Equal(defaultIP) return ip == nil || ip.Equal(defaultIP)
} }
func findNextPort(proto string, allocated *collections.OrderedIntSet) (int, error) {
port := nextPort(proto)
for allocated.Exists(port) {
port = nextPort(proto)
}
if port > EndPortRange {
return 0, ErrPortExceedsRange
}
return port, nil
}
func nextPort(proto string) int { func nextPort(proto string) int {
c := currentDynamicPort[proto] + 1 c := currentDynamicPort[proto] + 1
currentDynamicPort[proto] = c currentDynamicPort[proto] = c

Просмотреть файл

@ -181,4 +181,20 @@ func TestPortAllocation(t *testing.T) {
if _, err := RequestPort(ip, "tcp", 80); err != nil { if _, err := RequestPort(ip, "tcp", 80); err != nil {
t.Fatal(err) t.Fatal(err)
} }
port, err = RequestPort(ip, "tcp", 0)
if err != nil {
t.Fatal(err)
}
port2, err := RequestPort(ip, "tcp", port+1)
if err != nil {
t.Fatal(err)
}
port3, err := RequestPort(ip, "tcp", 0)
if err != nil {
t.Fatal(err)
}
if port3 == port2 {
t.Fatal("Requesting a dynamic port should never allocate a used port")
}
} }