mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Add setting to disable tcp/udp server (inbound)
This commit is contained in:
parent
7da3773f7f
commit
5a21f026f2
@ -70,7 +70,16 @@
|
||||
color: "Silver",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
server: {value:"server", required:true},
|
||||
server: {
|
||||
value: RED.settings.tcpInAllowInboundConnections === false ? "client" : "server",
|
||||
validate: function(v, opt) {
|
||||
console.log("validating client/server mode")
|
||||
if (v === 'server' && RED.settings.tcpInAllowInboundConnections === false) {
|
||||
return RED._("node-red:tcpin.errors.inbound-disabled");
|
||||
}
|
||||
return ["client", "server"].indexOf(v) >= 0
|
||||
}
|
||||
},
|
||||
host: {
|
||||
value:"",
|
||||
validate:function(v, opt) {
|
||||
@ -218,7 +227,16 @@
|
||||
return RED._("node-red:tcpin.errors.invalid-port");
|
||||
}
|
||||
},
|
||||
beserver: {value:"client", required:true},
|
||||
beserver: {
|
||||
value: "client",
|
||||
validate: function(v, opt) {
|
||||
console.log("validating client/server mode")
|
||||
if (v === 'server' && RED.settings.tcpInAllowInboundConnections === false) {
|
||||
return RED._("node-red:tcpin.errors.inbound-disabled");
|
||||
}
|
||||
return ["client", "server", "reply"].indexOf(v) >= 0
|
||||
}
|
||||
},
|
||||
base64: {value:false, required:true},
|
||||
end: {value:false, required:true},
|
||||
tls: {type:"tls-config", value:'', required:false,
|
||||
|
@ -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.errors.inbound-disabled",{host:node.host,port:node.port}));
|
||||
node.status({fill:"red",shape:"dot",text:"tcpin.errors.inbound-disabled"});
|
||||
}
|
||||
}
|
||||
RED.nodes.registerType("tcp in",TcpIn);
|
||||
RED.nodes.registerType("tcp in",TcpIn, {
|
||||
settings: {
|
||||
tcpInAllowInboundConnections: {
|
||||
value: true,
|
||||
exportable: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function TcpOut(n) {
|
||||
@ -434,7 +444,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;
|
||||
@ -507,11 +517,13 @@ module.exports = function(RED) {
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
node.warn(RED._("tcpin.errors.inbound-disabled",{host:node.host,port:node.port}));
|
||||
node.status({fill:"red",shape:"dot",text:"tcpin.errors.inbound-disabled"});
|
||||
}
|
||||
}
|
||||
RED.nodes.registerType("tcp out",TcpOut);
|
||||
|
||||
|
||||
function TcpGet(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.server = n.server;
|
||||
|
@ -18,7 +18,7 @@
|
||||
<script type="text/html" data-template-name="udp in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-port"><i class="fa fa-sign-in"></i> <span data-i18n="udp.label.listen"></span></label>
|
||||
<select id="node-input-multicast" style='width:70%'>
|
||||
<select id="node-input-multicast" style="width:70%">
|
||||
<option value="false" data-i18n="udp.udpmsgs"></option>
|
||||
<option value="true" data-i18n="udp.mcmsgs"></option>
|
||||
</select>
|
||||
@ -68,7 +68,16 @@
|
||||
validate:RED.validators.number(false)
|
||||
},
|
||||
ipv: {value:"udp4"},
|
||||
multicast: {value:"false"},
|
||||
multicast: {
|
||||
value:"false",
|
||||
validate: function(v, opt) {
|
||||
console.log("validating client/server mode")
|
||||
if (RED.settings.udpInAllowInboundConnections === false) {
|
||||
return RED._("node-red:udp.errors.inbound-disabled");
|
||||
}
|
||||
return true
|
||||
}
|
||||
},
|
||||
group: {
|
||||
value:"",
|
||||
validate:function(v,opt) {
|
||||
|
@ -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.errors.inbound-disabled",{host:node.host,port:node.port}));
|
||||
node.status({fill:"red",shape:"dot",text:"udp.errors.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
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
@ -647,6 +647,7 @@
|
||||
"connections_plural": "__count__ connections"
|
||||
},
|
||||
"errors": {
|
||||
"inbound-disabled": "inbound connections are disabled",
|
||||
"connection-lost": "connection lost to __host__:__port__",
|
||||
"timeout": "timeout closed socket port __port__",
|
||||
"cannot-listen": "unable to listen on port __port__, error: __error__",
|
||||
@ -711,6 +712,7 @@
|
||||
"re-use": "udp re-use socket: __outport__ -> __host__:__port__"
|
||||
},
|
||||
"errors": {
|
||||
"inbound-disabled": "inbound connections are disabled",
|
||||
"access-error": "UDP access error, you may need root access for ports below 1024",
|
||||
"error": "error: __error__",
|
||||
"bad-mcaddress": "Bad Multicast Address",
|
||||
|
Loading…
x
Reference in New Issue
Block a user