add setKeepAlive function, which enables and sets the TCP keep-alive timer

This commit is contained in:
Julian Lamb 2010-04-20 19:01:41 -04:00 committed by Ryan Dahl
parent 27ec33aad7
commit 5f8f561d61
4 changed files with 81 additions and 2 deletions

View File

@ -2042,6 +2042,15 @@ Disables the Nagle algorithm. By default TCP connections use the Nagle
algorithm, they buffer data before sending it off. Setting `noDelay` will
immediately fire off data each time `stream.write()` is called.
### stream.setKeepAlive(enable=false, initialDelay)
Enable/disable keep-alive functionality, and optionally set the initial
delay before the first keepalive probe is sent on an idle stream.
Set `initialDelay` (in milliseconds) to set the delay between the last
data packet received and the first keepalive probe. Setting 0 for
initialDelay will leave the value unchanged from the default
(or previous) setting.
## DNS

View File

@ -38,6 +38,7 @@ var read = binding.read;
var write = binding.write;
var toRead = binding.toRead;
var setNoDelay = binding.setNoDelay;
var setKeepAlive= binding.setKeepAlive;
var socketError = binding.socketError;
var getsockname = binding.getsockname;
var errnoException = binding.errnoException;
@ -744,9 +745,17 @@ Stream.prototype.address = function () {
Stream.prototype.setNoDelay = function (v) {
if (this.type == 'tcp') setNoDelay(this.fd, v);
if ((this.type == 'tcp4')||(this.type == 'tcp6')) {
setNoDelay(this.fd, v);
}
};
Stream.prototype.setKeepAlive = function (enable, time) {
if ((this.type == 'tcp4')||(this.type == 'tcp6')) {
var secondDelay = Math.ceil(time/1000);
setKeepAlive(this.fd, enable, secondDelay);
}
};
Stream.prototype.setTimeout = function (msecs) {
timeout.enroll(this, msecs);

View File

@ -1062,11 +1062,43 @@ static Handle<Value> SetNoDelay(const Arguments& args) {
if (r < 0) {
return ThrowException(ErrnoException(errno, "setsockopt"));
}
return Undefined();
}
static Handle<Value> SetKeepAlive(const Arguments& args) {
int r;
HandleScope scope;
bool enable = false;
int time = 0;
FD_ARG(args[0])
if (args.Length() > 0) enable = args[1]->IsTrue();
if (enable == true) {
time = args[2]->Int32Value();
}
int flags = enable ? 1 : 0;
r = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags));
if ((time > 0)&&(r >= 0)) {
#if defined(__APPLE__)
// Mac uses a different setting name than Linux
r = setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, (void *)&time, sizeof(time));
#elif defined(__sun)
// Solaris doesn't support TCP_KEEPIDLE, so do nothing here
#else
// assume anything else uses the Linux/BSD method
r = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&time, sizeof(time));
#endif
}
if (r < 0) {
return ThrowException(ErrnoException(errno, "setsockopt"));
}
return Undefined();
}
//
// G E T A D D R I N F O
//
@ -1287,6 +1319,7 @@ void InitNet2(Handle<Object> target) {
NODE_SET_METHOD(target, "socketError", SocketError);
NODE_SET_METHOD(target, "toRead", ToRead);
NODE_SET_METHOD(target, "setNoDelay", SetNoDelay);
NODE_SET_METHOD(target, "setKeepAlive", SetKeepAlive);
NODE_SET_METHOD(target, "getsockname", GetSockName);
NODE_SET_METHOD(target, "getpeername", GetPeerName);
NODE_SET_METHOD(target, "getaddrinfo", GetAddrInfo);

View File

@ -0,0 +1,28 @@
require("../common");
net = require('net');
var serverConnection;
var echoServer = net.createServer(function (connection) {
serverConnection = connection;
connection.setTimeout(0);
assert.notEqual(connection.setKeepAlive,undefined);
// send a keepalive packet after 1000 ms
connection.setKeepAlive(true,1000);
connection.addListener("end", function () {
connection.end();
});
});
echoServer.listen(PORT);
var clientConnection = net.createConnection(PORT);
clientConnection.setTimeout(0);
setTimeout( function() {
// make sure both connections are still open
assert.equal(serverConnection.readyState,"open");
assert.equal(clientConnection.readyState,"open");
serverConnection.end();
clientConnection.end();
echoServer.close();
}, 1200);