|
|
@ -59,7 +59,7 @@ exports.connect = exports.createConnection = function(port /* [host], [cb] */) { |
|
|
|
|
|
|
|
/* called when creating new Socket, or when re-using a closed Socket */ |
|
|
|
function initSocketHandle(self) { |
|
|
|
self._pendingWriteReqs = 0; |
|
|
|
self._writeRequests = []; |
|
|
|
|
|
|
|
self._flags = 0; |
|
|
|
self._connectQueueSize = 0; |
|
|
@ -237,7 +237,7 @@ Socket.prototype.destroySoon = function() { |
|
|
|
this.writable = false; |
|
|
|
this._flags |= FLAG_DESTROY_SOON; |
|
|
|
|
|
|
|
if (this._pendingWriteReqs == 0) { |
|
|
|
if (this._writeRequests.length == 0) { |
|
|
|
this.destroy(); |
|
|
|
} |
|
|
|
}; |
|
|
@ -342,42 +342,29 @@ Socket.prototype.setEncoding = function(encoding) { |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
Socket.prototype._getpeername = function() { |
|
|
|
if (!this._handle || !this._handle.getpeername) { |
|
|
|
return {}; |
|
|
|
} |
|
|
|
if (!this._peername) { |
|
|
|
this._peername = this._handle.getpeername(); |
|
|
|
} |
|
|
|
return this._peername; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
Socket.prototype.__defineGetter__('remoteAddress', function() { |
|
|
|
return this._getpeername().address; |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
Socket.prototype.__defineGetter__('remotePort', function() { |
|
|
|
return this._getpeername().port; |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
* Arguments data, [encoding], [cb] |
|
|
|
*/ |
|
|
|
Socket.prototype.write = function(data, arg1, arg2) { |
|
|
|
var encoding, cb; |
|
|
|
Socket.prototype.write = function(data /* [encoding], [fd], [cb] */) { |
|
|
|
var encoding, fd, cb; |
|
|
|
|
|
|
|
// parse arguments
|
|
|
|
if (arg1) { |
|
|
|
if (typeof arg1 === 'string') { |
|
|
|
encoding = arg1; |
|
|
|
cb = arg2; |
|
|
|
} else if (typeof arg1 === 'function') { |
|
|
|
cb = arg1; |
|
|
|
if (typeof arguments[3] == 'function') { |
|
|
|
cb = arguments[3]; |
|
|
|
fd = arguments[2]; |
|
|
|
encoding = arguments[1]; |
|
|
|
} else if (typeof arguments[2] == 'function') { |
|
|
|
cb = arguments[2]; |
|
|
|
if (typeof arguments[1] == 'number') { |
|
|
|
fd = arguments[1]; |
|
|
|
} else { |
|
|
|
throw new Error("bad arg"); |
|
|
|
encoding = arguments[1]; |
|
|
|
} |
|
|
|
} else if (typeof arguments[1] == 'function') { |
|
|
|
cb = arguments[1]; |
|
|
|
} else { |
|
|
|
if (typeof arguments[1] == 'number') { |
|
|
|
fd = arguments[1]; |
|
|
|
} else { |
|
|
|
encoding = arguments[1]; |
|
|
|
fd = arguments[2]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -392,9 +379,9 @@ Socket.prototype.write = function(data, arg1, arg2) { |
|
|
|
if (this._connecting) { |
|
|
|
this._connectQueueSize += data.length; |
|
|
|
if (this._connectQueue) { |
|
|
|
this._connectQueue.push([data, encoding, cb]); |
|
|
|
this._connectQueue.push([data, encoding, fd, cb]); |
|
|
|
} else { |
|
|
|
this._connectQueue = [[data, encoding, cb]]; |
|
|
|
this._connectQueue = [[data, encoding, fd, cb]]; |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
@ -408,7 +395,7 @@ Socket.prototype.write = function(data, arg1, arg2) { |
|
|
|
|
|
|
|
writeReq.oncomplete = afterWrite; |
|
|
|
writeReq.cb = cb; |
|
|
|
this._pendingWriteReqs++; |
|
|
|
this._writeRequests.push(writeReq); |
|
|
|
|
|
|
|
return this._handle.writeQueueSize == 0; |
|
|
|
}; |
|
|
@ -423,9 +410,10 @@ function afterWrite(status, handle, req, buffer) { |
|
|
|
} |
|
|
|
// TODO check status.
|
|
|
|
|
|
|
|
self._pendingWriteReqs--; |
|
|
|
var req_ = self._writeRequests.shift(); |
|
|
|
assert.equal(req, req_); |
|
|
|
|
|
|
|
if (self._pendingWriteReqs == 0) { |
|
|
|
if (self._writeRequests.length == 0) { |
|
|
|
// TODO remove all uses of ondrain - this is not a good hack.
|
|
|
|
if (self.ondrain) self.ondrain(); |
|
|
|
self.emit('drain'); |
|
|
@ -433,7 +421,7 @@ function afterWrite(status, handle, req, buffer) { |
|
|
|
|
|
|
|
if (req.cb) req.cb(); |
|
|
|
|
|
|
|
if (self._pendingWriteReqs == 0 && self._flags & FLAG_DESTROY_SOON) { |
|
|
|
if (self._writeRequests.length == 0 && self._flags & FLAG_DESTROY_SOON) { |
|
|
|
self.destroy(); |
|
|
|
} |
|
|
|
} |
|
|
@ -679,11 +667,17 @@ Server.prototype.listen = function() { |
|
|
|
|
|
|
|
var port = toPort(arguments[0]); |
|
|
|
|
|
|
|
var TCP = process.binding('tcp_wrap').TCP |
|
|
|
|
|
|
|
if (arguments.length == 0 || typeof arguments[0] == 'function') { |
|
|
|
// Don't bind(). OS will assign a port with INADDR_ANY.
|
|
|
|
// The port can be found with server.address()
|
|
|
|
listen(self, null, null); |
|
|
|
|
|
|
|
} else if (arguments[0] instanceof TCP) { |
|
|
|
self._handle = arguments[0]; |
|
|
|
listen(self, null, -1, -1); |
|
|
|
|
|
|
|
} else if (isPipeName(arguments[0])) { |
|
|
|
// UNIX socket or Windows pipe.
|
|
|
|
listen(self, arguments[0], -1, -1); |
|
|
@ -712,6 +706,7 @@ Server.prototype.address = function() { |
|
|
|
function onconnection(clientHandle) { |
|
|
|
var handle = this; |
|
|
|
var self = handle.socket; |
|
|
|
var peername; |
|
|
|
|
|
|
|
debug('onconnection'); |
|
|
|
|
|
|
@ -725,12 +720,29 @@ function onconnection(clientHandle) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// Todo: implement this for unix sockets
|
|
|
|
if (clientHandle.getpeername) { |
|
|
|
peername = clientHandle.getpeername(); |
|
|
|
if (!peername.address || !peername.port) { |
|
|
|
var err = errnoException(errno, 'accept'); |
|
|
|
clientHandle.close(); |
|
|
|
self.emit('error', err); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var socket = new Socket({ |
|
|
|
handle: clientHandle, |
|
|
|
allowHalfOpen: self.allowHalfOpen |
|
|
|
}); |
|
|
|
socket.readable = socket.writable = true; |
|
|
|
|
|
|
|
if (peername) { |
|
|
|
socket.remoteAddress = peername.address; |
|
|
|
socket.remotePort = peername.port; |
|
|
|
// TODO: set family as well
|
|
|
|
} |
|
|
|
|
|
|
|
socket.resume(); |
|
|
|
|
|
|
|
self.connections++; |
|
|
|