Skip to content

Commit

Permalink
Accept lists of ports
Browse files Browse the repository at this point in the history
Modified existing methods to work with a list of ports instead of a
starting port and ending port.
  • Loading branch information
darthneko committed Jan 23, 2015
1 parent c2092ce commit eb5a2dd
Showing 1 changed file with 48 additions and 58 deletions.
106 changes: 48 additions & 58 deletions lib/portscanner.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
var net = require('net')
, Socket = net.Socket
, async = require('async')
var net = require('net');
var Socket = net.Socket;
var async = require('async');

var portscanner = exports
var portscanner = exports;

/**
* Finds the first port with a status of 'open', implying the port is in use and
* there is likely a service listening on it.
*
* @param {Number} startPort - Port to begin status check on (inclusive).
* @param {Number} endPort - Last port to check status on (inclusive).
* Defaults to 65535.
* @param {List} portList - List of ports to check on.
* @param {String} host - Where to scan. Defaults to '127.0.0.1'.
* @param {Function} callback - function (error, port) { ... }
* - {Object|null} error - Any errors that occurred while port scanning.
Expand All @@ -19,17 +17,15 @@ var portscanner = exports
* necessarily the first open port checked. If no
* open port is found, the value is false.
*/
portscanner.findAPortInUse = function(startPort, endPort, host, callback) {
findAPortWithStatus('open', startPort, endPort, host, callback)
portscanner.findAPortInUse = function(portList, host, callback) {
findAPortWithStatus('open', portList, host, callback);
}

/**
* Finds the first port with a status of 'closed', implying the port is not in
* use.
*
* @param {Number} startPort - Port to begin status check on (inclusive).
* @param {Number} endPort - Last port to check status on (inclusive).
* Defaults to 65535.
* @param {List} portList - List of ports to check on.
* @param {String} host - Where to scan. Defaults to '127.0.0.1'.
* @param {Function} callback - function (error, port) { ... }
* - {Object|null} error - Any errors that occurred while port scanning.
Expand All @@ -38,8 +34,8 @@ portscanner.findAPortInUse = function(startPort, endPort, host, callback) {
* necessarily the first closed port checked. If no
* closed port is found, the value is false.
*/
portscanner.findAPortNotInUse = function(startPort, endPort, host, callback) {
findAPortWithStatus('closed', startPort, endPort, host, callback)
portscanner.findAPortNotInUse = function(portList, host, callback) {
findAPortWithStatus('closed', portList, host, callback);
}

/**
Expand All @@ -59,30 +55,30 @@ portscanner.findAPortNotInUse = function(startPort, endPort, host, callback) {
portscanner.checkPortStatus = function(port, options, callback) {
if (typeof options === 'string') {
// Assume this param is the host option
options = {host: options}
options = {host: options};
}

var host = options.host || '127.0.0.1'
var timeout = options.timeout || 400
var host = options.host || '127.0.0.1';
var timeout = options.timeout || 400;
var connectionRefused = false;

var socket = new Socket()
, status = null
, error = null
var socket = new Socket();
var status = null;
var error = null;

// Socket connection established, port is open
socket.on('connect', function() {
status = 'open'
socket.destroy()
})
status = 'open';
socket.destroy();
});

// If no response, assume port is not listening
socket.setTimeout(timeout)
socket.setTimeout(timeout);
socket.on('timeout', function() {
status = 'closed'
error = new Error('Timeout (' + timeout + 'ms) occurred waiting for ' + host + ':' + port + ' to be available')
socket.destroy()
})
status = 'closed';
error = new Error('Timeout (' + timeout + 'ms) occurred waiting for ' + host + ':' + port + ' to be available');
socket.destroy();
});

// Assuming the port is not open if an error. May need to refine based on
// exception
Expand All @@ -93,59 +89,53 @@ portscanner.checkPortStatus = function(port, options, callback) {
else
connectionRefused = true;
status = 'closed'
})
});

// Return after the socket has closed
socket.on('close', function(exception) {
if(exception && !connectionRefused)
error = exception;
else
error = null;
callback(error, status)
})
callback(error, status);
});

socket.connect(port, host)
socket.connect(port, host);
}

function findAPortWithStatus(status, startPort, endPort, host, callback) {
endPort = endPort || 65535
var foundPort = false
var numberOfPortsChecked = 0
var port = startPort
function findAPortWithStatus(status, portList, host, callback) {
var foundPort = false;
var portIndex = 0;
var port = portList[portIndex];

// Returns true if a port with matching status has been found or if checked
// the entire range of ports
var hasFoundPort = function() {
return foundPort || numberOfPortsChecked === (endPort - startPort + 1)
}
return foundPort || (portIndex === portList.length);
};

// Checks the status of the port
var checkNextPort = function(callback) {
portscanner.checkPortStatus(port, host, function(error, statusOfPort) {
numberOfPortsChecked++
if (statusOfPort === status) {
foundPort = true
callback(error)
foundPort = true;
callback(error);
} else {
port = portList[++portIndex];
callback(null);
}
else {
port++
callback(null)
}
})
}
});
};

// Check the status of each port until one with a matching status has been
// found or the range of ports has been exhausted
async.until(hasFoundPort, checkNextPort, function(error) {
if (error) {
callback(error, port)
callback(error, port);
} else if (foundPort) {
callback(null, port);
} else {
callback(null, false);
}
else if (foundPort) {
callback(null, port)
}
else {
callback(null, false)
}
})
}

});
}

0 comments on commit eb5a2dd

Please sign in to comment.