aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Peach <mrpeach@users.sourceforge.net>2010-08-05 20:26:24 +0000
committerMartin Peach <mrpeach@users.sourceforge.net>2010-08-05 20:26:24 +0000
commit9c67d5068500a6c3d98b55b076f0e2803c8a7dad (patch)
tree0010c7bebd1322d31fb242e0cb50a37bb85b3663
parente235fd08762e573955760bcc82a65c88c75e1089 (diff)
_WIN32 multicast works (needed to bind socket before joining multicast).
svn path=/trunk/externals/mrpeach/; revision=13757
-rw-r--r--net/udpreceive-help.pd86
-rw-r--r--net/udpreceive.c85
2 files changed, 107 insertions, 64 deletions
diff --git a/net/udpreceive-help.pd b/net/udpreceive-help.pd
index 745beec..530e503 100644
--- a/net/udpreceive-help.pd
+++ b/net/udpreceive-help.pd
@@ -1,43 +1,43 @@
-#N canvas 238 505 742 371 12;
-#X floatatom 394 264 3 0 0 0 - - -;
-#X floatatom 421 264 3 0 0 0 - - -;
-#X floatatom 448 264 3 0 0 0 - - -;
-#X floatatom 475 264 3 0 0 0 - - -;
-#X obj 171 120 udpreceive 9997;
-#X floatatom 502 265 5 0 0 0 - - -;
-#X obj 394 238 unpack 0 0 0 0 0;
-#X msg 171 90 status;
-#X floatatom 273 185 9 0 0 0 - - -;
-#X obj 454 211 tgl 15 0 empty empty empty 17 7 0 10 -4034 -1 -1 0 1
-;
-#X floatatom 333 211 9 0 0 0 - - -;
-#X text 301 76 IP address to accept from (optional);
-#X text -30 90 get status on right outlet:;
-#X text 166 185 bytes received:;
-#X text 181 209 total bytes received:;
-#X text 351 263 from:;
-#X text 299 97 Specify a multicast address (from 224.0.0.0 to 239.255.255.255)
-to use multicasting;
-#X text 162 57 Creation arguments: port number to listen on (required)
-;
-#X text 124 33 [udpreceive] receives bytes over a udp connection.;
-#X obj 171 254 spigot;
-#X obj 210 234 tgl 15 0 empty empty enable_print: -77 8 0 10 -4034
--1 -1 0 1;
-#X obj 171 279 print received;
-#X obj 273 152 route received total from multicast;
-#X text 466 320 Martin Peach 2010/08/02;
-#X connect 4 0 19 0;
-#X connect 4 1 22 0;
-#X connect 6 0 0 0;
-#X connect 6 1 1 0;
-#X connect 6 2 2 0;
-#X connect 6 3 3 0;
-#X connect 6 4 5 0;
-#X connect 7 0 4 0;
-#X connect 19 0 21 0;
-#X connect 20 0 19 1;
-#X connect 22 0 8 0;
-#X connect 22 1 10 0;
-#X connect 22 2 6 0;
-#X connect 22 3 9 0;
+#N canvas 238 505 742 371 12;
+#X floatatom 394 264 3 0 0 0 - - -;
+#X floatatom 421 264 3 0 0 0 - - -;
+#X floatatom 448 264 3 0 0 0 - - -;
+#X floatatom 475 264 3 0 0 0 - - -;
+#X obj 171 120 udpreceive 9997;
+#X floatatom 502 265 5 0 0 0 - - -;
+#X obj 394 238 unpack 0 0 0 0 0;
+#X msg 171 90 status;
+#X floatatom 273 185 9 0 0 0 - - -;
+#X obj 454 211 tgl 15 0 empty empty empty 17 7 0 10 -4034 -1 -1 0 1
+;
+#X floatatom 333 211 9 0 0 0 - - -;
+#X text -30 90 get status on right outlet:;
+#X text 166 185 bytes received:;
+#X text 181 209 total bytes received:;
+#X text 351 263 from:;
+#X text 299 97 Specify a multicast address (from 224.0.0.0 to 239.255.255.255)
+to use multicasting;
+#X text 162 57 Creation arguments: port number to listen on (required)
+;
+#X text 124 33 [udpreceive] receives bytes over a udp connection.;
+#X obj 171 254 spigot;
+#X obj 210 234 tgl 15 0 empty empty enable_print: -77 8 0 10 -4034
+-1 -1 0 1;
+#X obj 171 279 print received;
+#X obj 273 152 route received total from multicast;
+#X text 301 75 IP address to listen on (optional);
+#X text 466 320 Martin Peach 2010/08/05;
+#X connect 4 0 18 0;
+#X connect 4 1 21 0;
+#X connect 6 0 0 0;
+#X connect 6 1 1 0;
+#X connect 6 2 2 0;
+#X connect 6 3 3 0;
+#X connect 6 4 5 0;
+#X connect 7 0 4 0;
+#X connect 18 0 20 0;
+#X connect 19 0 18 1;
+#X connect 21 0 8 0;
+#X connect 21 1 10 0;
+#X connect 21 2 6 0;
+#X connect 21 3 9 0;
diff --git a/net/udpreceive.c b/net/udpreceive.c
index 3a0886a..1a2df09 100644
--- a/net/udpreceive.c
+++ b/net/udpreceive.c
@@ -42,6 +42,7 @@ typedef struct _udpreceive
void udpreceive_setup(void);
static void udpreceive_free(t_udpreceive *x);
static void *udpreceive_new(t_symbol *s, int argc, t_atom *argv);
+static void udpreceive_sock_err(t_udpreceive *x, char *err_string);
static void udpreceive_status(t_udpreceive *x);
static void udpreceive_read(t_udpreceive *x, int sockfd);
@@ -72,7 +73,7 @@ static void udpreceive_read(t_udpreceive *x, int sockfd)
if (read < 0)
{
- sys_sockerror("udpreceive_read");
+ udpreceive_sock_err(x, "udpreceive_read");
sys_closesocket(x->x_connectsocket);
return;
}
@@ -97,7 +98,7 @@ static void *udpreceive_new(t_symbol *s, int argc, t_atom *argv)
t_udpreceive *x;
struct sockaddr_in server;
struct hostent *hp;
-#if defined MACOSX || defined _WIN32
+#if defined __APPLE__ || defined _WIN32
struct ip_mreq mreq;
#else
struct ip_mreqn mreq;
@@ -107,6 +108,7 @@ static void *udpreceive_new(t_symbol *s, int argc, t_atom *argv)
int intarg, i;
char addr[256] = {'\0'};
+ x = (t_udpreceive *)pd_new(udpreceive_class); /* if something fails we return 0 instead of x. Is this OK? */
#ifdef DEBUG
post("udpreceive_new:argc is %d s is %s", argc, s->s_name);
#endif
@@ -137,7 +139,7 @@ static void *udpreceive_new(t_symbol *s, int argc, t_atom *argv)
#endif
if (sockfd < 0)
{
- sys_sockerror("udpreceive: socket");
+ udpreceive_sock_err(x, "udpreceive: socket");
return 0;
}
server.sin_family = AF_INET;
@@ -147,7 +149,7 @@ static void *udpreceive_new(t_symbol *s, int argc, t_atom *argv)
hp = gethostbyname(addr);
if (hp == 0)
{
- error("udpreceive: bad host?\n");
+ pd_error(x, "udpreceive: bad host?\n");
return 0;
}
memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
@@ -157,42 +159,54 @@ static void *udpreceive_new(t_symbol *s, int argc, t_atom *argv)
intarg = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
(char *)&intarg, sizeof(intarg)) < 0)
- error("udpreceive: setsockopt (SO_REUSEADDR) failed");
+ udpreceive_sock_err(x, "udpreceive: setsockopt (SO_REUSEADDR) failed");
+
+ /* assign server port number */
+ server.sin_port = htons((u_short)portno);
/* if a multicast address was specified, join the multicast group */
/* hop count defaults to 1 so we won't leave the subnet*/
if (0xE0000000 == (ntohl(server.sin_addr.s_addr) & 0xF0000000))
{
-#if defined MACOSX || defined _WIN32
+ server.sin_addr.s_addr = INADDR_ANY;
+ /* first bind the socket to INADDR_ANY */
+ if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
+ {
+ udpreceive_sock_err(x, "udpreceive: bind");
+ sys_closesocket(sockfd);
+ return (0);
+ }
+ /* second join the multicast group */
+ memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
+
+#if defined __APPLE__ || defined _WIN32
mreq.imr_multiaddr.s_addr = server.sin_addr.s_addr;
mreq.imr_interface.s_addr = INADDR_ANY;/* can put a specific local IP address here if host is multihomed */
#else
mreq.imr_multiaddr.s_addr = server.sin_addr.s_addr;
mreq.imr_address.s_addr = INADDR_ANY;
mreq.imr_ifindex = 0;
-#endif //MACOSX || _WIN32
+#endif //__APPLE__ || _WIN32
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(char *)&mreq, sizeof(mreq)) < 0)
- error("udpreceive: setsockopt (IP_ADD_MEMBERSHIP) failed");
+ udpreceive_sock_err(x, "udpreceive: setsockopt IP_ADD_MEMBERSHIP");
else
{
multicast_joined = 1;
post ("udpreceive: added to multicast group");
}
}
-
-
- /* assign server port number */
- server.sin_port = htons((u_short)portno);
-
- /* name the socket */
- if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
- {
- sys_sockerror("udpreceive: bind");
- sys_closesocket(sockfd);
- return (0);
- }
- x = (t_udpreceive *)pd_new(udpreceive_class);
+ else
+ {
+ /* name the socket */
+ if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
+ {
+ udpreceive_sock_err(x, "udpreceive: bind");
+ sys_closesocket(sockfd);
+ return (0);
+ }
+ }
+
x->x_msgout = outlet_new(&x->x_obj, &s_anything);
x->x_addrout = outlet_new(&x->x_obj, &s_anything);
x->x_connectsocket = sockfd;
@@ -214,6 +228,35 @@ static void *udpreceive_new(t_symbol *s, int argc, t_atom *argv)
return (x);
}
+static void udpreceive_sock_err(t_udpreceive *x, char *err_string)
+{
+/* prints the last error from errno or WSAGetLastError() */
+#ifdef _WIN32
+ LPVOID lpMsgBuf;
+ DWORD dwRetVal = WSAGetLastError();
+ int len = 0, i;
+ char *cp;
+
+ if (len = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS
+ , NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&lpMsgBuf, 0, NULL))
+ {
+ cp = (char *)lpMsgBuf;
+ for(i = 0; i < len; ++i)
+ {
+ if (cp[i] < 0x20)
+ { /* end string at first weird character */
+ cp[i] = 0;
+ break;
+ }
+ }
+ pd_error(x, "%s: %s (%d)", err_string, lpMsgBuf, dwRetVal);
+ LocalFree(lpMsgBuf);
+ }
+#else
+ pd_error(x, "%s: %s (%d)", err_string, strerror(errno), errno);
+#endif
+}
+
static void udpreceive_status(t_udpreceive *x)
{
t_atom output_atom;