From 54d4079457ff915172ae513d7612fb3730a01ea8 Mon Sep 17 00:00:00 2001
From: ZJ van de Weg
Date: Sun, 17 Sep 2023 08:22:15 +0200
Subject: [PATCH 1/6] npm: Remove production flag on npm invocation
When installing packages the `--production` flag used to be added to the
arguments that `npm` received. As npm wants developers to use the
`--omit=dev` flag instead it warned users on STDERR. Standard error was
captured by Node-RED and output to the logs as being an error. This
caught users off-guard and they expected something to have gone
wrong.
With this change the `--omit=dev` is used instead, to remove the
warning.
This change works for NPM of version 8 and beyond[1], included in
Node.JS 16. This change will not work on NPM version 6[2] which is included
in Node.JS 14[3].
[1]: https://docs.npmjs.com/cli/v8/commands/npm-install#omit
[2]: https://docs.npmjs.com/cli/v6/commands/npm-install
[3]: https://nodejs.org/en/download/releases#looking-for-latest-release-of-a-version-branch
---
packages/node_modules/@node-red/registry/lib/externalModules.js | 2 +-
packages/node_modules/@node-red/registry/lib/installer.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/node_modules/@node-red/registry/lib/externalModules.js b/packages/node_modules/@node-red/registry/lib/externalModules.js
index b76f748a4..476f3dfbf 100644
--- a/packages/node_modules/@node-red/registry/lib/externalModules.js
+++ b/packages/node_modules/@node-red/registry/lib/externalModules.js
@@ -263,7 +263,7 @@ async function installModule(moduleDetails) {
"module": moduleDetails.module,
"version": moduleDetails.version,
"dir": installDir,
- "args": ["--production","--engine-strict"]
+ "args": ["--omit=dev","--engine-strict"]
}
return hooks.trigger("preInstall", triggerPayload).then((result) => {
// preInstall passed
diff --git a/packages/node_modules/@node-red/registry/lib/installer.js b/packages/node_modules/@node-red/registry/lib/installer.js
index 95022fbb1..aeb22be3d 100644
--- a/packages/node_modules/@node-red/registry/lib/installer.js
+++ b/packages/node_modules/@node-red/registry/lib/installer.js
@@ -215,7 +215,7 @@ async function installModule(module,version,url) {
"dir": installDir,
"isExisting": isExisting,
"isUpgrade": isUpgrade,
- "args": ['--no-audit','--no-update-notifier','--no-fund','--save','--save-prefix=~','--production','--engine-strict']
+ "args": ['--no-audit','--no-update-notifier','--no-fund','--save','--save-prefix=~','--omit=dev','--engine-strict']
}
return hooks.trigger("preInstall", triggerPayload).then((result) => {
From c7335ed25b182ff6ecec9b238394d768aae3ee6a Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Tue, 31 Oct 2023 09:11:17 +0000
Subject: [PATCH 2/6] Let debug node status msg length be settable via settings
---
packages/node_modules/@node-red/nodes/core/common/21-debug.js | 3 ++-
packages/node_modules/node-red/settings.js | 4 ++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/packages/node_modules/@node-red/nodes/core/common/21-debug.js b/packages/node_modules/@node-red/nodes/core/common/21-debug.js
index 5a22194ad..fe9827fce 100644
--- a/packages/node_modules/@node-red/nodes/core/common/21-debug.js
+++ b/packages/node_modules/@node-red/nodes/core/common/21-debug.js
@@ -5,6 +5,7 @@ module.exports = function(RED) {
const fs = require("fs-extra");
const path = require("path");
var debuglength = RED.settings.debugMaxLength || 1000;
+ var statuslength = RED.settings.debugStatusLength || 32;
var useColors = RED.settings.debugUseColors || false;
util.inspect.styles.boolean = "red";
const { hasOwnProperty } = Object.prototype;
@@ -164,7 +165,7 @@ module.exports = function(RED) {
}
}
- if (st.length > 32) { st = st.substr(0,32) + "..."; }
+ if (st.length > statuslength) { st = st.substr(0,statuslength) + "..."; }
var newStatus = {fill:fill, shape:shape, text:st};
if (JSON.stringify(newStatus) !== node.oldState) { // only send if we have to
diff --git a/packages/node_modules/node-red/settings.js b/packages/node_modules/node-red/settings.js
index 80b559030..864707538 100644
--- a/packages/node_modules/node-red/settings.js
+++ b/packages/node_modules/node-red/settings.js
@@ -449,6 +449,7 @@ module.exports = {
* - ui (for use with Node-RED Dashboard)
* - debugUseColors
* - debugMaxLength
+ * - debugStatusLength
* - execMaxBufferSize
* - httpRequestTimeout
* - mqttReconnectTime
@@ -504,6 +505,9 @@ module.exports = {
/** The maximum length, in characters, of any message sent to the debug sidebar tab */
debugMaxLength: 1000,
+ /** The maximum length, in characters, of status messages under the debug node */
+ //debugStatusLength: 32,
+
/** Maximum buffer size for the exec node. Defaults to 10Mb */
//execMaxBufferSize: 10000000,
From f2cb5ea44e9cc8f45133376b05b9fb042ff532fb Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Wed, 1 Nov 2023 12:07:50 +0000
Subject: [PATCH 3/6] Allow msg.reset to reset connection when tcp request in
stay connected mode
---
.../@node-red/nodes/core/network/31-tcpin.js | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js b/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js
index d95d03b10..7cf34f4f8 100644
--- a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js
+++ b/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js
@@ -547,10 +547,16 @@ module.exports = function(RED) {
this.on("input", function(msg, nodeSend, nodeDone) {
var i = 0;
- if ((!Buffer.isBuffer(msg.payload)) && (typeof msg.payload !== "string")) {
+ if (msg.payload !== undefined && (!Buffer.isBuffer(msg.payload)) && (typeof msg.payload !== "string")) {
msg.payload = msg.payload.toString();
}
+ if (node.out === "sit" && msg?.reset === true && node?.last_id && clients[node.last_id]) {
+ node.status({});
+ clients[node.last_id].client.destroy();
+ delete clients[node.last_id];
+ }
+
var host = node.server || msg.host;
var port = node.port || msg.port;
@@ -627,7 +633,9 @@ module.exports = function(RED) {
clients[connection_id].connecting = false;
let event;
while (event = dequeue(clients[connection_id].msgQueue)) {
- clients[connection_id].client.write(event.msg.payload);
+ if (event.msg.payload !== undefined) {
+ clients[connection_id].client.write(event.msg.payload);
+ }
event.nodeDone();
}
if (node.out === "time" && node.splitc < 0) {
From bfe5a8a986fcc4c72a67d3a9f2903d724313abfa Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Wed, 1 Nov 2023 12:27:11 +0000
Subject: [PATCH 4/6] Update 31-tcpin.js
don't send if payload not defined.
---
.../node_modules/@node-red/nodes/core/network/31-tcpin.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js b/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js
index 7cf34f4f8..406ea0247 100644
--- a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js
+++ b/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js
@@ -831,7 +831,9 @@ module.exports = function(RED) {
else if (!clients[connection_id].connecting && clients[connection_id].connected) {
if (clients[connection_id] && clients[connection_id].client) {
let event = dequeue(clients[connection_id].msgQueue)
- clients[connection_id].client.write(event.msg.payload);
+ if (event.msg.payload !== undefined ) {
+ clients[connection_id].client.write(event.msg.payload);
+ }
event.nodeDone();
}
}
From 32e8f4eac6e4aa7dad6a3429bfef4ee30aea0c94 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Wed, 1 Nov 2023 12:33:57 +0000
Subject: [PATCH 5/6] Add help info
---
.../@node-red/nodes/locales/en-US/network/31-tcpin.html | 2 ++
1 file changed, 2 insertions(+)
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/network/31-tcpin.html b/packages/node_modules/@node-red/nodes/locales/en-US/network/31-tcpin.html
index 173f003f7..dd42c6614 100644
--- a/packages/node_modules/@node-red/nodes/locales/en-US/network/31-tcpin.html
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/network/31-tcpin.html
@@ -40,6 +40,8 @@
returned characters into a fixed buffer, match a specified character before returning,
wait a fixed timeout from first reply and then return, sit and wait for data, or send then close the connection
immediately, without waiting for a reply.
+ If in sit and wait mode (remain connected) you can send msg.reset = true;
to force a break in
+ the connection and an automatic reconnection.
The response will be output in msg.payload
as a buffer, so you may want to .toString() it.
If you leave tcp host or port blank they must be set by using the msg.host
and msg.port
properties in every message sent to the node.
From f49f692ffa38e74628258c3ebf62b59644cf49d2 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Fri, 3 Nov 2023 11:57:16 +0000
Subject: [PATCH 6/6] Better fix for TCP node reset
now handles reply out node,
and can specify which connection to reset.
---
.../@node-red/nodes/core/network/31-tcpin.js | 63 +++++++++++++------
.../nodes/locales/en-US/network/31-tcpin.html | 4 +-
2 files changed, 47 insertions(+), 20 deletions(-)
diff --git a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js b/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js
index 406ea0247..15401e374 100644
--- a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js
+++ b/packages/node_modules/@node-red/nodes/core/network/31-tcpin.js
@@ -411,23 +411,33 @@ module.exports = function(RED) {
if (msg._session && msg._session.type == "tcp") {
var client = connectionPool[msg._session.id];
if (client) {
- if (Buffer.isBuffer(msg.payload)) {
- client.write(msg.payload);
- } else if (typeof msg.payload === "string" && node.base64) {
- client.write(Buffer.from(msg.payload,'base64'));
- } else {
- client.write(Buffer.from(""+msg.payload));
+ if (msg?.reset === true) {
+ client.destroy();
+ }
+ else {
+ if (Buffer.isBuffer(msg.payload)) {
+ client.write(msg.payload);
+ } else if (typeof msg.payload === "string" && node.base64) {
+ client.write(Buffer.from(msg.payload,'base64'));
+ } else {
+ client.write(Buffer.from(""+msg.payload));
+ }
}
}
}
else {
for (var i in connectionPool) {
- if (Buffer.isBuffer(msg.payload)) {
- connectionPool[i].write(msg.payload);
- } else if (typeof msg.payload === "string" && node.base64) {
- connectionPool[i].write(Buffer.from(msg.payload,'base64'));
- } else {
- connectionPool[i].write(Buffer.from(""+msg.payload));
+ if (msg?.reset === true) {
+ connectionPool[i].destroy();
+ }
+ else {
+ if (Buffer.isBuffer(msg.payload)) {
+ connectionPool[i].write(msg.payload);
+ } else if (typeof msg.payload === "string" && node.base64) {
+ connectionPool[i].write(Buffer.from(msg.payload,'base64'));
+ } else {
+ connectionPool[i].write(Buffer.from(""+msg.payload));
+ }
}
}
}
@@ -551,15 +561,29 @@ module.exports = function(RED) {
msg.payload = msg.payload.toString();
}
- if (node.out === "sit" && msg?.reset === true && node?.last_id && clients[node.last_id]) {
- node.status({});
- clients[node.last_id].client.destroy();
- delete clients[node.last_id];
- }
-
var host = node.server || msg.host;
var port = node.port || msg.port;
+ if (node.out === "sit" && msg?.reset) {
+ if (msg.reset === true) { // kill all connections
+ for (var cl in clients) {
+ if (clients[cl].hasOwnProperty("client")) {
+ clients[cl].client.destroy();
+ delete clients[cl];
+ }
+ }
+ }
+ if (typeof(msg.reset) === "string" && msg.reset.includes(":")) { // just kill connection host:port
+ if (clients.hasOwnProperty(msg.reset) && clients[msg.reset].hasOwnProperty("client")) {
+ clients[msg.reset].client.destroy();
+ delete clients[msg.reset];
+ }
+ }
+ const cc = Object.keys(clients).length;
+ node.status({fill:"green",shape:cc===0?"ring":"dot",text:RED._("tcpin.status.connections",{count:cc})});
+ if ((host === undefined || port === undefined) && !msg.hasOwnProperty("payload")) { return; }
+ }
+
// Store client information independently
// the clients object will have:
// clients[id].client, clients[id].msg, clients[id].timeout
@@ -627,7 +651,8 @@ module.exports = function(RED) {
clients[connection_id].connecting = true;
clients[connection_id].client.connect(connOpts, function() {
//node.log(RED._("tcpin.errors.client-connected"));
- node.status({fill:"green",shape:"dot",text:"common.status.connected"});
+ // node.status({fill:"green",shape:"dot",text:"common.status.connected"});
+ node.status({fill:"green",shape:"dot",text:RED._("tcpin.status.connections",{count:Object.keys(clients).length})});
if (clients[connection_id] && clients[connection_id].client) {
clients[connection_id].connected = true;
clients[connection_id].connecting = false;
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/network/31-tcpin.html b/packages/node_modules/@node-red/nodes/locales/en-US/network/31-tcpin.html
index dd42c6614..708df0449 100644
--- a/packages/node_modules/@node-red/nodes/locales/en-US/network/31-tcpin.html
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/network/31-tcpin.html
@@ -30,6 +30,8 @@
before being sent.
If msg._session
is not present the payload is
sent to all connected clients.
+ In Reply-to mode, setting msg.reset = true
will reset the connection
+ specified by _session.id, or all connections if no _session.id is specified.
Note: On some systems you may need root or administrator access
to access ports below 1024.
@@ -40,7 +42,7 @@
returned characters into a fixed buffer, match a specified character before returning,
wait a fixed timeout from first reply and then return, sit and wait for data, or send then close the connection
immediately, without waiting for a reply.
- If in sit and wait mode (remain connected) you can send msg.reset = true;
to force a break in
+
If in sit and wait mode (remain connected) you can send msg.reset = true
or msg.reset = "host:port"
to force a break in
the connection and an automatic reconnection.
The response will be output in msg.payload
as a buffer, so you may want to .toString() it.
If you leave tcp host or port blank they must be set by using the msg.host
and msg.port
properties in every message sent to the node.