From 9207c28a5c1db944931a9ae972ff856c44702670 Mon Sep 17 00:00:00 2001 From: Dorian Niemiec Date: Thu, 22 Feb 2024 00:52:43 +0100 Subject: [PATCH] Update to GreenRhombus 1.0.4 --- index.js | 61 ++++++++++++++++++++++++++++++++++++++++++++++++-------- mod.info | 2 +- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/index.js b/index.js index 90d9e59..5534c3b 100644 --- a/index.js +++ b/index.js @@ -130,6 +130,7 @@ function createFastCGIHandler(options) { function fastCGISocketHandler(chunk) { var chunkIndex = 0; + while (chunkIndex < chunk.length || (headerIndex == 8 && bodyIndex == packetBody.length && paddingLength == 0)) { if (headerIndex < 8) { chunk.copy(packetHeader, headerIndex, chunkIndex, Math.min(chunk.length, chunkIndex + 8 - headerIndex)); @@ -167,7 +168,7 @@ function createFastCGIHandler(options) { if (processedPacket.requestID != requestID) return; //Drop the packet if (processedPacket.type == STDOUT) { try { - if(processedPacket.content.length > 0) emulatedStdout.push(processedPacket.content); + if(processedPacket.content.length > 0) stdoutPush(processedPacket.content); } catch (err) { //STDOUT will be lost instead of crashing the server } @@ -195,7 +196,7 @@ function createFastCGIHandler(options) { } else if (protocolStatus == CANT_MPX_CONN) { err = new Error("Multiplexed connections not supported by the FastCGI application"); } - emulatedStdout.push(null); + stdoutPush(null); if (emulatedStdout._readableState && emulatedStdout._readableState.flowing !== null && !emulatedStdout.endEmitted) { emulatedStdout.on("end", function() { emulatedStderr.push(null); @@ -206,7 +207,7 @@ function createFastCGIHandler(options) { eventEmitter.emit("error", err); } } else { - emulatedStdout.push(null); + stdoutPush(null); if (emulatedStdout._readableState && emulatedStdout._readableState.flowing !== null && !emulatedStdout.endEmitted) { emulatedStdout.on("end", function() { emulatedStderr.push(null); @@ -249,9 +250,48 @@ function createFastCGIHandler(options) { } }); + function stdoutPush(data) { + if(data === null) { + stdoutToEnd = true; + } else { + stdoutBuffer = Buffer.concat([stdoutBuffer, Buffer.from(data)]); + } + var hpLength = hp.length; + for(var i = 0; i < hpLength; i++) { + var func = hp.shift(); + if(func) func(); + } + emulatedStdout.resume(); + } + + var zeroed = false; + var stdoutBuffer = Buffer.alloc(0); + var stdoutToEnd = false; + var hp = []; var emulatedStdout = new stream.Readable({ - read: function () {} + read: function (n) { + var s = this; + var handler = function () { + if (stdoutBuffer.length == 0) { + if (!stdoutToEnd) { + hp.push(handler); + s.pause(); + } else { + s.push(null); + } + } else { + var bytesToPush = Math.min(stdoutBuffer.length, n); + var bufferToPush = stdoutBuffer.subarray(0, bytesToPush); + stdoutBuffer = stdoutBuffer.subarray(bytesToPush); + s.push(bufferToPush); + if (stdoutBuffer.length == 0 && !stdoutToEnd) s.pause(); + } + }; + if (n != 0) handler(); + } }); + emulatedStdout.pause(); //Reduce backpressure + var emulatedStderr = new stream.Readable({ read: function () {} }); @@ -281,8 +321,9 @@ function createFastCGIHandler(options) { var socket = net.createConnection(options, function () { eventEmitter.emit("connect"); }).on("error", function (err) { - emulatedStdout.push(null); + stdoutPush(null); emulatedStderr.push(null); + eventEmitter.removeAllListeners("exit"); eventEmitter.emit("error", err); }).on("data", fastCGISocketHandler); @@ -422,7 +463,7 @@ Mod.prototype.callback = function (req, res, serverconsole, responseEnd, href, e res.write(buffer.substr(headerendline + eol.length), "latin1"); } catch (ex) { handler.removeAllListeners("exit"); - handler.stdout.removeAllListeners("dat"); + handler.stdout.removeAllListeners("data"); if (!callServerError) { res.writeHead(500); res.end(ex.stack); @@ -438,6 +479,7 @@ Mod.prototype.callback = function (req, res, serverconsole, responseEnd, href, e handler.stdout.pipe(res, { end: false }); + dataHandler = function () {}; //Prevent event listener memory leaks } } }; @@ -470,16 +512,18 @@ Mod.prototype.callback = function (req, res, serverconsole, responseEnd, href, e } }); - res.on("close", function() { + res.prependListener("close", function() { if(handler.stdout) handler.stdout.unpipe(res); //Prevent server crashes with write after the end }); + res.on("error", function() {}); //Suppress response stream errors + function handlerConnection() { - handler.init(); handler.stdout.on("data", dataHandler); handler.stderr.on("data", function (data) { stderr += data.toString(); }); + handler.init(); req.pipe(handler.stdin); handler.on("exit", function (code, signal) { if (!cned && (signal || code !== 0)) { @@ -496,6 +540,7 @@ Mod.prototype.callback = function (req, res, serverconsole, responseEnd, href, e serverconsole.errmessage("There were FastCGI application errors:"); serverconsole.errmessage(preparedStderr); } + handler.stdout.removeListener("data", dataHandler); handler.stdout.unpipe(res); //Prevent server crashes with write after the end if(!res.finished) res.end(); } diff --git a/mod.info b/mod.info index 3600377..4d456bd 100755 --- a/mod.info +++ b/mod.info @@ -1,4 +1,4 @@ { "name": "GreenRhombus FastCGI client for SVR.JS", - "version": "1.0.3" + "version": "1.0.4" }