status-react/ubuntu-server.js

144 lines
4.4 KiB
JavaScript
Executable File

#!/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") });
}