arnaucube
arnaucube/socketioMEANseedPublic Self-hosted repository
socketioMEANseed/www/node_modules/portfinder/lib/portfinder.js
www/node_modules/portfinder/lib/portfinder.jsRaw
  1/*
  2 * portfinder.js: A simple tool to find an open port on the current machine.
  3 *
  4 * (C) 2011, Charlie Robbins
  5 *
  6 */
  7 
  8var fs = require('fs'),
  9    net = require('net'),
 10    path = require('path'),
 11    async = require('async'),
 12    mkdirp = require('mkdirp').mkdirp;
 13
 14//
 15// ### @basePort {Number}
 16// The lowest port to begin any port search from
 17//
 18exports.basePort = 8000;
 19
 20//
 21// ### @basePath {string}
 22// Default path to begin any socket search from
 23//
 24exports.basePath = '/tmp/portfinder'
 25
 26//
 27// ### function getPort (options, callback)
 28// #### @options {Object} Settings to use when finding the necessary port
 29// #### @callback {function} Continuation to respond to when complete.
 30// Responds with a unbound port on the current machine.
 31//
 32exports.getPort = function (options, callback) {
 33  if (!callback) {
 34    callback = options;
 35    options = {}; 
 36  }
 37  
 38  options.port   = options.port   || exports.basePort;
 39  options.host   = options.host   || null;
 40  options.server = options.server || net.createServer(function () {
 41    //
 42    // Create an empty listener for the port testing server.
 43    //
 44  });
 45  
 46  function onListen () {
 47    options.server.removeListener('error', onError);
 48    options.server.close();
 49    callback(null, options.port)
 50  }
 51  
 52  function onError (err) {
 53    options.server.removeListener('listening', onListen);
 54
 55    if (err.code !== 'EADDRINUSE' && err.code !== 'EACCES') {
 56      return callback(err);
 57    }
 58
 59    exports.getPort({
 60      port: exports.nextPort(options.port),
 61      host: options.host,
 62      server: options.server
 63    }, callback);
 64  }
 65
 66  options.server.once('error', onError);
 67  options.server.once('listening', onListen);
 68  options.server.listen(options.port, options.host);
 69};
 70
 71//
 72// ### function getPorts (count, options, callback)
 73// #### @count {Number} The number of ports to find
 74// #### @options {Object} Settings to use when finding the necessary port
 75// #### @callback {function} Continuation to respond to when complete.
 76// Responds with an array of unbound ports on the current machine.
 77//
 78exports.getPorts = function (count, options, callback) {
 79  if (!callback) {
 80    callback = options;
 81    options = {};
 82  }
 83
 84  var lastPort = null;
 85  async.timesSeries(count, function(index, asyncCallback) {
 86    if (lastPort) {
 87      options.port = exports.nextPort(lastPort);
 88    }
 89
 90    exports.getPort(options, function (err, port) {
 91      if (err) {
 92        asyncCallback(err);
 93      } else {
 94        lastPort = port;
 95        asyncCallback(null, port);
 96      }
 97    });
 98  }, callback);
 99};
100
101//
102// ### function getSocket (options, callback)
103// #### @options {Object} Settings to use when finding the necessary port
104// #### @callback {function} Continuation to respond to when complete.
105// Responds with a unbound socket using the specified directory and base
106// name on the current machine.
107//
108exports.getSocket = function (options, callback) {
109  if (!callback) {
110    callback = options;
111    options = {};
112  }
113
114  options.mod  = options.mod    || 0755;
115  options.path = options.path   || exports.basePath + '.sock';
116  
117  //
118  // Tests the specified socket
119  //
120  function testSocket () {
121    fs.stat(options.path, function (err) {
122      //
123      // If file we're checking doesn't exist (thus, stating it emits ENOENT),
124      // we should be OK with listening on this socket.
125      //
126      if (err) {
127        if (err.code == 'ENOENT') {
128          callback(null, options.path);
129        }
130        else {
131          callback(err);
132        }
133      }
134      else {
135        //
136        // This file exists, so it isn't possible to listen on it. Lets try
137        // next socket.
138        //
139        options.path = exports.nextSocket(options.path);
140        exports.getSocket(options, callback);
141      }
142    });
143  }
144  
145  //
146  // Create the target `dir` then test connection
147  // against the socket.
148  //
149  function createAndTestSocket (dir) {
150    mkdirp(dir, options.mod, function (err) {
151      if (err) {
152        return callback(err);
153      }
154      
155      options.exists = true;
156      testSocket();
157    });
158  }
159  
160  //
161  // Check if the parent directory of the target
162  // socket path exists. If it does, test connection
163  // against the socket. Otherwise, create the directory
164  // then test connection. 
165  //
166  function checkAndTestSocket () {
167    var dir = path.dirname(options.path);
168    
169    fs.stat(dir, function (err, stats) {
170      if (err || !stats.isDirectory()) {
171        return createAndTestSocket(dir);
172      }
173
174      options.exists = true;
175      testSocket();
176    });
177  }
178  
179  //
180  // If it has been explicitly stated that the 
181  // target `options.path` already exists, then 
182  // simply test the socket.
183  //
184  return options.exists 
185    ? testSocket()
186    : checkAndTestSocket();
187};
188
189//
190// ### function nextPort (port)
191// #### @port {Number} Port to increment from.
192// Gets the next port in sequence from the 
193// specified `port`.
194//
195exports.nextPort = function (port) {
196  return port + 1;
197};
198
199//
200// ### function nextSocket (socketPath)
201// #### @socketPath {string} Path to increment from
202// Gets the next socket path in sequence from the 
203// specified `socketPath`.
204//
205exports.nextSocket = function (socketPath) {
206  var dir = path.dirname(socketPath),
207      name = path.basename(socketPath, '.sock'),
208      match = name.match(/^([a-zA-z]+)(\d*)$/i),
209      index = parseInt(match[2]),
210      base = match[1];
211  
212  if (isNaN(index)) {
213    index = 0;
214  }
215  
216  index += 1;
217  return path.join(dir, base + index + '.sock');
218};