diff options
Diffstat (limited to 'tcpclient.c')
-rw-r--r-- | tcpclient.c | 254 |
1 files changed, 147 insertions, 107 deletions
diff --git a/tcpclient.c b/tcpclient.c index 6939bbc..a1519b1 100644 --- a/tcpclient.c +++ b/tcpclient.c @@ -1,5 +1,5 @@ /* tcpclient.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) 2004 Olaf Matthes */ @@ -18,9 +18,8 @@ /* 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/ */ /* */ /* ---------------------------------------------------------------------------- */ @@ -29,14 +28,11 @@ #include "iemnet.h" #include <string.h> -#include <pthread.h> - static t_class *tcpclient_class; static char objName[] = "tcpclient"; -typedef struct _tcpclient -{ +typedef struct _tcpclient { t_object x_obj; t_clock *x_clock; t_outlet *x_msgout; @@ -55,11 +51,8 @@ typedef struct _tcpclient int x_port; // port we're connected to long x_addr; // address we're connected to as 32bit int - /* multithread stuff */ - pthread_t x_threadid; /* id of child thread */ - pthread_attr_t x_threadattr; /* attributes of child thread */ - t_iemnet_floatlist *x_floatlist; + t_iemnet_floatlist *x_floatlist; } t_tcpclient; @@ -91,114 +84,135 @@ static void tcpclient_info(t_tcpclient *x) } /* connection handling */ - -static void *tcpclient_child_connect(void *w) +static int tcpclient_do_disconnect(int fd, t_iemnet_sender*sender, + t_iemnet_receiver*receiver) +{ + if(sender) { + iemnet__sender_destroy(sender, 0); + sender=NULL; + } + if(receiver) { + iemnet__receiver_destroy(receiver, 0); + receiver=NULL; + } + if (fd >= 0) { + iemnet__closesocket(fd); + return 1; + } + return 0; +} +static int tcpclient_do_connect(const char*host, unsigned short port, + t_tcpclient*x, + t_iemnet_sender**senderOUT, t_iemnet_receiver**receiverOUT, long*addrOUT) { - t_tcpclient *x = (t_tcpclient*) w; struct sockaddr_in server; struct hostent *hp; - int sockfd; - - t_iemnet_sender*sender; + int sockfd=-1; + t_iemnet_sender* sender; t_iemnet_receiver*receiver; - if (x->x_fd >= 0) - { - error("%s_connect: already connected", objName); - return (x); - } - - /* create a socket */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); - DEBUG("send socket %d\n", sockfd); - if (sockfd < 0) - { - sys_sockerror("tcpclient: socket"); - return (x); - } /* connect socket using hostname provided in command line */ + memset(&server, 0, sizeof(server)); server.sin_family = AF_INET; - hp = gethostbyname(x->x_hostname); - if (hp == 0) - { - sys_sockerror("tcpclient: bad host?\n"); - return (x); - } + hp = gethostbyname(host); + if (hp == 0) { + sys_sockerror("tcpclient: bad host?\n"); + return (-1); + } memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + sys_sockerror("tcpclient: socket"); + return (sockfd); + } + /* assign client port number */ - server.sin_port = htons((u_short)x->x_port); + server.sin_port = htons((u_short)port); /* try to connect */ - if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) - { - sys_sockerror("tcpclient: connecting stream socket"); - sys_closesocket(sockfd); - return (x); - } - - sender=iemnet__sender_create(sockfd); - receiver=iemnet__receiver_create(sockfd, x, tcpclient_receive_callback); - - /* update the tcpclient-object (thread safe) */ - sys_lock(); - x->x_fd = sockfd; - x->x_addr = ntohl(*(long *)hp->h_addr); - - x->x_sender=sender; - x->x_receiver=receiver; + if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { + sys_sockerror("tcpclient: connecting stream socket"); + iemnet__closesocket(sockfd); + return (-1); + } - x->x_connectstate = 1; + sender=iemnet__sender_create(sockfd, NULL, NULL, 0); + receiver=iemnet__receiver_create(sockfd, x, tcpclient_receive_callback, + 0); - /* use callback to set outlet in main thread */ - clock_delay(x->x_clock, 0); - sys_unlock(); - return (x); + if(addrOUT) { + *addrOUT= ntohl(*(long *)hp->h_addr); + } + if(senderOUT) { + *senderOUT=sender; + } + if(receiverOUT) { + *receiverOUT=receiver; + } + return sockfd; } + static void tcpclient_tick(t_tcpclient *x) { - outlet_float(x->x_connectout, 1); + outlet_float(x->x_connectout, 1); } static void tcpclient_disconnect(t_tcpclient *x); -static void tcpclient_connect(t_tcpclient *x, t_symbol *hostname, t_floatarg fportno) +static void tcpclient_connect(t_tcpclient *x, t_symbol *hostname, + t_floatarg fportno) { - if(x->x_fd>=0)tcpclient_disconnect(x); + long addr=0; + int state; + if(x->x_hostname || x->x_port) { + state=tcpclient_do_disconnect(x->x_fd, x->x_sender, x->x_receiver); + if(state) { + outlet_float(x->x_connectout, 0); + } else { + if(!x->x_port) { + pd_error(x, "[%s]: not connected", objName); + } + } + } + /* we get hostname and port and pass them on to the child thread that establishes the connection */ x->x_hostname = hostname->s_name; x->x_port = fportno; - x->x_connectstate = 0; - /* start child thread */ - if(pthread_create(&x->x_threadid, &x->x_threadattr, tcpclient_child_connect, x) < 0) - error("%s: could not create new thread", objName); + + + state=tcpclient_do_connect(x->x_hostname, x->x_port, x, + &x->x_sender, &x->x_receiver, + &x->x_addr); + x->x_connectstate=(state>0); + x->x_fd=state; + if(state>0) { + outlet_float(x->x_connectout, 1); + } + } static void tcpclient_disconnect(t_tcpclient *x) { - if (x->x_fd >= 0) - { - int fd=x->x_fd; - x->x_fd = -1; + if(x->x_hostname || x->x_port) { + int state=tcpclient_do_disconnect(x->x_fd, x->x_sender, x->x_receiver); - DEBUG("disconnecting %x", x); - if(x->x_sender)iemnet__sender_destroy(x->x_sender); x->x_sender=NULL; - if(x->x_receiver)iemnet__receiver_destroy(x->x_receiver); x->x_receiver=NULL; - DEBUG("disconnect cleaning up %x", x); - sys_closesocket(fd); - - - x->x_connectstate = 0; - outlet_float(x->x_connectout, 0); + if(!state && !x->x_port) { + pd_error(x, "[%s]: not connected", objName); } - else pd_error(x, "%s: not connected", objName); + } + outlet_float(x->x_connectout, 0); + + x->x_port=0; + x->x_hostname=NULL; } /* sending/receiving */ -static void tcpclient_send(t_tcpclient *x, t_symbol *s, int argc, t_atom *argv) +static void tcpclient_send(t_tcpclient *x, t_symbol *s, int argc, + t_atom *argv) { int size=0; t_atom output_atom; @@ -211,39 +225,70 @@ static void tcpclient_send(t_tcpclient *x, t_symbol *s, int argc, t_atom *argv) iemnet__chunk_destroy(chunk); SETFLOAT(&output_atom, size); - outlet_anything( x->x_statusout, gensym("sent"), 1, &output_atom); + outlet_anything( x->x_statusout, gensym("sendbuffersize"), 1, + &output_atom); if(size<0) { tcpclient_disconnect(x); } } -static void tcpclient_receive_callback(void*y, t_iemnet_chunk*c) { +static void tcpclient_receive_callback(void*y, t_iemnet_chunk*c) +{ t_tcpclient *x=(t_tcpclient*)y; if(c) { iemnet__addrout(x->x_statusout, x->x_addrout, x->x_addr, x->x_port); - x->x_floatlist=iemnet__chunk2list(c, x->x_floatlist); // get's destroyed in the dtor - iemnet__streamout(x->x_msgout, x->x_floatlist->argc, x->x_floatlist->argv, x->x_serialize); + x->x_floatlist=iemnet__chunk2list(c, + x->x_floatlist); // get's destroyed in the dtor + iemnet__streamout(x->x_msgout, x->x_floatlist->argc, x->x_floatlist->argv, + x->x_serialize); } else { // disconnected tcpclient_disconnect(x); } } -static void tcpclient_serialize(t_tcpclient *x, t_floatarg doit) { +static void tcpclient_serialize(t_tcpclient *x, t_floatarg doit) +{ x->x_serialize=doit; } /* constructor/destructor */ +static void tcpclient_free_simple(t_tcpclient *x) +{ + if(x->x_clock) { + clock_free(x->x_clock); + } + x->x_clock=NULL; + if(x->x_floatlist) { + iemnet__floatlist_destroy(x->x_floatlist); + } + x->x_floatlist=NULL; + + if(x->x_msgout) { + outlet_free(x->x_msgout); + } + if(x->x_addrout) { + outlet_free(x->x_addrout); + } + if(x->x_connectout) { + outlet_free(x->x_connectout); + } + if(x->x_statusout) { + outlet_free(x->x_statusout); + } +} static void *tcpclient_new(void) { t_tcpclient *x = (t_tcpclient *)pd_new(tcpclient_class); x->x_msgout = outlet_new(&x->x_obj, 0); /* received data */ x->x_addrout = outlet_new(&x->x_obj, gensym("list")); - x->x_connectout = outlet_new(&x->x_obj, gensym("float")); /* connection state */ - x->x_statusout = outlet_new(&x->x_obj, 0);/* last outlet for everything else */ + x->x_connectout = outlet_new(&x->x_obj, + gensym("float")); /* connection state */ + x->x_statusout = outlet_new(&x->x_obj, + 0);/* last outlet for everything else */ x->x_serialize=1; @@ -258,36 +303,34 @@ static void *tcpclient_new(void) x->x_clock = clock_new(x, (t_method)tcpclient_tick); x->x_floatlist=iemnet__floatlist_create(1024); - /* prepare child thread */ - if(pthread_attr_init(&x->x_threadattr) < 0) - error("%s: warning: could not prepare child thread", objName); - if(pthread_attr_setdetachstate(&x->x_threadattr, PTHREAD_CREATE_DETACHED) < 0) - error("%s: warning: could not prepare child thread", objName); - - return (x); } static void tcpclient_free(t_tcpclient *x) { tcpclient_disconnect(x); - if(x->x_clock)clock_free(x->x_clock);x->x_clock=NULL; - if(x->x_floatlist)iemnet__floatlist_destroy(x->x_floatlist);x->x_floatlist=NULL; + tcpclient_free_simple(x); } IEMNET_EXTERN void tcpclient_setup(void) { - if(!iemnet__register(objName))return; + if(!iemnet__register(objName)) { + return; + } tcpclient_class = class_new(gensym(objName), (t_newmethod)tcpclient_new, (t_method)tcpclient_free, sizeof(t_tcpclient), 0, A_DEFFLOAT, 0); - class_addmethod(tcpclient_class, (t_method)tcpclient_connect, gensym("connect") + class_addmethod(tcpclient_class, (t_method)tcpclient_connect, + gensym("connect") , A_SYMBOL, A_FLOAT, 0); - class_addmethod(tcpclient_class, (t_method)tcpclient_disconnect, gensym("disconnect"), 0); + class_addmethod(tcpclient_class, (t_method)tcpclient_disconnect, + gensym("disconnect"), 0); - class_addmethod(tcpclient_class, (t_method)tcpclient_serialize, gensym("serialize"), A_FLOAT, 0); + class_addmethod(tcpclient_class, (t_method)tcpclient_serialize, + gensym("serialize"), A_FLOAT, 0); - class_addmethod(tcpclient_class, (t_method)tcpclient_send, gensym("send"), A_GIMME, 0); + class_addmethod(tcpclient_class, (t_method)tcpclient_send, gensym("send"), + A_GIMME, 0); class_addlist(tcpclient_class, (t_method)tcpclient_send); class_addbang(tcpclient_class, (t_method)tcpclient_info); @@ -297,7 +340,4 @@ IEMNET_EXTERN void tcpclient_setup(void) IEMNET_INITIALIZER(tcpclient_setup); - - - /* end of tcpclient.c */ |