Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cleaned up port iteration, added methods to check ports from array, checking for proper port range #30

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion example/portscan.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ server.listen(3005, '127.0.0.1', function() {
})

// Finds a port that a service is listening on
portscanner.findAPortInUse(3000, 3010, '127.0.0.1', function(error, port) {
portscanner.findAPortInUse(3010, 3000, '127.0.0.1', function(error, port) {
// Port should be 3005 as the HTTP server is listening on that port
console.log('Found an open port at ' + port)
if (error) console.error(error);
Expand All @@ -31,5 +31,20 @@ server.listen(3005, '127.0.0.1', function() {
console.log('Found a closed port at ' + port)
if (error) console.error(error);
})

var list = [3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,3010];
// Finds a port that a service is listening on
portscanner.findAPortInUseFromList(list, '127.0.0.1', function(error, port) {
// Port should be 3005 as the HTTP server is listening on that port
console.log('Found an open port of '+list+' at ' + port)
if (error) console.error(error);
})
// Finds a port no service is listening on
portscanner.findAPortNotInUseFromList(list, '127.0.0.1', function(error, port) {
// Will return any number between 3000 and 3010 (inclusive), that's not 3005.
// The order is unknown as the port status checks are asynchronous.
console.log('Found a closed port of '+list+' at ' + port)
if (error) console.error(error);
})
})

110 changes: 89 additions & 21 deletions lib/portscanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,24 @@ var portscanner = exports
* open port is found, the value is false.
*/
portscanner.findAPortInUse = function(startPort, endPort, host, callback) {
findAPortWithStatus('open', startPort, endPort, host, callback)
findAPortWithStatus('open', makePortRangeIter(startPort, endPort), host, callback)
}

/**
* Finds the first port with a status of 'open', implying the port is in use and
* there is likely a service listening on it, taking possible ports from the list.
*
* @param {Array<Number>} list - List of ports to check.
* @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.
* - {Number|Boolean} port - The first open port found. Note, this is the
* first port that returns status as 'open', not
* necessarily the first open port checked. If no
* open port is found, the value is false.
*/
portscanner.findAPortInUseFromList = function(list, host, callback) {
findAPortWithStatus('open', new ArrayIter(list), host, callback)
}

/**
Expand All @@ -39,7 +56,24 @@ portscanner.findAPortInUse = function(startPort, endPort, host, callback) {
* closed port is found, the value is false.
*/
portscanner.findAPortNotInUse = function(startPort, endPort, host, callback) {
findAPortWithStatus('closed', startPort, endPort, host, callback)
findAPortWithStatus('closed', makePortRangeIter(startPort, endPort), host, callback)
}

/**
* Finds the first port with a status of 'closed', implying the port is not in
* use, taking possible ports from the list.
*
* @param {Array<Number>} list - List of ports to check.
* @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.
* - {Number|Boolean} port - The first closed port found. Note, this is the
* first port that returns status as 'closed', not
* necessarily the first closed port checked. If no
* closed port is found, the value is false.
*/
portscanner.findAPortNotInUseFromList = function(list, host, callback) {
findAPortWithStatus('closed', new ArrayIter(list), host, callback)
}

/**
Expand Down Expand Up @@ -107,45 +141,79 @@ portscanner.checkPortStatus = function(port, options, callback) {
socket.connect(port, host)
}

function findAPortWithStatus(status, startPort, endPort, host, callback) {
endPort = endPort || 65535


function findAPortWithStatus(status, ports, host, callback) {
var foundPort = false
var numberOfPortsChecked = 0
var port = startPort

// 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)
var hasFoundPortOrCheckedAll = function() {
return foundPort !== false || !ports.hasNext()
}

// Checks the status of the port
var checkNextPort = function(callback) {
var port = ports.next();
// console.log('checking port', port);
portscanner.checkPortStatus(port, host, function(error, statusOfPort) {
numberOfPortsChecked++
if(error != null) return callback(error);

if (statusOfPort === status) {
foundPort = true
callback(error)
}
else {
port++
callback(null)
foundPort = 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) {
async.until(hasFoundPortOrCheckedAll, checkNextPort, function(error) {
if (error) {
callback(error, port)
}
else if (foundPort) {
callback(null, port)
callback(error, null)
}
else {
callback(null, false)
callback(null, foundPort)
}
})
}


function RangeIterIncl(from, to){
this.cur = from;
this.end = to+1;
}

RangeIterIncl.prototype.hasNext = function(){
return this.cur < this.end
}

RangeIterIncl.prototype.next = function(){
return this.cur++
}

function ArrayIter(array){
this.array = array
this.len = array.length
this.idx = 0
}

ArrayIter.prototype.hasNext = function(){
return this.idx < this.len
}

ArrayIter.prototype.next = function(){
return this.array[this.idx++]
}

function makePortRangeIter(from, to){
from = from || 0
to = to || 65535
if(from < to){
return new RangeIterIncl(from, to)
}
else{
return new RangeIterIncl(to, from)
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"checker",
"status"
],
"version": "1.0.0",
"version": "1.0.1",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not bump version in pull request.

And, supporting array of ports needs minor update, not patch update.

"preferGlobal": false,
"homepage": "https://github.com/baalexander/node-portscanner",
"author": [
Expand Down