Skip to content

Commit

Permalink
added http protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
jackyz committed Dec 29, 2012
1 parent 6554694 commit 9123207
Show file tree
Hide file tree
Showing 7 changed files with 360 additions and 65 deletions.
119 changes: 119 additions & 0 deletions boot.js
@@ -0,0 +1,119 @@
var http = require('http');
var url = require('url');

var timeout = 2000; // 2'

function encode(str){
// todo return "AB + AB XOR BASE64(PATH)"
return str;
}

function load(surl, cb){
var options = url.parse(surl);
var req = http.request({
hostname: options.hostname,
port: 80,
method:'GET',
path: '/',
agent: false,
headers: {
'Content-Type':'image/jpeg',
'Cookie': encode(url.path)
}
}, function(res){
if (res.statusCode != 200) return cb(res.statusCode);
var buf = [], len = 0;
res.on('data', function(d){
buf.push(d);
len += d.length;
});
res.on('end', function(){
var c = Buffer.concat(buf, len).toString();
cb(null, c);
});
});
req.on('error', function(e){
cb(e);
});
// req.setTimeout(timeout);
req.setTimeout(timeout, function(){
req.abort();
// cb('ETIMEOUT');
});
req.end();
}

function try_upstreams(upstreams, system, token, cb){
if (upstreams.length == 0) {
cb("all_upstreams_failed");
} else {
var upstream = upstreams[0];
var url = 'http://'+upstream+'/'+system+'?token='+token;
console.log('try upstream %s ...', upstream);
load(url, function(e,c){
if (e) {
console.log('upstream %s failed.', upstream);
upstreams.shift();
try_upstreams(upstreams, system, token, cb);
} else {
console.log('upstream %s hit.', upstream);
cb(null, c);
}
});
}
}

function get_local(){
// todo get ip address of local machine
return '0.0.0.0';
}

var app = null;

function start(){
// align params
var args = process.argv.slice(0); // clone level 1
args.shift(); args.shift();
var system = args.shift();
var s = args.shift().split('@');
var token = s[0];
var host = s[1] || get_local();
var upstreams = args;
// try upstream
try_upstreams(upstreams, system, token, function(e,c){
if(e) {
console.error('all upstreams fails. reactive please.');
process.exit(1);
}
console.log("start...\n%s", c);
// app = eval('((function(){'+c+'})())');
// app.start(host, function(){
// console.log('started');
// });
});
// restart automatically to prevent too long connection
var hour = 3600000; // 1 hour
setInterval(restart, (system == 'worker') ? hour * 24 : hour);
}

function restart(){
console.log("shutdown...");
app.stop(function(){
start();
});
}

if(!module.parent){
start();
}

// node boot system token@host up1 up2 up3

// * starts local(dns/wpad/http/socks5) on 192.168.1.3 for share
// node boot local 12345@192.168.1.3 1.2.3.4 5.6.7.8

// * starts worker on 202.106.107.108 for locals
// node boot worker 12345@202.106.107.108 1.2.3.4 5.6.7.8

// * starts helper on 202.106.107.108 for workers
// node boot helper 12345@202.106.107.108 1.2.3.4 5.6.7.8
22 changes: 13 additions & 9 deletions config.json
Expand Up @@ -22,24 +22,28 @@
"socks5": {},
"proto": "shadow"
},
"worker": {
"shadow": {
},
"http": {
},
"socks5": {
}
}
"proto": {
"direct": {},
"socks5": {
"ip": "127.0.0.1",
"host": "127.0.0.1",
"port": 7070
},
"shadow": {
"ip": "127.0.0.1",
"host": "127.0.0.1",
"port": 7070,
"pass": "cool"
},
"mask": {
}
},
"worker": {
"socks5": {},
"shadow": {
"pass": "cool"
"http": {
"host": "127.0.0.1",
"port": 7070
}
},
"helper": {
Expand Down
14 changes: 14 additions & 0 deletions local.js
@@ -0,0 +1,14 @@
var debug = require('debug')('APP');

/*
// node http leaks socket, bug 3536
process.on('uncaughtException', function(e){
debug('UNCAUGHTEXCEPTION', e);
});
*/

require('./socks5').start({port:1080});
require('./http').start({port:8080});
require('./dns').start({port:53});
require('./wpad').start({port:80});

34 changes: 21 additions & 13 deletions proto/direct.js
Expand Up @@ -4,20 +4,28 @@ var debug = require('debug')('PROTO:DIRECT')

// Socket

function connect(){
var h, p;
if (typeof arguments[0] == 'object') { // call by (options) params
var opt = arguments[0];
p = opt.port;
h = opt.host;
} else { // call by (port, host) params
p = arguments[0];
h = arguments[1];
function createConnection(){ // port,host,options
var options = {};

if (typeof arguments[0] === 'object') {
options = arguments[0];
} else if (typeof arguments[1] === 'object') {
options = arguments[1];
options.port = arguments[0];
} else if (typeof arguments[2] === 'object') {
options = arguments[2];
options.port = arguments[0];
options.host = arguments[1];
} else {
if (typeof arguments[0] === 'number') {
options.port = arguments[0];
}
if (typeof arguments[1] === 'string') {
options.host = arguments[1];
}
}
debug("==[]==> %s:%s", h, p);
var socks = new net.Socket();
return socks.connect(p, h);
return socks.connect(options.port, options.host);
};

exports.connect = connect;
// exports.connect = net.connect;
exports.createConnection = createConnection;
138 changes: 138 additions & 0 deletions proto/http.js
@@ -0,0 +1,138 @@
var debug = require('debug')('PROTO:HTTP')
, net = require('net')
, http = require('http')
, util = require('util')
, stream = require('stream')
, config = require('../util/config');

var _host = config('proto', 'http', 'host') || '127.0.0.1';
var _port = config('proto', 'http', 'port') || 7070;

// ---- http client interface

function createConnection(){ // port,host,options
var options = {};

if (typeof arguments[0] === 'object') {
options = arguments[0];
} else if (typeof arguments[1] === 'object') {
options = arguments[1];
options.port = arguments[0];
} else if (typeof arguments[2] === 'object') {
options = arguments[2];
options.port = arguments[0];
options.host = arguments[1];
} else {
if (typeof arguments[0] === 'number') {
options.port = arguments[0];
}
if (typeof arguments[1] === 'string') {
options.host = arguments[1];
}
}
var socks = new HttpClientSocket(_host, _port);
return socks.connect(options.port, options.host);
};

exports.createConnection = createConnection;

// ---- http client implement

function HttpClientSocket(socks_host, socks_port) {
stream.Stream.call(this);

this.socket = null; // not init yet
this.socks_host = socks_host;
this.socks_port = socks_port;
}
util.inherits(HttpClientSocket, stream.Stream);

HttpClientSocket.prototype.setTimeout = function(msecs, callback) {
this.socket.setTimeout(msecs, callback);
};

HttpClientSocket.prototype.setNoDelay = function() {
this.socket.setNoDelay();
};

HttpClientSocket.prototype.setKeepAlive = function(setting, msecs) {
this.socket.setKeepAlive(setting, msecs);
};

HttpClientSocket.prototype.address = function() {
return this.socket.address();
};

HttpClientSocket.prototype.pause = function() {
this.socket.pause();
};

HttpClientSocket.prototype.resume = function() {
this.socket.resume();
};

HttpClientSocket.prototype.end = function(data, encoding) {
return this.socket.end(data, encoding);
};

HttpClientSocket.prototype.destroy = function(exception) {
this.socket.destroy(exception);
};

HttpClientSocket.prototype.destroySoon = function() {
this.socket.destroySoon();
this.writable = false; // node's http library asserts writable to be false after destroySoon
};

HttpClientSocket.prototype.setEncoding = function(encoding) {
this.socket.setEncoding(encoding);
};

HttpClientSocket.prototype.write = function(data, arg1, arg2) {
return this.socket.write(data, arg1, arg2);
};

HttpClientSocket.prototype.connect = function(port, host) {
var self = this;
var req = http.request({
port: self._port,
hostname: self._host,
method: 'CONNECT',
path: host+':'+port
});
req.end();
req.on('connect', function(res, socket, head){
self.socket = socket;
self.establish_connection();
});
req.on('timeout', function(){
self.emit('timeout');
});
req.on('error', function(e){
self.emit('error',e);
});
return self;
};

HttpClientSocket.prototype.establish_connection = function() {
var self = this;

self.socket.on('data', function(data) {
self.emit('data', data);
});
self.socket.on('close', function(had_error) {
self.emit('close', had_error);
});
self.socket.on('end', function() {
self.emit('end');
});
self.socket.on('error', function(error) {
self.emit('error', error);
});

self.socket._httpMessage = self._httpMessage;
self.socket.parser = self.parser;
self.socket.ondata = self.ondata;
self.writable = true;
self.emit('connect');
};

0 comments on commit 9123207

Please sign in to comment.