diff --git a/packages/node_modules/@node-red/editor-client/src/sass/editor.scss b/packages/node_modules/@node-red/editor-client/src/sass/editor.scss index dcc8060d4..090a0e518 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/editor.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/editor.scss @@ -231,6 +231,12 @@ button.red-ui-tray-resize-button { border: 1px solid var(--red-ui-secondary-border-color); max-width: 450px; } + .form-row > div.form-tips { + width: 70%; + display: inline-block; + box-sizing: border-box; + max-width: 350px; // 100 less for label width + } .form-tips code { border: none; padding: auto; diff --git a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.html b/packages/node_modules/@node-red/nodes/core/network/31-tcpin.html index d967ca971..701db4e6e 100644 --- a/packages/node_modules/@node-red/nodes/core/network/31-tcpin.html +++ b/packages/node_modules/@node-red/nodes/core/network/31-tcpin.html @@ -23,6 +23,12 @@ + +
+ +
+
+ @@ -70,7 +76,9 @@ color: "Silver", defaults: { name: {value:""}, - server: {value:"server", required:true}, + server: { + value: RED.settings.tcpInAllowInboundConnections === false ? "client" : "server", + }, host: { value:"", validate:function(v, opt) { @@ -107,8 +115,14 @@ var sockettype = $("#node-input-server").val(); if (sockettype == "client") { $("#node-input-host-row").show(); + $(".form-row.inbound-disabled-tip").addClass("hide") } else { $("#node-input-host-row").hide(); + if(RED.settings.tcpInAllowInboundConnections === false) { + $(".form-row.inbound-disabled-tip").removeClass("hide") + } else { + $(".form-row.inbound-disabled-tip").addClass("hide") + } } var datamode = $("#node-input-datamode").val(); var datatype = $("#node-input-datatype").val(); @@ -142,6 +156,11 @@ $("#node-input-usetls").on("click",function() { updateTLSOptions(); }); + setTimeout(function() { + // form tips have a max-width to prevent the initial edit form size calc making it overly large. + // once the form is built and displayed, remove the size limit so that it sizes with the other elements. + $('.form-tips').css({"max-width": "unset"}) + }, 500) }, oneditsave: function() { if (!$("#node-input-usetls").is(':checked')) { @@ -162,7 +181,10 @@ - +
+ +
+
@@ -242,16 +264,23 @@ $("#node-input-host-row").hide(); $("#node-input-end-row").hide(); $("#node-input-tls-enable").hide(); + $(".form-row.inbound-disabled-tip").addClass("hide") } else if (sockettype == "client"){ $("#node-input-port-row").show(); $("#node-input-host-row").show(); $("#node-input-end-row").show(); $("#node-input-tls-enable").show(); + $(".form-row.inbound-disabled-tip").addClass("hide") } else { $("#node-input-port-row").show(); $("#node-input-host-row").hide(); $("#node-input-end-row").show(); $("#node-input-tls-enable").show(); + if(RED.settings.tcpInAllowInboundConnections === false) { + $(".form-row.inbound-disabled-tip").removeClass("hide") + } else { + $(".form-row.inbound-disabled-tip").addClass("hide") + } } }; updateOptions(); @@ -272,6 +301,11 @@ $("#node-input-usetls").on("click",function() { updateTLSOptions(); }); + setTimeout(function() { + // form tips have a max-width to prevent the initial edit form size calc making it overly large. + // once the form is built and displayed, remove the size limit so that it sizes with the other elements. + $('.form-tips').css({"max-width": "unset"}) + }, 500) }, oneditsave: function() { if (!$("#node-input-usetls").is(':checked')) { 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 500bbe2c2..7fce37d37 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 @@ -19,6 +19,7 @@ module.exports = function(RED) { let reconnectTime = RED.settings.socketReconnectTime || 10000; let socketTimeout = RED.settings.socketTimeout || null; const msgQueueSize = RED.settings.tcpMsgQueueSize || 1000; + const allowInbound = RED.settings.tcpInAllowInboundConnections === false ? false : true const Denque = require('denque'); const net = require('net'); const tls = require('tls'); @@ -196,8 +197,7 @@ module.exports = function(RED) { clearTimeout(reconnectTimeout); if (!node.connected) { done(); } }); - } - else { + } else if (allowInbound) { let srv = net; let connOpts; if (n.tls) { @@ -308,9 +308,19 @@ module.exports = function(RED) { }); } }); + } else { + node.warn(RED._("tcpin.status.inbound-disabled",{host:node.host,port:node.port})); + node.status({fill:"gray",shape:"circle",text:"tcpin.status.inbound-disabled"}); } } - RED.nodes.registerType("tcp in",TcpIn); + RED.nodes.registerType("tcp in",TcpIn, { + settings: { + tcpInAllowInboundConnections: { + value: true, + exportable: true + } + } + }); function TcpOut(n) { @@ -444,7 +454,7 @@ module.exports = function(RED) { nodeDone(); }); } - else { + else if (allowInbound) { const connectedSockets = new Set(); node.status({text:RED._("tcpin.status.connections",{count:0})}); let srv = net; @@ -517,11 +527,13 @@ module.exports = function(RED) { }); } }); + } else { + node.warn(RED._("tcpin.status.inbound-disabled",{host:node.host,port:node.port})); + node.status({fill:"gray",shape:"circle",text:"tcpin.status.inbound-disabled"}); } } RED.nodes.registerType("tcp out",TcpOut); - function TcpGet(n) { RED.nodes.createNode(this,n); this.server = n.server; diff --git a/packages/node_modules/@node-red/nodes/core/network/32-udp.html b/packages/node_modules/@node-red/nodes/core/network/32-udp.html index 4d5eeb23e..f70cf973d 100644 --- a/packages/node_modules/@node-red/nodes/core/network/32-udp.html +++ b/packages/node_modules/@node-red/nodes/core/network/32-udp.html @@ -18,11 +18,15 @@ diff --git a/packages/node_modules/@node-red/nodes/core/network/32-udp.js b/packages/node_modules/@node-red/nodes/core/network/32-udp.js index d42d3a7c3..e3b202182 100644 --- a/packages/node_modules/@node-red/nodes/core/network/32-udp.js +++ b/packages/node_modules/@node-red/nodes/core/network/32-udp.js @@ -16,9 +16,10 @@ module.exports = function(RED) { "use strict"; - var os = require('os'); - var dgram = require('dgram'); - var udpInputPortsInUse = {}; + const os = require('os'); + const dgram = require('dgram'); + const udpInputPortsInUse = {}; + const allowInbound = RED.settings.udpInAllowInboundConnections === false ? false : true // The Input Node function UDPin(n) { @@ -29,97 +30,102 @@ module.exports = function(RED) { this.iface = n.iface || null; this.multicast = n.multicast; this.ipv = n.ipv || "udp4"; - var node = this; - - if (node.iface && node.iface.indexOf(".") === -1) { - try { - if ((os.networkInterfaces())[node.iface][0].hasOwnProperty("scopeid")) { - if (node.ipv === "udp4") { - node.iface = (os.networkInterfaces())[node.iface][1].address; - } else { - node.iface = (os.networkInterfaces())[node.iface][0].address; - } - } - else { - if (node.ipv === "udp4") { - node.iface = (os.networkInterfaces())[node.iface][0].address; - } else { - node.iface = (os.networkInterfaces())[node.iface][1].address; - } - } - } - catch(e) { - node.warn(RED._("udp.errors.ifnotfound",{iface:node.iface})); - node.iface = null; - } - } - - var opts = {type:node.ipv, reuseAddr:true}; - if (process.version.indexOf("v0.10") === 0) { opts = node.ipv; } - var server; - - if (!udpInputPortsInUse.hasOwnProperty(node.port)) { - server = dgram.createSocket(opts); // default to udp4 - server.bind(node.port, function() { - if (node.multicast == "true") { - server.setBroadcast(true); - server.setMulticastLoopback(false); - try { - server.setMulticastTTL(128); - server.addMembership(node.group,node.iface); - if (node.iface) { node.status({text:n.iface+" : "+node.iface}); } - node.log(RED._("udp.status.mc-group",{group:node.group})); - } catch (e) { - if (e.errno == "EINVAL") { - node.error(RED._("udp.errors.bad-mcaddress")); - } else if (e.errno == "ENODEV") { - node.error(RED._("udp.errors.interface")); + const node = this; + let server; + if (allowInbound) { + if (node.iface && node.iface.indexOf(".") === -1) { + try { + if ((os.networkInterfaces())[node.iface][0].hasOwnProperty("scopeid")) { + if (node.ipv === "udp4") { + node.iface = (os.networkInterfaces())[node.iface][1].address; } else { - node.error(RED._("udp.errors.error",{error:e.errno})); + node.iface = (os.networkInterfaces())[node.iface][0].address; + } + } + else { + if (node.ipv === "udp4") { + node.iface = (os.networkInterfaces())[node.iface][0].address; + } else { + node.iface = (os.networkInterfaces())[node.iface][1].address; } } } + catch(e) { + node.warn(RED._("udp.errors.ifnotfound",{iface:node.iface})); + node.iface = null; + } + } + + let opts = {type:node.ipv, reuseAddr:true}; + if (process.version.indexOf("v0.10") === 0) { opts = node.ipv; } + + if (!udpInputPortsInUse.hasOwnProperty(node.port)) { + server = dgram.createSocket(opts); // default to udp4 + server.bind(node.port, function() { + if (node.multicast == "true") { + server.setBroadcast(true); + server.setMulticastLoopback(false); + try { + server.setMulticastTTL(128); + server.addMembership(node.group,node.iface); + if (node.iface) { node.status({text:n.iface+" : "+node.iface}); } + node.log(RED._("udp.status.mc-group",{group:node.group})); + } catch (e) { + if (e.errno == "EINVAL") { + node.error(RED._("udp.errors.bad-mcaddress")); + } else if (e.errno == "ENODEV") { + node.error(RED._("udp.errors.interface")); + } else { + node.error(RED._("udp.errors.error",{error:e.errno})); + } + } + } + }); + udpInputPortsInUse[node.port] = server; + } + else { + node.log(RED._("udp.errors.alreadyused",{port:node.port})); + server = udpInputPortsInUse[node.port]; // re-use existing + if (node.iface) { node.status({text:n.iface+" : "+node.iface}); } + } + + server.on("error", function (err) { + if ((err.code == "EACCES") && (node.port < 1024)) { + node.error(RED._("udp.errors.access-error")); + } else { + node.error(RED._("udp.errors.error",{error:err.code})); + } + server.close(); }); - udpInputPortsInUse[node.port] = server; + + server.on('message', function (message, remote) { + let msg; + if (node.datatype =="base64") { + msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port }; + } else if (node.datatype =="utf8") { + msg = { payload:message.toString('utf8'), fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port }; + } else { + msg = { payload:message, fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port }; + } + node.send(msg); + }); + + server.on('listening', function () { + const address = server.address(); + node.log(RED._("udp.status.listener-at",{host:node.iface||address.address,port:address.port})); + + }); + } else { + node.warn(RED._("udp.status.inbound-disabled",{host:node.host,port:node.port})); + node.status({fill:"gray",shape:"circle",text:"udp.status.inbound-disabled"}); } - else { - node.log(RED._("udp.errors.alreadyused",{port:node.port})); - server = udpInputPortsInUse[node.port]; // re-use existing - if (node.iface) { node.status({text:n.iface+" : "+node.iface}); } - } - - server.on("error", function (err) { - if ((err.code == "EACCES") && (node.port < 1024)) { - node.error(RED._("udp.errors.access-error")); - } else { - node.error(RED._("udp.errors.error",{error:err.code})); - } - server.close(); - }); - - server.on('message', function (message, remote) { - var msg; - if (node.datatype =="base64") { - msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port }; - } else if (node.datatype =="utf8") { - msg = { payload:message.toString('utf8'), fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port }; - } else { - msg = { payload:message, fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port }; - } - node.send(msg); - }); - - server.on('listening', function () { - var address = server.address(); - node.log(RED._("udp.status.listener-at",{host:node.iface||address.address,port:address.port})); - - }); - node.on("close", function() { try { - if (node.multicast == "true") { server.dropMembership(node.group); } - server.close(); - node.log(RED._("udp.status.listener-stopped")); + if (server) { + if (node.multicast == "true") { server.dropMembership(node.group); } + server.close(); + node.log(RED._("udp.status.listener-stopped")); + } } catch (err) { //node.error(err); } @@ -133,7 +139,14 @@ module.exports = function(RED) { RED.httpAdmin.get('/udp-ports/:id', RED.auth.needsPermission('udp-ports.read'), function(req,res) { res.json(Object.keys(udpInputPortsInUse)); }); - RED.nodes.registerType("udp in",UDPin); + RED.nodes.registerType("udp in",UDPin, { + settings: { + udpInAllowInboundConnections: { + value: true, + exportable: true + } + } + }); diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json index bc89992e2..219ec94f6 100644 --- a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json +++ b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json @@ -650,6 +650,9 @@ "never": "never - keep connection open", "immed": "immediately - don't wait for reply" }, + "tip": { + "inbound-disabled": "inbound connections are disabled for this Node-RED instance" + }, "status": { "connecting": "connecting to __host__:__port__", "connected": "connected to __host__:__port__", @@ -658,7 +661,8 @@ "connection-from": "connection from __host__:__port__", "connection-closed": "connection closed from __host__:__port__", "connections": "__count__ connection", - "connections_plural": "__count__ connections" + "connections_plural": "__count__ connections", + "inbound-disabled": "inbound connections are disabled" }, "errors": { "connection-lost": "connection lost to __host__:__port__", @@ -711,7 +715,8 @@ "tip": { "in": "Tip: Make sure your firewall will allow the data in.", "out": "Tip: leave address and port blank if you want to set using msg.ip and msg.port.", - "port": "Ports already in use: " + "port": "Ports already in use: ", + "inbound-disabled": "inbound connections are disabled for this Node-RED instance" }, "status": { "listener-at": "udp listener at __host__:__port__", @@ -722,7 +727,8 @@ "bc-ready": "udp broadcast ready: __outport__ -> __host__:__port__", "ready": "udp ready: __outport__ -> __host__:__port__", "ready-nolocal": "udp ready: __host__:__port__", - "re-use": "udp re-use socket: __outport__ -> __host__:__port__" + "re-use": "udp re-use socket: __outport__ -> __host__:__port__", + "inbound-disabled": "inbound connections are disabled" }, "errors": { "access-error": "UDP access error, you may need root access for ports below 1024", 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 708df0449..574891304 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 @@ -16,9 +16,11 @@