From 010723cb02b26c608537fc537d5e963ff6402f9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Tue, 23 Mar 2010 11:54:21 +0000 Subject: forked mrpeach's "net" svn path=/trunk/externals/iem/iemnet/; revision=13240 --- udpreceive.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 udpreceive.c (limited to 'udpreceive.c') diff --git a/udpreceive.c b/udpreceive.c new file mode 100644 index 0000000..a9ac791 --- /dev/null +++ b/udpreceive.c @@ -0,0 +1,160 @@ +/* x_net_udpreceive.c 20060424. Martin Peach did it based on x_net.c. x_net.c header follows: */ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "s_stuff.h" + +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#include +#endif + + +/* ----------------------------- udpreceive ------------------------- */ + +static t_class *udpreceive_class; + +#define MAX_UDP_RECEIVE 65536L // longer than data in maximum UDP packet + +typedef struct _udpreceive +{ + t_object x_obj; + t_outlet *x_msgout; + t_outlet *x_addrout; + int x_connectsocket; + t_atom x_addrbytes[5]; + t_atom x_msgoutbuf[MAX_UDP_RECEIVE]; + char x_msginbuf[MAX_UDP_RECEIVE]; +} t_udpreceive; + +void udpreceive_setup(void); +static void udpreceive_free(t_udpreceive *x); +static void *udpreceive_new(t_floatarg fportno); +static void udpreceive_read(t_udpreceive *x, int sockfd); + +static void udpreceive_read(t_udpreceive *x, int sockfd) +{ + int i, read = 0; + struct sockaddr_in from; + socklen_t fromlen = sizeof(from); + long addr; + unsigned short port; + + read = recvfrom(sockfd, x->x_msginbuf, MAX_UDP_RECEIVE, 0, (struct sockaddr *)&from, &fromlen); +#ifdef DEBUG + post("udpreceive_read: read %lu x->x_connectsocket = %d", + read, x->x_connectsocket); +#endif + /* get the sender's ip */ + addr = ntohl(from.sin_addr.s_addr); + port = ntohs(from.sin_port); + + x->x_addrbytes[0].a_w.w_float = (addr & 0xFF000000)>>24; + x->x_addrbytes[1].a_w.w_float = (addr & 0x0FF0000)>>16; + x->x_addrbytes[2].a_w.w_float = (addr & 0x0FF00)>>8; + x->x_addrbytes[3].a_w.w_float = (addr & 0x0FF); + x->x_addrbytes[4].a_w.w_float = port; + outlet_list(x->x_addrout, &s_list, 5L, x->x_addrbytes); + + if (read < 0) + { + sys_sockerror("udpreceive_read"); + sys_closesocket(x->x_connectsocket); + return; + } + if (read > 0) + { + for (i = 0; i < read; ++i) + { + /* convert the bytes in the buffer to floats in a list */ + x->x_msgoutbuf[i].a_w.w_float = (float)(unsigned char)x->x_msginbuf[i]; + } + /* send the list out the outlet */ + if (read > 1) outlet_list(x->x_msgout, &s_list, read, x->x_msgoutbuf); + else outlet_float(x->x_msgout, x->x_msgoutbuf[0].a_w.w_float); + } +} + +static void *udpreceive_new(t_floatarg fportno) +{ + t_udpreceive *x; + struct sockaddr_in server; + int sockfd, portno = fportno; + int intarg, i; + + /* create a socket */ + sockfd = socket(AF_INET, SOCK_DGRAM, 0); +#ifdef DEBUG + post("udpreceive_new: socket %d port %d", sockfd, portno); +#endif + if (sockfd < 0) + { + sys_sockerror("udpreceive: socket"); + return (0); + } + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + + /* enable delivery of all multicast or broadcast (but not unicast) + * UDP datagrams to all sockets bound to the same port */ + intarg = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, + (char *)&intarg, sizeof(intarg)) < 0) + post("udpreceive: setsockopt (SO_REUSEADDR) failed"); + + /* 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); + x->x_msgout = outlet_new(&x->x_obj, &s_anything); + x->x_addrout = outlet_new(&x->x_obj, &s_list); + x->x_connectsocket = sockfd; + + /* convert the bytes in the buffer to floats in a list */ + for (i = 0; i < MAX_UDP_RECEIVE; ++i) + { + x->x_msgoutbuf[i].a_type = A_FLOAT; + x->x_msgoutbuf[i].a_w.w_float = 0; + } + for (i = 0; i < 5; ++i) + { + x->x_addrbytes[i].a_type = A_FLOAT; + x->x_addrbytes[i].a_w.w_float = 0; + } + sys_addpollfn(x->x_connectsocket, (t_fdpollfn)udpreceive_read, x); + return (x); +} + +static void udpreceive_free(t_udpreceive *x) +{ + if (x->x_connectsocket >= 0) + { + sys_rmpollfn(x->x_connectsocket); + sys_closesocket(x->x_connectsocket); + } +} + +void udpreceive_setup(void) +{ + udpreceive_class = class_new(gensym("udpreceive"), + (t_newmethod)udpreceive_new, (t_method)udpreceive_free, + sizeof(t_udpreceive), CLASS_NOINLET, A_DEFFLOAT, 0); +} + +/* end udpreceive.c */ -- cgit v1.2.1