forked from coolaj86/telebit.js
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
3fa6d15848 | |||
73c4444b51 | |||
687b2a3567 | |||
fb8aa998b3 | |||
4a1f020100 | |||
e72a5f1f56 | |||
3c068debc0 | |||
bd8d32d8ec | |||
78407f2a3e |
@ -790,6 +790,9 @@ var parsers = {
|
||||
answers[parts[0]] = parts[1];
|
||||
});
|
||||
|
||||
if (answers.relay) {
|
||||
console.info("using --relay " + answers.relay);
|
||||
}
|
||||
// things that aren't straight-forward copy-over
|
||||
if (!answers.advanced && !answers.relay) {
|
||||
answers.relay = 'telebit.cloud';
|
||||
|
@ -52,10 +52,15 @@ function _connect(state) {
|
||||
+ "(" + clientHandlers.count() + " clients)");
|
||||
|
||||
conn.tunnelCid = cid;
|
||||
conn.tunnelRead = tun.data.byteLength;
|
||||
conn.tunnelWritten = 0;
|
||||
if (tun.data) {
|
||||
conn.tunnelRead = tun.data.byteLength;
|
||||
} else {
|
||||
conn.tunnelRead = 0;
|
||||
}
|
||||
conn.tunnelWritten = 0;
|
||||
|
||||
conn.on('data', function onLocalData(chunk) {
|
||||
//var chunk = conn.read();
|
||||
if (conn.tunnelClosing) {
|
||||
console.warn("[onLocalData] received data for '"+cid+"' over socket after connection was ended");
|
||||
return;
|
||||
@ -67,8 +72,10 @@ function _connect(state) {
|
||||
// down the data we are getting to send over. We also want to pause all active connections
|
||||
// if any connections are paused to make things more fair so one connection doesn't get
|
||||
// stuff waiting for all other connections to finish because it tried writing near the border.
|
||||
var bufSize = wsHandlers.sendMessage(Packer.pack(tun, chunk));
|
||||
if (pausedClients.length || bufSize > 1024*1024) {
|
||||
var bufSize = wsHandlers.sendMessage(Packer.packHeader(tun, chunk));
|
||||
// Sending 2 messages instead of copying the buffer
|
||||
var bufSize2 = wsHandlers.sendMessage(chunk);
|
||||
if (pausedClients.length || (bufSize + bufSize2) > 1024*1024) {
|
||||
// console.log('[onLocalData] paused connection', cid, 'to allow websocket to catch up');
|
||||
conn.pause();
|
||||
pausedClients.push(conn);
|
||||
@ -80,14 +87,15 @@ function _connect(state) {
|
||||
console.info("[onLocalEnd] connection '" + cid + "' ended, will probably close soon");
|
||||
conn.tunnelClosing = true;
|
||||
if (!sentEnd) {
|
||||
wsHandlers.sendMessage(Packer.pack(tun, null, 'end'));
|
||||
wsHandlers.sendMessage(Packer.packHeader(tun, null, 'end'));
|
||||
sentEnd = true;
|
||||
}
|
||||
});
|
||||
conn.on('error', function onLocalError(err) {
|
||||
console.info("[onLocalError] connection '" + cid + "' errored:", err);
|
||||
if (!sentEnd) {
|
||||
wsHandlers.sendMessage(Packer.pack(tun, {message: err.message, code: err.code}, 'error'));
|
||||
var packBody = true;
|
||||
wsHandlers.sendMessage(Packer.packHeader(tun, {message: err.message, code: err.code}, 'error', packBody));
|
||||
sentEnd = true;
|
||||
}
|
||||
});
|
||||
@ -95,7 +103,7 @@ function _connect(state) {
|
||||
delete localclients[cid];
|
||||
console.log('[onLocalClose] closed "' + cid + '" read:'+conn.tunnelRead+', wrote:'+conn.tunnelWritten+' (' + clientHandlers.count() + ' clients)');
|
||||
if (!sentEnd) {
|
||||
wsHandlers.sendMessage(Packer.pack(tun, null, hadErr && 'error' || 'end'));
|
||||
wsHandlers.sendMessage(Packer.packHeader(tun, null, hadErr && 'error' || 'end'));
|
||||
sentEnd = true;
|
||||
}
|
||||
});
|
||||
@ -119,11 +127,13 @@ function _connect(state) {
|
||||
conn.tunnelRead += opts.data.byteLength;
|
||||
|
||||
if (!conn.remotePaused && conn.bufferSize > 1024*1024) {
|
||||
wsHandlers.sendMessage(Packer.pack(opts, conn.tunnelRead, 'pause'));
|
||||
var packBody = true;
|
||||
wsHandlers.sendMessage(Packer.packHeader(opts, conn.tunnelRead, 'pause', packBody));
|
||||
conn.remotePaused = true;
|
||||
|
||||
conn.once('drain', function () {
|
||||
wsHandlers.sendMessage(Packer.pack(opts, conn.tunnelRead, 'resume'));
|
||||
var packBody = true;
|
||||
wsHandlers.sendMessage(Packer.packHeader(opts, conn.tunnelRead, 'resume', packBody));
|
||||
conn.remotePaused = false;
|
||||
});
|
||||
}
|
||||
@ -188,7 +198,8 @@ function _connect(state) {
|
||||
var cmd = [id, name].concat(Array.prototype.slice.call(arguments, 1));
|
||||
if (state.debug) { console.log('[DEBUG] command sending', cmd); }
|
||||
|
||||
wsHandlers.sendMessage(Packer.pack(null, cmd, 'control'));
|
||||
var packBody = true;
|
||||
wsHandlers.sendMessage(Packer.packHeader(null, cmd, 'control', packBody));
|
||||
setTimeout(function () {
|
||||
if (pendingCommands[id]) {
|
||||
console.warn('command', name, id, 'timed out');
|
||||
@ -236,6 +247,23 @@ function _connect(state) {
|
||||
|
||||
var connCallback;
|
||||
|
||||
function hyperPeek(tun) {
|
||||
var m;
|
||||
var str;
|
||||
if (tun.data) {
|
||||
if ('http' === tun.service) {
|
||||
str = tun.data.toString();
|
||||
m = str.match(/(?:^|[\r\n])Host: ([^\r\n]+)[\r\n]*/im);
|
||||
tun._name = tun._hostname = (m && m[1].toLowerCase() || '').split(':')[0];
|
||||
}
|
||||
else if ('https' === tun.service || 'tls' === tun.service) {
|
||||
tun._name = tun._servername = sni(tun.data);
|
||||
} else {
|
||||
tun._name = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var packerHandlers = {
|
||||
oncontrol: function (opts) {
|
||||
var cmd, err;
|
||||
@ -294,27 +322,18 @@ function _connect(state) {
|
||||
err = { message: 'unknown command "'+cmd[1]+'"', code: 'E_UNKNOWN_COMMAND' };
|
||||
}
|
||||
|
||||
wsHandlers.sendMessage(Packer.pack(null, [-cmd[0], err], 'control'));
|
||||
var packBody = true;
|
||||
wsHandlers.sendMessage(Packer.packHeader(null, [-cmd[0], err], 'control', packBody));
|
||||
}
|
||||
|
||||
, onmessage: function (tun) {
|
||||
, onconnection: function (tun) {
|
||||
var cid = tun._id = Packer.addrToId(tun);
|
||||
var str;
|
||||
var m;
|
||||
|
||||
if ('http' === tun.service) {
|
||||
str = tun.data.toString();
|
||||
m = str.match(/(?:^|[\r\n])Host: ([^\r\n]+)[\r\n]*/im);
|
||||
tun._name = tun._hostname = (m && m[1].toLowerCase() || '').split(':')[0];
|
||||
}
|
||||
else if ('https' === tun.service || 'tls' === tun.service) {
|
||||
tun._name = tun._servername = sni(tun.data);
|
||||
} else {
|
||||
tun._name = '';
|
||||
}
|
||||
|
||||
if (clientHandlers.write(cid, tun)) { return; }
|
||||
// this data should have been gathered already as part of the proxy protocol
|
||||
// but if it's available again here we can double check
|
||||
hyperPeek(tun);
|
||||
|
||||
// TODO use readable streams instead
|
||||
wstunneler.pause();
|
||||
require(state.sortingHat).assign(state, tun, function (err, conn) {
|
||||
if (err) {
|
||||
@ -328,6 +347,18 @@ function _connect(state) {
|
||||
});
|
||||
}
|
||||
|
||||
, onmessage: function (tun) {
|
||||
var cid = tun._id = Packer.addrToId(tun);
|
||||
var handled;
|
||||
|
||||
hyperPeek(tun);
|
||||
|
||||
handled = clientHandlers.write(cid, tun);
|
||||
|
||||
// quasi backwards compat
|
||||
if (!handled) { console.log("[debug] did not get 'connection' event"); packerHandlers.onconnection(tun); }
|
||||
}
|
||||
|
||||
, onpause: function (opts) {
|
||||
var cid = Packer.addrToId(opts);
|
||||
if (localclients[cid]) {
|
||||
@ -338,7 +369,8 @@ function _connect(state) {
|
||||
console.log('[TunnelPause] remote tried pausing finished connection', cid);
|
||||
// Often we have enough latency that we've finished sending before we're told to pause, so
|
||||
// don't worry about sending back errors, since we won't be sending data over anyway.
|
||||
// wsHandlers.sendMessage(Packer.pack(opts, {message: 'no matching connection', code: 'E_NO_CONN'}, 'error'));
|
||||
// var packBody = true;
|
||||
// wsHandlers.sendMessage(Packer.packHeader(opts, {message: 'no matching connection', code: 'E_NO_CONN'}, 'error', packBody));
|
||||
}
|
||||
}
|
||||
, onresume: function (opts) {
|
||||
@ -349,7 +381,8 @@ function _connect(state) {
|
||||
localclients[cid].resume();
|
||||
} else {
|
||||
console.log('[TunnelResume] remote tried resuming finished connection', cid);
|
||||
// wsHandlers.sendMessage(Packer.pack(opts, {message: 'no matching connection', code: 'E_NO_CONN'}, 'error'));
|
||||
// var packBody = true;
|
||||
// wsHandlers.sendMessage(Packer.packHeader(opts, {message: 'no matching connection', code: 'E_NO_CONN'}, 'error', packBody));
|
||||
}
|
||||
}
|
||||
|
||||
@ -366,7 +399,7 @@ function _connect(state) {
|
||||
|
||||
, _onConnectError: function (cid, opts, err) {
|
||||
console.info("[_onConnectError] opening '" + cid + "' failed because " + err.message);
|
||||
wsHandlers.sendMessage(Packer.pack(opts, null, 'error'));
|
||||
wsHandlers.sendMessage(Packer.packHeader(opts, null, 'error'));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -362,21 +362,47 @@ module.exports.assign = function (state, tun, cb) {
|
||||
state._serveIndex = require('serve-index');
|
||||
var serveIndex;
|
||||
var serveStatic;
|
||||
var dlStatic;
|
||||
if (isFile) {
|
||||
serveStatic = state._serveStatic(path.dirname(conf.handler), { dotfiles: 'allow', index: [ 'index.html' ] });
|
||||
dlStatic = state._serveStatic(path.dirname(conf.handler), { acceptRanges: false, dotfiles: 'allow', index: [ 'index.html' ] });
|
||||
serveIndex = function (req, res, next) { next(); };
|
||||
isFile = path.basename(conf.handler);
|
||||
} else {
|
||||
serveStatic = state._serveStatic(conf.handler, { dotfiles: 'allow', index: [ 'index.html' ] });
|
||||
serveIndex = state._serveIndex(conf.handler, { hidden: true, icons: true, view: 'tiles' });
|
||||
dlStatic = state._serveStatic(conf.handler, { acceptRanges: false, dotfiles: 'allow', index: [ 'index.html' ] });
|
||||
serveIndex = state._serveIndex(conf.handler, {
|
||||
hidden: true, icons: true
|
||||
, template: require('serve-tpl-attachment')({ privatefiles: 'ignore' })
|
||||
});
|
||||
}
|
||||
handler = function (req, res) {
|
||||
var qIndex = req.url.indexOf('?');
|
||||
var fIndex;
|
||||
var fname;
|
||||
if (-1 === qIndex) {
|
||||
qIndex = req.url.length;
|
||||
}
|
||||
req.querystring = req.url.substr(qIndex);
|
||||
req.url = req.url.substr(0, qIndex);
|
||||
req.query = require('querystring').parse(req.querystring.substr(1));
|
||||
if (isFile) {
|
||||
req.url = '/' + isFile;
|
||||
}
|
||||
serveStatic(req, res, function () {
|
||||
serveIndex(req, res, state._finalHandler(req, res));
|
||||
});
|
||||
//console.log('[req.query]', req.url, req.query);
|
||||
if (req.query.download) {
|
||||
fIndex = req.url.lastIndexOf('/');
|
||||
fname = req.url.substr(fIndex + 1);
|
||||
res.setHeader('Content-Disposition', 'attachment; filename="'+decodeURIComponent(fname)+'"');
|
||||
res.setHeader('Content-Type', 'application/octet-stream');
|
||||
dlStatic(req, res, function () {
|
||||
serveIndex(req, res, state._finalHandler(req, res));
|
||||
});
|
||||
} else {
|
||||
serveStatic(req, res, function () {
|
||||
serveIndex(req, res, state._finalHandler(req, res));
|
||||
});
|
||||
}
|
||||
};
|
||||
handlerservers[conf.handler] = http.createServer(handler);
|
||||
handlerservers[conf.handler].emit('connection', tlsSocket);
|
||||
|
@ -8,6 +8,7 @@ module.exports = function (pkg) {
|
||||
https.get(url, function (resp) {
|
||||
var str = '';
|
||||
resp.on('data', function (chunk) {
|
||||
//var chunk = conn.read();
|
||||
str += chunk.toString('utf8');
|
||||
});
|
||||
resp.on('end', function () {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "telebit",
|
||||
"version": "0.19.28",
|
||||
"version": "0.20.0-wip",
|
||||
"description": "Break out of localhost. Connect to any device from anywhere over any tcp port or securely in a browser. A secure tunnel. A poor man's reverse VPN.",
|
||||
"main": "lib/remote.js",
|
||||
"files": [
|
||||
@ -59,15 +59,16 @@
|
||||
"js-yaml": "^3.11.0",
|
||||
"jsonwebtoken": "^7.1.9",
|
||||
"mkdirp": "^0.5.1",
|
||||
"proxy-packer": "^1.4.3",
|
||||
"proxy-packer": "^2.0.2",
|
||||
"ps-list": "^5.0.0",
|
||||
"recase": "^1.0.4",
|
||||
"redirect-https": "^1.1.5",
|
||||
"serve-index": "^1.9.1",
|
||||
"serve-static": "^1.13.2",
|
||||
"serve-tpl-attachment": "^1.0.4",
|
||||
"sni": "^1.0.0",
|
||||
"socket-pair": "^1.0.3",
|
||||
"ws": "^2.2.3"
|
||||
"ws": "^2.3.1"
|
||||
},
|
||||
"trulyOptionalDependencies": {
|
||||
"bluebird": "^3.5.1"
|
||||
|
Loading…
x
Reference in New Issue
Block a user