Merge pull request #4406 from node-red/tcp-request-node-reset-when-in-stay-connected-mode

Let msg.reset  reset Tcp request node connection when in stay connected mode
This commit is contained in:
Nick O'Leary 2023-11-07 17:42:17 +00:00 committed by GitHub
commit 5b5b06cc06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 16 deletions

View File

@ -411,23 +411,33 @@ module.exports = function(RED) {
if (msg._session && msg._session.type == "tcp") { if (msg._session && msg._session.type == "tcp") {
var client = connectionPool[msg._session.id]; var client = connectionPool[msg._session.id];
if (client) { if (client) {
if (Buffer.isBuffer(msg.payload)) { if (msg?.reset === true) {
client.write(msg.payload); client.destroy();
} else if (typeof msg.payload === "string" && node.base64) { }
client.write(Buffer.from(msg.payload,'base64')); else {
} else { if (Buffer.isBuffer(msg.payload)) {
client.write(Buffer.from(""+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 { else {
for (var i in connectionPool) { for (var i in connectionPool) {
if (Buffer.isBuffer(msg.payload)) { if (msg?.reset === true) {
connectionPool[i].write(msg.payload); connectionPool[i].destroy();
} else if (typeof msg.payload === "string" && node.base64) { }
connectionPool[i].write(Buffer.from(msg.payload,'base64')); else {
} else { if (Buffer.isBuffer(msg.payload)) {
connectionPool[i].write(Buffer.from(""+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));
}
} }
} }
} }
@ -547,13 +557,33 @@ module.exports = function(RED) {
this.on("input", function(msg, nodeSend, nodeDone) { this.on("input", function(msg, nodeSend, nodeDone) {
var i = 0; 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(); msg.payload = msg.payload.toString();
} }
var host = node.server || msg.host; var host = node.server || msg.host;
var port = node.port || msg.port; 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 // Store client information independently
// the clients object will have: // the clients object will have:
// clients[id].client, clients[id].msg, clients[id].timeout // clients[id].client, clients[id].msg, clients[id].timeout
@ -621,13 +651,16 @@ module.exports = function(RED) {
clients[connection_id].connecting = true; clients[connection_id].connecting = true;
clients[connection_id].client.connect(connOpts, function() { clients[connection_id].client.connect(connOpts, function() {
//node.log(RED._("tcpin.errors.client-connected")); //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) { if (clients[connection_id] && clients[connection_id].client) {
clients[connection_id].connected = true; clients[connection_id].connected = true;
clients[connection_id].connecting = false; clients[connection_id].connecting = false;
let event; let event;
while (event = dequeue(clients[connection_id].msgQueue)) { 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(); event.nodeDone();
} }
if (node.out === "time" && node.splitc < 0) { if (node.out === "time" && node.splitc < 0) {
@ -823,7 +856,9 @@ module.exports = function(RED) {
else if (!clients[connection_id].connecting && clients[connection_id].connected) { else if (!clients[connection_id].connecting && clients[connection_id].connected) {
if (clients[connection_id] && clients[connection_id].client) { if (clients[connection_id] && clients[connection_id].client) {
let event = dequeue(clients[connection_id].msgQueue) 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(); event.nodeDone();
} }
} }

View File

@ -30,6 +30,8 @@
before being sent.</p> before being sent.</p>
<p>If <code>msg._session</code> is not present the payload is <p>If <code>msg._session</code> is not present the payload is
sent to <b>all</b> connected clients.</p> sent to <b>all</b> connected clients.</p>
<p>In Reply-to mode, setting <code>msg.reset = true</code> will reset the connection
specified by _session.id, or all connections if no _session.id is specified.</p>
<p><b>Note: </b>On some systems you may need root or administrator access <p><b>Note: </b>On some systems you may need root or administrator access
to access ports below 1024.</p> to access ports below 1024.</p>
</script> </script>
@ -40,6 +42,8 @@
returned characters into a fixed buffer, match a specified character before returning, 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 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.</p> immediately, without waiting for a reply.</p>
<p>If in sit and wait mode (remain connected) you can send <code>msg.reset = true</code> or <code>msg.reset = "host:port"</code> to force a break in
the connection and an automatic reconnection.</p>
<p>The response will be output in <code>msg.payload</code> as a buffer, so you may want to .toString() it.</p> <p>The response will be output in <code>msg.payload</code> as a buffer, so you may want to .toString() it.</p>
<p>If you leave tcp host or port blank they must be set by using the <code>msg.host</code> and <code>msg.port</code> properties in every message sent to the node.</p> <p>If you leave tcp host or port blank they must be set by using the <code>msg.host</code> and <code>msg.port</code> properties in every message sent to the node.</p>
</script> </script>