aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorMartin Peach <mrpeach@users.sourceforge.net>2010-07-30 19:09:36 +0000
committerMartin Peach <mrpeach@users.sourceforge.net>2010-07-30 19:09:36 +0000
commit68557af56a0a729e4456ac1c246b06f0b17a6abc (patch)
tree505e80c38880e8cb542441722d6fdfbf3e48bbcf /net
parentd4d83ffdf3500990354da688eac349ebd20f33ce (diff)
Added method to select interface when multicasting, updated help patch.
svn path=/trunk/externals/mrpeach/; revision=13734
Diffstat (limited to 'net')
-rw-r--r--net/udpsend-help.pd73
-rw-r--r--net/udpsend.c85
2 files changed, 128 insertions, 30 deletions
diff --git a/net/udpsend-help.pd b/net/udpsend-help.pd
index 0114f07..7401fa5 100644
--- a/net/udpsend-help.pd
+++ b/net/udpsend-help.pd
@@ -1,31 +1,44 @@
-#N canvas 609 110 590 348 12;
-#X msg 72 182 disconnect;
-#X msg 16 59 connect 127.0.0.1 9997;
-#X obj 16 306 tgl 15 0 empty empty connected 20 7 0 8 -24198 -241291
--1 1 1;
-#X text 220 60 <--first;
-#X msg 25 81 send 0 1 2 3;
-#X text 8 5 udpsend sends bytes over a udp connection.;
-#X text 8 28 Used in conjunction with packOSC will send OSC over udp
-;
-#X obj 16 283 udpsend;
-#X msg 32 103 send ../doc/5.reference/test.txt;
-#X obj 387 151 openpanel;
-#X msg 387 175 send \$1;
-#X obj 387 132 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -241291
+#N canvas 304 215 898 550 12;
+#X msg 268 188 disconnect;
+#X msg 87 7 connect 127.0.0.1 9997;
+#X obj 405 368 tgl 15 0 empty empty connected 20 7 0 8 -24198 -241291
+-1 0 1;
+#X msg 109 29 send 0 1 2 3;
+#X text 100 345 udpsend sends bytes over a udp connection.;
+#X text 177 395 Used in conjunction with packOSC will send OSC over
+udp;
+#X obj 405 345 udpsend;
+#X msg 131 51 send ../doc/5.reference/test.txt;
+#X obj 201 97 openpanel;
+#X msg 201 121 send \$1;
+#X obj 201 78 bng 15 250 50 0 empty empty empty 17 7 0 10 -24198 -241291
-1;
-#X text 327 104 send a file;
-#X text 141 81 send raw data;
-#X text 410 130 ...any file;
-#X msg 40 126 99 98 97;
-#X text 361 311 Martin Peach 2007/06/20;
-#X text 120 126 'send' prefix is optional;
-#X connect 0 0 7 0;
-#X connect 1 0 7 0;
-#X connect 4 0 7 0;
-#X connect 7 0 2 0;
-#X connect 8 0 7 0;
-#X connect 9 0 10 0;
-#X connect 10 0 7 0;
-#X connect 11 0 9 0;
-#X connect 15 0 7 0;
+#X text 42 52 send a file;
+#X text 207 28 send raw data;
+#X text 221 77 ...any file;
+#X msg 234 154 99 98 97;
+#X text 299 154 'send' prefix is optional;
+#X msg 371 291 multicast_interface 192.168.0.88;
+#X msg 346 266 multicast_interface eth1;
+#X msg 298 218 connect 239.200.200.200 9977;
+#X text 595 358 Martin Peach 2010/07/30;
+#X text 251 6 <--first connect to a host and port;
+#X text 349 187 <--disconnect before connecting to another address
+;
+#X text 509 217 send to a multicast address;
+#X text 481 242 specify an interface to use with multicast;
+#X msg 323 243 multicast_interface 1;
+#X text 531 265 by index \, name or address;
+#X connect 0 0 6 0;
+#X connect 1 0 6 0;
+#X connect 3 0 6 0;
+#X connect 6 0 2 0;
+#X connect 7 0 6 0;
+#X connect 8 0 9 0;
+#X connect 9 0 6 0;
+#X connect 10 0 8 0;
+#X connect 14 0 6 0;
+#X connect 16 0 6 0;
+#X connect 17 0 6 0;
+#X connect 18 0 6 0;
+#X connect 24 0 6 0;
diff --git a/net/udpsend.c b/net/udpsend.c
index 2cf082b..a281e23 100644
--- a/net/udpsend.c
+++ b/net/udpsend.c
@@ -18,6 +18,9 @@
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
+#include <sys/ioctl.h> // for SIOCGIFCONF
+#include <net/if.h> // for SIOCGIFCONF
+#include <arpa/inet.h>
#endif
static t_class *udpsend_class;
@@ -33,6 +36,7 @@ static void udpsend_free(t_udpsend *x);
static void udpsend_send(t_udpsend *x, t_symbol *s, int argc, t_atom *argv);
static void udpsend_disconnect(t_udpsend *x);
static void udpsend_connect(t_udpsend *x, t_symbol *hostname, t_floatarg fportno);
+static void udpsend_set_multicast_interface (t_udpsend *x, t_symbol *s, int argc, t_atom *argv);
static void *udpsend_new(void);
static void *udpsend_new(void)
@@ -87,6 +91,8 @@ Enable sending of broadcast messages (if hostname is a broadcast address)*/
}
memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
+ if (0xE0000000 == (ntohl(server.sin_addr.s_addr) & 0xF0000000))
+ post ("udpsend: connecting to a multicast address");
/* assign client port number */
server.sin_port = htons((u_short)portno);
@@ -102,6 +108,83 @@ Enable sending of broadcast messages (if hostname is a broadcast address)*/
outlet_float(x->x_obj.ob_outlet, 1);
}
+static void udpsend_set_multicast_interface (t_udpsend *x, t_symbol *s, int argc, t_atom *argv)
+{
+ struct sockaddr_in server;
+ struct sockaddr *sa;
+ struct hostent *hp = 0;
+ struct ifconf ifc;
+ int n_ifaces = 32, i, origbuflen, found = 0;
+ char ifname[IFNAMSIZ]; /* longest possible interface name */
+ t_symbol *interface = gensym("none");
+ int if_index = -1;
+
+ if (x->x_fd < 0)
+ {
+ pd_error(x, "udpsend_set_multicast_interface: not connected");
+ return;
+ }
+ switch (argv[0].a_type)
+ {
+ case A_FLOAT:
+ if_index = (int)atom_getfloat(&argv[0]);
+ break;
+ case A_SYMBOL:
+ interface = atom_getsymbol(&argv[0]);
+ break;
+ default:
+ pd_error(x, "udpsend_set_multicast_interface: argument not float or symbol");
+ return;
+ }
+ if (if_index == -1)
+ {
+ hp = gethostbyname(interface->s_name); // if interface is a dotted or named IP address (192.168.0.88)
+ }
+ if (hp != 0) memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
+ else // maybe interface is its name (eth0) or index (1)
+ { // scan all the interfaces to get the IP address of interface
+ // find the number of interfaces
+ origbuflen = n_ifaces * sizeof (struct ifreq);// save maximum length for free()
+ ifc.ifc_len = origbuflen; // SIOCGIFCONF changes it to valid length
+ ifc.ifc_buf = (char*)getzbytes(origbuflen);
+ if (ifc.ifc_buf != NULL)
+ { //
+ if (ioctl(x->x_fd, SIOCGIFCONF, &ifc) < 0) // get list of interfaces
+ sys_sockerror("udpsend_set_multicast_interface: getting list of interfaces");
+ else
+ {
+ n_ifaces = ifc.ifc_len/sizeof(struct ifreq);
+ post("udpsend: %d interface%s available:", n_ifaces, (n_ifaces == 1)?"":"s");
+ for(i = 0; i < n_ifaces; i++)
+ {
+ sa = (struct sockaddr *)&(ifc.ifc_req[i].ifr_addr);
+ strncpy (ifname, ifc.ifc_req[i].ifr_name, IFNAMSIZ);
+ post("[%d]: %s: %s", i, ifname, inet_ntoa(((struct sockaddr_in *)sa)->sin_addr));
+ if
+ (
+ (i == if_index) ||
+ ((if_index == -1) && (!strncmp(interface->s_name, ifname, IFNAMSIZ)))
+ )
+ {
+ server.sin_addr = ((struct sockaddr_in *)sa)->sin_addr;
+ found = 1;
+ }
+ }
+ }
+ }
+ freebytes(ifc.ifc_buf, origbuflen);
+
+ if (! found)
+ {
+ post("udpsend_set_multicast_interface: bad host name? (%s)\n", interface->s_name);
+ return;
+ }
+ }
+ if (setsockopt(x->x_fd, IPPROTO_IP, IP_MULTICAST_IF, &server.sin_addr, sizeof(struct in_addr)) < 0)
+ sys_sockerror("udpsend_set_multicast_interface: setsockopt");
+ else post("udpsend multicast interface is %s", inet_ntoa(server.sin_addr));
+}
+
static void udpsend_disconnect(t_udpsend *x)
{
if (x->x_fd >= 0)
@@ -246,6 +329,8 @@ void udpsend_setup(void)
sizeof(t_udpsend), 0, 0);
class_addmethod(udpsend_class, (t_method)udpsend_connect,
gensym("connect"), A_SYMBOL, A_FLOAT, 0);
+ class_addmethod(udpsend_class, (t_method)udpsend_set_multicast_interface,
+ gensym("multicast_interface"), A_GIMME, 0);
class_addmethod(udpsend_class, (t_method)udpsend_disconnect,
gensym("disconnect"), 0);
class_addmethod(udpsend_class, (t_method)udpsend_send, gensym("send"),