@@ -39,27 +39,55 @@ 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
44
if err != nil {
44
45
return 0 , 0 , err
45
46
}
47
+
48
+ start := uint64 (allocateStart )
49
+ if count > uint64 (allocateEnd - allocateStart + 1 ) {
50
+ return 0 , 0 , fmt .Errorf ("can not allocate %d ports" , count )
51
+ }
52
+ for start < allocateEnd {
53
+ needReturn := true
54
+ for i := start ; i < start + count ; i ++ {
55
+ if _ , ok := usedPort [i ]; ok {
56
+ needReturn = false
57
+ break
58
+ }
59
+ }
60
+ if needReturn {
61
+ return start , start + count - 1 , nil
62
+ }
63
+ start += count
64
+ }
65
+ return 0 , 0 , fmt .Errorf ("there is not enough %d free ports" , count )
66
+ }
67
+
68
+ func getUsedPorts (ip string , protocol string ) (map [uint64 ]bool , error ) {
69
+ netprocData , err := procnet .ReadStatsFileData (protocol )
70
+ if err != nil {
71
+ return nil , err
72
+ }
46
73
netprocItems := procnet .Parse (netprocData )
47
74
// 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
75
// So we need some trick to process this situation.
49
76
if protocol == "tcp" {
50
77
tempTCPV6Data , err := procnet .ReadStatsFileData ("tcp6" )
51
78
if err != nil {
52
- return 0 , 0 , err
79
+ return nil , err
53
80
}
54
81
netprocItems = append (netprocItems , procnet .Parse (tempTCPV6Data )... )
55
82
}
56
83
if protocol == "udp" {
57
84
tempUDPV6Data , err := procnet .ReadStatsFileData ("udp6" )
58
85
if err != nil {
59
- return 0 , 0 , err
86
+ return nil , err
60
87
}
61
88
netprocItems = append (netprocItems , procnet .Parse (tempUDPV6Data )... )
62
89
}
90
+
63
91
if ip != "" {
64
92
netprocItems = filter (netprocItems , func (s procnet.NetworkDetail ) bool {
65
93
// 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 +103,13 @@ func portAllocate(protocol string, ip string, count uint64) (uint64, uint64, err
75
103
76
104
ipTableItems , err := iptable .ReadIPTables ("nat" )
77
105
if err != nil {
78
- return 0 , 0 , err
106
+ return nil , err
79
107
}
80
108
destinationPorts := iptable .ParseIPTableRules (ipTableItems )
81
109
82
110
for _ , port := range destinationPorts {
83
111
usedPort [port ] = true
84
112
}
85
113
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 )
114
+ return usedPort , nil
104
115
}
0 commit comments