@node-red/nodes 5.0.0-beta.1 → 5.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/common/25-status.js +7 -5
- package/core/common/lib/debug/debug-utils.js +88 -14
- package/core/function/89-delay.html +14 -1
- package/core/function/89-delay.js +49 -4
- package/core/function/90-exec.js +17 -9
- package/core/network/05-tls.html +56 -6
- package/core/network/05-tls.js +26 -1
- package/core/network/10-mqtt.js +11 -6
- package/core/network/21-httprequest.js +83 -53
- package/core/network/22-websocket.js +5 -1
- package/core/network/31-tcpin.js +152 -140
- package/core/network/32-udp.js +12 -8
- package/core/storage/10-file.html +2 -2
- package/locales/de/messages.json +4 -1
- package/locales/en-US/function/89-delay.html +12 -3
- package/locales/en-US/messages.json +11 -3
- package/locales/es-ES/messages.json +4 -1
- package/locales/fr/messages.json +4 -1
- package/locales/ja/messages.json +4 -1
- package/package.json +7 -7
package/core/common/25-status.js
CHANGED
|
@@ -20,13 +20,15 @@ module.exports = function(RED) {
|
|
|
20
20
|
function StatusNode(n) {
|
|
21
21
|
RED.nodes.createNode(this,n);
|
|
22
22
|
var node = this;
|
|
23
|
-
this.scope = n.scope
|
|
23
|
+
this.scope = n.scope;
|
|
24
24
|
|
|
25
25
|
// auto-filter out any directly connected nodes to avoid simple loopback
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
this.scope
|
|
26
|
+
if (Array.isArray(this.scope)) {
|
|
27
|
+
const w = this.wires.flat();
|
|
28
|
+
for (let i = 0; i < this.scope.length; i++) {
|
|
29
|
+
if (w.includes(this.scope[i])) {
|
|
30
|
+
this.scope.splice(i, 1);
|
|
31
|
+
}
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
|
|
@@ -32,6 +32,9 @@ RED.debug = (function() {
|
|
|
32
32
|
var numMessages = 100; // Hardcoded number of message to show in debug window scrollback
|
|
33
33
|
|
|
34
34
|
var debugNodeTreeList;
|
|
35
|
+
var debugPaused = false;
|
|
36
|
+
let debugPausedMessage
|
|
37
|
+
let debugPausedMessageCount = 0
|
|
35
38
|
|
|
36
39
|
function init(_config) {
|
|
37
40
|
config = _config;
|
|
@@ -39,14 +42,18 @@ RED.debug = (function() {
|
|
|
39
42
|
var content = $("<div>").css({"position":"relative","height":"100%"});
|
|
40
43
|
var toolbar = $('<div class="red-ui-sidebar-header">'+
|
|
41
44
|
'<span class="button-group">'+
|
|
42
|
-
'<a id="red-ui-sidebar-debug-
|
|
45
|
+
'<a id="red-ui-sidebar-debug-pause" class="red-ui-sidebar-header-button" href="#"><i class="fa fa-pause"></i></a>'+
|
|
43
46
|
'</span>'+
|
|
44
47
|
'<span class="button-group">'+
|
|
45
|
-
'<a id="red-ui-sidebar-debug-
|
|
46
|
-
|
|
48
|
+
'<a id="red-ui-sidebar-debug-filter" style="padding-right: 3px" class="red-ui-sidebar-header-button" href="#"><i class="fa fa-filter"></i> <span></span> <i style="padding-left: 5px;" class="fa fa-caret-down"></i></a>'+
|
|
49
|
+
'</span>'+
|
|
50
|
+
'<span class="button-group">'+
|
|
51
|
+
'<a id="red-ui-sidebar-debug-clear" style="border-right: none; padding-right: 2px" class="red-ui-sidebar-header-button" href="#" data-clear-type="all"><i class="fa fa-trash"></i> <span>all</span></a>' +
|
|
52
|
+
'<a id="red-ui-sidebar-debug-clear-opts" style="padding: 3px; border-left: none;" class="red-ui-sidebar-header-button" href="#"><i class="fa fa-caret-down"></i></a>'+
|
|
47
53
|
'</span></div>').appendTo(content);
|
|
48
54
|
|
|
49
55
|
var footerToolbar = $('<div>'+
|
|
56
|
+
'<span id="red-ui-sidebar-debug-info" style="float: left;"></span>' +
|
|
50
57
|
'<span class="button-group"><a id="red-ui-sidebar-debug-open" class="red-ui-footer-button" href="#"><i class="fa fa-desktop"></i></a></span> ' +
|
|
51
58
|
'</div>');
|
|
52
59
|
|
|
@@ -185,6 +192,39 @@ RED.debug = (function() {
|
|
|
185
192
|
});
|
|
186
193
|
RED.popover.tooltip(toolbar.find('#red-ui-sidebar-debug-filter'),RED._('node-red:debug.sidebar.filterLog'));
|
|
187
194
|
|
|
195
|
+
toolbar.find("#red-ui-sidebar-debug-pause").on("click", function(e) {
|
|
196
|
+
e.preventDefault();
|
|
197
|
+
toggleDebugflow();
|
|
198
|
+
});
|
|
199
|
+
var pauseTooltip = RED.popover.tooltip(toolbar.find("#red-ui-sidebar-debug-pause"),RED._('node-red:debug.sidebar.pause'),"core:pause-debug-messages");
|
|
200
|
+
function toggleDebugflow() {
|
|
201
|
+
debugPaused = !debugPaused;
|
|
202
|
+
if (debugPaused) {
|
|
203
|
+
debugPausedMessageCount = 0
|
|
204
|
+
debugPausedMessage = $('<div class="red-ui-debug-msg red-ui-debug-msg-paused">')
|
|
205
|
+
$(`<div class="red-ui-debug-msg-meta">
|
|
206
|
+
<span class="red-ui-debug-msg-date">${getTimestamp()}</span>
|
|
207
|
+
<span class="red-ui-debug-msg-name">${RED._('node-red:debug.sidebar.paused')}</span>
|
|
208
|
+
</div>`).appendTo(debugPausedMessage);
|
|
209
|
+
$('<div class="red-ui-debug-msg-meta"><span class="red-ui-debug-msg-name"> </span></div>').appendTo(debugPausedMessage);
|
|
210
|
+
const atBottom = (sbc.scrollHeight-messageList.height()-sbc.scrollTop) < 5;
|
|
211
|
+
messageList.append(debugPausedMessage);
|
|
212
|
+
if (atBottom) {
|
|
213
|
+
messageList.scrollTop(sbc.scrollHeight);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
$("#red-ui-sidebar-debug-pause i").removeClass("fa-pause").addClass("fa-play");
|
|
217
|
+
pauseTooltip.setAction("core:resume-debug-messages");
|
|
218
|
+
pauseTooltip.setContent(RED._('node-red:debug.sidebar.resume'))
|
|
219
|
+
$("#red-ui-sidebar-debug-info").text(RED._('node-red:debug.sidebar.paused'));
|
|
220
|
+
} else {
|
|
221
|
+
$("#red-ui-sidebar-debug-pause i").removeClass("fa-play").addClass("fa-pause");
|
|
222
|
+
pauseTooltip.setAction("core:pause-debug-messages");
|
|
223
|
+
pauseTooltip.setContent(RED._('node-red:debug.sidebar.pause'))
|
|
224
|
+
$("#red-ui-sidebar-debug-info").text("");
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
188
228
|
toolbar.find("#red-ui-sidebar-debug-clear").on("click", function(e) {
|
|
189
229
|
e.preventDefault();
|
|
190
230
|
var action = RED.settings.get("debug.clearType","all")
|
|
@@ -389,15 +429,36 @@ RED.debug = (function() {
|
|
|
389
429
|
var stack = [];
|
|
390
430
|
var busy = false;
|
|
391
431
|
function handleDebugMessage(o) {
|
|
392
|
-
if (
|
|
393
|
-
|
|
394
|
-
busy
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
432
|
+
if (!debugPaused) {
|
|
433
|
+
if (o) { stack.push(o); }
|
|
434
|
+
if (!busy && (stack.length > 0)) {
|
|
435
|
+
busy = true;
|
|
436
|
+
const message = stack.shift()
|
|
437
|
+
// call any preDebugLog hooks, allowing them to modify the message or block it from being displayed
|
|
438
|
+
RED.hooks.trigger('debugPreProcessMessage', { message }).then(result => {
|
|
439
|
+
if (result === false) {
|
|
440
|
+
return false; // A hook returned false - halt processing of this message
|
|
441
|
+
}
|
|
442
|
+
return processDebugMessage(message);
|
|
443
|
+
}).then(processArtifacts => {
|
|
444
|
+
if (processArtifacts === false) {
|
|
445
|
+
return false; // A hook returned false - halt processing of this message
|
|
446
|
+
}
|
|
447
|
+
const { message, element, payload } = processArtifacts || {};
|
|
448
|
+
return RED.hooks.trigger('debugPostProcessMessage', { message, element, payload });
|
|
449
|
+
}).catch(err => {
|
|
450
|
+
console.error("Error in debug process message hooks", err);
|
|
451
|
+
}).finally(() => {
|
|
452
|
+
setTimeout(function() {
|
|
453
|
+
busy = false;
|
|
454
|
+
handleDebugMessage();
|
|
455
|
+
}, 15); // every 15mS = 66 times a second
|
|
456
|
+
if (stack.length > numMessages) { stack = stack.splice(-numMessages); }
|
|
457
|
+
})
|
|
458
|
+
}
|
|
459
|
+
} else {
|
|
460
|
+
debugPausedMessageCount++
|
|
461
|
+
debugPausedMessage.find('.red-ui-debug-msg-name').last().text(RED._("node-red:debug.sidebar.messagesDropped",{count:debugPausedMessageCount}));
|
|
401
462
|
}
|
|
402
463
|
}
|
|
403
464
|
|
|
@@ -519,10 +580,13 @@ RED.debug = (function() {
|
|
|
519
580
|
sourceId: sourceNode && sourceNode.id,
|
|
520
581
|
rootPath: path,
|
|
521
582
|
nodeSelector: config.messageSourceClick,
|
|
522
|
-
enablePinning: true
|
|
583
|
+
enablePinning: true,
|
|
584
|
+
tools: o.tools // permit preDebugLog hooks to add extra tools to the <debugMessage> element
|
|
523
585
|
});
|
|
524
586
|
// Do this in a separate step so the element functions aren't stripped
|
|
525
587
|
debugMessage.appendTo(el);
|
|
588
|
+
// add the meta row tools container, even if there are no tools, so that the postProcessDebugMessage hook can add tools
|
|
589
|
+
const tools = $('<span class="red-ui-debug-msg-tools button-group"></span>').appendTo(metaRow)
|
|
526
590
|
// NOTE: relying on function error to have a "type" that all other msgs don't
|
|
527
591
|
if (o.hasOwnProperty("type") && (o.type === "function")) {
|
|
528
592
|
var errorLvlType = 'error';
|
|
@@ -534,7 +598,6 @@ RED.debug = (function() {
|
|
|
534
598
|
msg.addClass('red-ui-debug-msg-level-' + errorLvl);
|
|
535
599
|
$('<span class="red-ui-debug-msg-topic">function : (' + errorLvlType + ')</span>').appendTo(metaRow);
|
|
536
600
|
} else {
|
|
537
|
-
var tools = $('<span class="red-ui-debug-msg-tools button-group"></span>').appendTo(metaRow);
|
|
538
601
|
var filterMessage = $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-caret-down"></i></button>').appendTo(tools);
|
|
539
602
|
filterMessage.on("click", function(e) {
|
|
540
603
|
e.preventDefault();
|
|
@@ -590,6 +653,14 @@ RED.debug = (function() {
|
|
|
590
653
|
if (atBottom) {
|
|
591
654
|
messageList.scrollTop(sbc.scrollHeight);
|
|
592
655
|
}
|
|
656
|
+
|
|
657
|
+
// return artifacts to permit postProcessDebugMessage hooks to modify the message element, access the
|
|
658
|
+
// processed payload or otherwise modify the message after it has been generated.
|
|
659
|
+
return {
|
|
660
|
+
message: o, // original debug message object, useful for any hook that might have tagged additional info onto it
|
|
661
|
+
element: msg, // the top-level element for this debug message
|
|
662
|
+
payload // the reconstructed debug message
|
|
663
|
+
}
|
|
593
664
|
}
|
|
594
665
|
|
|
595
666
|
function clearMessageList(clearFilter, filteredOnly) {
|
|
@@ -598,6 +669,9 @@ RED.debug = (function() {
|
|
|
598
669
|
} else {
|
|
599
670
|
$(".red-ui-debug-msg:not(.hide)").remove();
|
|
600
671
|
}
|
|
672
|
+
if (debugPaused) {
|
|
673
|
+
messageList.append(debugPausedMessage);
|
|
674
|
+
}
|
|
601
675
|
config.clear();
|
|
602
676
|
if (!!clearFilter) {
|
|
603
677
|
clearFilterSettings();
|
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
<label></label>
|
|
64
64
|
<select id="node-input-rate-type" style="width:270px !important">
|
|
65
65
|
<option value="all" data-i18n="delay.limitall"></option>
|
|
66
|
+
<option value="burst" data-i18n="delay.limitburst"></option>
|
|
66
67
|
<option value="topic" data-i18n="delay.limittopic"></option>
|
|
67
68
|
</select>
|
|
68
69
|
</div>
|
|
@@ -185,6 +186,8 @@
|
|
|
185
186
|
return this._("delay.label.limit")+" "+rate;
|
|
186
187
|
} else if (this.pauseType == "timed") {
|
|
187
188
|
return this._("delay.label.limitTopic")+" "+rate;
|
|
189
|
+
} else if (this.pauseType == "burst") {
|
|
190
|
+
return this._("delay.label.burst")+" "+rate;
|
|
188
191
|
} else {
|
|
189
192
|
return this._("delay.label.limitTopic")+" "+rate;
|
|
190
193
|
}
|
|
@@ -245,6 +248,9 @@
|
|
|
245
248
|
$("#node-input-delay-action").val('rate');
|
|
246
249
|
$("#node-input-rate-type").val('topic');
|
|
247
250
|
$("#node-input-rate-topic-type").val('timed');
|
|
251
|
+
} else if (this.pauseType == "burst") {
|
|
252
|
+
$("#node-input-delay-action").val('rate');
|
|
253
|
+
$("#node-input-rate-type").val('burst');
|
|
248
254
|
}
|
|
249
255
|
|
|
250
256
|
if (!this.timeoutUnits) {
|
|
@@ -294,12 +300,17 @@
|
|
|
294
300
|
if (this.value === "all") {
|
|
295
301
|
$("#rate-details-per-topic").hide();
|
|
296
302
|
$("#node-input-drop-select-queue").attr('disabled', false);
|
|
303
|
+
$("#rate-override").show();
|
|
304
|
+
} else if (this.value === "burst") {
|
|
305
|
+
$("#rate-details-per-topic").hide();
|
|
306
|
+
$("#node-input-drop-select-queue").attr('disabled', true);
|
|
307
|
+
$("#rate-override").hide();
|
|
297
308
|
} else if (this.value === "topic") {
|
|
298
309
|
if ($("#node-input-drop-select").val() === "queue") {
|
|
299
|
-
$("#node-input-drop-select").val("drop");
|
|
300
310
|
}
|
|
301
311
|
$("#node-input-drop-select-queue").attr('disabled', true);
|
|
302
312
|
$("#rate-details-per-topic").show();
|
|
313
|
+
$("#rate-override").show();
|
|
303
314
|
}
|
|
304
315
|
}).trigger("change");
|
|
305
316
|
},
|
|
@@ -312,6 +323,8 @@
|
|
|
312
323
|
action = $("#node-input-rate-type").val();
|
|
313
324
|
if (action === "all") {
|
|
314
325
|
this.pauseType = "rate";
|
|
326
|
+
} else if (action === "burst") {
|
|
327
|
+
this.pauseType = "burst";
|
|
315
328
|
} else {
|
|
316
329
|
this.pauseType = $("#node-input-rate-topic-type").val();
|
|
317
330
|
}
|
|
@@ -42,6 +42,7 @@ module.exports = function(RED) {
|
|
|
42
42
|
this.timeoutUnits = n.timeoutUnits;
|
|
43
43
|
this.randomUnits = n.randomUnits;
|
|
44
44
|
this.rateUnits = n.rateUnits;
|
|
45
|
+
this.burst = n.rate;
|
|
45
46
|
|
|
46
47
|
if (n.timeoutUnits === "milliseconds") {
|
|
47
48
|
this.timeout = n.timeout;
|
|
@@ -57,12 +58,16 @@ module.exports = function(RED) {
|
|
|
57
58
|
|
|
58
59
|
if (n.rateUnits === "minute") {
|
|
59
60
|
this.rate = (60 * 1000)/n.rate;
|
|
61
|
+
this.timer = n.nbRateUnits * (60 * 1000);
|
|
60
62
|
} else if (n.rateUnits === "hour") {
|
|
61
63
|
this.rate = (60 * 60 * 1000)/n.rate;
|
|
64
|
+
this.timer = n.nbRateUnits * (60 * 60 * 1000);
|
|
62
65
|
} else if (n.rateUnits === "day") {
|
|
63
66
|
this.rate = (24 * 60 * 60 * 1000)/n.rate;
|
|
67
|
+
this.timer = n.nbRateUnits * (24 * 60 * 60 * 1000);
|
|
64
68
|
} else { // Default to seconds
|
|
65
69
|
this.rate = 1000/n.rate;
|
|
70
|
+
this.timer = n.nbRateUnits * 1000;
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
this.rate *= (n.nbRateUnits > 0 ? n.nbRateUnits : 1);
|
|
@@ -159,7 +164,8 @@ module.exports = function(RED) {
|
|
|
159
164
|
if (node.pauseType === "delay") {
|
|
160
165
|
node.on("input", function(msg, send, done) {
|
|
161
166
|
var id = ourTimeout(function() {
|
|
162
|
-
node.idList.
|
|
167
|
+
var idx = node.idList.indexOf(id);
|
|
168
|
+
if (idx !== -1) { node.idList.splice(idx, 1); }
|
|
163
169
|
if (node.timeout > 1000) {
|
|
164
170
|
node.status({fill:"blue",shape:"dot",text:node.idList.length});
|
|
165
171
|
}
|
|
@@ -184,7 +190,8 @@ module.exports = function(RED) {
|
|
|
184
190
|
}
|
|
185
191
|
if (delayvar < 0) { delayvar = 0; }
|
|
186
192
|
var id = ourTimeout(function() {
|
|
187
|
-
node.idList.
|
|
193
|
+
var idx = node.idList.indexOf(id);
|
|
194
|
+
if (idx !== -1) { node.idList.splice(idx, 1); }
|
|
188
195
|
if (node.idList.length === 0) { node.status({}); }
|
|
189
196
|
send(msg);
|
|
190
197
|
if (delayvar >= 0) {
|
|
@@ -192,7 +199,8 @@ module.exports = function(RED) {
|
|
|
192
199
|
}
|
|
193
200
|
done();
|
|
194
201
|
}, delayvar, () => done());
|
|
195
|
-
|
|
202
|
+
if (Object.keys(msg).length === 2 && msg.hasOwnProperty("flush")) { id.clear(); }
|
|
203
|
+
else { node.idList.push(id); }
|
|
196
204
|
if (msg.hasOwnProperty("reset")) { clearDelayList(true); }
|
|
197
205
|
if (msg.hasOwnProperty("flush")) { flushDelayList(msg.flush); done(); }
|
|
198
206
|
if (delayvar >= 0) {
|
|
@@ -206,7 +214,8 @@ module.exports = function(RED) {
|
|
|
206
214
|
node.on("input", function(msg, send, done) {
|
|
207
215
|
var wait = node.randomFirst + (node.diff * Math.random());
|
|
208
216
|
var id = ourTimeout(function() {
|
|
209
|
-
node.idList.
|
|
217
|
+
var idx = node.idList.indexOf(id);
|
|
218
|
+
if (idx !== -1) { node.idList.splice(idx, 1); }
|
|
210
219
|
send(msg);
|
|
211
220
|
if (node.timeout >= 1000) {
|
|
212
221
|
node.status({fill:"blue",shape:"dot",text:node.idList.length});
|
|
@@ -336,6 +345,42 @@ module.exports = function(RED) {
|
|
|
336
345
|
});
|
|
337
346
|
}
|
|
338
347
|
|
|
348
|
+
// Handle the burst mode
|
|
349
|
+
else if (node.pauseType === "burst") {
|
|
350
|
+
node.timers = [];
|
|
351
|
+
node.inflight = 0;
|
|
352
|
+
node.status({ fill: "green", shape: "ring", text: "" })
|
|
353
|
+
node.on("input", function(msg, send, done) {
|
|
354
|
+
if (msg.hasOwnProperty("reset")) {
|
|
355
|
+
node.timers.forEach((t) => clearTimeout(t));
|
|
356
|
+
node.timers = [];
|
|
357
|
+
node.inflight = 0;
|
|
358
|
+
node.status({ fill: "green", shape: "ring", text: "" });
|
|
359
|
+
done();
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
if (node.inflight < node.burst) {
|
|
363
|
+
node.inflight += 1;
|
|
364
|
+
send(msg);
|
|
365
|
+
node.timers[node.inflight-1] = setTimeout(() => {
|
|
366
|
+
if (node.inflight == node.burst) {
|
|
367
|
+
node.status({ fill: "green", shape: "ring", text: "" });
|
|
368
|
+
}
|
|
369
|
+
node.inflight -= 1;
|
|
370
|
+
}, node.timer);
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
if (node.outputs === 2) { send([null,msg]); }
|
|
374
|
+
node.status({ fill: "red", shape: "dot", text: "" });
|
|
375
|
+
}
|
|
376
|
+
done();
|
|
377
|
+
});
|
|
378
|
+
node.on("close", function() {
|
|
379
|
+
node.timers.forEach((t) => clearTimeout(t));
|
|
380
|
+
node.status({});
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
339
384
|
// The topic based fair queue and last arrived on all topics queue
|
|
340
385
|
else if ((node.pauseType === "queue") || (node.pauseType === "timed")) {
|
|
341
386
|
node.intervalID = setInterval(function() {
|
package/core/function/90-exec.js
CHANGED
|
@@ -105,18 +105,26 @@ module.exports = function(RED) {
|
|
|
105
105
|
}
|
|
106
106
|
node.activeProcesses[child.pid] = child;
|
|
107
107
|
child.stdout.on('data', function (data) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
108
|
+
try {
|
|
109
|
+
if (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null) {
|
|
110
|
+
// console.log('[exec] stdout: ' + data,child.pid);
|
|
111
|
+
if (isUtf8(data)) { msg.payload = data.toString(); }
|
|
112
|
+
else { msg.payload = data; }
|
|
113
|
+
nodeSend([RED.util.cloneMessage(msg),null,null]);
|
|
114
|
+
}
|
|
115
|
+
} catch (err) {
|
|
116
|
+
node.error(err.toString());
|
|
113
117
|
}
|
|
114
118
|
});
|
|
115
119
|
child.stderr.on('data', function (data) {
|
|
116
|
-
|
|
117
|
-
if (
|
|
118
|
-
|
|
119
|
-
|
|
120
|
+
try {
|
|
121
|
+
if (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null) {
|
|
122
|
+
if (isUtf8(data)) { msg.payload = data.toString(); }
|
|
123
|
+
else { msg.payload = data; }
|
|
124
|
+
nodeSend([null,RED.util.cloneMessage(msg),null]);
|
|
125
|
+
}
|
|
126
|
+
} catch (err) {
|
|
127
|
+
node.error(err.toString());
|
|
120
128
|
}
|
|
121
129
|
});
|
|
122
130
|
child.on('close', function (code,signal) {
|
package/core/network/05-tls.html
CHANGED
|
@@ -15,17 +15,18 @@
|
|
|
15
15
|
-->
|
|
16
16
|
|
|
17
17
|
<script type="text/html" data-template-name="tls-config">
|
|
18
|
-
<div class="form-row" class="hide" id="node-config-row-uselocalfiles">
|
|
19
|
-
<input type="checkbox" id="node-config-input-uselocalfiles" style="display: inline-block; width: auto; vertical-align: top;">
|
|
20
|
-
<label for="node-config-input-uselocalfiles" style="width: 70%;"><span data-i18n="tls.label.use-local-files"></label>
|
|
21
|
-
</div>
|
|
22
18
|
<div class="form-row">
|
|
23
19
|
<label style="width: 120px;" for="node-config-input-certType"><i class="fa fa-bars"></i> <span data-i18n="tls.label.certtype"></label>
|
|
24
20
|
<select id="node-config-input-certType">
|
|
25
21
|
<option value="files" data-i18n="tls.label.files"></option>
|
|
26
22
|
<option value="pfx" data-i18n="tls.label.pfx"></option>
|
|
23
|
+
<option value="env" data-i18n="tls.label.env"></option>
|
|
27
24
|
</select>
|
|
28
25
|
</div>
|
|
26
|
+
<div class="form-row" class="hide" id="node-config-row-uselocalfiles">
|
|
27
|
+
<input type="checkbox" id="node-config-input-uselocalfiles" style="display: inline-block; width: auto; vertical-align: top;">
|
|
28
|
+
<label for="node-config-input-uselocalfiles" style="width: 70%;"><span data-i18n="tls.label.use-local-files"></label>
|
|
29
|
+
</div>
|
|
29
30
|
<div class="form-row" id="node-tls-conf-cer">
|
|
30
31
|
<label style="width: 120px;"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.cert"></span></label>
|
|
31
32
|
<span class="tls-config-input-data">
|
|
@@ -38,6 +39,10 @@
|
|
|
38
39
|
<input type="hidden" id="node-config-input-certdata">
|
|
39
40
|
<input class="hide tls-config-input-path" style="width: calc(100% - 170px);" type="text" id="node-config-input-cert" data-i18n="[placeholder]tls.placeholder.cert">
|
|
40
41
|
</div>
|
|
42
|
+
<div class="form-row" id="node-tls-conf-cer-env">
|
|
43
|
+
<label style="width: 120px;"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.cert"></span></label>
|
|
44
|
+
<input type="text" id="node-config-input-certEnv">
|
|
45
|
+
</div>
|
|
41
46
|
<div class="form-row" id="node-tls-conf-key">
|
|
42
47
|
<label style="width: 120px;" for="node-config-input-key"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.key"></span></label>
|
|
43
48
|
<span class="tls-config-input-data">
|
|
@@ -50,6 +55,10 @@
|
|
|
50
55
|
<input type="hidden" id="node-config-input-keydata">
|
|
51
56
|
<input class="hide tls-config-input-path" style="width: calc(100% - 170px);" type="text" id="node-config-input-key" data-i18n="[placeholder]tls.placeholder.key">
|
|
52
57
|
</div>
|
|
58
|
+
<div class="form-row" id="node-tls-conf-key-env">
|
|
59
|
+
<label style="width: 120px;"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.key"></span></label>
|
|
60
|
+
<input type="text" id="node-config-input-keyEnv">
|
|
61
|
+
</div>
|
|
53
62
|
<div class="form-row" id="node-tls-conf-p12">
|
|
54
63
|
<label style="width: 120px;" for="node-config-input-p12"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.p12"></span></label>
|
|
55
64
|
<span class="tls-config-input-data">
|
|
@@ -78,6 +87,10 @@
|
|
|
78
87
|
<input type="hidden" id="node-config-input-cadata">
|
|
79
88
|
<input class="hide tls-config-input-path" style="width: calc(100% - 170px);" type="text" id="node-config-input-ca" data-i18n="[placeholder]tls.placeholder.ca">
|
|
80
89
|
</div>
|
|
90
|
+
<div class="form-row" id="node-tls-conf-ca-env">
|
|
91
|
+
<label style="width: 120px;"><i class="fa fa-file-text-o"></i> <span data-i18n="tls.label.ca"></span></label>
|
|
92
|
+
<input type="text" id="node-config-input-caEnv">
|
|
93
|
+
</div>
|
|
81
94
|
<div class="form-row">
|
|
82
95
|
<input type="checkbox" id="node-config-input-verifyservercert" style="display: inline-block; width: auto; vertical-align: top;">
|
|
83
96
|
<label for="node-config-input-verifyservercert" style="width: calc(100% - 170px);" data-i18n="tls.label.verify-server-cert"></label>
|
|
@@ -131,7 +144,10 @@
|
|
|
131
144
|
caname: {value:""},
|
|
132
145
|
servername: {value:""},
|
|
133
146
|
verifyservercert: {value: true},
|
|
134
|
-
alpnprotocol: {value: ""}
|
|
147
|
+
alpnprotocol: {value: ""},
|
|
148
|
+
certEnv: {value: ""},
|
|
149
|
+
keyEnv: {value: ""},
|
|
150
|
+
caEnv: {value: ""}
|
|
135
151
|
},
|
|
136
152
|
credentials: {
|
|
137
153
|
certdata: {type:"text"},
|
|
@@ -152,15 +168,45 @@
|
|
|
152
168
|
$("#node-tls-conf-cer").hide();
|
|
153
169
|
$("#node-tls-conf-key").hide();
|
|
154
170
|
$("#node-tls-conf-ca").hide();
|
|
171
|
+
$("#node-tls-conf-cer-env").hide();
|
|
172
|
+
$("#node-tls-conf-key-env").hide();
|
|
173
|
+
$("#node-tls-conf-ca-env").hide();
|
|
155
174
|
$("#node-tls-conf-p12").show();
|
|
175
|
+
$("#node-config-row-uselocalfiles").show();
|
|
156
176
|
}
|
|
157
|
-
else {
|
|
177
|
+
else if ($("#node-config-input-certType").val() === "env") {
|
|
178
|
+
$("#node-tls-conf-cer").hide();
|
|
179
|
+
$("#node-tls-conf-key").hide();
|
|
180
|
+
$("#node-tls-conf-ca").hide();
|
|
181
|
+
$("#node-tls-conf-cer-env").show();
|
|
182
|
+
$("#node-tls-conf-key-env").show();
|
|
183
|
+
$("#node-tls-conf-ca-env").show();
|
|
184
|
+
$("#node-tls-conf-p12").hide();
|
|
185
|
+
$("#node-config-row-uselocalfiles").hide();
|
|
186
|
+
} else {
|
|
158
187
|
$("#node-tls-conf-cer").show();
|
|
159
188
|
$("#node-tls-conf-key").show();
|
|
160
189
|
$("#node-tls-conf-ca").show();
|
|
190
|
+
$("#node-tls-conf-cer-env").hide();
|
|
191
|
+
$("#node-tls-conf-key-env").hide();
|
|
192
|
+
$("#node-tls-conf-ca-env").hide();
|
|
161
193
|
$("#node-tls-conf-p12").hide();
|
|
194
|
+
$("#node-config-row-uselocalfiles").show();
|
|
162
195
|
}
|
|
163
196
|
});
|
|
197
|
+
|
|
198
|
+
$("#node-config-input-certEnv").typedInput({
|
|
199
|
+
type:"env",
|
|
200
|
+
types:["env"]
|
|
201
|
+
});
|
|
202
|
+
$("#node-config-input-keyEnv").typedInput({
|
|
203
|
+
type:"env",
|
|
204
|
+
types:["env"]
|
|
205
|
+
});
|
|
206
|
+
$("#node-config-input-caEnv").typedInput({
|
|
207
|
+
type:"env",
|
|
208
|
+
types:["env"]
|
|
209
|
+
});
|
|
164
210
|
|
|
165
211
|
function updateFileUpload() {
|
|
166
212
|
if ($("#node-config-input-uselocalfiles").is(':checked')) {
|
|
@@ -218,15 +264,19 @@
|
|
|
218
264
|
$("#tls-config-button-cert-clear").on("click", function() {
|
|
219
265
|
clearNameData("cert");
|
|
220
266
|
});
|
|
267
|
+
RED.popover.tooltip($("#tls-config-button-cert-clear"), RED._("common.label.delete"));
|
|
221
268
|
$("#tls-config-button-key-clear").on("click", function() {
|
|
222
269
|
clearNameData("key");
|
|
223
270
|
});
|
|
271
|
+
RED.popover.tooltip($("#tls-config-button-key-clear"), RED._("common.label.delete"));
|
|
224
272
|
$("#tls-config-button-ca-clear").on("click", function() {
|
|
225
273
|
clearNameData("ca");
|
|
226
274
|
});
|
|
275
|
+
RED.popover.tooltip($("#tls-config-button-ca-clear"), RED._("common.label.delete"));
|
|
227
276
|
$("#tls-config-button-p12-clear").on("click", function() {
|
|
228
277
|
clearNameData("p12");
|
|
229
278
|
});
|
|
279
|
+
RED.popover.tooltip($("#tls-config-button-p12-clear"), RED._("common.label.delete"));
|
|
230
280
|
|
|
231
281
|
if (RED.settings.tlsConfigDisableLocalFiles) {
|
|
232
282
|
$("#node-config-row-uselocalfiles").hide();
|
package/core/network/05-tls.js
CHANGED
|
@@ -23,10 +23,14 @@ module.exports = function(RED) {
|
|
|
23
23
|
this.valid = true;
|
|
24
24
|
this.verifyservercert = n.verifyservercert;
|
|
25
25
|
var certPath, keyPath, caPath, p12Path;
|
|
26
|
+
var certEnv, keyEnv, caEnv;
|
|
26
27
|
if (n.cert) { certPath = n.cert.trim(); }
|
|
27
28
|
if (n.key) { keyPath = n.key.trim(); }
|
|
28
29
|
if (n.ca) { caPath = n.ca.trim(); }
|
|
29
30
|
if (n.p12) { p12Path = n.p12.trim(); }
|
|
31
|
+
if (n.certEnv) { certEnv = n.certEnv }
|
|
32
|
+
if (n.keyEnv) { keyEnv = n.keyEnv }
|
|
33
|
+
if (n.caEnv) { caEnv = n.caEnv }
|
|
30
34
|
this.certType = n.certType || "files";
|
|
31
35
|
this.servername = (n.servername||"").trim();
|
|
32
36
|
this.alpnprotocol = (n.alpnprotocol||"").trim();
|
|
@@ -41,13 +45,23 @@ module.exports = function(RED) {
|
|
|
41
45
|
return;
|
|
42
46
|
}
|
|
43
47
|
}
|
|
48
|
+
else if (this.certType === "env") {
|
|
49
|
+
if (certEnv) {
|
|
50
|
+
this.certEnv = Buffer.from(RED.util.evaluateNodeProperty(certEnv, 'env', this))
|
|
51
|
+
}
|
|
52
|
+
if (keyEnv) {
|
|
53
|
+
this.keyEnv = Buffer.from(RED.util.evaluateNodeProperty(keyEnv, 'env', this))
|
|
54
|
+
}
|
|
55
|
+
if (caEnv) {
|
|
56
|
+
this.caEnv = Buffer.from(RED.util.evaluateNodeProperty(caEnv, 'env', this))
|
|
57
|
+
}
|
|
58
|
+
}
|
|
44
59
|
else if ((certPath && certPath.length > 0) || (keyPath && keyPath.length > 0) || (caPath && caPath.length > 0)) {
|
|
45
60
|
if ( (certPath && certPath.length > 0) !== (keyPath && keyPath.length > 0)) {
|
|
46
61
|
this.valid = false;
|
|
47
62
|
this.error(RED._("tls.error.missing-file"));
|
|
48
63
|
return;
|
|
49
64
|
}
|
|
50
|
-
|
|
51
65
|
try {
|
|
52
66
|
if (certPath) {
|
|
53
67
|
this.cert = fs.readFileSync(certPath);
|
|
@@ -122,6 +136,17 @@ module.exports = function(RED) {
|
|
|
122
136
|
opts.ca = this.ca;
|
|
123
137
|
}
|
|
124
138
|
}
|
|
139
|
+
else if (this.certType === "env") {
|
|
140
|
+
if (this.keyEnv) {
|
|
141
|
+
opts.key = this.keyEnv
|
|
142
|
+
}
|
|
143
|
+
if (this.certEnv) {
|
|
144
|
+
opts.cert= this.certEnv
|
|
145
|
+
}
|
|
146
|
+
if (this.caEnv) {
|
|
147
|
+
opts.ca = this.caEnv
|
|
148
|
+
}
|
|
149
|
+
}
|
|
125
150
|
else {
|
|
126
151
|
if (this.pfx) {
|
|
127
152
|
opts.pfx = this.pfx;
|
package/core/network/10-mqtt.js
CHANGED
|
@@ -227,6 +227,7 @@ module.exports = function(RED) {
|
|
|
227
227
|
* Handle the payload / packet recieved in MQTT In and MQTT Sub nodes
|
|
228
228
|
*/
|
|
229
229
|
function subscriptionHandler(node, datatype ,topic, payload, packet) {
|
|
230
|
+
if (!packet) { packet = {}; }
|
|
230
231
|
const msg = {topic:topic, payload:null, qos:packet.qos, retain:packet.retain};
|
|
231
232
|
const v5 = (node && node.brokerConn)
|
|
232
233
|
? node.brokerConn.v5()
|
|
@@ -1074,12 +1075,16 @@ module.exports = function(RED) {
|
|
|
1074
1075
|
|
|
1075
1076
|
if (!subscription.handler) {
|
|
1076
1077
|
subscription.handler = function (mtopic, mpayload, mpacket) {
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1078
|
+
try {
|
|
1079
|
+
const sops = subscription.options ? subscription.options.properties : {}
|
|
1080
|
+
const pops = (mpacket && mpacket.properties) || {}
|
|
1081
|
+
if (subIdsAvailable && pops.subscriptionIdentifier && sops.subscriptionIdentifier && (pops.subscriptionIdentifier !== sops.subscriptionIdentifier)) {
|
|
1082
|
+
//do nothing as subscriptionIdentifier does not match
|
|
1083
|
+
} else if (matchTopic(topic, mtopic)) {
|
|
1084
|
+
subscription.callback && subscription.callback(mtopic, mpayload, mpacket)
|
|
1085
|
+
}
|
|
1086
|
+
} catch (err) {
|
|
1087
|
+
node.error("MQTT subscription handler error: " + err.toString());
|
|
1083
1088
|
}
|
|
1084
1089
|
}
|
|
1085
1090
|
}
|