diff --git a/lib/sorting-hat.js b/lib/sorting-hat.js index 184d850..576eda2 100644 --- a/lib/sorting-hat.js +++ b/lib/sorting-hat.js @@ -73,7 +73,7 @@ module.exports.assign = function (state, tun, cb) { cb(null, false); return; } - cb(null, getNetConn(sshPort)); + getNetConn(sshPort, cb); } var handlers = {}; @@ -86,6 +86,7 @@ module.exports.assign = function (state, tun, cb) { state.httpRedirectServer = require('http').createServer(state.greenlock.middleware(state.redirectHttps)); } state.httpRedirectServer.emit('connection', socket); + process.nextTick(function () { socket.resume(); }); }; handlers.https = function (tlsSocket) { console.log('Encrypted', tlsSocket.encrypted, tlsSocket.remoteAddress, tlsSocket.remotePort); @@ -98,6 +99,7 @@ module.exports.assign = function (state, tun, cb) { }); } state.defaultHttpServer.emit('connection', tlsSocket); + process.nextTick(function () { tlsSocket.resume(); }); }; function getNetConn(port, cb) { @@ -113,19 +115,16 @@ module.exports.assign = function (state, tun, cb) { , remoteAddress: tun.address , remotePort: tun.port }; - var conn = net.createConnection(netOpts); - conn.once('connect', function () { + var conn = net.createConnection(netOpts, function () { // this will happen before 'data' or 'readable' is triggered // We use the data from the netOpts object so that the createConnection function has // the oppurtunity of removing/changing it if it wants/needs to handle it differently. cb(null, conn); - conn.removeListener('error', onError); + cb = function () {}; // for error events + }); + conn.on('error', function (err) { + cb(err); }); - function onError(err) { - if (cb) { cb(err); } - } - conn.on('error', onError); - return conn; } function redirectHttp(cb) { @@ -240,21 +239,16 @@ module.exports.assign = function (state, tun, cb) { function invokeHandler(conf, tlsSocket, tun, id) { if (parseInt(conf.handler, 10)) { // TODO http-proxy with proper headers and ws support - //tlsSocket.pause(); - var conn = getNetConn(conf.handler, function (err/*, conn*/) { + getNetConn(conf.handler, function (err, conn) { + process.nextTick(function () { tlsSocket.resume(); }); if (err) { - console.log("[DEBUG] need to handle error"); require('./handlers/local-app-error.js')({ handler: conf.handler, socket: tlsSocket }); return; } console.info("Port-Forwarding '" + (tun.name || tun.serviceport) + "' to '" + conf.handler + "'"); - //conn.pipe(tlsSocket); - //tlsSocket.pipe(conn); - //tlsSocket.resume(); + conn.pipe(tlsSocket); + tlsSocket.pipe(conn); }); - conn.pipe(tlsSocket); - tlsSocket.pipe(conn); - tlsSocket.resume(); return; } var handle = tun.name || tun.port; @@ -272,6 +266,7 @@ module.exports.assign = function (state, tun, cb) { tlsSocket._id = id; if (handlerservers[conf.handler]) { handlerservers[conf.handler].emit('connection', tlsSocket); + process.nextTick(function () { tlsSocket.resume(); }); return; } @@ -299,6 +294,7 @@ module.exports.assign = function (state, tun, cb) { if (handler) { handlerservers[conf.handler] = http.createServer(handler); handlerservers[conf.handler].emit('connection', tlsSocket); + process.nextTick(function () { tlsSocket.resume(); }); return; } @@ -334,8 +330,6 @@ module.exports.assign = function (state, tun, cb) { tlsSocket._handle.onread(firstChunk.length, firstChunk); trySsh({ data: firstChunk }, function (err, conn) { - process.nextTick(function () { tlsSocket.resume(); }); - if (conn) { conn.pipe(tlsSocket); tlsSocket.pipe(conn); diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..6e8a418 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,10 @@ +There are a number of conditions and whatnot that must be tested in more-or-less real-world conditions. + +telebit http 3000 // have an app listening on localhost:3000 +telebit http 4545 // do not have an app listening + +telebit ssh auto // do have ssh listening on localhost:22 +telebit ssh 4545 // do have ssh listenening + +telebit tcp 3000 // have an echo server listening on localhost:3000 +telebit tcp 4545 // no server listening diff --git a/tests/echo.js b/tests/echo.js new file mode 100644 index 0000000..507b425 --- /dev/null +++ b/tests/echo.js @@ -0,0 +1,27 @@ +'use strict'; + +var net = require('net'); +var server = net.createServer(function (conn) { + function echo(chunk) { + conn.write(chunk); + if (chunk.length <= 10 && /\b(q|quit|end|cancel)\b/i.test(chunk.toString('utf8'))) { + conn.end(); + conn.removeListener('data', echo); + } + } + conn.on('data', echo); + // NOTE: early versions of telebit do not support a 'connection' event + // and therefore will say hello after the first message from the client + conn.write( + "[Echo Server] Hello! I'm an echo server.\n" + + "[Echo Server] I try to be your friend but when I see things like q|quit|end|cancel, I give up.\n" + ); +}); +server.on('error', function (err) { + console.error("[echo server]"); + console.error(err); +}); +server.listen(process.argv[2] || 3000, function () { + console.info("Listening on", this.address()); + console.info('ctrl+c to cancel'); +});