From e79d89cbca7353baeed6a76c2799df8871ef4814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Thu, 1 Apr 2010 07:20:31 +0000 Subject: tcpclient fixes and features fixed the callback (API changed but due to cast this has gone unnoticed) featured settable ports (and now creation failure is port is taken) svn path=/trunk/externals/iem/iemnet/; revision=13327 --- tcpreceive-help.pd | 36 +++++------ tcpreceive.c | 180 +++++++++++++++++++++++++++++++++-------------------- 2 files changed, 128 insertions(+), 88 deletions(-) diff --git a/tcpreceive-help.pd b/tcpreceive-help.pd index 8cfbbe4..12c3a12 100644 --- a/tcpreceive-help.pd +++ b/tcpreceive-help.pd @@ -1,22 +1,14 @@ -#N canvas 713 11 478 294 12; -#X floatatom 206 144 3 0 0 0 - - -; -#X floatatom 233 144 3 0 0 0 - - -; -#X floatatom 260 144 3 0 0 0 - - -; -#X floatatom 287 144 3 0 0 0 - - -; -#X text 163 143 from; -#X obj 155 185 print message; -#X obj 155 57 tcpreceive 9997; -#X floatatom 257 96 5 0 0 0 - - -; -#X text 303 94 connections; -#X text 32 16 tcpreceive receives bytes over a tcp connection.; -#X floatatom 315 144 5 0 0 0 - - -; -#X obj 206 117 unpack 0 0 0 0 0; -#X text 265 235 Martin Peach 2008/11/05; -#X connect 6 0 5 0; -#X connect 6 1 11 0; -#X connect 6 2 7 0; -#X connect 11 0 0 0; -#X connect 11 1 1 0; -#X connect 11 2 2 0; -#X connect 11 3 3 0; -#X connect 11 4 10 0; +#N canvas 546 11 478 294 12; +#X obj 47 185 print message; +#X obj 47 97 tcpreceive 9997; +#X text 32 16 tcpreceive receives bytes over a tcp connection.; +#X obj 179 119 print status; +#X obj 91 164 print from; +#X obj 135 141 print #connections; +#X msg 47 71 port 10000; +#X text 196 260 IOhannes m zmölnig 2010/03/31; +#X connect 1 0 0 0; +#X connect 1 1 4 0; +#X connect 1 2 5 0; +#X connect 1 3 3 0; +#X connect 6 0 1 0; diff --git a/tcpreceive.c b/tcpreceive.c index 3dc6c9f..e44e088 100644 --- a/tcpreceive.c +++ b/tcpreceive.c @@ -22,9 +22,11 @@ /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* */ +static const char*objName="tcpreceive"; #include "iemnet.h" #ifndef _WIN32 +/* needed for TCP_NODELAY */ # include #endif @@ -49,13 +51,12 @@ typedef struct _tcpreceive t_outlet *x_msgout; t_outlet *x_addrout; t_outlet *x_connectout; - + t_outlet *x_statout; int x_connectsocket; + int x_port; int x_nconnections; t_tcpconnection x_connection[MAX_CONNECTIONS]; - - t_atom x_addrbytes[5]; } t_tcpreceive; @@ -69,27 +70,25 @@ static int tcpreceive_find_socket(t_tcpreceive *x, int fd) { static int tcpreceive_disconnect(t_tcpreceive *x, int id); -static void tcpreceive_read_callback(t_tcpconnection *y, int argc, t_atom*argv) +static void tcpreceive_read_callback(void *w, t_iemnet_chunk*c, int argc, t_atom*argv) { + t_tcpconnection*y=(t_tcpconnection*)w; t_tcpreceive*x=NULL; int index=-1; if(NULL==y || NULL==(x=y->owner))return; + index=tcpreceive_find_socket(x, y->socket); if(index>=0) { - if(argc) { // TODO?: outlet info about connection iemnet__streamout(x->x_msgout, argc, argv); } else { // disconnected - int sockfd=y->socket; tcpreceive_disconnect(x, index); } } - } - /* tcpreceive_addconnection tries to add the socket fd to the list */ /* returns 1 on success, else 0 */ static int tcpreceive_addconnection(t_tcpreceive *x, int fd, long addr, unsigned short port) @@ -106,7 +105,7 @@ static int tcpreceive_addconnection(t_tcpreceive *x, int fd, long addr, unsigned x->x_connection[i].receiver= iemnet__receiver_create(fd, x->x_connection+i, - (t_iemnet_receivecallback)tcpreceive_read_callback); + tcpreceive_read_callback); return 1; } @@ -138,13 +137,9 @@ static void tcpreceive_connectpoll(t_tcpreceive *x) port = ntohs(from.sin_port); if (tcpreceive_addconnection(x, fd, addr, port)) { - outlet_float(x->x_connectout, ++x->x_nconnections); - 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, gensym("list"), 5L, x->x_addrbytes); + x->x_nconnections++; + outlet_float(x->x_connectout, x->x_nconnections); + iemnet__addrout(x->x_statout, x->x_addrout, addr, port); } else { @@ -203,69 +198,61 @@ static int tcpreceive_disconnect_socket(t_tcpreceive *x, int fd) return 0; } -static void tcpreceive_free(t_tcpreceive *x) -{ /* is this ever called? */ - if (x->x_connectsocket >= 0) - { - sys_rmpollfn(x->x_connectsocket); - sys_closesocket(x->x_connectsocket); - } - tcpreceive_disconnect_all(x); -} - -static void *tcpreceive_new(t_floatarg fportno) +static void tcpreceive_port(t_tcpreceive*x, t_floatarg fportno) { - t_tcpreceive *x; - struct sockaddr_in server; - int sockfd, portno = fportno; - int intarg, i; + static t_atom ap[1]; + int portno = fportno; + struct sockaddr_in server; + socklen_t serversize=sizeof(server); + int sockfd = x->x_connectsocket; + int intarg; + + SETFLOAT(ap, -1); + if(x->x_port == portno) { + return; + } + + /* cleanup any open ports */ + if(sockfd>=0) { + sys_rmpollfn(sockfd); + sys_closesocket(sockfd); + x->x_connectsocket=-1; + x->x_port=-1; + } + - /* create a socket */ sockfd = socket(AF_INET, SOCK_STREAM, 0); - DEBUG("socket %d port %d", sockfd, portno); - if (sockfd < 0) - { - sys_sockerror("tcpreceive: socket"); - return (0); - } - server.sin_family = AF_INET; - server.sin_addr.s_addr = INADDR_ANY; + if(sockfd<0) { + error("[%s]: unable to create socket", objName); + return; + } - /* ask OS to allow another Pd to repoen this port after we close it. */ + /* ask OS to allow another Pd to reopen this port after we close it. */ intarg = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, - (char *)&intarg, sizeof(intarg)) < 0) - post("tcpreceive: setsockopt (SO_REUSEADDR) failed"); + (char *)&intarg, sizeof(intarg)) + < 0) + error("[%s]: setsockopt (SO_REUSEADDR) failed", objName); + /* Stream (TCP) sockets are set NODELAY */ intarg = 1; if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&intarg, sizeof(intarg)) < 0) - post("setsockopt (TCP_NODELAY) failed\n"); + post("[%s]: setsockopt (TCP_NODELAY) failed", objName); + - /* assign server port number */ + 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, sizeof(server)) < 0) + if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0) { - sys_sockerror("tcpreceive: bind"); + sys_sockerror("[tcpreceive] bind failed"); sys_closesocket(sockfd); - return (0); - } - x = (t_tcpreceive *)pd_new(tcpreceive_class); - x->x_msgout = outlet_new(&x->x_obj, 0); - x->x_addrout = outlet_new(&x->x_obj, gensym("list")); - x->x_connectout = outlet_new(&x->x_obj, gensym("float")); - /* clear the connection list */ - for (i = 0; i < MAX_CONNECTIONS; ++i) - { - x->x_connection[i].socket = -1; - x->x_connection[i].addr = 0L; - x->x_connection[i].port = 0; - } - for (i = 0; i < 5; ++i) - { - SETFLOAT(x->x_addrbytes+i, 0); + sockfd = -1; + outlet_anything(x->x_statout, gensym("port"), 1, ap); + return; } /* streaming protocol */ @@ -274,13 +261,69 @@ static void *tcpreceive_new(t_floatarg fportno) sys_sockerror("tcpreceive: listen"); sys_closesocket(sockfd); sockfd = -1; + outlet_anything(x->x_statout, gensym("port"), 1, ap); + return; } else { - sys_addpollfn(sockfd, (t_fdpollfn)tcpreceive_connectpoll, x); + sys_addpollfn(sockfd, + (t_fdpollfn)tcpreceive_connectpoll, + x); // wait for new connections } + x->x_connectsocket = sockfd; - x->x_nconnections = 0; + x->x_port = portno; + + // find out which port is actually used (useful when assigning "0") + if(!getsockname(sockfd, (struct sockaddr *)&server, &serversize)) { + x->x_port=ntohs(server.sin_port); + } + + + SETFLOAT(ap, x->x_port); + outlet_anything(x->x_statout, gensym("port"), 1, ap); +} + + +static void tcpreceive_free(t_tcpreceive *x) +{ /* is this ever called? */ + if (x->x_connectsocket >= 0) + { + sys_rmpollfn(x->x_connectsocket); + sys_closesocket(x->x_connectsocket); + } + tcpreceive_disconnect_all(x); +} + +static void *tcpreceive_new(t_floatarg fportno) +{ + t_tcpreceive *x; + int portno = fportno; + int i; + + x = (t_tcpreceive *)pd_new(tcpreceive_class); + x->x_msgout = outlet_new(&x->x_obj, 0); + x->x_addrout = outlet_new(&x->x_obj, gensym("list")); /* legacy */ + x->x_connectout = outlet_new(&x->x_obj, gensym("float")); /* legacy */ + x->x_statout = outlet_new(&x->x_obj, 0);/* outlet for everything else */ + + x->x_connectsocket=-1; + x->x_port=-1; + x->x_nconnections=0; + + /* clear the connection list */ + for (i = 0; i < MAX_CONNECTIONS; ++i) + { + x->x_connection[i].socket = -1; + x->x_connection[i].addr = 0L; + x->x_connection[i].port = 0; + } + + + + + + tcpreceive_port(x, portno); return (x); } @@ -290,8 +333,13 @@ void tcpreceive_setup(void) { tcpreceive_class = class_new(gensym("tcpreceive"), (t_newmethod)tcpreceive_new, (t_method)tcpreceive_free, - sizeof(t_tcpreceive), CLASS_NOINLET, A_DEFFLOAT, 0); + sizeof(t_tcpreceive), + 0, + A_DEFFLOAT, 0); + + class_addmethod(tcpreceive_class, (t_method)tcpreceive_port, gensym("port"), A_DEFFLOAT, 0); } /* end x_net_tcpreceive.c */ + -- cgit v1.2.1