Net improvements

This commit is contained in:
Kagami Hiiragi 2015-02-17 15:35:40 +03:00
parent 49e4aa4158
commit e52e226662
2 changed files with 29 additions and 53 deletions

View File

@ -91,7 +91,7 @@ TcpTransport.prototype._sendVersion = function() {
}));
};
TcpTransport.prototype._setupClient = function(client, accepted) {
TcpTransport.prototype._setupClient = function(client, incoming) {
var self = this;
self._client = client;
var cache = Buffer(0);
@ -107,8 +107,8 @@ TcpTransport.prototype._setupClient = function(client, accepted) {
client.on("connect", function() {
// NOTE(Kagami): This handler shouldn't be called at all for
// accepted sockets but let's be sure.
if (!accepted) {
// incoming connections but let's be sure.
if (!incoming) {
self.emit("open");
self._sendVersion();
}
@ -155,7 +155,7 @@ TcpTransport.prototype._setupClient = function(client, accepted) {
}
self.send("verack");
verackSent = true;
if (accepted) {
if (incoming) {
self._sendVersion();
} else if (verackReceived) {
self.emit("established");
@ -256,27 +256,21 @@ TcpTransport.prototype.listen = function() {
var server = self._server = net.createServer();
server.listen.apply(server, arguments);
// TODO(Kagami): We may want to specify some limits for number of
// connected users.
var clientIdCounter = 0;
// TODO(Kagami): Limit number of connected clients (220/192 per
// PyBitmessage).
server.on("connection", function(client) {
var addr = client.remoteAddress;
var port = client.remotePort;
if (self._clients[addr]) {
// NOTE(Kagami): Doesn't allow more than one connection per IP.
// This may obstruct people behind NAT but we copy PyBitmessage's
// behavior here.
client.end();
return self.emit("warning", new Error(
unmap(addr) + " was tried to create second connection"
));
}
self._clients[addr] = client;
var id = client.id = clientIdCounter++;
self._clients[id] = client;
client.on("close", function() {
delete self._clients[addr];
delete self._clients[id];
});
var transport = new self.constructor(self);
var accepted = true;
transport._setupClient(client, accepted);
var incoming = true;
transport._setupClient(client, incoming);
var addr = client.remoteAddress;
var port = client.remotePort;
self.emit("connection", transport, unmap(addr), port);
// Emit "open" manually because "connect" for this socket won't be
// fired.
@ -304,8 +298,8 @@ TcpTransport.prototype.send = function() {
TcpTransport.prototype.broadcast = function() {
var data = getmsg(arguments);
if (this._server) {
Object.keys(this._clients).forEach(function(ip) {
this._clients[ip].write(data);
Object.keys(this._clients).forEach(function(id) {
this._clients[id].write(data);
}, this);
} else {
throw new Error("Not listening");
@ -316,8 +310,8 @@ TcpTransport.prototype.close = function() {
if (this._client) {
this._client.end();
} else if (this._server) {
Object.keys(this._clients).forEach(function(ip) {
this._clients[ip].end();
Object.keys(this._clients).forEach(function(id) {
this._clients[id].end();
}, this);
this._server.close();
}

View File

@ -80,7 +80,7 @@ WsTransport.prototype._handleTimeout = function() {
});
};
WsTransport.prototype._setupClient = function(client, accepted) {
WsTransport.prototype._setupClient = function(client, incoming) {
var self = this;
self._client = client;
var verackSent = false;
@ -89,8 +89,8 @@ WsTransport.prototype._setupClient = function(client, accepted) {
client.on("open", function() {
// NOTE(Kagami): This handler shouldn't be called at all for
// accepted sockets but let's be sure.
if (!accepted) {
// incoming connections but let's be sure.
if (!incoming) {
// NOTE(Kagami): We may set timeout only after connection was
// opened because socket may not yet be available when
// `_setupClient` is called.
@ -130,7 +130,7 @@ WsTransport.prototype._setupClient = function(client, accepted) {
}
self.send("verack");
verackSent = true;
if (accepted) {
if (incoming) {
self._sendVersion();
} else if (verackReceived) {
established = true;
@ -185,33 +185,15 @@ WsTransport.prototype.listen = function(options, callback) {
var self = this;
var server = self._server = new WebSocketServer(options, callback);
// TODO(Kagami): We may want to specify some limits for number of
// connected users.
// TODO(Kagami): Limit number of connected clients (220/192 per
// PyBitmessage).
server.on("connection", function(client) {
var addr = client._socket.remoteAddress;
var port = client._remotePort;
var i;
// NOTE(Kagami): O(n) search because `clients` array is already
// provided by `ws` library. We may want to optmize it though and
// also disable `clientTracking` option.
for (i = 0; i < server.clients.length; i++) {
if (server.clients[i] !== client &&
server.clients[i]._socket.remoteAddress === addr) {
// NOTE(Kagami): Doesn't allow more than one connection per IP.
// This may obstruct people behind NAT but we copy
// PyBitmessage's behavior here.
client.close();
return self.emit("warning", new Error(
unmap(addr) + " was tried to create second connection"
));
}
}
var transport = new self.constructor(self);
var accepted = true;
transport._setupClient(client, accepted);
var incoming = true;
transport._setupClient(client, incoming);
transport._handleTimeout();
var addr = client._socket.remoteAddress;
var port = client._socket.remotePort;
self.emit("connection", transport, unmap(addr), port);
// Emit "open" manually because it won't be fired for already opened
// socket.