diff options
author | Martin Peach <mrpeach@users.sourceforge.net> | 2010-08-05 20:26:24 +0000 |
---|---|---|
committer | Martin Peach <mrpeach@users.sourceforge.net> | 2010-08-05 20:26:24 +0000 |
commit | 9c67d5068500a6c3d98b55b076f0e2803c8a7dad (patch) | |
tree | 0010c7bebd1322d31fb242e0cb50a37bb85b3663 /net | |
parent | e235fd08762e573955760bcc82a65c88c75e1089 (diff) |
_WIN32 multicast works (needed to bind socket before joining multicast).
svn path=/trunk/externals/mrpeach/; revision=13757
Diffstat (limited to 'net')
-rw-r--r-- | net/udpreceive-help.pd | 86 | ||||
-rw-r--r-- | net/udpreceive.c | 85 |
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; |