|
@@ -7,9 +7,13 @@ import (
|
|
|
"sync"
|
|
|
)
|
|
|
|
|
|
+type portMap struct {
|
|
|
+ p map[int]struct{}
|
|
|
+ last int
|
|
|
+}
|
|
|
+
|
|
|
type (
|
|
|
- portMap map[int]bool
|
|
|
- protocolMap map[string]portMap
|
|
|
+ protocolMap map[string]*portMap
|
|
|
ipMapping map[string]protocolMap
|
|
|
)
|
|
|
|
|
@@ -71,8 +75,8 @@ func RequestPort(ip net.IP, proto string, port int) (int, error) {
|
|
|
mapping := getOrCreate(ip)
|
|
|
|
|
|
if port > 0 {
|
|
|
- if !mapping[proto][port] {
|
|
|
- mapping[proto][port] = true
|
|
|
+ if _, ok := mapping[proto].p[port]; !ok {
|
|
|
+ mapping[proto].p[port] = struct{}{}
|
|
|
return port, nil
|
|
|
} else {
|
|
|
return 0, NewErrPortAlreadyAllocated(ip.String(), port)
|
|
@@ -94,8 +98,8 @@ func ReleasePort(ip net.IP, proto string, port int) error {
|
|
|
|
|
|
ip = getDefault(ip)
|
|
|
|
|
|
- mapping := getOrCreate(ip)
|
|
|
- delete(mapping[proto], port)
|
|
|
+ mapping := getOrCreate(ip)[proto]
|
|
|
+ delete(mapping.p, port)
|
|
|
|
|
|
return nil
|
|
|
}
|
|
@@ -114,8 +118,8 @@ func getOrCreate(ip net.IP) protocolMap {
|
|
|
|
|
|
if _, ok := globalMap[ipstr]; !ok {
|
|
|
globalMap[ipstr] = protocolMap{
|
|
|
- "tcp": portMap{},
|
|
|
- "udp": portMap{},
|
|
|
+ "tcp": &portMap{p: map[int]struct{}{}, last: 0},
|
|
|
+ "udp": &portMap{p: map[int]struct{}{}, last: 0},
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -123,21 +127,28 @@ func getOrCreate(ip net.IP) protocolMap {
|
|
|
}
|
|
|
|
|
|
func findPort(ip net.IP, proto string) (int, error) {
|
|
|
- port := BeginPortRange
|
|
|
+ mapping := getOrCreate(ip)[proto]
|
|
|
|
|
|
- mapping := getOrCreate(ip)
|
|
|
-
|
|
|
- for mapping[proto][port] {
|
|
|
- port++
|
|
|
+ if mapping.last == 0 {
|
|
|
+ mapping.p[BeginPortRange] = struct{}{}
|
|
|
+ mapping.last = BeginPortRange
|
|
|
+ return BeginPortRange, nil
|
|
|
+ }
|
|
|
|
|
|
+ for port := mapping.last + 1; port != mapping.last; port++ {
|
|
|
if port > EndPortRange {
|
|
|
- return 0, ErrAllPortsAllocated
|
|
|
+ port = BeginPortRange
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- mapping[proto][port] = true
|
|
|
+ if _, ok := mapping.p[port]; !ok {
|
|
|
+ mapping.p[port] = struct{}{}
|
|
|
+ mapping.last = port
|
|
|
+ return port, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
- return port, nil
|
|
|
+ return 0, ErrAllPortsAllocated
|
|
|
}
|
|
|
|
|
|
func getDefault(ip net.IP) net.IP {
|