Skip to content

Instantly share code, notes, and snippets.

@billywhizz
Created December 6, 2011 18:53
Show Gist options
  • Save billywhizz/1439413 to your computer and use it in GitHub Desktop.
Save billywhizz/1439413 to your computer and use it in GitHub Desktop.
minimal node.js tcp server
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;
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();
@anilt11
Copy link

anilt11 commented Mar 7, 2012

Hello Sir,

Thanks for posting such a nice and clean code.

I have some questions as below.

  1. socket.sent in below code spinnet is sending data or receiving data? I dont want to send data back to the sender. I only want to receive data from sender and send it to all other connected clients(optionally).
  2. Also, want to identify connected clients by IP or any other means.

Please help me. (here is my emailid: anilt11@yahoo.com)

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();
}
});

},

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment