minimal node.js tcp server
var TCPServer = require("./lib/tcp").Server;
var s = new TCPServer({
host: "0.0.0.0",
port: 80,
backlog: 128,
secure: true,
maxconn: 10000,
credentials: {
cert: require("fs").readFileSync("./cert.pem").toString(),
key: require("fs").readFileSync("./key.pem").toString(),
ciphers: "RC4-SHA:AES128-SHA:AES256-SHA"
},
nodelay: false,
keepalive: {
on: false,
delay: 30000
},
onConnect: function() {
// "this" object has the client socket
console.log("connect");
},
onData: function(buffer, start, len) {
// "this" object has the client socket
var socket = this;
socket.send(buffer.slice(start, start + len), null, function(status, handle, r, buffer) {
if(status != 0) {
socket.destroy();
}
});
},
onEnd: function() {
// "this" object has the client socket
console.log("end");
},
onError: function(err) {
// "this" object has the client socket
console.log("error");
console.log(err);
var ex = this.destroy();
if(ex) console.log(ex);
}
});
s.onError = function(err) {
console.log("server.error");
console.log(err);
}
s.listen();
var TCP = process.binding("tcp_wrap").TCP;
try {
var crypto = process.binding("crypto");
var SecureContext = crypto.SecureContext;
} catch (e) {
throw new Error("node.js not compiled with openssl crypto support.");
}
function noop() {};
function createCredentials(key, cert, ciphers) {
var c = new SecureContext();
c.init();
c.setKey(key);
c.setCert(cert);
if(ciphers) c.setCiphers(ciphers);
c.addRootCerts();
c.context = c;
return c;
}
function TCPServer(options, handle) {
var _server = this;
var socket = handle?handle:new TCP();
options.maxconn = options.maxconn || 1000;
socket.onconnection = function(client) {
if(!client) {
if(_server.onError) _server.onError(new Error("Accept Failed: " + errno));
return;
}
var pair;
var send;
["onEnd", "onConnect", "onError", "onData"].forEach(function(foo) {
client[foo] = options[foo]?options[foo]:noop;
});
if(options.secure) {
send = function(buff, encoding, cb) {
if(encoding) {
buff = new Buffer(buff, encoding);
}
var wr = pair.cleartext.write(buff);
if (!wr) {
shutdown();
return false;
}
wr.oncomplete = cb;
return true;
}
}
else {
send = function(buff, encoding, cb) {
if(encoding) {
buff = new Buffer(buff, encoding);
}
var wr = client.write(buff);
if (!wr) {
shutdown();
return false;
}
wr.oncomplete = cb;
return true;
}
}
function shutdown() {
try {
client.readStop();
client.onread = noop;
var shutdownReq = client.shutdown();
shutdownReq.oncomplete = function(status, handle, req) {
client.onEnd.apply(client);
handle.close();
};
return null;
}
catch(ex) {
return ex;
}
}
if(options.nodelay) client.setNoDelay();
if(options.keepalive && options.keepalive.on) {
client.setKeepAlive(true, options.keepalive.delay);
}
client.destroy = shutdown;
client.send = send;
if(options.secure) {
client.onread = function(buffer, offset, length) {
if(!buffer) {
shutdown();
}
else {
var ret = pair.encrypted.write(buffer.slice(offset, offset + length));
}
};
var serverCreds = createCredentials(options.credentials.key, options.credentials.cert, options.credentials.ciphers);
pair = require("tls").createSecurePair(serverCreds, true);
pair.on("secure", function() {
client.onConnect.apply(client);
});
pair.encrypted.on("data", function(chunk) {
var wr = client.write(chunk);
wr.oncomplete = function(status, handle, req, buffer) {
};
});
pair.cleartext.on("data", function(chunk) {
client.onData.call(client, chunk, 0, chunk.length);
});
}
else {
client.onread = function(buffer, offset, length) {
if(!buffer) {
shutdown();
return;
}
client.onData.call(client, buffer, offset, length);
};
client.onConnect.apply(client);
}
client.readStart();
};
_server.listen = function() {
if(handle) {
r = handle.listen(options.backlog || 128);
return;
}
var r = socket.bind(options.host, options.port);
if(r) {
if(_server.onError) _server.onError(new Error("Bind Failed:" + errno));
socket.close();
}
else {
r = socket.listen(options.backlog || 128);
if(r < 0) {
if(_server.onError) _server.onError(new Error("Listen Failed: " + errno));
socket.close();
}
}
}
}
exports.Server = TCPServer;