Skip to content
This repository has been archived by the owner on Oct 30, 2018. It is now read-only.

Commit

Permalink
Merge pull request #466 from bookchin/master
Browse files Browse the repository at this point in the history
v4.0.0-rc.6
  • Loading branch information
bookchin committed Sep 27, 2016
2 parents d07b284 + fd059be commit 57b2c79
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 3 deletions.
3 changes: 3 additions & 0 deletions lib/network/index.js
Expand Up @@ -40,6 +40,7 @@ var TriggerManager = require('../sips').SIP0003.TriggerManager;
* @param {Number} options.rpcPort - Listening port for RPC
* @param {Boolean} options.doNotTraverseNat - Skip NAT traversal strategies
* @param {Number} options.maxTunnels - Max number of tunnels to provide
* @param {Number} options.maxConnections - Max concurrent connections
* @param {Number} options.tunnelServerPort - Port for tunnel server to use
* @param {Object} options.tunnelGatewayRange
* @param {Number} options.tunnelGatewayRange.min - Min port for gateway bind
Expand Down Expand Up @@ -121,6 +122,7 @@ Network.DEFAULTS = {
rpcPort: 4000,
doNotTraverseNat: false,
maxTunnels: 3,
maxConnections: 100,
tunnelServerPort: 4001,
tunnelGatewayRange: { min: 4002, max: 4004 }
};
Expand Down Expand Up @@ -373,6 +375,7 @@ Network.prototype._initNetworkInterface = function() {
logger: this._logger,
cors: true,
maxTunnels: this._options.maxTunnels,
maxConnections: this._options.maxConnections,
tunnelServerPort: this._options.tunnelServerPort,
tunnelGatewayRange: this._options.tunnelGatewayRange,
doNotTraverseNat: this._options.doNotTraverseNat
Expand Down
38 changes: 36 additions & 2 deletions lib/network/transport.js
Expand Up @@ -24,6 +24,7 @@ var ContactChecker = require('./contact-checker');
* @param {Object} options.tunnelGatewayRange
* @param {Number} options.tunnelGatewayRange.min - Min port for gateway bind
* @param {Number} options.tunnelGatewayRange.max - Max port for gateway bind
* @param {Number} options.maxConnections - Limit concurrent connections
*/
function Transport(contact, options) {
if (!(this instanceof Transport)) {
Expand All @@ -36,6 +37,8 @@ function Transport(contact, options) {
this._tunnelServerPort = options.tunnelServerPort || 0;
this._doNotTraverseNat = options.doNotTraverseNat;
this._tunnelGatewayRange = options.tunnelGatewayRange;
this._numConnections = 0;
this._maxConnections = options.maxConnections;

kad.transports.HTTP.call(this, contact, options);
this._bindTunnelServer();
Expand All @@ -45,9 +48,15 @@ Transport.DEFAULTS = {
maxTunnels: 3,
tunnelServerPort: 0,
doNotTraverseNat: false,
tunnelGatewayRange: { min: 0, max: 0 }
tunnelGatewayRange: { min: 0, max: 0 },
maxConnections: 100
};

/**
* Triggered when the max connections limit is reached
* @event Transport#connectionLimitReached
*/

inherits(Transport, kad.transports.HTTP);

/**
Expand All @@ -68,7 +77,9 @@ Transport.prototype._open = function(callback) {
ip.isPublic(self._contact.address) ? 'public' : 'private'
);

return kad.transports.HTTP.prototype._open.call(self, callback);
kad.transports.HTTP.prototype._open.call(self, callback);
self._setLimitOnConnections();
return;
}

self._requiresTraversal = true;
Expand Down Expand Up @@ -100,6 +111,29 @@ Transport.prototype._open = function(callback) {
_traverseNat();
});
});
self._setLimitOnConnections();
};

/**
* Sets a limit to the number of concurrent connections
* @private
*/
Transport.prototype._setLimitOnConnections = function() {
var self = this;

this._server.on('connection', function(socket) {
if (self._numConnections >= self._maxConnections) {
self._log.warn('connection limit reached, destroying socket');
socket.destroy();
return self.emit('connectionLimitReached');
}

socket.on('close', function() {
self._numConnections--;
});

self._numConnections++;
});
};

/**
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "storj-lib",
"version": "4.0.0-rc.5",
"version": "4.0.0-rc.6",
"description": "implementation of the storj protocol for node.js and the browser",
"main": "index.js",
"directories": {
Expand Down
38 changes: 38 additions & 0 deletions test/network/transport.unit.js
Expand Up @@ -7,6 +7,7 @@ var Contact = require('../../lib/network/contact');
var KeyPair = require('../../lib/crypto-tools/keypair');
var proxyquire = require('proxyquire');
var kad = require('kad');
var EventEmitter = require('events').EventEmitter;

describe('Network/Transport', function() {

Expand All @@ -25,6 +26,43 @@ describe('Network/Transport', function() {

});

describe('#_setLimitOnConnections', function() {

var server = new EventEmitter();
var transport = new EventEmitter();
transport._numConnections = 0;
transport._maxConnections = 1;
transport._server = server;
transport._log = { warn: sinon.stub() };

it('should inc the num connections and dec on close', function(done) {
var socket = new EventEmitter();
Transport.prototype._setLimitOnConnections.call(transport);
server.emit('connection', socket);
setImmediate(function() {
expect(transport._numConnections).to.equal(1);
socket.emit('close');
setImmediate(function() {
expect(transport._numConnections).to.equal(0);
done();
});
});
});

it('should destroy sockets after limit', function(done) {
var socket = { destroy: sinon.stub() };
transport._numConnections = 1;
Transport.prototype._setLimitOnConnections.call(transport);
server.emit('connection', socket);
setImmediate(function() {
expect(transport._log.warn.called).to.equal(true);
expect(socket.destroy.called).to.equal(true);
done();
});
});

});

describe('#_open', function() {

it('should attempt to forward port with upnp', function(done) {
Expand Down

0 comments on commit 57b2c79

Please sign in to comment.