1 | var net = require('net')
|
2 | var Socket = net.Socket
|
3 | var async = require('async')
|
4 | var isNumberLike = require('is-number-like')
|
5 | var promisify = require('./promisify')
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 | function findAPortInUse () {
|
36 | var params = [].slice.call(arguments)
|
37 | params.unshift('open')
|
38 | return findAPortWithStatus.apply(null, params)
|
39 | }
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 | function findAPortNotInUse () {
|
46 | var params = [].slice.call(arguments)
|
47 | params.unshift('closed')
|
48 | return findAPortWithStatus.apply(null, params)
|
49 | }
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 | function checkPortStatus (port) {
|
69 | var args, host, opts, callback
|
70 |
|
71 | args = [].slice.call(arguments, 1)
|
72 |
|
73 | if (typeof args[0] === 'string') {
|
74 | host = args[0]
|
75 | } else if (typeof args[0] === 'object') {
|
76 | opts = args[0]
|
77 | } else if (typeof args[0] === 'function') {
|
78 | callback = args[0]
|
79 | }
|
80 |
|
81 | if (typeof args[1] === 'object') {
|
82 | opts = args[1]
|
83 | } else if (typeof args[1] === 'function') {
|
84 | callback = args[1]
|
85 | }
|
86 |
|
87 | if (typeof args[2] === 'function') {
|
88 | callback = args[2]
|
89 | }
|
90 |
|
91 | if (!callback) return promisify(checkPortStatus, arguments)
|
92 |
|
93 | opts = opts || {}
|
94 |
|
95 | host = host || opts.host || '127.0.0.1'
|
96 |
|
97 | var timeout = opts.timeout || 400
|
98 | var connectionRefused = false
|
99 |
|
100 | var socket = new Socket()
|
101 | var status = null
|
102 | var error = null
|
103 |
|
104 |
|
105 | socket.on('connect', function () {
|
106 | status = 'open'
|
107 | socket.destroy()
|
108 | })
|
109 |
|
110 |
|
111 | socket.setTimeout(timeout)
|
112 | socket.on('timeout', function () {
|
113 | status = 'closed'
|
114 | error = new Error('Timeout (' + timeout + 'ms) occurred waiting for ' + host + ':' + port + ' to be available')
|
115 | socket.destroy()
|
116 | })
|
117 |
|
118 |
|
119 |
|
120 | socket.on('error', function (exception) {
|
121 | if (exception.code !== 'ECONNREFUSED') {
|
122 | error = exception
|
123 | } else {
|
124 | connectionRefused = true
|
125 | }
|
126 | status = 'closed'
|
127 | })
|
128 |
|
129 |
|
130 | socket.on('close', function (exception) {
|
131 | if (exception && !connectionRefused) { error = error || exception } else { error = null }
|
132 | callback(error, status)
|
133 | })
|
134 |
|
135 | socket.connect(port, host)
|
136 | }
|
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 | function findAPortWithStatus (status) {
|
153 | var params, startPort, endPort, portList, host, opts, callback
|
154 |
|
155 | params = [].slice.call(arguments, 1)
|
156 |
|
157 | if (params[0] instanceof Array) {
|
158 | portList = params[0]
|
159 | } else if (isNumberLike(params[0])) {
|
160 | startPort = parseInt(params[0], 10)
|
161 | }
|
162 |
|
163 | if (typeof params[1] === 'function') {
|
164 | callback = params[1]
|
165 | } else if (typeof params[1] === 'string') {
|
166 | host = params[1]
|
167 | } else if (typeof params[1] === 'object') {
|
168 | opts = params[1]
|
169 | } else if (isNumberLike(params[1])) {
|
170 | endPort = parseInt(params[1], 10)
|
171 | }
|
172 |
|
173 | if (typeof params[2] === 'string') {
|
174 | host = params[2]
|
175 | } else if (typeof params[2] === 'object') {
|
176 | opts = params[2]
|
177 | } else if (typeof params[2] === 'function') {
|
178 | callback = params[2]
|
179 | }
|
180 |
|
181 | if (typeof params[3] === 'function') {
|
182 | callback = params[3]
|
183 | }
|
184 |
|
185 | if (!callback) return promisify(findAPortWithStatus, arguments)
|
186 |
|
187 | opts = opts || {}
|
188 |
|
189 | host = host || opts.host
|
190 |
|
191 | if (startPort && endPort && endPort < startPort) {
|
192 |
|
193 | var tempStartPort = startPort
|
194 | startPort = endPort
|
195 | endPort = tempStartPort
|
196 | }
|
197 |
|
198 | endPort = endPort || 65535
|
199 |
|
200 | var foundPort = false
|
201 | var numberOfPortsChecked = 0
|
202 | var port = portList ? portList[0] : startPort
|
203 |
|
204 |
|
205 |
|
206 | var hasFoundPort = function () {
|
207 | return foundPort || numberOfPortsChecked === (portList ? portList.length : endPort - startPort + 1)
|
208 | }
|
209 |
|
210 |
|
211 | var checkNextPort = function (callback) {
|
212 | checkPortStatus(port, host, opts, function (error, statusOfPort) {
|
213 | numberOfPortsChecked++
|
214 | if (statusOfPort === status) {
|
215 | foundPort = true
|
216 | callback(error)
|
217 | } else {
|
218 | port = portList ? portList[numberOfPortsChecked] : port + 1
|
219 | callback(null)
|
220 | }
|
221 | })
|
222 | }
|
223 |
|
224 |
|
225 |
|
226 | async.until(hasFoundPort, checkNextPort, function (error) {
|
227 | if (error) {
|
228 | callback(error, port)
|
229 | } else if (foundPort) {
|
230 | callback(null, port)
|
231 | } else {
|
232 | callback(null, false)
|
233 | }
|
234 | })
|
235 | }
|
236 |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 |
|
242 |
|
243 |
|
244 |
|
245 |
|
246 |
|
247 | module.exports = {
|
248 | findAPortInUse: findAPortInUse,
|
249 | findAPortNotInUse: findAPortNotInUse,
|
250 | checkPortStatus: checkPortStatus
|
251 | }
|