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.c | 180 +++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 114 insertions(+), 66 deletions(-) (limited to 'tcpreceive.c') 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