| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var net = require('net'); | 
					
						
							|  |  |  | var sni = require('sni'); | 
					
						
							|  |  |  | var jwt = require('jsonwebtoken'); | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  | var packer = require('tunnel-packer'); | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | var Transform = require('stream').Transform; | 
					
						
							|  |  |  | var util = require('util'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function MyTransform(options) { | 
					
						
							|  |  |  |   if (!(this instanceof MyTransform)) { | 
					
						
							|  |  |  |     return new MyTransform(options); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   this.__my_addr = options.address; | 
					
						
							|  |  |  |   Transform.call(this, options); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | util.inherits(MyTransform, Transform); | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  | function transform(me, data, encoding, callback) { | 
					
						
							|  |  |  |   var address = me.__my_addr; | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  |   me.push(packer.pack(address, data)); | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  |   callback(); | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  | } | 
					
						
							|  |  |  | MyTransform.prototype._transform = function (data, encoding, callback) { | 
					
						
							|  |  |  |   return transform(this, data, encoding, callback); | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  | function socketToAddr(socket) { | 
					
						
							|  |  |  |   return { family: socket.remoteFamily, address: socket.remoteAddress, port: socket.remotePort }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function addrToId(address) { | 
					
						
							|  |  |  |   return address.family + ',' + address.address + ',' + address.port; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function socketToId(socket) { | 
					
						
							|  |  |  |   return addrToId(socketToAddr(socket)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //require('cluster-store').create().then(function (/*store*/) {
 | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  |   // initialization is now complete
 | 
					
						
							|  |  |  |   //store.set('foo', 'bar');
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var remotes = {}; | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |   setInterval(function () { | 
					
						
							|  |  |  |     Object.keys(remotes).forEach(function (id) { | 
					
						
							|  |  |  |       var remote = remotes[id]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       console.log('Remote ', id, 'has', Object.keys(remote.clients).length, 'clients', remote.socket.bytesRead, remote.socket.bytesWritten); | 
					
						
							|  |  |  |       /* | 
					
						
							|  |  |  |       forEach(function (cid) { | 
					
						
							|  |  |  |         var client = remote.clients[cid]; | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       */ | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }, 5000); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var server443 = net.createServer(function (browser) { | 
					
						
							|  |  |  |     browser.once('data', function (hello) { | 
					
						
							|  |  |  |       //require('fs').writeFileSync('/tmp/sni.hello.bin', hello);
 | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  |       var servername = sni(hello); | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  |       var remote = remotes[servername]; | 
					
						
							|  |  |  |       if (!remote) { | 
					
						
							|  |  |  |         console.log("no remote for '" + servername + "'"); | 
					
						
							|  |  |  |         browser.end(); | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  |       var address = socketToAddr(browser); | 
					
						
							|  |  |  |       var id = addrToId(address); | 
					
						
							|  |  |  |       var wrapForRemote = new MyTransform({ id: id, remoteId: remote.id, address: address, servername: servername }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       //socket.unshift(hello);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       //remote.socket/*.pipe(transform)*/.pipe(socket, { end: false });
 | 
					
						
							|  |  |  |       var bstream = browser.pipe(wrapForRemote); | 
					
						
							|  |  |  |       /* | 
					
						
							|  |  |  |       function write() { | 
					
						
							|  |  |  |         console.log("client '" + address.address + "' writing to '" + servername + "'"); | 
					
						
							|  |  |  |         var bytes = browser.read(); | 
					
						
							|  |  |  |         if (bytes) { | 
					
						
							|  |  |  |           console.log("wrote ", bytes.byteLength); | 
					
						
							|  |  |  |           remote.socket.write(bytes, write); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |           console.log("nothing to write right now"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       bstream.on('readable', write); | 
					
						
							|  |  |  |       */ | 
					
						
							|  |  |  |       bstream.on('data', function (chunk) { | 
					
						
							|  |  |  |         console.log("client '" + address.address + "' writing to '" + servername + "'", chunk.byteLength); | 
					
						
							|  |  |  |         remote.socket.write(chunk); | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  |       var data = packer.pack(address, hello); | 
					
						
							|  |  |  |       console.log("client '" + address.address + "' greeting '" + servername + "'", hello.byteLength, data.byteLength); | 
					
						
							|  |  |  |       remote.socket.write(data); | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  |       remote.clients[id] = browser; | 
					
						
							|  |  |  |       bstream.on('error', function () { | 
					
						
							|  |  |  |         console.error("browser has erred"); | 
					
						
							|  |  |  |         //wrapForRemote.write('|_ERROR_|');
 | 
					
						
							|  |  |  |         delete remote.clients[id]; | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  |       bstream.on('end', function () { | 
					
						
							|  |  |  |         console.log("browser has closed the socket"); | 
					
						
							|  |  |  |         //wrapForRemote.write('|_END_|');
 | 
					
						
							|  |  |  |         delete remote.clients[id]; | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   server443.listen(443, function () { | 
					
						
							|  |  |  |     console.log('listening on 443'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  |   var server5443 = net.createServer(function (rserver) { | 
					
						
							|  |  |  |     rserver.once('data', function (hello) { | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  |       var token; | 
					
						
							|  |  |  |       try { | 
					
						
							|  |  |  |         token = jwt.decode(hello.toString('utf8')); | 
					
						
							|  |  |  |         console.log(token); | 
					
						
							|  |  |  |       } catch(e) { | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  |         rserver.end(); | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (!token.name) { | 
					
						
							|  |  |  |         console.log("no 'name' in token"); | 
					
						
							|  |  |  |         rserver.end(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var remote = { | 
					
						
							|  |  |  |         socket: rserver | 
					
						
							|  |  |  |       , id: socketToId(rserver) | 
					
						
							|  |  |  |       , clients: {} | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |       var unpacker = packer.create({ onMessage: function (opts) { | 
					
						
							|  |  |  |         // opts.data
 | 
					
						
							|  |  |  |         var id = addrToId(opts); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         console.log("remote '" + remote.id + "' has data for '" + id + "'", opts.data.byteLength); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!remote.clients[id]) { | 
					
						
							|  |  |  |           console.log('no client for', id, opts.data.toString('utf8').substr(0, 100)); | 
					
						
							|  |  |  |           //remote.socket.write(packer.pack(opts, Buffer.from('|__END__|')));
 | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         remote.clients[id].write(opts.data); | 
					
						
							|  |  |  |       } }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       console.log('new remote:', token.name); | 
					
						
							|  |  |  |       /* | 
					
						
							|  |  |  |       var data = packer.pack({ family: 'IPv4', address: '254.254.254.1', port: 443 }, Buffer.from(remote.id)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       rserver.write(data, function () { | 
					
						
							|  |  |  |         remotes[token.name] = remote; | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 18:41:45 -04:00
										 |  |  |       remotes[token.name] = remote; | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  |       rserver.on('data', function (chunk) { | 
					
						
							|  |  |  |         unpacker.fns.addChunk(chunk); | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |       function closeEm() { | 
					
						
							| 
									
										
										
										
											2016-09-22 18:41:45 -04:00
										 |  |  |         console.log("closing connection to '" + token.name + "'"); | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  |         delete remotes[token.name]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Object.keys(remote.clients).forEach(function (cid) { | 
					
						
							|  |  |  |           remote.clients[cid].end(); | 
					
						
							|  |  |  |           delete remote.clients[cid]; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         //remote = null;
 | 
					
						
							|  |  |  |         //rserver = null;
 | 
					
						
							|  |  |  |         //unpacker = null;
 | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       rserver.on('end', closeEm); | 
					
						
							|  |  |  |       rserver.on('error', closeEm); | 
					
						
							| 
									
										
										
										
											2016-09-15 19:11:08 -04:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   server5443.listen(5443, function () { | 
					
						
							|  |  |  |     console.log('listening on 5443'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-09-27 12:39:53 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var http80 = require('http').createServer(); | 
					
						
							|  |  |  |   http80.on('request', function (req, res) { | 
					
						
							|  |  |  |     res.end('Happy Day!'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var server80 = net.createServer(function (client) { | 
					
						
							|  |  |  |     http80.emit('connection', client); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   server80.listen(80, function () { | 
					
						
							|  |  |  |     console.log('listening on 80'); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2016-09-22 18:18:13 -04:00
										 |  |  | //});
 |