@@ -39,27 +39,59 @@ func filter(ss []procnet.NetworkDetail, filterFunc func(detail procnet.NetworkDe
39
39
}
40
40
41
41
func portAllocate (protocol string , ip string , count uint64 ) (uint64 , uint64 , error ) {
42
- netprocData , err := procnet . ReadStatsFileData ( protocol )
42
+ usedPort , err := getUsedPorts ( ip , protocol )
43
43
if err != nil {
44
44
return 0 , 0 , err
45
45
}
46
- netprocItems := procnet .Parse (netprocData )
46
+
47
+ start := uint64 (allocateStart )
48
+ if count > uint64 (allocateEnd - allocateStart + 1 ) {
49
+ return 0 , 0 , fmt .Errorf ("can not allocate %d ports" , count )
50
+ }
51
+ for start < allocateEnd {
52
+ needReturn := true
53
+ for i := start ; i < start + count ; i ++ {
54
+ if _ , ok := usedPort [i ]; ok {
55
+ needReturn = false
56
+ break
57
+ }
58
+ }
59
+ if needReturn {
60
+ return start , start + count - 1 , nil
61
+ }
62
+ start += count
63
+ }
64
+ return 0 , 0 , fmt .Errorf ("there is not enough %d free ports" , count )
65
+ }
66
+
67
+ func getUsedPorts (ip string , protocol string ) (map [uint64 ]bool , error ) {
68
+ netprocItems := []procnet.NetworkDetail {}
69
+
70
+ if protocol == "tcp" || protocol == "udp" {
71
+ netprocData , err := procnet .ReadStatsFileData (protocol )
72
+ if err != nil {
73
+ return nil , err
74
+ }
75
+ netprocItems = append (netprocItems , procnet .Parse (netprocData )... )
76
+ }
77
+
47
78
// In some circumstances, when we bind address like "0.0.0.0:80", we will get the formation of ":::80" in /proc/net/tcp6.
48
79
// So we need some trick to process this situation.
49
80
if protocol == "tcp" {
50
81
tempTCPV6Data , err := procnet .ReadStatsFileData ("tcp6" )
51
82
if err != nil {
52
- return 0 , 0 , err
83
+ return nil , err
53
84
}
54
85
netprocItems = append (netprocItems , procnet .Parse (tempTCPV6Data )... )
55
86
}
56
87
if protocol == "udp" {
57
88
tempUDPV6Data , err := procnet .ReadStatsFileData ("udp6" )
58
89
if err != nil {
59
- return 0 , 0 , err
90
+ return nil , err
60
91
}
61
92
netprocItems = append (netprocItems , procnet .Parse (tempUDPV6Data )... )
62
93
}
94
+
63
95
if ip != "" {
64
96
netprocItems = filter (netprocItems , func (s procnet.NetworkDetail ) bool {
65
97
// In some circumstances, when we bind address like "0.0.0.0:80", we will get the formation of ":::80" in /proc/net/tcp6.
@@ -75,30 +107,13 @@ func portAllocate(protocol string, ip string, count uint64) (uint64, uint64, err
75
107
76
108
ipTableItems , err := iptable .ReadIPTables ("nat" )
77
109
if err != nil {
78
- return 0 , 0 , err
110
+ return nil , err
79
111
}
80
112
destinationPorts := iptable .ParseIPTableRules (ipTableItems )
81
113
82
114
for _ , port := range destinationPorts {
83
115
usedPort [port ] = true
84
116
}
85
117
86
- start := uint64 (allocateStart )
87
- if count > uint64 (allocateEnd - allocateStart + 1 ) {
88
- return 0 , 0 , fmt .Errorf ("can not allocate %d ports" , count )
89
- }
90
- for start < allocateEnd {
91
- needReturn := true
92
- for i := start ; i < start + count ; i ++ {
93
- if _ , ok := usedPort [i ]; ok {
94
- needReturn = false
95
- break
96
- }
97
- }
98
- if needReturn {
99
- return start , start + count - 1 , nil
100
- }
101
- start += count
102
- }
103
- return 0 , 0 , fmt .Errorf ("there is not enough %d free ports" , count )
118
+ return usedPort , nil
104
119
}
0 commit comments