From c5e0079ae1323ad4c35d28f83ce732bb3820c46a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Mon, 31 Aug 2015 22:11:51 +0000 Subject: un-threaded receive svn path=/trunk/externals/iem/iemnet/; revision=17543 --- udpreceive.c | 180 ++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 122 insertions(+), 58 deletions(-) (limited to 'udpreceive.c') diff --git a/udpreceive.c b/udpreceive.c index e2a1c30..5fc092e 100644 --- a/udpreceive.c +++ b/udpreceive.c @@ -1,5 +1,5 @@ /* udpreceive.c - * copyright (c) 2010 IOhannes m zmölnig, IEM + * copyright (c) 2010 IOhannes m zmölnig, IEM * copyright (c) 2006-2010 Martin Peach * copyright (c) Miller Puckette */ @@ -18,22 +18,21 @@ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ -/* along with this program; if not, write to the Free Software */ -/* Foundation, Inc., */ -/* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +/* along with this program; if not, see */ +/* http://www.gnu.org/licenses/ */ #define DEBUGLEVEL 1 static const char objName[] = "udpreceive"; #include "iemnet.h" +#include /* ----------------------------- udpreceive ------------------------- */ static t_class *udpreceive_class; -typedef struct _udpreceive -{ +typedef struct _udpreceive { t_object x_obj; t_outlet *x_msgout; t_outlet *x_addrout; @@ -42,80 +41,84 @@ typedef struct _udpreceive int x_connectsocket; int x_port; t_iemnet_receiver*x_receiver; - t_iemnet_floatlist *x_floatlist; + t_iemnet_floatlist *x_floatlist; + + int x_reuseport, x_reuseaddr; } t_udpreceive; -static void udpreceive_read_callback(void*y, t_iemnet_chunk*c) { +static void udpreceive_read_callback(void*y, t_iemnet_chunk*c) +{ t_udpreceive*x=(t_udpreceive*)y; if(c) { iemnet__addrout(x->x_statout, x->x_addrout, c->addr, c->port); - x->x_floatlist=iemnet__chunk2list(c, x->x_floatlist); // gets destroyed in the dtor - outlet_list(x->x_msgout, gensym("list"), x->x_floatlist->argc, x->x_floatlist->argv); + x->x_floatlist=iemnet__chunk2list(c, + x->x_floatlist); // gets destroyed in the dtor + outlet_list(x->x_msgout, gensym("list"), x->x_floatlist->argc, + x->x_floatlist->argv); } else { post("[%s] nothing received", objName); } } -static void udpreceive_port(t_udpreceive*x, t_floatarg fportno) +static int udpreceive_setport(t_udpreceive*x, unsigned short portno) { - static t_atom ap[1]; - int portno = fportno; struct sockaddr_in server; socklen_t serversize=sizeof(server); int sockfd = x->x_connectsocket; int intarg; + memset(&server, 0, sizeof(server)); - SETFLOAT(ap, -1); if(x->x_port == portno) { - return; + return 1; } /* cleanup any open ports */ if(sockfd>=0) { - iemnet__receiver_destroy(x->x_receiver); + iemnet__receiver_destroy(x->x_receiver, 0); x->x_connectsocket=-1; x->x_port=-1; } sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd<0) { - error("[%s]: unable to create socket", objName); - return; + pd_error(x, "[%s]: unable to create socket", objName); + return 0; } /* ask OS to allow another Pd to reopen this port after we close it. */ #ifdef SO_REUSEADDR - intarg = 1; - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, - (char *)&intarg, sizeof(intarg)) - < 0) { - error("[%s]: setsockopt (SO_REUSEADDR) failed", objName); + if(x->x_reuseaddr) { + intarg = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, + (void *)&intarg, sizeof(intarg)) + < 0) { + pd_error(x, "[%s]: setsockopt (SO_REUSEADDR) failed", objName); + } } #endif /* SO_REUSEADDR */ #ifdef SO_REUSEPORT - intarg = 1; - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, - (char *)&intarg, sizeof(intarg)) - < 0) { - error("[%s]: setsockopt (SO_REUSEPORT) failed", objName); + if(x->x_reuseport) { + intarg = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, + (void *)&intarg, sizeof(intarg)) + < 0) { + pd_error(x, "[%s]: setsockopt (SO_REUSEPORT) failed", objName); + } } #endif /* SO_REUSEPORT */ - server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons((u_short)portno); /* name the socket */ - if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0) - { - sys_sockerror("[udpreceive] bind failed"); - sys_closesocket(sockfd); - sockfd = -1; - outlet_anything(x->x_statout, gensym("port"), 1, ap); - return; - } + if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0) { + sys_sockerror("[udpreceive] bind failed"); + iemnet__closesocket(sockfd); + sockfd = -1; + return 0; + } x->x_connectsocket = sockfd; x->x_port = portno; @@ -126,54 +129,115 @@ static void udpreceive_port(t_udpreceive*x, t_floatarg fportno) } x->x_receiver=iemnet__receiver_create(sockfd, - x, - udpreceive_read_callback); + x, + udpreceive_read_callback, + 0); + return 1; +} + +static void udpreceive_port(t_udpreceive*x, t_symbol*s, int argc, + t_atom*argv) +{ + t_atom ap[1]; + if(argc) { + if(argc>1 || A_FLOAT != argv->a_type) { + pd_error(x, "[%s] usage: port []", objName); + return; + } + SETFLOAT(ap, -1); + if(!udpreceive_setport(x, atom_getint(argv))) { + outlet_anything(x->x_statout, gensym("port"), 1, ap); + } + } SETFLOAT(ap, x->x_port); outlet_anything(x->x_statout, gensym("port"), 1, ap); } +static void udpreceive_optionI(t_udpreceive*x, t_symbol*s, int argc, + t_atom*argv) +{ + int*reuse=NULL; + if(gensym("reuseport")==s) { + reuse=&x->x_reuseport; + } + if(gensym("reuseaddr")==s) { + reuse=&x->x_reuseaddr; + } + + if(!reuse) { + pd_error(x, "[%s]: unknown option '%s'", objName, s->s_name); + return; + } + if(argc) { + if(1==argc && A_FLOAT == argv->a_type) { + *reuse=atom_getint(argv); + return; + } else { + pd_error(x, "[%s] usage: %s []", objName, s->s_name); + return; + } + } else { + t_atom ap[1]; + SETFLOAT(ap, *reuse); + outlet_anything(x->x_statout, s, 1, ap); + } +} static void *udpreceive_new(t_floatarg fportno) { - t_udpreceive*x = (t_udpreceive *)pd_new(udpreceive_class); + t_udpreceive*x = (t_udpreceive *)pd_new(udpreceive_class); + + x->x_msgout = outlet_new(&x->x_obj, 0); + x->x_addrout = outlet_new(&x->x_obj, gensym("list")); + x->x_statout = outlet_new(&x->x_obj, 0); - x->x_msgout = outlet_new(&x->x_obj, 0); - x->x_addrout = outlet_new(&x->x_obj, gensym("list")); - x->x_statout = outlet_new(&x->x_obj, 0); + x->x_connectsocket = -1; + x->x_port = -1; + x->x_receiver = NULL; - x->x_connectsocket = -1; - x->x_port = -1; - x->x_receiver = NULL; + x->x_reuseaddr = 1; + x->x_reuseport = 0; - x->x_floatlist=iemnet__floatlist_create(1024); + x->x_floatlist=iemnet__floatlist_create(1024); - udpreceive_port(x, fportno); + udpreceive_setport(x, fportno); - return (x); + return (x); } static void udpreceive_free(t_udpreceive *x) { - iemnet__receiver_destroy(x->x_receiver); + iemnet__receiver_destroy(x->x_receiver, 0); x->x_connectsocket=0; outlet_free(x->x_msgout); outlet_free(x->x_addrout); outlet_free(x->x_statout); - if(x->x_floatlist)iemnet__floatlist_destroy(x->x_floatlist);x->x_floatlist=NULL; + if(x->x_floatlist) { + iemnet__floatlist_destroy(x->x_floatlist); + } + x->x_floatlist=NULL; } IEMNET_EXTERN void udpreceive_setup(void) { - if(!iemnet__register(objName))return; - udpreceive_class = class_new(gensym(objName), - (t_newmethod)udpreceive_new, (t_method)udpreceive_free, - sizeof(t_udpreceive), 0, A_DEFFLOAT, 0); - - class_addmethod(udpreceive_class, (t_method)udpreceive_port, - gensym("port"), A_DEFFLOAT, 0); + if(!iemnet__register(objName)) { + return; + } + udpreceive_class = class_new(gensym(objName), + (t_newmethod)udpreceive_new, (t_method)udpreceive_free, + sizeof(t_udpreceive), 0, A_DEFFLOAT, 0); + + class_addmethod(udpreceive_class, (t_method)udpreceive_port, + gensym("port"), A_GIMME, 0); + + /* options for opening new sockets */ + class_addmethod(udpreceive_class, (t_method)udpreceive_optionI, + gensym("reuseaddr"), A_GIMME, 0); + class_addmethod(udpreceive_class, (t_method)udpreceive_optionI, + gensym("reuseport"), A_GIMME, 0); DEBUGMETHOD(udpreceive_class); } -- cgit v1.2.1