var getaddrinfo = process.getaddrinfo;
var needsLookup = process.needsLookup;
var EINPROGRESS = process.EINPROGRESS;
+var END_OF_FILE = 42;
function Socket (peerInfo) {
var slice = self.recvBuffer.slice(self.recvBuffer.used,
self.recvBuffer.used + bytesRead);
self.recvBuffer.used += bytesRead;
- self.emit('receive', slice);
+ self.emit('data', slice);
}
};
self.readable = false;
}
// if we didn't find one, take the last
if (!buffer) {
- buffer = self.sendQueue[self.sendQueue.length-1];
+ buffer = self._sendQueueLast();
// if last buffer is used up
if (buffer.length == buffer.used) buffer = self._allocateSendBuffer();
}
};
+Socket.prototype._sendQueueLast = function () {
+ return this.sendQueue.length > 0 ? this.sendQueue[this.sendQueue.length-1]
+ : null;
+};
+
+
// Returns true if all the data was flushed to socket. Returns false if
// something was queued. If data was queued, then the "drain" event will
// signal when it has been finally flushed to socket.
Socket.prototype.send = function (data, encoding) {
var self = this;
+
if (!self.writable) throw new Error('Socket is not writable');
+
+ if (self._sendQueueLast == END_OF_FILE) {
+ throw new Error('socket.close() called already; cannot write.');
+ }
+
if (typeof(data) == 'string') {
self._sendString(data, encoding);
} else {
// Flushes the write buffer out. Emits "drain" if the buffer is empty.
Socket.prototype.flush = function () {
var self = this;
- if (!self.writable) throw new Error('Socket is not writable');
var bytesWritten;
while (self.sendQueue.length > 0) {
+ if (!self.writable) throw new Error('Socket is not writable');
+
var b = self.sendQueue[0];
+ if (b == END_OF_FILE) {
+ self._shutdown();
+ break;
+ }
+
if (b.sent == b.used) {
// this can be improved - save the buffer for later?
self.sendQueue.shift()
this.writeWatcher.stop();
this.readWatcher.stop();
close(this.fd);
- debug('close peer ' + this.fd);
+ debug('close socket ' + this.fd);
this.fd = null;
this.emit('close', exception);
}
Socket.prototype._shutdown = function () {
if (this.writable) {
this.writable = false;
- shutdown(this.fd, "write");
+ shutdown(this.fd, 'write');
}
};
Socket.prototype.close = function () {
- var self = this;
- var closeMethod;
- if (self.readable && self.writable) {
- closeMethod = self._shutdown;
- } else if (!self.readable && self.writable) {
- // already got EOF
- closeMethod = self.forceClose;
- }
- // In the case we've already shutdown write side,
- // but haven't got EOF: ignore. In the case we're
- // fully closed already: ignore.
-
- if (closeMethod) {
- if (self.sendQueueSize == 0) {
- // no queue. just shut down the socket.
- closeMethod();
- } else {
- self.addListener("drain", closeMethod);
+ if (this.writable) {
+ if (this._sendQueueLast() != END_OF_FILE) {
+ this.sendQueue.push(END_OF_FILE);
+ this.flush();
}
}
};
var sys = require("sys");
var net = require("./lib/net");
-var server = new net.Server(function (stream) {
- sys.puts("connection (" + stream.fd + "): "
- + stream.remoteAddress
+var server = new net.Server(function (socket) {
+ sys.puts("connection (" + socket.fd + "): "
+ + socket.remoteAddress
+ " port "
- + stream.remotePort
+ + socket.remotePort
);
sys.puts("server fd: " + server.fd);
- stream.addListener("receive", function (b) {
- stream.send("pong ascii\r\n", "ascii");
- stream.send(b);
- stream.send("pong utf8\r\n", "utf8");
+ socket.addListener("data", function (b) {
+ socket.send("pong ascii\r\n", "ascii");
+ socket.send(b);
+ socket.send("pong utf8\r\n", "utf8");
});
- stream.addListener('drain', function () {
- sys.puts("server-side socket drain");
+ socket.addListener("eof", function () {
+ sys.puts("server peer eof");
+ socket.close();
});
- stream.addListener("eof", function () {
- sys.puts("server peer eof");
- stream.close();
+ socket.addListener('drain', function () {
+ sys.puts("server-side socket drain");
});
});
server.listen(8000);