217 lines
6.3 KiB
JavaScript
217 lines
6.3 KiB
JavaScript
"use strict";
|
|
|
|
const fs = require('fs');
|
|
const zlib = require('zlib');
|
|
const https = require('https');
|
|
const selfsigned = require('selfsigned');
|
|
|
|
function getCookies(req) {
|
|
let found = {};
|
|
let cookies = req.headers.cookie;
|
|
|
|
if (cookies) {
|
|
for (let cookie of cookies.split(';')) {
|
|
let parts = cookie.split('=');
|
|
|
|
found[parts.shift().trim()] = decodeURI(parts.join('='));
|
|
}
|
|
}
|
|
|
|
return found;
|
|
}
|
|
|
|
class Server {
|
|
constructor() {
|
|
this.buffers = {};
|
|
this.startCallback = {};
|
|
this.receiveCallback = {};
|
|
this.respondCallback = {};
|
|
this.ip = serverConfig.ip;
|
|
this.port = serverConfig.port;
|
|
this.backendUrl = "https://" + this.ip + ":" + this.port;
|
|
this.version = "dev-r23.4";
|
|
this.mime = {
|
|
txt: 'text/plain',
|
|
jpg: 'image/jpeg',
|
|
png: 'image/png',
|
|
json: 'application/json'
|
|
};
|
|
|
|
this.addRespondCallback("DONE", this.killResponse.bind(this));
|
|
}
|
|
|
|
resetBuffer(sessionID) {
|
|
this.buffers[sessionID] = undefined;
|
|
}
|
|
|
|
putInBuffer(sessionID, data, bufLength) {
|
|
if (this.buffers[sessionID] === undefined || this.buffers[sessionID].allocated !== bufLength) {
|
|
this.buffers[sessionID] = {
|
|
written: 0,
|
|
allocated: bufLength,
|
|
buffer: Buffer.alloc(bufLength)
|
|
};
|
|
}
|
|
|
|
let buf = this.buffers[sessionID];
|
|
|
|
data.copy(buf.buffer, buf.written, 0);
|
|
buf.written += data.length;
|
|
return buf.written === buf.allocated;
|
|
}
|
|
|
|
getFromBuffer(sessionID) {
|
|
return this.buffers[sessionID].buffer;
|
|
}
|
|
|
|
addStartCallback(type, worker) {
|
|
this.startCallback[type] = worker;
|
|
}
|
|
|
|
addReceiveCallback(type, worker) {
|
|
this.receiveCallback[type] = worker;
|
|
}
|
|
|
|
addRespondCallback(type, worker) {
|
|
this.respondCallback[type] = worker;
|
|
}
|
|
|
|
getIp() {
|
|
return this.ip;
|
|
}
|
|
|
|
getPort() {
|
|
return this.port;
|
|
}
|
|
|
|
getBackendUrl() {
|
|
return this.backendUrl;
|
|
}
|
|
|
|
getVersion() {
|
|
return this.version;
|
|
}
|
|
|
|
generateCertifcate() {
|
|
let perms = selfsigned.generate([{ name: 'commonName', value: this.ip + "/" }], { days: 365 });
|
|
return {cert: perms.cert, key: perms.private};
|
|
}
|
|
|
|
sendZlibJson(resp, output, sessionID) {
|
|
resp.writeHead(200, "OK", {'Content-Type': this.mime['json'], 'content-encoding' : 'deflate', 'Set-Cookie' : 'PHPSESSID=' + sessionID});
|
|
|
|
zlib.deflate(output, function (err, buf) {
|
|
resp.end(buf);
|
|
});
|
|
}
|
|
|
|
sendTextJson(resp, output) {
|
|
resp.writeHead(200, "OK", {'Content-Type': this.mime['json']});
|
|
resp.end(output);
|
|
}
|
|
|
|
sendFile(resp, file) {
|
|
let pathSlic = file.split("/");
|
|
let type = this.mime[pathSlic[pathSlic.length -1].split(".")[1]] || this.mime['txt'];
|
|
let fileStream = fs.createReadStream(file);
|
|
|
|
fileStream.on('open', function () {
|
|
resp.setHeader('Content-Type', type);
|
|
fileStream.pipe(resp);
|
|
});
|
|
}
|
|
|
|
killResponse() {
|
|
return;
|
|
}
|
|
|
|
sendResponse(sessionID, req, resp, body) {
|
|
let output = "";
|
|
|
|
// get response
|
|
if (req.method === "POST" || req.method === "PUT") {
|
|
output = router.getResponse(req, body, sessionID);
|
|
} else {
|
|
output = router.getResponse(req, "", sessionID);
|
|
}
|
|
|
|
// execute data received callback
|
|
for (let type in this.receiveCallback) {
|
|
this.receiveCallback[type](sessionID, req, resp, body, output);
|
|
}
|
|
|
|
// send response
|
|
if (output in this.respondCallback) {
|
|
this.respondCallback[output](sessionID, req, resp, body);
|
|
} else {
|
|
this.sendZlibJson(resp, output, sessionID);
|
|
}
|
|
}
|
|
|
|
handleRequest(req, resp) {
|
|
const IP = req.connection.remoteAddress.replace("::ffff:", "");
|
|
const sessionID = parseInt(getCookies(req)['PHPSESSID']);
|
|
|
|
logger.logRequest("[" + sessionID + "][" + IP + "] " + req.url);
|
|
|
|
// request without data
|
|
if (req.method === "GET") {
|
|
server.sendResponse(sessionID, req, resp, "");
|
|
}
|
|
|
|
// request with data
|
|
if (req.method === "POST") {
|
|
req.on('data', function (data) {
|
|
zlib.inflate(data, function (err, body) {
|
|
let jsonData = ((body !== typeof "undefined" && body !== null && body !== "") ? body.toString() : '{}');
|
|
server.sendResponse(sessionID, req, resp, jsonData);
|
|
});
|
|
});
|
|
}
|
|
|
|
// emulib responses
|
|
if (req.method === "PUT") {
|
|
req.on('data', function(data) {
|
|
// receive data
|
|
if (req.headers.hasOwnProperty("expect")) {
|
|
const requestLength = parseInt(req.headers["content-length"]);
|
|
|
|
if (!server.putInBuffer(parseInt(req.headers.sessionid), data, requestLength)) {
|
|
resp.writeContinue();
|
|
}
|
|
}
|
|
}).on('end', function() {
|
|
let data = server.getFromBuffer(sessionID);
|
|
server.resetBuffer(sessionID);
|
|
|
|
zlib.inflate(data, function (err, body) {
|
|
let jsonData = ((body !== typeof "undefined" && body !== null && body !== "") ? body.toString() : '{}');
|
|
server.sendResponse(sessionID, req, resp, jsonData);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
start() {
|
|
// execute start callback
|
|
logger.logWarning("Server: executing startup callbacks...");
|
|
|
|
for (let type in this.startCallback) {
|
|
this.startCallback[type]();
|
|
}
|
|
|
|
/* create server */
|
|
let httpsServer = https.createServer(this.generateCertifcate(), (req, res) => {
|
|
this.handleRequest(req, res);
|
|
}).listen(this.port, this.ip, function() {
|
|
logger.logSuccess("Started server");
|
|
});
|
|
|
|
/* server is already running */
|
|
httpsServer.on('error', function(e) {
|
|
logger.logError("» Port " + e.port + " is already in use, check if the server isn't already running");
|
|
});
|
|
}
|
|
}
|
|
|
|
module.exports.server = new Server(); |