#!/usr/bin/env node /** * Copyright (C) 2016, Canonical Ltd. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * */ console.debug = console.log; var net = require('net'); var repl = require('repl'); var vm = require('vm'); var util = require('util'); var Buffer = require('buffer').Buffer; var DEBUG = 1; function rnUbuntuServer(readable, writable) { console.reportErrorsAsExceptions = false; // XXX: var sandbox = { console: console, util: util }; vm.createContext(sandbox); var state = 'start'; var length = 0; var buffer = new Buffer(0); var internalEval = function(code) { DEBUG > 3 && console.error("-- internalEval: executing script(length=" + code.length + "): " + code.slice(0, 80) + " ... " + code.slice(-80)); DEBUG > 3 && console.error("-- before sandbox=" + util.inspect(sandbox, { colors: true, depth: null })); var result = vm.runInContext(code, sandbox); DEBUG > 3 && console.error("-- internalEval: result = " + result); DEBUG > 3 && console.error("-- after sandbox=" + util.inspect(sandbox, { colors: true, depth: null })); return result; }; var sendResponse = function(result) { function sendResponsePacket(response) { const sizeBuf = new Buffer(4); const dataBuf = new Buffer(response); sizeBuf.writeUInt32LE(dataBuf.length, 0); writable.write(sizeBuf); writable.write(dataBuf); } var stringifiedResult = JSON.stringify(result); DEBUG > 3 && console.error("-- sending result=" + stringifiedResult); if (stringifiedResult === undefined) { sendResponsePacket('undefined'); return; } sendResponsePacket(stringifiedResult); } readable.on('error', function (exc) { console.warn("ignoring exception: " + exc); }); readable.on('data', function(chunk) { DEBUG > 2 && console.error("-- Data received from RN Client: state = " + state) DEBUG > 2 && console.error("-- chunk length: " + chunk.length) DEBUG > 2 && console.error("-- buffer length(original): " + buffer.length) if (chunk == null || state === 'eof') return; buffer = Buffer.concat([buffer, chunk]); DEBUG > 2 && console.error("-- buffer length(concat): " + buffer.length) while(true) { if (state === 'start') { if (buffer.length < 4) return; length = buffer.readUInt32LE(0); DEBUG > 2 && console.error("-- New Packet: length=" + length); if (buffer.length >= length + 4) { var result = internalEval(buffer.toString('utf8', 4, length + 4)); var tmpBuffer = new Buffer(buffer.length - 4 - length); buffer.copy(tmpBuffer, 0, length + 4, buffer.length); buffer = tmpBuffer; sendResponse(result); } else { state = 'script'; } } if (state === 'script') { DEBUG > 2 && console.error("-- Packet length: " + length); if (buffer.length >= length + 4) { var result = internalEval(buffer.toString('utf8', 4, length + 4)); var tmpBuffer = new Buffer(buffer.length - 4 - length); buffer.copy(tmpBuffer, 0, length + 4, buffer.length); buffer = tmpBuffer; state = 'start'; sendResponse(result); } else { return; } } } }); readable.on('end', function() { state = 'eof'; DEBUG && console.error("-- Session ended"); }); } var closeDangerousConnection = function(sock) { var remoteAddress = sock.remoteAddress; if(remoteAddress.indexOf("127.0.0.1") == -1) { console.log("WARN: connection not from localhost, will be closed: ", remoteAddress); sock.destroy(); return true; } else { console.log("Connection from: ", remoteAddress); return false; } } if (process.argv.indexOf('--pipe') != -1) { console.log = console.error rnUbuntuServer(process.stdin, process.stdout); } else { var port = process.env['REACT_SERVER_PORT'] || 5000; process.argv.forEach((val, index) => { if (val == '--port') { port = process.argv[++index]; } }); var server = net.createServer((sock) => { DEBUG && console.error("-- Connection from RN client"); if(!closeDangerousConnection(sock)) rnUbuntuServer(sock, sock); }).listen(port, function() { console.error("-- Server starting") }); }