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