Created
December 6, 2011 18:53
-
-
Save billywhizz/1439413 to your computer and use it in GitHub Desktop.
minimal node.js tcp server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello Sir,
Thanks for posting such a nice and clean code.
I have some questions as below.
Please help me. (here is my emailid: [email protected])
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();
}
});
},