Partial fix for Issue #45 - allows msg.destip and msg.port properties to override static config.

Signed-off-by: Dave C-J <dave@conway-jones.co.uk>
This commit is contained in:
Dave C-J 2013-10-24 19:58:57 +01:00
parent f1f00da1a8
commit a4160a6bea
2 changed files with 84 additions and 78 deletions

View File

@ -63,6 +63,7 @@
<script type="text/x-red" data-help-name="udp in"> <script type="text/x-red" data-help-name="udp in">
<p>A udp input node, that produces a <b>msg.payload</b> containing a <i>BUFFER</i>, string, or base64 encoded string. Supports multicast.</p> <p>A udp input node, that produces a <b>msg.payload</b> containing a <i>BUFFER</i>, string, or base64 encoded string. Supports multicast.</p>
<p>It also provides <b>msg.fromip</b> in the form ipaddress:port .</p> <p>It also provides <b>msg.fromip</b> in the form ipaddress:port .</p>
<p>On some systems you may need to be root to use ports below 1024 and/or broadcast.</p>
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
@ -145,8 +146,9 @@
<script type="text/x-red" data-help-name="udp out"> <script type="text/x-red" data-help-name="udp out">
<p>This node sends <b>msg.payload</b> to the designated udp host and port. Supports multicast.</p> <p>This node sends <b>msg.payload</b> to the designated udp host and port. Supports multicast.</p>
<p>You may also use <b>msg.destip</b> and <b>msg.port</b> to override the values manually configured.</p>
<p>If you select broadcast either set the address to the local broadcast ip address, or maybe try 255.255.255.255, which is the global broadcast address.</p> <p>If you select broadcast either set the address to the local broadcast ip address, or maybe try 255.255.255.255, which is the global broadcast address.</p>
<p>On some systems you may need to be root to use broadcast.</p> <p>On some systems you may need to be root to use ports below 1024 and/or broadcast.</p>
</script> </script>
<script type="text/javascript"> <script type="text/javascript">

View File

@ -19,97 +19,101 @@ var dgram = require('dgram');
// The Input Node // The Input Node
function UDPin(n) { function UDPin(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
this.group = n.group; this.group = n.group;
this.port = n.port; this.port = n.port;
this.host = n.host || null; this.host = n.host || null;
this.datatype = n.datatype; this.datatype = n.datatype;
this.iface = n.iface || null; this.iface = n.iface || null;
this.multicast = n.multicast; this.multicast = n.multicast;
var node = this; var node = this;
var server = dgram.createSocket('udp4'); var server = dgram.createSocket('udp4');
server.on("error", function (err) { server.on("error", function (err) {
console.log("udp listener error:\n" + err.stack); //console.log("udp listener error:\n" + err.stack);
server.close(); if ((err.code == "EACCES") && (node.port < 1024)) { node.error("UDP access error, you may need root access for ports below 1024"); }
}); else { node.error("UDP error : "+err.code); }
server.close();
});
server.on('message', function (message, remote) { server.on('message', function (message, remote) {
var msg; var msg;
if (node.datatype =="base64") { msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port }; } if (node.datatype =="base64") { msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port }; }
else if (node.datatype =="utf8") { msg = { payload:message.toString('utf8'), fromip:remote.address+':'+remote.port }; } else if (node.datatype =="utf8") { msg = { payload:message.toString('utf8'), fromip:remote.address+':'+remote.port }; }
else { msg = { payload:message, fromip:remote.address+':'+remote.port }; } else { msg = { payload:message, fromip:remote.address+':'+remote.port }; }
node.send(msg); node.send(msg);
}); });
server.on('listening', function () { server.on('listening', function () {
var address = server.address(); var address = server.address();
node.log('udp listener at ' + address.address + ":" + address.port); node.log('udp listener at ' + address.address + ":" + address.port);
if (node.multicast == "true") { if (node.multicast == "true") {
server.setBroadcast(true) server.setBroadcast(true)
server.setMulticastTTL(128); server.setMulticastTTL(128);
server.addMembership(node.group,node.iface); server.addMembership(node.group,node.iface);
node.log("udp multicast group "+node.group); node.log("udp multicast group "+node.group);
} }
}); });
node.on("close", function() { node.on("close", function() {
try { try {
server.close(); server.close();
node.log('udp listener stopped'); node.log('udp listener stopped');
} }
catch (err) { console.log(err); } catch (err) { console.log(err); }
}); });
server.bind(node.port,node.host); server.bind(node.port,node.host);
} }
RED.nodes.registerType("udp in",UDPin); RED.nodes.registerType("udp in",UDPin);
// The Output Node // The Output Node
function UDPout(n) { function UDPout(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
//this.group = n.group; //this.group = n.group;
this.port = n.port; this.port = n.port;
this.base64 = n.base64; this.base64 = n.base64;
this.addr = n.addr; this.addr = n.addr;
this.iface = n.iface || null; this.iface = n.iface || null;
this.multicast = n.multicast; this.multicast = n.multicast;
var node = this; var node = this;
var sock = dgram.createSocket('udp4'); // only use ipv4 for now var sock = dgram.createSocket('udp4'); // only use ipv4 for now
sock.bind(node.port); // have to bind before you can enable broadcast... sock.bind(node.port); // have to bind before you can enable broadcast...
if (this.multicast != "false") { if (this.multicast != "false") {
sock.setBroadcast(true); // turn on broadcast sock.setBroadcast(true); // turn on broadcast
if (this.multicast == "multi") { if (this.multicast == "multi") {
sock.setMulticastTTL(128); sock.setMulticastTTL(128);
sock.addMembership(node.addr,node.iface); // Add to the multicast group sock.addMembership(node.addr,node.iface); // Add to the multicast group
node.log('udp multicast ready : '+node.addr+":"+node.port); node.log('udp multicast ready : '+node.addr+":"+node.port);
} }
else node.log('udp broadcast ready : '+node.addr+":"+node.port); else node.log('udp broadcast ready : '+node.addr+":"+node.port);
} }
else node.log('udp ready : '+node.addr+":"+node.port); else node.log('udp ready : '+node.addr+":"+node.port);
node.on("input", function(msg) { node.on("input", function(msg) {
if (msg.payload != null) { if (msg.payload != null) {
//console.log("UDP:",msg.payload); //console.log("UDP:",msg.payload);
var message; var add = msg.destip || node.addr;
if (node.base64) { message = new Buffer(b64string, 'base64'); } var por = msg.port || node.addr;
else { message = new Buffer(""+msg.payload); } var message;
console.log("UDP send :",node.addr,node.port); if (node.base64) { message = new Buffer(b64string, 'base64'); }
sock.send(message, 0, message.length, node.port, node.addr, function(err, bytes) { else { message = new Buffer(""+msg.payload); }
if (err) node.error("udp : "+err); //console.log("UDP send :",add,por);
}); sock.send(message, 0, message.length, por, add, function(err, bytes) {
} if (err) node.error("udp : "+err);
}); });
}
});
node.on("close", function() { node.on("close", function() {
try { try {
sock.close(); sock.close();
node.log('udp output stopped'); node.log('udp output stopped');
} }
catch (err) { console.log(err); } catch (err) { console.log(err); }
}); });
} }
RED.nodes.registerType("udp out",UDPout); RED.nodes.registerType("udp out",UDPout);