From 29f2b2b9168fd2d45ec5a2699dab2e5ab44ad10b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Thu, 25 Mar 2010 08:28:36 +0000 Subject: most of the tcp-objects seem to work now; performance increase as measured until now is great :-) svn path=/trunk/externals/iem/iemnet/; revision=13265 --- tcpsend.c | 318 ++++++++++++++++++++++---------------------------------------- 1 file changed, 110 insertions(+), 208 deletions(-) (limited to 'tcpsend.c') diff --git a/tcpsend.c b/tcpsend.c index b576eae..98ac620 100644 --- a/tcpsend.c +++ b/tcpsend.c @@ -1,254 +1,156 @@ -/* tcpsend.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. */ - -/* network */ - -#include "m_pd.h" -#include "s_stuff.h" -#include +/* tcpsend.c + * copyright (c) 2010 IOhannes m zmölnig, IEM + * copyright (c) 2006-2010 Martin Peach + * copyright (c) Miller Puckette + */ + +/* */ +/* A client for unidirectional communication from within Pd. */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ + + +#include "iemnet.h" #include -#ifdef _WIN32 -#include -#else -#include -#include -#include -#include -#include +#ifndef _WIN32 +# include #endif + static t_class *tcpsend_class; typedef struct _tcpsend { - t_object x_obj; - int x_fd; + t_object x_obj; + int x_fd; + t_iemnet_sender*x_sender; } t_tcpsend; -void tcpsend_setup(void); -static void tcpsend_free(t_tcpsend *x); -static void tcpsend_send(t_tcpsend *x, t_symbol *s, int argc, t_atom *argv); -static void tcpsend_disconnect(t_tcpsend *x); -static void tcpsend_connect(t_tcpsend *x, t_symbol *hostname, t_floatarg fportno); -static void *tcpsend_new(void); - -static void *tcpsend_new(void) +static void tcpsend_disconnect(t_tcpsend *x) { - t_tcpsend *x = (t_tcpsend *)pd_new(tcpsend_class); - outlet_new(&x->x_obj, &s_float); - x->x_fd = -1; - return (x); + if (x->x_fd >= 0) + { + if(x->x_sender)iemnet__sender_destroy(x->x_sender); x->x_sender=NULL; + sys_closesocket(x->x_fd); + x->x_fd = -1; + outlet_float(x->x_obj.ob_outlet, 0); + post("tcpsend: disconnected"); + } } + + static void tcpsend_connect(t_tcpsend *x, t_symbol *hostname, - t_floatarg fportno) + t_floatarg fportno) { - struct sockaddr_in server; - struct hostent *hp; - int sockfd; - int portno = fportno; - int intarg; + struct sockaddr_in server; + struct hostent *hp; + int sockfd; + int portno = fportno; + int intarg; - if (x->x_fd >= 0) + if (x->x_fd >= 0) { - error("tcpsend: already connected"); - return; + error("tcpsend: already connected"); + return; } - /* create a socket */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); + /* create a socket */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); #ifdef DEBUG - fprintf(stderr, "tcpsend_connect: send socket %d\n", sockfd); + fprintf(stderr, "tcpsend_connect: send socket %d\n", sockfd); #endif - if (sockfd < 0) + if (sockfd < 0) { - sys_sockerror("tcpsend: socket"); - return; + sys_sockerror("tcpsend: socket"); + return; } - /* connect socket using hostname provided in command line */ - server.sin_family = AF_INET; - hp = gethostbyname(hostname->s_name); - if (hp == 0) + /* connect socket using hostname provided in command line */ + server.sin_family = AF_INET; + hp = gethostbyname(hostname->s_name); + if (hp == 0) { - post("tcpsend: bad host?\n"); - return; + post("tcpsend: bad host?\n"); + return; } - /* for stream (TCP) sockets, specify "nodelay" */ - intarg = 1; - if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, - (char *)&intarg, sizeof(intarg)) < 0) - post("tcpsend: setsockopt (TCP_NODELAY) failed\n"); + /* for stream (TCP) sockets, specify "nodelay" */ + intarg = 1; + if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, + (char *)&intarg, sizeof(intarg)) < 0) + post("tcpsend: setsockopt (TCP_NODELAY) failed\n"); - memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); + memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); - /* assign client port number */ - server.sin_port = htons((u_short)portno); + /* assign client port number */ + server.sin_port = htons((u_short)portno); - post("tcpsend: connecting to port %d", portno); - /* try to connect. */ - if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) + post("tcpsend: connecting to port %d", portno); + /* try to connect. */ + if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) { - sys_sockerror("tcpsend: connecting stream socket"); - sys_closesocket(sockfd); - return; + sys_sockerror("tcpsend: connecting stream socket"); + sys_closesocket(sockfd); + return; } - x->x_fd = sockfd; - outlet_float(x->x_obj.ob_outlet, 1); -} + x->x_fd = sockfd; -static void tcpsend_disconnect(t_tcpsend *x) -{ - if (x->x_fd >= 0) - { - sys_closesocket(x->x_fd); - x->x_fd = -1; - outlet_float(x->x_obj.ob_outlet, 0); - post("tcpsend: disconnected"); - } + x->x_sender=iemnet__sender_create(sockfd); + + outlet_float(x->x_obj.ob_outlet, 1); } static void tcpsend_send(t_tcpsend *x, t_symbol *s, int argc, t_atom *argv) { -#define BYTE_BUF_LEN 65536 // arbitrary maximum similar to max IP packet size - static char byte_buf[BYTE_BUF_LEN]; - int i, j; - unsigned int d; - unsigned char c; - float f, e; - char *bp; - int length, sent; - int result; - static double lastwarntime; - static double pleasewarn; - double timebefore; - double timeafter; - int late; - char fpath[FILENAME_MAX]; - FILE *fptr; - -#ifdef DEBUG - post("s: %s", s->s_name); - post("argc: %d", argc); -#endif - for (i = j = 0; i < argc; ++i) - { - if (argv[i].a_type == A_FLOAT) - { - f = argv[i].a_w.w_float; - d = (unsigned int)f; - e = f - d; - if (e != 0) - { - error("tcpsend_send: item %d (%f) is not an integer", i, f); - return; - } - c = (unsigned char)d; - if (c != d) - { - error("tcpsend_send: item %d (%f) is not between 0 and 255", i, f); - return; - } -#ifdef DEBUG - post("tcpsend_send: argv[%d]: %d", i, c); -#endif - byte_buf[j++] = c; - } - else if (argv[i].a_type == A_SYMBOL) - { - - atom_string(&argv[i], fpath, FILENAME_MAX); -#ifdef DEBUG - post ("tcpsend fname: %s", fpath); -#endif - fptr = fopen(fpath, "rb"); - if (fptr == NULL) - { - post("tcpsend: unable to open \"%s\"", fpath); - return; - } - rewind(fptr); -#ifdef DEBUG - post("tcpsend: d is %d", d); -#endif - while ((d = fgetc(fptr)) != EOF) - { - byte_buf[j++] = (char)(d & 0x0FF); -#ifdef DEBUG - post("tcpsend: byte_buf[%d] = %d", j-1, byte_buf[j-1]); -#endif - if (j >= BYTE_BUF_LEN) - { - post ("tcpsend: file too long, truncating at %lu", BYTE_BUF_LEN); - break; - } - } - fclose(fptr); - fptr = NULL; - post("tcpsend: read \"%s\" length %d byte%s", fpath, j, ((d==1)?"":"s")); - } - else - { - error("tcpsend_send: item %d is not a float or a file name", i); - return; - } - } - - length = j; - if ((x->x_fd >= 0) && (length > 0)) - { - for (bp = byte_buf, sent = 0; sent < length;) - { - timebefore = sys_getrealtime(); - result = send(x->x_fd, byte_buf, length-sent, 0); - timeafter = sys_getrealtime(); - late = (timeafter - timebefore > 0.005); - if (late || pleasewarn) - { - if (timeafter > lastwarntime + 2) - { - post("tcpsend blocked %d msec", - (int)(1000 * ((timeafter - timebefore) + pleasewarn))); - pleasewarn = 0; - lastwarntime = timeafter; - } - else if (late) pleasewarn += timeafter - timebefore; - } - if (result <= 0) - { - sys_sockerror("tcpsend"); - tcpsend_disconnect(x); - break; - } - else - { - sent += result; - bp += result; - } - } - } - else error("tcpsend: not connected"); + int size=0; + t_iemnet_sender*sender=x->x_sender; + t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv); + if(sender && chunk) { + size=iemnet__sender_send(sender, chunk); + } + iemnet__chunk_destroy(chunk); } static void tcpsend_free(t_tcpsend *x) { - tcpsend_disconnect(x); + tcpsend_disconnect(x); +} + +static void *tcpsend_new(void) +{ + t_tcpsend *x = (t_tcpsend *)pd_new(tcpsend_class); + outlet_new(&x->x_obj, &s_float); + x->x_fd = -1; + return (x); } void tcpsend_setup(void) { - tcpsend_class = class_new(gensym("tcpsend"), (t_newmethod)tcpsend_new, - (t_method)tcpsend_free, - sizeof(t_tcpsend), 0, 0); - class_addmethod(tcpsend_class, (t_method)tcpsend_connect, - gensym("connect"), A_SYMBOL, A_FLOAT, 0); - class_addmethod(tcpsend_class, (t_method)tcpsend_disconnect, - gensym("disconnect"), 0); - class_addmethod(tcpsend_class, (t_method)tcpsend_send, gensym("send"), - A_GIMME, 0); - class_addlist(tcpsend_class, (t_method)tcpsend_send); + tcpsend_class = class_new(gensym("tcpsend"), + (t_newmethod)tcpsend_new, (t_method)tcpsend_free, + sizeof(t_tcpsend), + 0, 0); + + class_addmethod(tcpsend_class, (t_method)tcpsend_connect, + gensym("connect"), A_SYMBOL, A_FLOAT, 0); + class_addmethod(tcpsend_class, (t_method)tcpsend_disconnect, + gensym("disconnect"), 0); + class_addmethod(tcpsend_class, (t_method)tcpsend_send, gensym("send"), + A_GIMME, 0); + class_addlist(tcpsend_class, (t_method)tcpsend_send); } /* end tcpsend.c */ -- cgit v1.2.1