diff options
author | Martin Peach <mrpeach@users.sourceforge.net> | 2010-07-30 19:09:36 +0000 |
---|---|---|
committer | Martin Peach <mrpeach@users.sourceforge.net> | 2010-07-30 19:09:36 +0000 |
commit | 68557af56a0a729e4456ac1c246b06f0b17a6abc (patch) | |
tree | 505e80c38880e8cb542441722d6fdfbf3e48bbcf | |
parent | d4d83ffdf3500990354da688eac349ebd20f33ce (diff) |
Added method to select interface when multicasting, updated help patch.
svn path=/trunk/externals/mrpeach/; revision=13734
-rw-r--r-- | net/udpsend-help.pd | 73 | ||||
-rw-r--r-- | net/udpsend.c | 85 |
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"), |