From ad3e4ced602b5ec7b1005635342e8f338c6bd2fa Mon Sep 17 00:00:00 2001 From: Martin Peach Date: Thu, 24 Aug 2006 06:51:16 +0000 Subject: Renamed files without x_net_ prefix. Removed extra copies of tcpserver and tcpclient svn path=/trunk/externals/mrpeach/; revision=5726 --- net/tcpclient.c | 443 +++++++++++++++++++++++++++++++++++ net/tcpreceive.c | 314 +++++++++++++++++++++++++ net/tcpsend.c | 222 ++++++++++++++++++ net/tcpserver.c | 619 +++++++++++++++++++++++++++++++++++++++++++++++++ net/udpreceive.c | 162 +++++++++++++ net/udpsend.c | 215 +++++++++++++++++ net/x_net_tcp_client.c | 443 ----------------------------------- net/x_net_tcp_server.c | 600 ----------------------------------------------- net/x_net_tcpclient.c | 443 ----------------------------------- net/x_net_tcpreceive.c | 314 ------------------------- net/x_net_tcpsend.c | 222 ------------------ net/x_net_tcpserver.c | 619 ------------------------------------------------- net/x_net_udpreceive.c | 162 ------------- net/x_net_udpsend.c | 215 ----------------- 14 files changed, 1975 insertions(+), 3018 deletions(-) create mode 100755 net/tcpclient.c create mode 100755 net/tcpreceive.c create mode 100755 net/tcpsend.c create mode 100755 net/tcpserver.c create mode 100755 net/udpreceive.c create mode 100755 net/udpsend.c delete mode 100755 net/x_net_tcp_client.c delete mode 100755 net/x_net_tcp_server.c delete mode 100755 net/x_net_tcpclient.c delete mode 100755 net/x_net_tcpreceive.c delete mode 100755 net/x_net_tcpsend.c delete mode 100755 net/x_net_tcpserver.c delete mode 100755 net/x_net_udpreceive.c delete mode 100755 net/x_net_udpsend.c (limited to 'net') diff --git a/net/tcpclient.c b/net/tcpclient.c new file mode 100755 index 0000000..366d421 --- /dev/null +++ b/net/tcpclient.c @@ -0,0 +1,443 @@ +/* x_net_tcp_client.c Martin Peach 20060508, working version 20060512 */ +/* linux version 20060515 */ +/* x_net_tcp_client.c is based on netclient: */ +/* -------------------------- netclient ------------------------------------- */ +/* */ +/* Extended 'netsend', connects to 'netserver'. */ +/* Uses child thread to connect to server. Thus needs pd0.35-test17 or later. */ +/* Written by Olaf Matthes (olaf.matthes@gmx.de) */ +/* Get source at http://www.akustische-kunst.org/puredata/maxlib/ */ +/* */ +/* 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. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* ---------------------------------------------------------------------------- */ +//define DEBUG + +#include "m_pd.h" +#include "s_stuff.h" + +#include +#include +#include +#include +#if defined(UNIX) || defined(unix) +#include +#include +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#else +#include +#endif + +#define DEFPOLLTIME 20 /* check for input every 20 ms */ + +static t_class *tcpclient_class; +static char objName[] = "tcpclient"; +#define MAX_UDP_RECEIVE 65536L // longer than data in maximum UDP packet + +typedef struct _tcpclient +{ + t_object x_obj; + t_clock *x_clock; + t_clock *x_poll; + t_outlet *x_msgout; + t_outlet *x_addrout; + t_outlet *x_outconnect; + int x_dump; // 1 = hexdump received bytes + int x_fd; // the socket + char *x_hostname; // address we want to connect to as text + int x_connectstate; // 0 = not connected, 1 = connected + int x_port; // port we're connected to + long x_addr; // address we're connected to as 32bit int + t_atom x_addrbytes[4]; // address we're connected to as 4 bytes + t_atom x_msgoutbuf[MAX_UDP_RECEIVE]; // received data as float atoms + unsigned char x_msginbuf[MAX_UDP_RECEIVE]; // received data as bytes + /* multithread stuff */ + pthread_t x_threadid; /* id of child thread */ + pthread_attr_t x_threadattr; /* attributes of child thread */ +} t_tcpclient; + +static void tcpclient_dump(t_tcpclient *x, t_float dump); +static void tcp_client_hexdump(unsigned char *buf, long len); +static void tcpclient_tick(t_tcpclient *x); +static void *tcpclient_child_connect(void *w); +static void tcpclient_connect(t_tcpclient *x, t_symbol *hostname, t_floatarg fportno); +static void tcpclient_disconnect(t_tcpclient *x); +static void tcpclient_send(t_tcpclient *x, t_symbol *s, int argc, t_atom *argv); +static void tcpclient_rcv(t_tcpclient *x); +static void tcpclient_poll(t_tcpclient *x); +static void *tcpclient_new(t_floatarg udpflag); +static void tcpclient_free(t_tcpclient *x); +#ifdef MSW +__declspec(dllexport) +#endif +void tcpclient_setup(void); + +static void tcpclient_dump(t_tcpclient *x, t_float dump) +{ + x->x_dump = (dump == 0)?0:1; +} + +static void tcp_client_hexdump(unsigned char *buf, long len) +{ +#define BYTES_PER_LINE 16 + char hexStr[(3*BYTES_PER_LINE)+1]; + char ascStr[BYTES_PER_LINE+1]; + long i, j, k = 0L; +#ifdef DEBUG + post("tcp_client_hexdump %d", len); +#endif + while (k < len) + { + for (i = j = 0; i < BYTES_PER_LINE; ++i, ++k, j+=3) + { + if (k < len) + { +#ifdef MSW + sprintf_s(&hexStr[j], 4, "%02X ", buf[k]); + sprintf_s(&ascStr[i], 2, "%c", ((buf[k] >= 32) && (buf[k] <= 126))? buf[k]: '.'); +#else + snprintf(&hexStr[j], 4, "%02X ", buf[k]); + snprintf(&ascStr[i], 2, "%c", ((buf[k] >= 32) && (buf[k] <= 126))? buf[k]: '.'); +#endif + } + else + { // the last line +#ifdef MSW + sprintf_s(&hexStr[j], 4, " "); + sprintf_s(&ascStr[i], 2, " "); +#else + snprintf(&hexStr[j], 4, " "); + snprintf(&ascStr[i], 2, " "); +#endif + } + } + post ("%s%s", hexStr, ascStr); + } +} + +static void tcpclient_tick(t_tcpclient *x) +{ + outlet_float(x->x_outconnect, 1); +} + +static void *tcpclient_child_connect(void *w) +{ + t_tcpclient *x = (t_tcpclient*) w; + struct sockaddr_in server; + struct hostent *hp; + int sockfd; + + if (x->x_fd >= 0) + { + error("%s_connect: already connected", objName); + return (x); + } + + /* create a socket */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); +#ifdef DEBUG + post("%s: send socket %d\n", objName, sockfd); +#endif + if (sockfd < 0) + { + sys_sockerror("tcpclient: socket"); + return (x); + } + /* connect socket using hostname provided in command line */ + server.sin_family = AF_INET; + hp = gethostbyname(x->x_hostname); + if (hp == 0) + { + sys_sockerror("tcpclient: bad host?\n"); + return (x); + } + memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); + + /* assign client port number */ + server.sin_port = htons((u_short)x->x_port); + + post("%s: connecting socket %d to port %d", objName, sockfd, x->x_port); + /* try to connect */ + if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) + { + sys_sockerror("tcpclient: connecting stream socket"); + sys_closesocket(sockfd); + return (x); + } + x->x_fd = sockfd; + x->x_addr = ntohl(*(long *)hp->h_addr); + /* outlet_float is not threadsafe ! */ + // outlet_float(x->x_obj.ob_outlet, 1); + x->x_connectstate = 1; + /* use callback instead to set outlet */ + clock_delay(x->x_clock, 0); + return (x); +} + +static void tcpclient_connect(t_tcpclient *x, t_symbol *hostname, t_floatarg fportno) +{ + /* 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) + post("%s: could not create new thread", objName); +} + +static void tcpclient_disconnect(t_tcpclient *x) +{ + if (x->x_fd >= 0) + { + sys_closesocket(x->x_fd); + x->x_fd = -1; + x->x_connectstate = 0; + outlet_float(x->x_outconnect, 0); + post("%s: disconnected", objName); + } + else post("%s: not connected", objName); +} + +static void tcpclient_send(t_tcpclient *x, t_symbol *s, int argc, t_atom *argv) +{ + static char byte_buf[65536];// arbitrary maximum similar to max IP packet size + int i, 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; + +#ifdef DEBUG + post("s: %s", s->s_name); + post("argc: %d", argc); +#endif + + for (i = 0; i < argc; ++i) + { + if (argv[i].a_type == A_FLOAT) + { + f = argv[i].a_w.w_float; + d = (int)f; + e = f - d; +#ifdef DEBUG + post("%s: argv[%d]: float:%f int:%d delta:%f", objName, i, f, d, e); +#endif + if (e != 0) + { + error("%s_send: item %d (%f) is not an integer", objName, i, f); + return; + } + if ((d < 0) || (d > 255)) + { + error("%s: item %d (%f) is not between 0 and 255", objName, i, f); + return; + } + c = (unsigned char)d; +#ifdef DEBUG + post("%s_send: argv[%d]: %d", objName, i, c); +#endif + byte_buf[i] = c; + } + else + { + error("%s_send: item %d is not a float", objName, i); + return; + } + } + + length = i; + 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("%s_send blocked %d msec", objName, + (int)(1000 * ((timeafter - timebefore) + pleasewarn))); + pleasewarn = 0; + lastwarntime = timeafter; + } + else if (late) pleasewarn += timeafter - timebefore; + } + if (result <= 0) + { + sys_sockerror("tcpclient_send"); + tcpclient_disconnect(x); + break; + } + else + { + sent += result; + bp += result; + } + } + } + else error("%s: not connected", objName); +} + +static void tcpclient_rcv(t_tcpclient *x) +{ + int sockfd = x->x_fd; + int ret; + int i; + fd_set readset; + fd_set exceptset; + struct timeval ztout; + + if(x->x_connectstate) + { + /* check if we can read/write from/to the socket */ + FD_ZERO(&readset); + FD_ZERO(&exceptset); + FD_SET(x->x_fd, &readset ); + FD_SET(x->x_fd, &exceptset ); + + ztout.tv_sec = 0; + ztout.tv_usec = 0; + + ret = select(sockfd+1, &readset, NULL, &exceptset, &ztout); + if(ret < 0) + { + error("%s: unable to read from socket", objName); + sys_closesocket(sockfd); + return; + } + if(FD_ISSET(sockfd, &readset) || FD_ISSET(sockfd, &exceptset)) + { + /* read from server */ + ret = recv(sockfd, x->x_msginbuf, MAX_UDP_RECEIVE, 0); + if(ret > 0) + { +#ifdef DEBUG + x->x_msginbuf[ret] = 0; + post("%s: received %d bytes ", objName, ret); +#endif + if (x->x_dump)tcp_client_hexdump(x->x_msginbuf, ret); + for (i = 0; i < ret; ++i) + { + /* convert the bytes in the buffer to floats in a list */ + x->x_msgoutbuf[i].a_w.w_float = (float)x->x_msginbuf[i]; + } + /* find sender's ip address and output it */ + x->x_addrbytes[0].a_w.w_float = (x->x_addr & 0xFF000000)>>24; + x->x_addrbytes[1].a_w.w_float = (x->x_addr & 0x0FF0000)>>16; + x->x_addrbytes[2].a_w.w_float = (x->x_addr & 0x0FF00)>>8; + x->x_addrbytes[3].a_w.w_float = (x->x_addr & 0x0FF); + outlet_list(x->x_addrout, &s_list, 4L, x->x_addrbytes); + /* send the list out the outlet */ + if (ret > 1) outlet_list(x->x_msgout, &s_list, ret, x->x_msgoutbuf); + else outlet_float(x->x_msgout, x->x_msgoutbuf[0].a_w.w_float); + } + else + { + if (ret < 0) + { + sys_sockerror("tcpclient: recv"); + tcpclient_disconnect(x); + } + else + { + post("%s: connection closed for socket %d\n", objName, sockfd); + tcpclient_disconnect(x); + } + } + } + } + else post("%s: not connected", objName); +} + +static void tcpclient_poll(t_tcpclient *x) +{ + if(x->x_connectstate) + tcpclient_rcv(x); /* try to read in case we're connected */ + clock_delay(x->x_poll, DEFPOLLTIME); /* see you later */ +} + +static void *tcpclient_new(t_floatarg udpflag) +{ + int i; + + t_tcpclient *x = (t_tcpclient *)pd_new(tcpclient_class); + x->x_msgout = outlet_new(&x->x_obj, &s_anything); /* received data */ + x->x_addrout = outlet_new(&x->x_obj, &s_list); + x->x_outconnect = outlet_new(&x->x_obj, &s_float); /* connection state */ + x->x_clock = clock_new(x, (t_method)tcpclient_tick); + x->x_poll = clock_new(x, (t_method)tcpclient_poll); + x->x_fd = -1; + /* convert the bytes in the buffer to floats in a list */ + for (i = 0; i < MAX_UDP_RECEIVE; ++i) + { + x->x_msgoutbuf[i].a_type = A_FLOAT; + x->x_msgoutbuf[i].a_w.w_float = 0; + } + for (i = 0; i < 4; ++i) + { + x->x_addrbytes[i].a_type = A_FLOAT; + x->x_addrbytes[i].a_w.w_float = 0; + } + x->x_addr = 0L; + /* prepare child thread */ + if(pthread_attr_init(&x->x_threadattr) < 0) + post("%s: warning: could not prepare child thread", objName); + if(pthread_attr_setdetachstate(&x->x_threadattr, PTHREAD_CREATE_DETACHED) < 0) + post("%s: warning: could not prepare child thread", objName); + clock_delay(x->x_poll, 0); /* start polling the input */ + return (x); +} + +static void tcpclient_free(t_tcpclient *x) +{ + tcpclient_disconnect(x); + clock_free(x->x_poll); + clock_free(x->x_clock); +} + +#ifdef MSW +__declspec(dllexport) +#endif +void tcpclient_setup(void) +{ + 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") + , A_SYMBOL, A_FLOAT, 0); + class_addmethod(tcpclient_class, (t_method)tcpclient_disconnect, gensym("disconnect"), 0); + class_addmethod(tcpclient_class, (t_method)tcpclient_send, gensym("send"), A_GIMME, 0); + class_addmethod(tcpclient_class, (t_method)tcpclient_rcv, gensym("receive"), 0); + class_addmethod(tcpclient_class, (t_method)tcpclient_rcv, gensym("rcv"), 0); + class_addmethod(tcpclient_class, (t_method)tcpclient_dump, gensym("dump"), A_FLOAT, 0); +} + +/* end of x_net_tcp.c */ diff --git a/net/tcpreceive.c b/net/tcpreceive.c new file mode 100755 index 0000000..4cce77d --- /dev/null +++ b/net/tcpreceive.c @@ -0,0 +1,314 @@ +/* x_net_tcpreceive.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. */ + +#include "m_pd.h" +#include "s_stuff.h" + +#ifdef MSW +#include +#include /* for socklen_t */ +#else +#include +#include +#include +#include +#include +#include +#endif + + +/* ----------------------------- tcpreceive ------------------------- */ + +static t_class *tcpreceive_class; + +#define MAX_UDP_RECEIVE 65536L // longer than data in maximum UDP packet +#define MAX_CONNECTIONS 128 // this is going to cause trouble down the line...:( + +typedef struct _tcpconnection +{ + long addr; + int socket; +} t_tcpconnection; + +typedef struct _tcpreceive +{ + t_object x_obj; + t_outlet *x_msgout; + t_outlet *x_addrout; + t_outlet *x_connectout; + int x_connectsocket; + int x_nconnections; + t_tcpconnection x_connection[MAX_CONNECTIONS]; + t_atom x_addrbytes[4]; + t_atom x_msgoutbuf[MAX_UDP_RECEIVE]; + char x_msginbuf[MAX_UDP_RECEIVE]; +} t_tcpreceive; + +#ifdef MSW +__declspec(dllexport) +#endif +void tcpreceive_setup(void); +static void tcpreceive_free(t_tcpreceive *x); +static void *tcpreceive_new(t_floatarg fportno); +static void tcpreceive_read(t_tcpreceive *x, int sockfd); +static void tcpreceive_connectpoll(t_tcpreceive *x); +static int tcpreceive_addconnection(t_tcpreceive * x, int fd, long addr); +static int tcpreceive_removeconnection(t_tcpreceive * x, int fd); +static void tcpreceive_closeall(t_tcpreceive *x); +static long tcpreceive_getconnection(t_tcpreceive * x, int fd); + +static void tcpreceive_read(t_tcpreceive *x, int sockfd) +{ + int i, read = 0; + long addr; + +// read = recvfrom(sockfd, x->x_msginbuf, MAX_UDP_RECEIVE, 0, (struct sockaddr *)&from, &fromlen); + read = recv(sockfd, x->x_msginbuf, MAX_UDP_RECEIVE, 0); +#ifdef DEBUG + post("tcpreceive_read: read %lu x->x_connectsocket = %d", + read, x->x_connectsocket); +#endif + if (read < 0) + { + sys_sockerror("tcpreceive_read: recv"); + sys_rmpollfn(sockfd); + sys_closesocket(sockfd); + tcpreceive_removeconnection(x, sockfd); + outlet_float(x->x_connectout, --x->x_nconnections); + } + else if (read == 0) + { + post("tcpreceive: EOF on socket %d\n", sockfd); + sys_rmpollfn(sockfd); + sys_closesocket(sockfd); + tcpreceive_removeconnection(x, sockfd); + outlet_float(x->x_connectout, --x->x_nconnections); + } + else if (read > 0) + { + for (i = 0; i < read; ++i) + { + /* convert the bytes in the buffer to floats in a list */ + x->x_msgoutbuf[i].a_w.w_float = (float)x->x_msginbuf[i]; + } + /* find sender's ip address and output it */ + addr = tcpreceive_getconnection(x, sockfd); + 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); + outlet_list(x->x_addrout, &s_list, 4L, x->x_addrbytes); + /* send the list out the outlet */ + if (read > 1) outlet_list(x->x_msgout, &s_list, read, x->x_msgoutbuf); + else outlet_float(x->x_msgout, x->x_msgoutbuf[0].a_w.w_float); + } +} + +static void *tcpreceive_new(t_floatarg fportno) +{ + t_tcpreceive *x; + struct sockaddr_in server; + int sockfd, portno = fportno; + int intarg, i; + + /* create a socket */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); +#ifdef DEBUG + post("tcpreceive_new: socket %d port %d", sockfd, portno); +#endif + if (sockfd < 0) + { + sys_sockerror("tcpreceive: socket"); + return (0); + } + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + + /* ask OS to allow another Pd to repoen 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"); + /* 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"); + + /* assign server port number */ + server.sin_port = htons((u_short)portno); + + /* name the socket */ + if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) + { + sys_sockerror("tcpreceive: bind"); + sys_closesocket(sockfd); + return (0); + } + x = (t_tcpreceive *)pd_new(tcpreceive_class); + x->x_msgout = outlet_new(&x->x_obj, &s_anything); + x->x_addrout = outlet_new(&x->x_obj, &s_list); + x->x_connectout = outlet_new(&x->x_obj, &s_float); + /* clear the connection list */ + for (i = 0; i < MAX_CONNECTIONS; ++i) + { + x->x_connection[i].socket = -1; + x->x_connection[i].addr = 0L; + } + /* convert the bytes in the buffer to floats in a list */ + for (i = 0; i < MAX_UDP_RECEIVE; ++i) + { + x->x_msgoutbuf[i].a_type = A_FLOAT; + x->x_msgoutbuf[i].a_w.w_float = 0; + } + for (i = 0; i < 4; ++i) + { + x->x_addrbytes[i].a_type = A_FLOAT; + x->x_addrbytes[i].a_w.w_float = 0; + } + + /* streaming protocol */ + if (listen(sockfd, 5) < 0) + { + sys_sockerror("tcpreceive: listen"); + sys_closesocket(sockfd); + sockfd = -1; + } + else + { + sys_addpollfn(sockfd, (t_fdpollfn)tcpreceive_connectpoll, x); + } + x->x_connectsocket = sockfd; + x->x_nconnections = 0; + +//udp version... sys_addpollfn(x->x_connectsocket, (t_fdpollfn)tcpreceive_read, x); + return (x); +} + +/* tcpreceive_connectpoll checks for incoming connection requests on the original socket */ +/* a new socket is assigned */ +static void tcpreceive_connectpoll(t_tcpreceive *x) +{ + struct sockaddr_in from; + socklen_t fromlen = sizeof(from); + long addr; + int fd; + + fd = accept(x->x_connectsocket, (struct sockaddr *)&from, &fromlen); + if (fd < 0) post("tcpreceive: accept failed"); + else + { + // t_socketreceiver *y = socketreceiver_new((void *)x, + // (t_socketnotifier)tcpreceive_notify, + // 0, 0); + + /* get the sender's ip */ + addr = ntohl(from.sin_addr.s_addr); + if (tcpreceive_addconnection(x, fd, addr)) + { + sys_addpollfn(fd, (t_fdpollfn)tcpreceive_read, x); + 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); + outlet_list(x->x_addrout, &s_list, 4L, x->x_addrbytes); + } + else + { + error ("tcpreceive: Too many connections"); + sys_closesocket(fd); + } + } +} + +/* 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) +{ + int i; + for (i = 0; i < MAX_CONNECTIONS; ++i) + { + if (x->x_connection[i].socket == -1) + { + x->x_connection[i].socket = fd; + x->x_connection[i].addr = addr; + return 1; + } + } + return 0; +} + +/* tcpreceive_closeall closes all open sockets and deletes them from the list */ +static void tcpreceive_closeall(t_tcpreceive *x) +{ + int i; + + for (i = 0; ((i < MAX_CONNECTIONS) && (x->x_nconnections > 0)); ++i) + { + if (x->x_connection[i].socket != -1) + { + post ("tcpreceive: closing socket %d", x->x_connection[i].socket); + sys_rmpollfn(x->x_connection[i].socket); + sys_closesocket(x->x_connection[i].socket); + x->x_connection[i].socket = -1; + x->x_connection[i].addr = 0L; + outlet_float(x->x_connectout, --x->x_nconnections); + } + } +} + +/* tcpreceive_removeconnection tries to delete the socket fd from the list */ +/* returns 1 on success, else 0 */ +static int tcpreceive_removeconnection(t_tcpreceive *x, int fd) +{ + int i; + for (i = 0; i < MAX_CONNECTIONS; ++i) + { + if (x->x_connection[i].socket == fd) + { + x->x_connection[i].socket = -1; + x->x_connection[i].addr = 0L; + return 1; + } + } + return 0; +} + +/* tcpreceive_getconnection tries to find the socket fd in the list */ +/* returns addr on success, else 0 */ +static long tcpreceive_getconnection(t_tcpreceive *x, int fd) +{ + int i; + for (i = 0; i < MAX_CONNECTIONS; ++i) + { + if (x->x_connection[i].socket == fd) + return x->x_connection[i].addr; + } + 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_closeall(x); +} + +#ifdef MSW +__declspec(dllexport) +#endif +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); +} + +/* end x_net_tcpreceive.c */ + diff --git a/net/tcpsend.c b/net/tcpsend.c new file mode 100755 index 0000000..cf8c33d --- /dev/null +++ b/net/tcpsend.c @@ -0,0 +1,222 @@ +/* x_net_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" + +#ifdef MSW +#include +#else +#include +#include +#include +#include +#include +#include +#include +#endif + +static t_class *tcpsend_class; + +typedef struct _tcpsend +{ + t_object x_obj; + int x_fd; +} t_tcpsend; + +#ifdef MSW +__declspec(dllexport) +#endif +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) +{ + t_tcpsend *x = (t_tcpsend *)pd_new(tcpsend_class); + outlet_new(&x->x_obj, &s_float); + x->x_fd = -1; + return (x); +} + +static void tcpsend_connect(t_tcpsend *x, t_symbol *hostname, + t_floatarg fportno) +{ + struct sockaddr_in server; + struct hostent *hp; + int sockfd; + int portno = fportno; + int intarg; + + if (x->x_fd >= 0) + { + error("tcpsend: already connected"); + return; + } + + /* create a socket */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); +#ifdef DEBUG + fprintf(stderr, "tcpsend_connect: send socket %d\n", sockfd); +#endif + if (sockfd < 0) + { + 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) + { + 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"); + + memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); + + /* 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) + { + sys_sockerror("tcpsend: connecting stream socket"); + sys_closesocket(sockfd); + return; + } + x->x_fd = sockfd; + outlet_float(x->x_obj.ob_outlet, 1); +} + +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"); + } +} + +static void tcpsend_send(t_tcpsend *x, t_symbol *s, int argc, t_atom *argv) +{ + static char byte_buf[65536];// arbitrary maximum similar to max IP packet size + int i, d; + char c; + float f, e; + char *bp; + int length, sent; + int result; + static double lastwarntime; + static double pleasewarn; + double timebefore; + double timeafter; + int late; + +#ifdef DEBUG + post("s: %s", s->s_name); + post("argc: %d", argc); +#endif + for (i = 0; i < argc; ++i) + { + if (argv[i].a_type == A_FLOAT) + { + f = argv[i].a_w.w_float; + d = (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[i] = c; + } + else + { + error("tcpsend_send: item %d is not a float", i); + return; + } + } + + length = i; + 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"); +} + +static void tcpsend_free(t_tcpsend *x) +{ + tcpsend_disconnect(x); +} + +#ifdef MSW +__declspec(dllexport) +#endif +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); +} + +/* end x_net_tcpsend.c*/ diff --git a/net/tcpserver.c b/net/tcpserver.c new file mode 100755 index 0000000..f6526c0 --- /dev/null +++ b/net/tcpserver.c @@ -0,0 +1,619 @@ +/* x_net_tcpserver.c Martin Peach 20060511 working version 20060512 */ +/* 20060515 works on linux too... */ +/* x_net_tcpserver.c is based on netserver: */ +/* -------------------------- netserver ------------------------------------- */ +/* */ +/* A server for bidirectional communication from within Pd. */ +/* Allows to send back data to specific clients connected to the server. */ +/* Written by Olaf Matthes */ +/* Get source at http://www.akustische-kunst.org/puredata/maxlib */ +/* */ +/* 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. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* ---------------------------------------------------------------------------- */ +//define DEBUG + +#include "m_pd.h" +#include "m_imp.h" +#include "s_stuff.h" + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +#if defined(UNIX) || defined(unix) +#include +#include +#include +#include +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#else +//#include +//#include +#include +#endif + +#define MAX_CONNECT 32 /* maximum number of connections */ +#define INBUFSIZE 65536L /* was 4096: size of receiving data buffer */ +#define MAX_UDP_RECEIVE 65536L /* longer than data in maximum UDP packet */ + +/* ----------------------------- tcpserver ------------------------- */ + +static t_class *tcpserver_class; +static t_binbuf *inbinbuf; +static char objName[] = "tcpserver"; + +typedef void (*t_tcpserver_socketnotifier)(void *x); +typedef void (*t_tcpserver_socketreceivefn)(void *x, t_binbuf *b); + +typedef struct _tcpserver_socketreceiver +{ + unsigned char *sr_inbuf; + int sr_inhead; + int sr_intail; + void *sr_owner; + t_tcpserver_socketnotifier sr_notifier; + t_tcpserver_socketreceivefn sr_socketreceivefn; +} t_tcpserver_socketreceiver; + +typedef struct _tcpserver +{ + t_object x_obj; + t_outlet *x_msgout; + t_outlet *x_connectout; + t_outlet *x_sockout; + t_outlet *x_addrout; + t_symbol *x_host[MAX_CONNECT]; + t_int x_fd[MAX_CONNECT]; + u_long x_addr[MAX_CONNECT]; + t_tcpserver_socketreceiver *x_sr[MAX_CONNECT]; + t_atom x_addrbytes[4]; + t_int x_sock_fd; + t_int x_connectsocket; + t_int x_nconnections; + t_atom x_msgoutbuf[MAX_UDP_RECEIVE]; + char x_msginbuf[MAX_UDP_RECEIVE]; +} t_tcpserver; + +static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new(void *owner, t_tcpserver_socketnotifier notifier, + t_tcpserver_socketreceivefn socketreceivefn); +static int tcpserver_socketreceiver_doread(t_tcpserver_socketreceiver *x); +static void tcpserver_socketreceiver_read(t_tcpserver_socketreceiver *x, int fd); +static void tcpserver_socketreceiver_free(t_tcpserver_socketreceiver *x); +static void tcpserver_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv); +static void tcp_server_send_bytes(int sockfd, t_tcpserver *x, int argc, t_atom *argv); +static void tcpserver_client_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv); +static void tcpserver_broadcast(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv); +static void tcpserver_notify(t_tcpserver *x); +static void tcpserver_connectpoll(t_tcpserver *x); +static void tcpserver_print(t_tcpserver *x); +static void *tcpserver_new(t_floatarg fportno); +static void tcpserver_free(t_tcpserver *x); +#ifdef MSW +__declspec(dllexport) +#endif +void tcpserver_setup(void); + +static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new(void *owner, t_tcpserver_socketnotifier notifier, + t_tcpserver_socketreceivefn socketreceivefn) +{ + t_tcpserver_socketreceiver *x = (t_tcpserver_socketreceiver *)getbytes(sizeof(*x)); + if (!x) + { + error("%s_socketreceiver: unable to allocate %d bytes", objName, sizeof(*x)); + } + else + { + x->sr_inhead = x->sr_intail = 0; + x->sr_owner = owner; + x->sr_notifier = notifier; + x->sr_socketreceivefn = socketreceivefn; + if (!(x->sr_inbuf = malloc(INBUFSIZE))) + { + freebytes(x, sizeof(*x)); + x = NULL; + error("%s_socketreceiver: unable to allocate %d bytes", objName, INBUFSIZE); + } + } + return (x); +} + +/* this is in a separately called subroutine so that the buffer isn't + sitting on the stack while the messages are getting passed. */ +static int tcpserver_socketreceiver_doread(t_tcpserver_socketreceiver *x) +{ + char messbuf[INBUFSIZE]; + char *bp = messbuf; + int indx, i; + int inhead = x->sr_inhead; + int intail = x->sr_intail; + unsigned char c; + t_tcpserver *y = x->sr_owner; + unsigned char *inbuf = x->sr_inbuf; + + if (intail == inhead) return (0); +#ifdef DEBUG + post ("%s_socketreceiver_doread: intail=%d inhead=%d", objName, intail, inhead); +#endif + + for (indx = intail, i = 0; indx != inhead; indx = (indx+1)&(INBUFSIZE-1), ++i) + { + c = *bp++ = inbuf[indx]; + y->x_msgoutbuf[i].a_w.w_float = (float)c; + } + if (i > 1) outlet_list(y->x_msgout, &s_list, i, y->x_msgoutbuf); + else outlet_float(y->x_msgout, y->x_msgoutbuf[0].a_w.w_float); + + // intail = (indx+1)&(INBUFSIZE-1); + x->sr_inhead = inhead; + x->sr_intail = indx;//intail; + return (1); +} + +static void tcpserver_socketreceiver_read(t_tcpserver_socketreceiver *x, int fd) +{ + int readto = (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1); + int ret, i; + t_tcpserver *y = x->sr_owner; + + y->x_sock_fd = fd; + /* the input buffer might be full. If so, drop the whole thing */ + if (readto == x->sr_inhead) + { + post("%s: dropped message", objName); + x->sr_inhead = x->sr_intail = 0; + readto = INBUFSIZE; + } + else + { + ret = recv(fd, x->sr_inbuf + x->sr_inhead, + readto - x->sr_inhead, 0); + if (ret < 0) + { + sys_sockerror("tcpserver: recv"); + if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner); + sys_rmpollfn(fd); + sys_closesocket(fd); + } + else if (ret == 0) + { + post("%s: connection closed on socket %d", objName, fd); + if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner); + sys_rmpollfn(fd); + sys_closesocket(fd); + } + else + { +#ifdef DEBUG + post ("%s_socketreceiver_read: ret = %d", objName, ret); +#endif + x->sr_inhead += ret; + if (x->sr_inhead >= INBUFSIZE) x->sr_inhead = 0; + /* output client's IP and socket no. */ + for(i = 0; i < y->x_nconnections; i++) /* search for corresponding IP */ + { + if(y->x_fd[i] == y->x_sock_fd) + { +// outlet_symbol(x->x_connectionip, x->x_host[i]); + /* find sender's ip address and output it */ + y->x_addrbytes[0].a_w.w_float = (y->x_addr[i] & 0xFF000000)>>24; + y->x_addrbytes[1].a_w.w_float = (y->x_addr[i] & 0x0FF0000)>>16; + y->x_addrbytes[2].a_w.w_float = (y->x_addr[i] & 0x0FF00)>>8; + y->x_addrbytes[3].a_w.w_float = (y->x_addr[i] & 0x0FF); + outlet_list(y->x_addrout, &s_list, 4L, y->x_addrbytes); + break; + } + } + outlet_float(y->x_sockout, y->x_sock_fd); /* the socket number */ + tcpserver_socketreceiver_doread(x); + } + } +} + +static void tcpserver_socketreceiver_free(t_tcpserver_socketreceiver *x) +{ + if (x != NULL) + { + free(x->sr_inbuf); + freebytes(x, sizeof(*x)); + } +} + +/* ---------------- main tcpserver (send) stuff --------------------- */ + +static void tcp_server_send_bytes(int client, t_tcpserver *x, int argc, t_atom *argv) +{ + static char byte_buf[MAX_UDP_RECEIVE];// arbitrary maximum similar to max IP packet size + int i, 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; + int sockfd = x->x_fd[client]; + + /* process & send data */ + if(sockfd >= 0) + { + for (i = 0; i < argc; ++i) + { + if (argv[i].a_type == A_FLOAT) + { + f = argv[i].a_w.w_float; + d = (int)f; + e = f - d; +#ifdef DEBUG + post("%s: argv[%d]: float:%f int:%d delta:%f", objName, i, f, d, e); +#endif + if (e != 0) + { + error("%s: item %d (%f) is not an integer", objName, i, f); + return; + } + if ((d < 0) || (d > 255)) + { + error("%s: item %d (%f) is not between 0 and 255", objName, i, f); + return; + } + c = (unsigned char)d; /* make sure it doesn't become negative; this only matters for post() */ +#ifdef DEBUG + post("%s: argv[%d]: %d", objName, i, c); +#endif + byte_buf[i] = c; + } + else + { + error("%s: item %d is not a float", objName, i); + return; + } + } + length = i; + if (length > 0) + { + for (bp = byte_buf, sent = 0; sent < length;) + { + timebefore = sys_getrealtime(); + result = send(sockfd, byte_buf, length-sent, 0); + timeafter = sys_getrealtime(); + late = (timeafter - timebefore > 0.005); + if (late || pleasewarn) + { + if (timeafter > lastwarntime + 2) + { + post("%s: send blocked %d msec", objName, + (int)(1000 * ((timeafter - timebefore) + pleasewarn))); + pleasewarn = 0; + lastwarntime = timeafter; + } + else if (late) pleasewarn += timeafter - timebefore; + } + if (result <= 0) + { + sys_sockerror("tcpserver: send"); + post("%s: could not send data to client %d", objName, client); + break; + } + else + { + sent += result; + bp += result; + } + } + } + } + else post("%s: not a valid socket number (%d)", objName, sockfd); +} + +/* send message to client using socket number */ +static void tcpserver_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) +{ + int i, sockfd; + int client = -1; + + if(x->x_nconnections < 0) + { + post("%s: no clients connected", objName); + return; + } + if(argc < 2) + { + post("%s: nothing to send", objName); + return; + } + /* get socket number of connection (first element in list) */ + if(argv[0].a_type == A_FLOAT) + { + sockfd = atom_getfloatarg(0, argc, argv); + for(i = 0; i < x->x_nconnections; i++) /* check if connection exists */ + { + if(x->x_fd[i] == sockfd) + { + client = i; /* the client we're sending to */ + break; + } + } + if(client == -1) + { + post("%s: no connection on socket %d", objName, sockfd); + return; + } + } + else + { + post("%s: no socket specified", objName); + return; + } + tcp_server_send_bytes(client, x, argc-1, &argv[1]); +} + +/* send message to client using client number + note that the client numbers might change in case a client disconnects! */ +/* clients start at 1 but our index starts at 0 */ +static void tcpserver_client_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) +{ + int client; + + if(x->x_nconnections < 0) + { + post("%s: no clients connected", objName); + return; + } + if(argc < 2) + { + post("%s: nothing to send", objName); + return; + } + /* get number of client (first element in list) */ + if(argv[0].a_type == A_FLOAT) + client = atom_getfloatarg(0, argc, argv); + else + { + post("%s: no client specified", objName); + return; + } + if (!((client > 0) && (client < MAX_CONNECT))) + { + post("%s: client %d out of range [1..%d]", objName, client, MAX_CONNECT); + return; + } + --client;/* zero based index*/ + tcp_server_send_bytes(client, x, argc-1, &argv[1]); +} + +/* broadcasts a message to all connected clients */ +static void tcpserver_broadcast(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) +{ + int client; + + /* enumerate through the clients and send each the message */ + for(client = 0; client < x->x_nconnections; client++) /* check if connection exists */ + { + if(x->x_fd[client] >= 0) + { /* socket exists for this client */ + tcp_server_send_bytes(client, x, argc, argv); + break; + } + } +} + +/* ---------------- main tcpserver (receive) stuff --------------------- */ + +static void tcpserver_notify(t_tcpserver *x) +{ + int i, k; + + /* remove connection from list */ + for(i = 0; i < x->x_nconnections; i++) + { + if(x->x_fd[i] == x->x_sock_fd) + { + x->x_nconnections--; + post("%s: \"%s\" removed from list of clients", objName, x->x_host[i]->s_name); + x->x_host[i] = NULL; /* delete entry */ + x->x_fd[i] = -1; + tcpserver_socketreceiver_free(x->x_sr[i]); + x->x_sr[i] = NULL; + + /* rearrange list now: move entries to close the gap */ + for(k = i; k < x->x_nconnections; k++) + { + x->x_host[k] = x->x_host[k + 1]; + x->x_fd[k] = x->x_fd[k + 1]; + } + } + } + outlet_float(x->x_connectout, x->x_nconnections); +} + +static void tcpserver_connectpoll(t_tcpserver *x) +{ + struct sockaddr_in incomer_address; + int sockaddrl = (int) sizeof( struct sockaddr ); + int fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl); + int i; + + if (fd < 0) post("%s: accept failed", objName); + else + { + t_tcpserver_socketreceiver *y = tcpserver_socketreceiver_new((void *)x, + (t_tcpserver_socketnotifier)tcpserver_notify, NULL);/* MP tcpserver_doit isn't used I think...*/ + if (!y) + { +#ifdef MSW + closesocket(fd); +#else + close(fd); +#endif + return; + } + sys_addpollfn(fd, (t_fdpollfn)tcpserver_socketreceiver_read, y); + x->x_nconnections++; + i = x->x_nconnections - 1; + x->x_host[i] = gensym(inet_ntoa(incomer_address.sin_addr)); + x->x_fd[i] = fd; + x->x_sr[i] = y; + post("%s: accepted connection from %s on socket %d", + objName, x->x_host[i]->s_name, x->x_fd[i]); + outlet_float(x->x_connectout, x->x_nconnections); + outlet_float(x->x_sockout, x->x_fd[i]); /* the socket number */ + x->x_addr[i] = ntohl(incomer_address.sin_addr.s_addr); + x->x_addrbytes[0].a_w.w_float = (x->x_addr[i] & 0xFF000000)>>24; + x->x_addrbytes[1].a_w.w_float = (x->x_addr[i] & 0x0FF0000)>>16; + x->x_addrbytes[2].a_w.w_float = (x->x_addr[i] & 0x0FF00)>>8; + x->x_addrbytes[3].a_w.w_float = (x->x_addr[i] & 0x0FF); + outlet_list(x->x_addrout, &s_list, 4L, x->x_addrbytes); + } +} + +static void tcpserver_print(t_tcpserver *x) +{ + int i; + + if(x->x_nconnections > 0) + { + post("%s: %d open connections:", objName, x->x_nconnections); + for(i = 0; i < x->x_nconnections; i++) + { + post(" \"%s\" on socket %d", + x->x_host[i]->s_name, x->x_fd[i]); + } + } + else post("%s: no open connections", objName); +} + +static void *tcpserver_new(t_floatarg fportno) +{ + t_tcpserver *x; + int i; + struct sockaddr_in server; + int sockfd, portno = fportno; + + /* create a socket */ + sockfd = socket(AF_INET, SOCK_STREAM, 0); +#ifdef DEBUG + post("%s: receive socket %d", objName, sockfd); +#endif + if (sockfd < 0) + { + sys_sockerror("tcpserver: socket"); + return (0); + } + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; +#ifdef IRIX + /* this seems to work only in IRIX but is unnecessary in + Linux. Not sure what NT needs in place of this. */ + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0) + post("setsockopt failed\n"); +#endif + /* assign server port number */ + server.sin_port = htons((u_short)portno); + /* name the socket */ + if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) + { + sys_sockerror("tcpserver: bind"); + sys_closesocket(sockfd); + return (0); + } + x = (t_tcpserver *)pd_new(tcpserver_class); + x->x_msgout = outlet_new(&x->x_obj, &s_anything); /* 1st outlet for received data */ + /* streaming protocol */ + if (listen(sockfd, 5) < 0) + { + sys_sockerror("tcpserver: listen"); + sys_closesocket(sockfd); + sockfd = -1; + } + else + { + sys_addpollfn(sockfd, (t_fdpollfn)tcpserver_connectpoll, x); + x->x_connectout = outlet_new(&x->x_obj, &s_float); /* 2nd outlet for number of connected clients */ + x->x_sockout = outlet_new(&x->x_obj, &s_float); /* 3rd outlet for socket number of current client */ + x->x_addrout = outlet_new(&x->x_obj, &s_list); /* 4th outlet for ip address of current client */ + inbinbuf = binbuf_new(); + } + x->x_connectsocket = sockfd; + x->x_nconnections = 0; + for(i = 0; i < MAX_CONNECT; i++) + { + x->x_fd[i] = -1; + x->x_sr[i] = NULL; + } + /* prepare to convert the bytes in the buffer to floats in a list */ + for (i = 0; i < MAX_UDP_RECEIVE; ++i) + { + x->x_msgoutbuf[i].a_type = A_FLOAT; + x->x_msgoutbuf[i].a_w.w_float = 0; + } + for (i = 0; i < 4; ++i) + { + x->x_addrbytes[i].a_type = A_FLOAT; + x->x_addrbytes[i].a_w.w_float = 0; + } + + return (x); +} + +static void tcpserver_free(t_tcpserver *x) +{ + int i; + + for(i = 0; i < MAX_CONNECT; i++) + { + if (x->x_fd[i] >= 0) + { + sys_rmpollfn(x->x_fd[i]); + sys_closesocket(x->x_fd[i]); + } + if (x->x_sr[i] != NULL) tcpserver_socketreceiver_free(x->x_sr[i]); + } + if (x->x_connectsocket >= 0) + { + sys_rmpollfn(x->x_connectsocket); + sys_closesocket(x->x_connectsocket); + } + + binbuf_free(inbinbuf); +} + +#ifdef MSW +__declspec(dllexport) +#endif +void tcpserver_setup(void) +{ + tcpserver_class = class_new(gensym(objName),(t_newmethod)tcpserver_new, (t_method)tcpserver_free, + sizeof(t_tcpserver), 0, A_DEFFLOAT, 0); + class_addmethod(tcpserver_class, (t_method)tcpserver_print, gensym("print"), 0); + class_addmethod(tcpserver_class, (t_method)tcpserver_send, gensym("send"), A_GIMME, 0); + class_addmethod(tcpserver_class, (t_method)tcpserver_client_send, gensym("client"), A_GIMME, 0); + class_addmethod(tcpserver_class, (t_method)tcpserver_broadcast, gensym("broadcast"), A_GIMME, 0); +} + +/* end of x_net_tcpserver.c */ diff --git a/net/udpreceive.c b/net/udpreceive.c new file mode 100755 index 0000000..cef02b2 --- /dev/null +++ b/net/udpreceive.c @@ -0,0 +1,162 @@ +/* x_net_udpreceive.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. */ + +#include "m_pd.h" +#include "s_stuff.h" + +#ifdef MSW +#include +#include +#else +#include +#include +#include +#include +#include +#include +#endif + + +/* ----------------------------- udpreceive ------------------------- */ + +static t_class *udpreceive_class; + +#define MAX_UDP_RECEIVE 65536L // longer than data in maximum UDP packet + +typedef struct _udpreceive +{ + t_object x_obj; + t_outlet *x_msgout; + t_outlet *x_addrout; + int x_connectsocket; + t_atom x_addrbytes[4]; + t_atom x_msgoutbuf[MAX_UDP_RECEIVE]; + char x_msginbuf[MAX_UDP_RECEIVE]; +} t_udpreceive; + +#ifdef MSW +__declspec(dllexport) +#endif +void udpreceive_setup(void); +static void udpreceive_free(t_udpreceive *x); +static void *udpreceive_new(t_floatarg fportno); +static void udpreceive_read(t_udpreceive *x, int sockfd); + +static void udpreceive_read(t_udpreceive *x, int sockfd) +{ + int i, read = 0; + struct sockaddr_in from; + socklen_t fromlen = sizeof(from); + long addr; + + read = recvfrom(sockfd, x->x_msginbuf, MAX_UDP_RECEIVE, 0, (struct sockaddr *)&from, &fromlen); +#ifdef DEBUG + post("udpreceive_read: read %lu x->x_connectsocket = %d", + read, x->x_connectsocket); +#endif + /* get the sender's ip */ + addr = ntohl(from.sin_addr.s_addr); + 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); + outlet_list(x->x_addrout, &s_list, 4L, x->x_addrbytes); + + if (read < 0) + { + sys_sockerror("udpreceive_read"); + sys_closesocket(x->x_connectsocket); + return; + } + if (read > 0) + { + for (i = 0; i < read; ++i) + { + /* convert the bytes in the buffer to floats in a list */ + x->x_msgoutbuf[i].a_w.w_float = (float)x->x_msginbuf[i]; + } + /* send the list out the outlet */ + if (read > 1) outlet_list(x->x_msgout, &s_list, read, x->x_msgoutbuf); + else outlet_float(x->x_msgout, x->x_msgoutbuf[0].a_w.w_float); + } +} + +static void *udpreceive_new(t_floatarg fportno) +{ + t_udpreceive *x; + struct sockaddr_in server; + int sockfd, portno = fportno; + int intarg, i; + + /* create a socket */ + sockfd = socket(AF_INET, SOCK_DGRAM, 0); +#ifdef DEBUG + post("udpreceive_new: socket %d port %d", sockfd, portno); +#endif + if (sockfd < 0) + { + sys_sockerror("udpreceive: socket"); + return (0); + } + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + + /* ask OS to allow another Pd to repoen this port after we close it. */ + intarg = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, + (char *)&intarg, sizeof(intarg)) < 0) + post("udpreceive: setsockopt (SO_REUSEADDR) failed"); + + /* assign server port number */ + server.sin_port = htons((u_short)portno); + + /* name the socket */ + if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) + { + sys_sockerror("udpreceive: bind"); + sys_closesocket(sockfd); + return (0); + } + x = (t_udpreceive *)pd_new(udpreceive_class); + x->x_msgout = outlet_new(&x->x_obj, &s_anything); + x->x_addrout = outlet_new(&x->x_obj, &s_list); + x->x_connectsocket = sockfd; + + /* convert the bytes in the buffer to floats in a list */ + for (i = 0; i < MAX_UDP_RECEIVE; ++i) + { + x->x_msgoutbuf[i].a_type = A_FLOAT; + x->x_msgoutbuf[i].a_w.w_float = 0; + } + for (i = 0; i < 4; ++i) + { + x->x_addrbytes[i].a_type = A_FLOAT; + x->x_addrbytes[i].a_w.w_float = 0; + } + sys_addpollfn(x->x_connectsocket, (t_fdpollfn)udpreceive_read, x); + return (x); +} + +static void udpreceive_free(t_udpreceive *x) +{ + if (x->x_connectsocket >= 0) + { + sys_rmpollfn(x->x_connectsocket); + sys_closesocket(x->x_connectsocket); + } +} + +#ifdef MSW +__declspec(dllexport) +#endif +void udpreceive_setup(void) +{ + udpreceive_class = class_new(gensym("udpreceive"), + (t_newmethod)udpreceive_new, (t_method)udpreceive_free, + sizeof(t_udpreceive), CLASS_NOINLET, A_DEFFLOAT, 0); +} + +/* end x_net_udpreceive.c */ + diff --git a/net/udpsend.c b/net/udpsend.c new file mode 100755 index 0000000..7b468f9 --- /dev/null +++ b/net/udpsend.c @@ -0,0 +1,215 @@ +/* x_net_udpsend.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 +#include +#ifdef MSW +#include +#else +#include +#include +#include +#include +#include +#endif + +static t_class *udpsend_class; + +typedef struct _udpsend +{ + t_object x_obj; + int x_fd; +} t_udpsend; + +#ifdef MSW +__declspec(dllexport) +#endif +void udpsend_setup(void); +static void udpsend_free(t_udpsend *x); +static void udpsend_send(t_udpsend *x, t_symbol *s, int argc, t_atom *argv); +static void udpsend_disconnect(t_udpsend *x); +static void udpsend_connect(t_udpsend *x, t_symbol *hostname, t_floatarg fportno); +static void *udpsend_new(void); + +static void *udpsend_new(void) +{ + t_udpsend *x = (t_udpsend *)pd_new(udpsend_class); + outlet_new(&x->x_obj, &s_float); + x->x_fd = -1; + return (x); +} + +static void udpsend_connect(t_udpsend *x, t_symbol *hostname, + t_floatarg fportno) +{ + struct sockaddr_in server; + struct hostent *hp; + int sockfd; + int portno = fportno; + + if (x->x_fd >= 0) + { + error("udpsend: already connected"); + return; + } + + /* create a socket */ + sockfd = socket(AF_INET, SOCK_DGRAM, 0); +#ifdef DEBUG + fprintf(stderr, "udpsend_connect: send socket %d\n", sockfd); +#endif + if (sockfd < 0) + { + sys_sockerror("udpsend: socket"); + return; + } + /* connect socket using hostname provided in command line */ + server.sin_family = AF_INET; + hp = gethostbyname(hostname->s_name); + if (hp == 0) + { + post("udpsend: bad host?\n"); + return; + } + memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); + + /* assign client port number */ + server.sin_port = htons((u_short)portno); + + post("udpsend: connecting to port %d", portno); + /* try to connect. */ + if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) + { + sys_sockerror("udpsend: connecting stream socket"); + sys_closesocket(sockfd); + return; + } + x->x_fd = sockfd; + outlet_float(x->x_obj.ob_outlet, 1); +} + +static void udpsend_disconnect(t_udpsend *x) +{ + if (x->x_fd >= 0) + { + sys_closesocket(x->x_fd); + x->x_fd = -1; + outlet_float(x->x_obj.ob_outlet, 0); + } +} + +static void udpsend_send(t_udpsend *x, t_symbol *s, int argc, t_atom *argv) +{ + static char byte_buf[65536];// arbitrary maximum similar to max IP packet size + int i, d; + char c; + float f, e; + char *bp; + int length, sent; + int result; + static double lastwarntime; + static double pleasewarn; + double timebefore; + double timeafter; + int late; + +#ifdef DEBUG + post("s: %s", s->s_name); + post("argc: %d", argc); +#endif + for (i = 0; i < argc; ++i) + { + if (argv[i].a_type == A_FLOAT) + { + f = argv[i].a_w.w_float; + d = (int)f; + e = f - d; + if (e != 0) + { + error("udpsend_send: item %d (%f) is not an integer", i, f); + return; + } + c = (unsigned char)d; + if (c != d) + { + error("udpsend_send: item %d (%f) is not between 0 and 255", i, f); + return; + } +#ifdef DEBUG + post("udpsend_send: argv[%d]: %d", i, c); +#endif + byte_buf[i] = c; + } + else + { + error("udpsend_send: item %d is not a float", i); + return; + } + } + + length = i; + 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("udpsend blocked %d msec", + (int)(1000 * ((timeafter - timebefore) + pleasewarn))); + pleasewarn = 0; + lastwarntime = timeafter; + } + else if (late) pleasewarn += timeafter - timebefore; + } + if (result <= 0) + { + sys_sockerror("udpsend"); + udpsend_disconnect(x); + break; + } + else + { + sent += result; + bp += result; + } + } + } + else error("udpsend: not connected"); +} + +static void udpsend_free(t_udpsend *x) +{ + udpsend_disconnect(x); +} + +#ifdef MSW +__declspec(dllexport) +#endif +void udpsend_setup(void) +{ + udpsend_class = class_new(gensym("udpsend"), (t_newmethod)udpsend_new, + (t_method)udpsend_free, + sizeof(t_udpsend), 0, 0); + class_addmethod(udpsend_class, (t_method)udpsend_connect, + gensym("connect"), A_SYMBOL, A_FLOAT, 0); + class_addmethod(udpsend_class, (t_method)udpsend_disconnect, + gensym("disconnect"), 0); + class_addmethod(udpsend_class, (t_method)udpsend_send, gensym("send"), + A_GIMME, 0); +} + +/* end x_net_udpsend.c*/ + diff --git a/net/x_net_tcp_client.c b/net/x_net_tcp_client.c deleted file mode 100755 index 366d421..0000000 --- a/net/x_net_tcp_client.c +++ /dev/null @@ -1,443 +0,0 @@ -/* x_net_tcp_client.c Martin Peach 20060508, working version 20060512 */ -/* linux version 20060515 */ -/* x_net_tcp_client.c is based on netclient: */ -/* -------------------------- netclient ------------------------------------- */ -/* */ -/* Extended 'netsend', connects to 'netserver'. */ -/* Uses child thread to connect to server. Thus needs pd0.35-test17 or later. */ -/* Written by Olaf Matthes (olaf.matthes@gmx.de) */ -/* Get source at http://www.akustische-kunst.org/puredata/maxlib/ */ -/* */ -/* 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. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* ---------------------------------------------------------------------------- */ -//define DEBUG - -#include "m_pd.h" -#include "s_stuff.h" - -#include -#include -#include -#include -#if defined(UNIX) || defined(unix) -#include -#include -#include -#include -#include -#include -#define SOCKET_ERROR -1 -#else -#include -#endif - -#define DEFPOLLTIME 20 /* check for input every 20 ms */ - -static t_class *tcpclient_class; -static char objName[] = "tcpclient"; -#define MAX_UDP_RECEIVE 65536L // longer than data in maximum UDP packet - -typedef struct _tcpclient -{ - t_object x_obj; - t_clock *x_clock; - t_clock *x_poll; - t_outlet *x_msgout; - t_outlet *x_addrout; - t_outlet *x_outconnect; - int x_dump; // 1 = hexdump received bytes - int x_fd; // the socket - char *x_hostname; // address we want to connect to as text - int x_connectstate; // 0 = not connected, 1 = connected - int x_port; // port we're connected to - long x_addr; // address we're connected to as 32bit int - t_atom x_addrbytes[4]; // address we're connected to as 4 bytes - t_atom x_msgoutbuf[MAX_UDP_RECEIVE]; // received data as float atoms - unsigned char x_msginbuf[MAX_UDP_RECEIVE]; // received data as bytes - /* multithread stuff */ - pthread_t x_threadid; /* id of child thread */ - pthread_attr_t x_threadattr; /* attributes of child thread */ -} t_tcpclient; - -static void tcpclient_dump(t_tcpclient *x, t_float dump); -static void tcp_client_hexdump(unsigned char *buf, long len); -static void tcpclient_tick(t_tcpclient *x); -static void *tcpclient_child_connect(void *w); -static void tcpclient_connect(t_tcpclient *x, t_symbol *hostname, t_floatarg fportno); -static void tcpclient_disconnect(t_tcpclient *x); -static void tcpclient_send(t_tcpclient *x, t_symbol *s, int argc, t_atom *argv); -static void tcpclient_rcv(t_tcpclient *x); -static void tcpclient_poll(t_tcpclient *x); -static void *tcpclient_new(t_floatarg udpflag); -static void tcpclient_free(t_tcpclient *x); -#ifdef MSW -__declspec(dllexport) -#endif -void tcpclient_setup(void); - -static void tcpclient_dump(t_tcpclient *x, t_float dump) -{ - x->x_dump = (dump == 0)?0:1; -} - -static void tcp_client_hexdump(unsigned char *buf, long len) -{ -#define BYTES_PER_LINE 16 - char hexStr[(3*BYTES_PER_LINE)+1]; - char ascStr[BYTES_PER_LINE+1]; - long i, j, k = 0L; -#ifdef DEBUG - post("tcp_client_hexdump %d", len); -#endif - while (k < len) - { - for (i = j = 0; i < BYTES_PER_LINE; ++i, ++k, j+=3) - { - if (k < len) - { -#ifdef MSW - sprintf_s(&hexStr[j], 4, "%02X ", buf[k]); - sprintf_s(&ascStr[i], 2, "%c", ((buf[k] >= 32) && (buf[k] <= 126))? buf[k]: '.'); -#else - snprintf(&hexStr[j], 4, "%02X ", buf[k]); - snprintf(&ascStr[i], 2, "%c", ((buf[k] >= 32) && (buf[k] <= 126))? buf[k]: '.'); -#endif - } - else - { // the last line -#ifdef MSW - sprintf_s(&hexStr[j], 4, " "); - sprintf_s(&ascStr[i], 2, " "); -#else - snprintf(&hexStr[j], 4, " "); - snprintf(&ascStr[i], 2, " "); -#endif - } - } - post ("%s%s", hexStr, ascStr); - } -} - -static void tcpclient_tick(t_tcpclient *x) -{ - outlet_float(x->x_outconnect, 1); -} - -static void *tcpclient_child_connect(void *w) -{ - t_tcpclient *x = (t_tcpclient*) w; - struct sockaddr_in server; - struct hostent *hp; - int sockfd; - - if (x->x_fd >= 0) - { - error("%s_connect: already connected", objName); - return (x); - } - - /* create a socket */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); -#ifdef DEBUG - post("%s: send socket %d\n", objName, sockfd); -#endif - if (sockfd < 0) - { - sys_sockerror("tcpclient: socket"); - return (x); - } - /* connect socket using hostname provided in command line */ - server.sin_family = AF_INET; - hp = gethostbyname(x->x_hostname); - if (hp == 0) - { - sys_sockerror("tcpclient: bad host?\n"); - return (x); - } - memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); - - /* assign client port number */ - server.sin_port = htons((u_short)x->x_port); - - post("%s: connecting socket %d to port %d", objName, sockfd, x->x_port); - /* try to connect */ - if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) - { - sys_sockerror("tcpclient: connecting stream socket"); - sys_closesocket(sockfd); - return (x); - } - x->x_fd = sockfd; - x->x_addr = ntohl(*(long *)hp->h_addr); - /* outlet_float is not threadsafe ! */ - // outlet_float(x->x_obj.ob_outlet, 1); - x->x_connectstate = 1; - /* use callback instead to set outlet */ - clock_delay(x->x_clock, 0); - return (x); -} - -static void tcpclient_connect(t_tcpclient *x, t_symbol *hostname, t_floatarg fportno) -{ - /* 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) - post("%s: could not create new thread", objName); -} - -static void tcpclient_disconnect(t_tcpclient *x) -{ - if (x->x_fd >= 0) - { - sys_closesocket(x->x_fd); - x->x_fd = -1; - x->x_connectstate = 0; - outlet_float(x->x_outconnect, 0); - post("%s: disconnected", objName); - } - else post("%s: not connected", objName); -} - -static void tcpclient_send(t_tcpclient *x, t_symbol *s, int argc, t_atom *argv) -{ - static char byte_buf[65536];// arbitrary maximum similar to max IP packet size - int i, 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; - -#ifdef DEBUG - post("s: %s", s->s_name); - post("argc: %d", argc); -#endif - - for (i = 0; i < argc; ++i) - { - if (argv[i].a_type == A_FLOAT) - { - f = argv[i].a_w.w_float; - d = (int)f; - e = f - d; -#ifdef DEBUG - post("%s: argv[%d]: float:%f int:%d delta:%f", objName, i, f, d, e); -#endif - if (e != 0) - { - error("%s_send: item %d (%f) is not an integer", objName, i, f); - return; - } - if ((d < 0) || (d > 255)) - { - error("%s: item %d (%f) is not between 0 and 255", objName, i, f); - return; - } - c = (unsigned char)d; -#ifdef DEBUG - post("%s_send: argv[%d]: %d", objName, i, c); -#endif - byte_buf[i] = c; - } - else - { - error("%s_send: item %d is not a float", objName, i); - return; - } - } - - length = i; - 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("%s_send blocked %d msec", objName, - (int)(1000 * ((timeafter - timebefore) + pleasewarn))); - pleasewarn = 0; - lastwarntime = timeafter; - } - else if (late) pleasewarn += timeafter - timebefore; - } - if (result <= 0) - { - sys_sockerror("tcpclient_send"); - tcpclient_disconnect(x); - break; - } - else - { - sent += result; - bp += result; - } - } - } - else error("%s: not connected", objName); -} - -static void tcpclient_rcv(t_tcpclient *x) -{ - int sockfd = x->x_fd; - int ret; - int i; - fd_set readset; - fd_set exceptset; - struct timeval ztout; - - if(x->x_connectstate) - { - /* check if we can read/write from/to the socket */ - FD_ZERO(&readset); - FD_ZERO(&exceptset); - FD_SET(x->x_fd, &readset ); - FD_SET(x->x_fd, &exceptset ); - - ztout.tv_sec = 0; - ztout.tv_usec = 0; - - ret = select(sockfd+1, &readset, NULL, &exceptset, &ztout); - if(ret < 0) - { - error("%s: unable to read from socket", objName); - sys_closesocket(sockfd); - return; - } - if(FD_ISSET(sockfd, &readset) || FD_ISSET(sockfd, &exceptset)) - { - /* read from server */ - ret = recv(sockfd, x->x_msginbuf, MAX_UDP_RECEIVE, 0); - if(ret > 0) - { -#ifdef DEBUG - x->x_msginbuf[ret] = 0; - post("%s: received %d bytes ", objName, ret); -#endif - if (x->x_dump)tcp_client_hexdump(x->x_msginbuf, ret); - for (i = 0; i < ret; ++i) - { - /* convert the bytes in the buffer to floats in a list */ - x->x_msgoutbuf[i].a_w.w_float = (float)x->x_msginbuf[i]; - } - /* find sender's ip address and output it */ - x->x_addrbytes[0].a_w.w_float = (x->x_addr & 0xFF000000)>>24; - x->x_addrbytes[1].a_w.w_float = (x->x_addr & 0x0FF0000)>>16; - x->x_addrbytes[2].a_w.w_float = (x->x_addr & 0x0FF00)>>8; - x->x_addrbytes[3].a_w.w_float = (x->x_addr & 0x0FF); - outlet_list(x->x_addrout, &s_list, 4L, x->x_addrbytes); - /* send the list out the outlet */ - if (ret > 1) outlet_list(x->x_msgout, &s_list, ret, x->x_msgoutbuf); - else outlet_float(x->x_msgout, x->x_msgoutbuf[0].a_w.w_float); - } - else - { - if (ret < 0) - { - sys_sockerror("tcpclient: recv"); - tcpclient_disconnect(x); - } - else - { - post("%s: connection closed for socket %d\n", objName, sockfd); - tcpclient_disconnect(x); - } - } - } - } - else post("%s: not connected", objName); -} - -static void tcpclient_poll(t_tcpclient *x) -{ - if(x->x_connectstate) - tcpclient_rcv(x); /* try to read in case we're connected */ - clock_delay(x->x_poll, DEFPOLLTIME); /* see you later */ -} - -static void *tcpclient_new(t_floatarg udpflag) -{ - int i; - - t_tcpclient *x = (t_tcpclient *)pd_new(tcpclient_class); - x->x_msgout = outlet_new(&x->x_obj, &s_anything); /* received data */ - x->x_addrout = outlet_new(&x->x_obj, &s_list); - x->x_outconnect = outlet_new(&x->x_obj, &s_float); /* connection state */ - x->x_clock = clock_new(x, (t_method)tcpclient_tick); - x->x_poll = clock_new(x, (t_method)tcpclient_poll); - x->x_fd = -1; - /* convert the bytes in the buffer to floats in a list */ - for (i = 0; i < MAX_UDP_RECEIVE; ++i) - { - x->x_msgoutbuf[i].a_type = A_FLOAT; - x->x_msgoutbuf[i].a_w.w_float = 0; - } - for (i = 0; i < 4; ++i) - { - x->x_addrbytes[i].a_type = A_FLOAT; - x->x_addrbytes[i].a_w.w_float = 0; - } - x->x_addr = 0L; - /* prepare child thread */ - if(pthread_attr_init(&x->x_threadattr) < 0) - post("%s: warning: could not prepare child thread", objName); - if(pthread_attr_setdetachstate(&x->x_threadattr, PTHREAD_CREATE_DETACHED) < 0) - post("%s: warning: could not prepare child thread", objName); - clock_delay(x->x_poll, 0); /* start polling the input */ - return (x); -} - -static void tcpclient_free(t_tcpclient *x) -{ - tcpclient_disconnect(x); - clock_free(x->x_poll); - clock_free(x->x_clock); -} - -#ifdef MSW -__declspec(dllexport) -#endif -void tcpclient_setup(void) -{ - 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") - , A_SYMBOL, A_FLOAT, 0); - class_addmethod(tcpclient_class, (t_method)tcpclient_disconnect, gensym("disconnect"), 0); - class_addmethod(tcpclient_class, (t_method)tcpclient_send, gensym("send"), A_GIMME, 0); - class_addmethod(tcpclient_class, (t_method)tcpclient_rcv, gensym("receive"), 0); - class_addmethod(tcpclient_class, (t_method)tcpclient_rcv, gensym("rcv"), 0); - class_addmethod(tcpclient_class, (t_method)tcpclient_dump, gensym("dump"), A_FLOAT, 0); -} - -/* end of x_net_tcp.c */ diff --git a/net/x_net_tcp_server.c b/net/x_net_tcp_server.c deleted file mode 100755 index 4438215..0000000 --- a/net/x_net_tcp_server.c +++ /dev/null @@ -1,600 +0,0 @@ -/* x_net_tcpserver.c Martin Peach 20060511 working version 20060512 */ -/* x_net_tcpserver.c is based on netserver: */ -/* -------------------------- netserver ------------------------------------- */ -/* */ -/* A server for bidirectional communication from within Pd. */ -/* Allows to send back data to specific clients connected to the server. */ -/* Written by Olaf Matthes */ -/* Get source at http://www.akustische-kunst.org/puredata/maxlib */ -/* */ -/* 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. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* ---------------------------------------------------------------------------- */ -//define DEBUG - -#include "m_pd.h" -#include "m_imp.h" -#include "s_stuff.h" - -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -#if defined(UNIX) || defined(unix) -#include -#include -#include -#include -#include -#include -#include -#include -#define SOCKET_ERROR -1 -#else -//#include -//#include -#include -#endif - -#define MAX_CONNECT 32 /* maximum number of connections */ -#define INBUFSIZE 65536L /* was 4096: size of receiving data buffer */ -#define MAX_UDP_RECEIVE 65536L /* longer than data in maximum UDP packet */ - -/* ----------------------------- tcpserver ------------------------- */ - -static t_class *tcpserver_class; -static t_binbuf *inbinbuf; -static char objName[] = "tcpserver"; - -typedef void (*t_tcpserver_socketnotifier)(void *x); -typedef void (*t_tcpserver_socketreceivefn)(void *x, t_binbuf *b); - -typedef struct _tcpserver -{ - t_object x_obj; - t_outlet *x_msgout; - t_outlet *x_connectout; - t_outlet *x_sockout; - t_outlet *x_addrout; - t_symbol *x_host[MAX_CONNECT]; - t_int x_fd[MAX_CONNECT]; - u_long x_addr[MAX_CONNECT]; - t_atom x_addrbytes[4]; - t_int x_sock_fd; - t_int x_connectsocket; - t_int x_nconnections; - t_atom x_msgoutbuf[MAX_UDP_RECEIVE]; - char x_msginbuf[MAX_UDP_RECEIVE]; -} t_tcpserver; - -typedef struct _tcpserver_socketreceiver -{ - unsigned char *sr_inbuf; - int sr_inhead; - int sr_intail; - void *sr_owner; - t_tcpserver_socketnotifier sr_notifier; - t_tcpserver_socketreceivefn sr_socketreceivefn; -} t_tcpserver_socketreceiver; - -static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new(void *owner, t_tcpserver_socketnotifier notifier, - t_tcpserver_socketreceivefn socketreceivefn); -static int tcpserver_socketreceiver_doread(t_tcpserver_socketreceiver *x); -static void tcpserver_socketreceiver_read(t_tcpserver_socketreceiver *x, int fd); -static void tcpserver_socketreceiver_free(t_tcpserver_socketreceiver *x); -static void tcpserver_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv); -static void tcp_server_send_bytes(int sockfd, t_tcpserver *x, int argc, t_atom *argv); -static void tcpserver_client_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv); -static void tcpserver_broadcast(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv); -static void tcpserver_notify(t_tcpserver *x); -static void tcpserver_connectpoll(t_tcpserver *x); -static void tcpserver_print(t_tcpserver *x); -static void *tcpserver_new(t_floatarg fportno); -static void tcpserver_free(t_tcpserver *x); -#ifdef MSW -__declspec(dllexport) -#endif -void tcpserver_setup(void); - -static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new(void *owner, t_tcpserver_socketnotifier notifier, - t_tcpserver_socketreceivefn socketreceivefn) -{ - t_tcpserver_socketreceiver *x = (t_tcpserver_socketreceiver *)getbytes(sizeof(*x)); - if (!x) - { - error("%s_socketreceiver: unable to allocate %d bytes", objName, sizeof(*x)); - } - else - { - x->sr_inhead = x->sr_intail = 0; - x->sr_owner = owner; - x->sr_notifier = notifier; - x->sr_socketreceivefn = socketreceivefn; - if (!(x->sr_inbuf = malloc(INBUFSIZE))) - { - freebytes(x, sizeof(*x)); - x = NULL; - error("%s_socketreceiver: unable to allocate %d bytes", objName, INBUFSIZE); - } - } - return (x); -} - -/* this is in a separately called subroutine so that the buffer isn't - sitting on the stack while the messages are getting passed. */ -static int tcpserver_socketreceiver_doread(t_tcpserver_socketreceiver *x) -{ - char messbuf[INBUFSIZE]; - char *bp = messbuf; - int indx, i; - int inhead = x->sr_inhead; - int intail = x->sr_intail; - unsigned char c; - t_tcpserver *y = x->sr_owner; - unsigned char *inbuf = x->sr_inbuf; - - if (intail == inhead) return (0); -#ifdef DEBUG - post ("%s_socketreceiver_doread: intail=%d inhead=%d", objName, intail, inhead); -#endif - - for (indx = intail, i = 0; indx != inhead; indx = (indx+1)&(INBUFSIZE-1), ++i) - { - c = *bp++ = inbuf[indx]; - y->x_msgoutbuf[i].a_w.w_float = (float)c; - } - if (i > 1) outlet_list(y->x_msgout, &s_list, i, y->x_msgoutbuf); - else outlet_float(y->x_msgout, y->x_msgoutbuf[0].a_w.w_float); - - // intail = (indx+1)&(INBUFSIZE-1); - x->sr_inhead = inhead; - x->sr_intail = indx;//intail; - return (1); -} - -static void tcpserver_socketreceiver_read(t_tcpserver_socketreceiver *x, int fd) -{ - char *semi; - int readto = (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1); - int ret, i; - t_tcpserver *y = x->sr_owner; - - y->x_sock_fd = fd; - /* the input buffer might be full. If so, drop the whole thing */ - if (readto == x->sr_inhead) - { - post("%s: dropped message", objName); - x->sr_inhead = x->sr_intail = 0; - readto = INBUFSIZE; - } - else - { - ret = recv(fd, x->sr_inbuf + x->sr_inhead, - readto - x->sr_inhead, 0); - if (ret < 0) - { - sys_sockerror("tcpserver: recv"); - if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner); - sys_rmpollfn(fd); - sys_closesocket(fd); - } - else if (ret == 0) - { - post("%s: connection closed on socket %d", objName, fd); - if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner); - sys_rmpollfn(fd); - sys_closesocket(fd); - } - else - { -#ifdef DEBUG - post ("%s_socketreceiver_read: ret = %d", objName, ret); -#endif - x->sr_inhead += ret; - if (x->sr_inhead >= INBUFSIZE) x->sr_inhead = 0; - /* output client's IP and socket no. */ - for(i = 0; i < y->x_nconnections; i++) /* search for corresponding IP */ - { - if(y->x_fd[i] == y->x_sock_fd) - { -// outlet_symbol(x->x_connectionip, x->x_host[i]); - /* find sender's ip address and output it */ - y->x_addrbytes[0].a_w.w_float = (y->x_addr[i] & 0xFF000000)>>24; - y->x_addrbytes[1].a_w.w_float = (y->x_addr[i] & 0x0FF0000)>>16; - y->x_addrbytes[2].a_w.w_float = (y->x_addr[i] & 0x0FF00)>>8; - y->x_addrbytes[3].a_w.w_float = (y->x_addr[i] & 0x0FF); - outlet_list(y->x_addrout, &s_list, 4L, y->x_addrbytes); - break; - } - } - outlet_float(y->x_sockout, y->x_sock_fd); /* the socket number */ - tcpserver_socketreceiver_doread(x); - } - } -} - -static void tcpserver_socketreceiver_free(t_tcpserver_socketreceiver *x) -{ - free(x->sr_inbuf); - freebytes(x, sizeof(*x)); -} - -/* ---------------- main tcpserver (send) stuff --------------------- */ - -static void tcp_server_send_bytes(int client, t_tcpserver *x, int argc, t_atom *argv) -{ - static char byte_buf[MAX_UDP_RECEIVE];// arbitrary maximum similar to max IP packet size - int i, 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; - int sockfd = x->x_fd[client]; - - /* process & send data */ - if(sockfd >= 0) - { - for (i = 0; i < argc; ++i) - { - if (argv[i].a_type == A_FLOAT) - { - f = argv[i].a_w.w_float; - d = (int)f; - e = f - d; -#ifdef DEBUG - post("%s: argv[%d]: float:%f int:%d delta:%f", objName, i, f, d, e); -#endif - if (e != 0) - { - error("%s: item %d (%f) is not an integer", objName, i, f); - return; - } - if ((d < 0) || (d > 255)) - { - error("%s: item %d (%f) is not between 0 and 255", objName, i, f); - return; - } - c = (unsigned char)d; /* make sure it doesn't become negative; this only matters for post() */ -#ifdef DEBUG - post("%s: argv[%d]: %d", objName, i, c); -#endif - byte_buf[i] = c; - } - else - { - error("%s: item %d is not a float", objName, i); - return; - } - } - length = i; - if (length > 0) - { - for (bp = byte_buf, sent = 0; sent < length;) - { - timebefore = sys_getrealtime(); - result = send(sockfd, byte_buf, length-sent, 0); - timeafter = sys_getrealtime(); - late = (timeafter - timebefore > 0.005); - if (late || pleasewarn) - { - if (timeafter > lastwarntime + 2) - { - post("%s: send blocked %d msec", objName, - (int)(1000 * ((timeafter - timebefore) + pleasewarn))); - pleasewarn = 0; - lastwarntime = timeafter; - } - else if (late) pleasewarn += timeafter - timebefore; - } - if (result <= 0) - { - sys_sockerror("tcpserver: send"); - post("%s: could not send data to client %d", objName, client); - break; - } - else - { - sent += result; - bp += result; - } - } - } - } - else post("%s: not a valid socket number (%d)", objName, sockfd); -} - -/* send message to client using socket number */ -static void tcpserver_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) -{ - int i, sockfd; - int client = -1; - - if(x->x_nconnections < 0) - { - post("%s: no clients connected", objName); - return; - } - if(argc < 2) - { - post("%s: nothing to send", objName); - return; - } - /* get socket number of connection (first element in list) */ - if(argv[0].a_type == A_FLOAT) - { - sockfd = atom_getfloatarg(0, argc, argv); - for(i = 0; i < x->x_nconnections; i++) /* check if connection exists */ - { - if(x->x_fd[i] == sockfd) - { - client = i; /* the client we're sending to */ - break; - } - } - if(client == -1) - { - post("%s: no connection on socket %d", objName, sockfd); - return; - } - } - else - { - post("%s: no socket specified", objName); - return; - } - tcp_server_send_bytes(client, x, argc-1, &argv[1]); -} - -/* send message to client using client number - note that the client numbers might change in case a client disconnects! */ -/* clients start at 1 but our index starts at 0 */ -static void tcpserver_client_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) -{ - int sockfd, client; - - if(x->x_nconnections < 0) - { - post("%s: no clients connected", objName); - return; - } - if(argc < 2) - { - post("%s: nothing to send", objName); - return; - } - /* get number of client (first element in list) */ - if(argv[0].a_type == A_FLOAT) - client = atom_getfloatarg(0, argc, argv); - else - { - post("%s: no client specified", objName); - return; - } - if (!((client > 0) && (client < MAX_CONNECT))) - { - post("%s: client %d out of range [1..%d]", objName, client, MAX_CONNECT); - return; - } - --client;/* zero based index*/ - tcp_server_send_bytes(client, x, argc-1, &argv[1]); -} - -/* broadcasts a message to all connected clients */ -static void tcpserver_broadcast(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) -{ - int client; - - /* enumerate through the clients and send each the message */ - for(client = 0; client < x->x_nconnections; client++) /* check if connection exists */ - { - if(x->x_fd[client] >= 0) - { /* socket exists for this client */ - tcp_server_send_bytes(client, x, argc, argv); - break; - } - } -} - -/* ---------------- main tcpserver (receive) stuff --------------------- */ - -static void tcpserver_notify(t_tcpserver *x) -{ - int i, k; - - /* remove connection from list */ - for(i = 0; i < x->x_nconnections; i++) - { - if(x->x_fd[i] == x->x_sock_fd) - { - x->x_nconnections--; - post("%s: \"%s\" removed from list of clients", objName, x->x_host[i]->s_name); - x->x_host[i] = NULL; /* delete entry */ - x->x_fd[i] = -1; - /* rearrange list now: move entries to close the gap */ - for(k = i; k < x->x_nconnections; k++) - { - x->x_host[k] = x->x_host[k + 1]; - x->x_fd[k] = x->x_fd[k + 1]; - } - } - } - outlet_float(x->x_connectout, x->x_nconnections); -} - -static void tcpserver_connectpoll(t_tcpserver *x) -{ - struct sockaddr_in incomer_address; - int sockaddrl = (int) sizeof( struct sockaddr ); - int fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl); - int i; - - if (fd < 0) post("%s: accept failed", objName); - else - { - t_tcpserver_socketreceiver *y = tcpserver_socketreceiver_new((void *)x, - (t_tcpserver_socketnotifier)tcpserver_notify, NULL);/* MP tcpserver_doit isn't used I think...*/ - if (!y) - { -#ifdef MSW - closesocket(fd); -#else - close(fd); -#endif - return; - } - sys_addpollfn(fd, (t_fdpollfn)tcpserver_socketreceiver_read, y); - x->x_nconnections++; - i = x->x_nconnections - 1; - x->x_host[i] = gensym(inet_ntoa(incomer_address.sin_addr)); - x->x_fd[i] = fd; - post("%s: accepted connection from %s on socket %d", - objName, x->x_host[i]->s_name, x->x_fd[i]); - outlet_float(x->x_connectout, x->x_nconnections); - outlet_float(x->x_sockout, x->x_fd[i]); /* the socket number */ - x->x_addr[i] = ntohl(incomer_address.sin_addr.s_addr); - x->x_addrbytes[0].a_w.w_float = (x->x_addr[i] & 0xFF000000)>>24; - x->x_addrbytes[1].a_w.w_float = (x->x_addr[i] & 0x0FF0000)>>16; - x->x_addrbytes[2].a_w.w_float = (x->x_addr[i] & 0x0FF00)>>8; - x->x_addrbytes[3].a_w.w_float = (x->x_addr[i] & 0x0FF); - outlet_list(x->x_addrout, &s_list, 4L, x->x_addrbytes); - } -} - -static void tcpserver_print(t_tcpserver *x) -{ - int i; - - if(x->x_nconnections > 0) - { - post("%s: %d open connections:", objName, x->x_nconnections); - for(i = 0; i < x->x_nconnections; i++) - { - post(" \"%s\" on socket %d", - x->x_host[i]->s_name, x->x_fd[i]); - } - } - else post("%s: no open connections", objName); -} - -static void *tcpserver_new(t_floatarg fportno) -{ - t_tcpserver *x; - int i; - struct sockaddr_in server; - int sockfd, portno = fportno; - - /* create a socket */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); -#ifdef DEBUG - post("%s: receive socket %d", objName, sockfd); -#endif - if (sockfd < 0) - { - sys_sockerror("tcpserver: socket"); - return (0); - } - server.sin_family = AF_INET; - server.sin_addr.s_addr = INADDR_ANY; -#ifdef IRIX - /* this seems to work only in IRIX but is unnecessary in - Linux. Not sure what NT needs in place of this. */ - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0) - post("setsockopt failed\n"); -#endif - /* assign server port number */ - server.sin_port = htons((u_short)portno); - /* name the socket */ - if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) - { - sys_sockerror("tcpserver: bind"); - sys_closesocket(sockfd); - return (0); - } - x = (t_tcpserver *)pd_new(tcpserver_class); - x->x_msgout = outlet_new(&x->x_obj, &s_anything); /* 1st outlet for received data */ - /* streaming protocol */ - if (listen(sockfd, 5) < 0) - { - sys_sockerror("tcpserver: listen"); - sys_closesocket(sockfd); - sockfd = -1; - } - else - { - sys_addpollfn(sockfd, (t_fdpollfn)tcpserver_connectpoll, x); - x->x_connectout = outlet_new(&x->x_obj, &s_float); /* 2nd outlet for number of connected clients */ - x->x_sockout = outlet_new(&x->x_obj, &s_float); /* 3rd outlet for socket number of current client */ - x->x_addrout = outlet_new(&x->x_obj, &s_list); /* 4th outlet for ip address of current client */ - inbinbuf = binbuf_new(); - } - x->x_connectsocket = sockfd; - x->x_nconnections = 0; - for(i = 0; i < MAX_CONNECT; i++) x->x_fd[i] = -1; - /* prepare to convert the bytes in the buffer to floats in a list */ - for (i = 0; i < MAX_UDP_RECEIVE; ++i) - { - x->x_msgoutbuf[i].a_type = A_FLOAT; - x->x_msgoutbuf[i].a_w.w_float = 0; - } - for (i = 0; i < 4; ++i) - { - x->x_addrbytes[i].a_type = A_FLOAT; - x->x_addrbytes[i].a_w.w_float = 0; - } - - return (x); -} - -static void tcpserver_free(t_tcpserver *x) -{ - int i; - - for(i = 0; i < x->x_nconnections; i++) - { - sys_rmpollfn(x->x_fd[i]); - sys_closesocket(x->x_fd[i]); - } - if (x->x_connectsocket >= 0) - { - sys_rmpollfn(x->x_connectsocket); - sys_closesocket(x->x_connectsocket); - } - binbuf_free(inbinbuf); -} - -#ifdef MSW -__declspec(dllexport) -#endif -void tcpserver_setup(void) -{ - tcpserver_class = class_new(gensym(objName),(t_newmethod)tcpserver_new, (t_method)tcpserver_free, - sizeof(t_tcpserver), 0, A_DEFFLOAT, 0); - class_addmethod(tcpserver_class, (t_method)tcpserver_print, gensym("print"), 0); - class_addmethod(tcpserver_class, (t_method)tcpserver_send, gensym("send"), A_GIMME, 0); - class_addmethod(tcpserver_class, (t_method)tcpserver_client_send, gensym("client"), A_GIMME, 0); - class_addmethod(tcpserver_class, (t_method)tcpserver_broadcast, gensym("broadcast"), A_GIMME, 0); -} diff --git a/net/x_net_tcpclient.c b/net/x_net_tcpclient.c deleted file mode 100755 index 366d421..0000000 --- a/net/x_net_tcpclient.c +++ /dev/null @@ -1,443 +0,0 @@ -/* x_net_tcp_client.c Martin Peach 20060508, working version 20060512 */ -/* linux version 20060515 */ -/* x_net_tcp_client.c is based on netclient: */ -/* -------------------------- netclient ------------------------------------- */ -/* */ -/* Extended 'netsend', connects to 'netserver'. */ -/* Uses child thread to connect to server. Thus needs pd0.35-test17 or later. */ -/* Written by Olaf Matthes (olaf.matthes@gmx.de) */ -/* Get source at http://www.akustische-kunst.org/puredata/maxlib/ */ -/* */ -/* 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. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* ---------------------------------------------------------------------------- */ -//define DEBUG - -#include "m_pd.h" -#include "s_stuff.h" - -#include -#include -#include -#include -#if defined(UNIX) || defined(unix) -#include -#include -#include -#include -#include -#include -#define SOCKET_ERROR -1 -#else -#include -#endif - -#define DEFPOLLTIME 20 /* check for input every 20 ms */ - -static t_class *tcpclient_class; -static char objName[] = "tcpclient"; -#define MAX_UDP_RECEIVE 65536L // longer than data in maximum UDP packet - -typedef struct _tcpclient -{ - t_object x_obj; - t_clock *x_clock; - t_clock *x_poll; - t_outlet *x_msgout; - t_outlet *x_addrout; - t_outlet *x_outconnect; - int x_dump; // 1 = hexdump received bytes - int x_fd; // the socket - char *x_hostname; // address we want to connect to as text - int x_connectstate; // 0 = not connected, 1 = connected - int x_port; // port we're connected to - long x_addr; // address we're connected to as 32bit int - t_atom x_addrbytes[4]; // address we're connected to as 4 bytes - t_atom x_msgoutbuf[MAX_UDP_RECEIVE]; // received data as float atoms - unsigned char x_msginbuf[MAX_UDP_RECEIVE]; // received data as bytes - /* multithread stuff */ - pthread_t x_threadid; /* id of child thread */ - pthread_attr_t x_threadattr; /* attributes of child thread */ -} t_tcpclient; - -static void tcpclient_dump(t_tcpclient *x, t_float dump); -static void tcp_client_hexdump(unsigned char *buf, long len); -static void tcpclient_tick(t_tcpclient *x); -static void *tcpclient_child_connect(void *w); -static void tcpclient_connect(t_tcpclient *x, t_symbol *hostname, t_floatarg fportno); -static void tcpclient_disconnect(t_tcpclient *x); -static void tcpclient_send(t_tcpclient *x, t_symbol *s, int argc, t_atom *argv); -static void tcpclient_rcv(t_tcpclient *x); -static void tcpclient_poll(t_tcpclient *x); -static void *tcpclient_new(t_floatarg udpflag); -static void tcpclient_free(t_tcpclient *x); -#ifdef MSW -__declspec(dllexport) -#endif -void tcpclient_setup(void); - -static void tcpclient_dump(t_tcpclient *x, t_float dump) -{ - x->x_dump = (dump == 0)?0:1; -} - -static void tcp_client_hexdump(unsigned char *buf, long len) -{ -#define BYTES_PER_LINE 16 - char hexStr[(3*BYTES_PER_LINE)+1]; - char ascStr[BYTES_PER_LINE+1]; - long i, j, k = 0L; -#ifdef DEBUG - post("tcp_client_hexdump %d", len); -#endif - while (k < len) - { - for (i = j = 0; i < BYTES_PER_LINE; ++i, ++k, j+=3) - { - if (k < len) - { -#ifdef MSW - sprintf_s(&hexStr[j], 4, "%02X ", buf[k]); - sprintf_s(&ascStr[i], 2, "%c", ((buf[k] >= 32) && (buf[k] <= 126))? buf[k]: '.'); -#else - snprintf(&hexStr[j], 4, "%02X ", buf[k]); - snprintf(&ascStr[i], 2, "%c", ((buf[k] >= 32) && (buf[k] <= 126))? buf[k]: '.'); -#endif - } - else - { // the last line -#ifdef MSW - sprintf_s(&hexStr[j], 4, " "); - sprintf_s(&ascStr[i], 2, " "); -#else - snprintf(&hexStr[j], 4, " "); - snprintf(&ascStr[i], 2, " "); -#endif - } - } - post ("%s%s", hexStr, ascStr); - } -} - -static void tcpclient_tick(t_tcpclient *x) -{ - outlet_float(x->x_outconnect, 1); -} - -static void *tcpclient_child_connect(void *w) -{ - t_tcpclient *x = (t_tcpclient*) w; - struct sockaddr_in server; - struct hostent *hp; - int sockfd; - - if (x->x_fd >= 0) - { - error("%s_connect: already connected", objName); - return (x); - } - - /* create a socket */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); -#ifdef DEBUG - post("%s: send socket %d\n", objName, sockfd); -#endif - if (sockfd < 0) - { - sys_sockerror("tcpclient: socket"); - return (x); - } - /* connect socket using hostname provided in command line */ - server.sin_family = AF_INET; - hp = gethostbyname(x->x_hostname); - if (hp == 0) - { - sys_sockerror("tcpclient: bad host?\n"); - return (x); - } - memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); - - /* assign client port number */ - server.sin_port = htons((u_short)x->x_port); - - post("%s: connecting socket %d to port %d", objName, sockfd, x->x_port); - /* try to connect */ - if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) - { - sys_sockerror("tcpclient: connecting stream socket"); - sys_closesocket(sockfd); - return (x); - } - x->x_fd = sockfd; - x->x_addr = ntohl(*(long *)hp->h_addr); - /* outlet_float is not threadsafe ! */ - // outlet_float(x->x_obj.ob_outlet, 1); - x->x_connectstate = 1; - /* use callback instead to set outlet */ - clock_delay(x->x_clock, 0); - return (x); -} - -static void tcpclient_connect(t_tcpclient *x, t_symbol *hostname, t_floatarg fportno) -{ - /* 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) - post("%s: could not create new thread", objName); -} - -static void tcpclient_disconnect(t_tcpclient *x) -{ - if (x->x_fd >= 0) - { - sys_closesocket(x->x_fd); - x->x_fd = -1; - x->x_connectstate = 0; - outlet_float(x->x_outconnect, 0); - post("%s: disconnected", objName); - } - else post("%s: not connected", objName); -} - -static void tcpclient_send(t_tcpclient *x, t_symbol *s, int argc, t_atom *argv) -{ - static char byte_buf[65536];// arbitrary maximum similar to max IP packet size - int i, 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; - -#ifdef DEBUG - post("s: %s", s->s_name); - post("argc: %d", argc); -#endif - - for (i = 0; i < argc; ++i) - { - if (argv[i].a_type == A_FLOAT) - { - f = argv[i].a_w.w_float; - d = (int)f; - e = f - d; -#ifdef DEBUG - post("%s: argv[%d]: float:%f int:%d delta:%f", objName, i, f, d, e); -#endif - if (e != 0) - { - error("%s_send: item %d (%f) is not an integer", objName, i, f); - return; - } - if ((d < 0) || (d > 255)) - { - error("%s: item %d (%f) is not between 0 and 255", objName, i, f); - return; - } - c = (unsigned char)d; -#ifdef DEBUG - post("%s_send: argv[%d]: %d", objName, i, c); -#endif - byte_buf[i] = c; - } - else - { - error("%s_send: item %d is not a float", objName, i); - return; - } - } - - length = i; - 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("%s_send blocked %d msec", objName, - (int)(1000 * ((timeafter - timebefore) + pleasewarn))); - pleasewarn = 0; - lastwarntime = timeafter; - } - else if (late) pleasewarn += timeafter - timebefore; - } - if (result <= 0) - { - sys_sockerror("tcpclient_send"); - tcpclient_disconnect(x); - break; - } - else - { - sent += result; - bp += result; - } - } - } - else error("%s: not connected", objName); -} - -static void tcpclient_rcv(t_tcpclient *x) -{ - int sockfd = x->x_fd; - int ret; - int i; - fd_set readset; - fd_set exceptset; - struct timeval ztout; - - if(x->x_connectstate) - { - /* check if we can read/write from/to the socket */ - FD_ZERO(&readset); - FD_ZERO(&exceptset); - FD_SET(x->x_fd, &readset ); - FD_SET(x->x_fd, &exceptset ); - - ztout.tv_sec = 0; - ztout.tv_usec = 0; - - ret = select(sockfd+1, &readset, NULL, &exceptset, &ztout); - if(ret < 0) - { - error("%s: unable to read from socket", objName); - sys_closesocket(sockfd); - return; - } - if(FD_ISSET(sockfd, &readset) || FD_ISSET(sockfd, &exceptset)) - { - /* read from server */ - ret = recv(sockfd, x->x_msginbuf, MAX_UDP_RECEIVE, 0); - if(ret > 0) - { -#ifdef DEBUG - x->x_msginbuf[ret] = 0; - post("%s: received %d bytes ", objName, ret); -#endif - if (x->x_dump)tcp_client_hexdump(x->x_msginbuf, ret); - for (i = 0; i < ret; ++i) - { - /* convert the bytes in the buffer to floats in a list */ - x->x_msgoutbuf[i].a_w.w_float = (float)x->x_msginbuf[i]; - } - /* find sender's ip address and output it */ - x->x_addrbytes[0].a_w.w_float = (x->x_addr & 0xFF000000)>>24; - x->x_addrbytes[1].a_w.w_float = (x->x_addr & 0x0FF0000)>>16; - x->x_addrbytes[2].a_w.w_float = (x->x_addr & 0x0FF00)>>8; - x->x_addrbytes[3].a_w.w_float = (x->x_addr & 0x0FF); - outlet_list(x->x_addrout, &s_list, 4L, x->x_addrbytes); - /* send the list out the outlet */ - if (ret > 1) outlet_list(x->x_msgout, &s_list, ret, x->x_msgoutbuf); - else outlet_float(x->x_msgout, x->x_msgoutbuf[0].a_w.w_float); - } - else - { - if (ret < 0) - { - sys_sockerror("tcpclient: recv"); - tcpclient_disconnect(x); - } - else - { - post("%s: connection closed for socket %d\n", objName, sockfd); - tcpclient_disconnect(x); - } - } - } - } - else post("%s: not connected", objName); -} - -static void tcpclient_poll(t_tcpclient *x) -{ - if(x->x_connectstate) - tcpclient_rcv(x); /* try to read in case we're connected */ - clock_delay(x->x_poll, DEFPOLLTIME); /* see you later */ -} - -static void *tcpclient_new(t_floatarg udpflag) -{ - int i; - - t_tcpclient *x = (t_tcpclient *)pd_new(tcpclient_class); - x->x_msgout = outlet_new(&x->x_obj, &s_anything); /* received data */ - x->x_addrout = outlet_new(&x->x_obj, &s_list); - x->x_outconnect = outlet_new(&x->x_obj, &s_float); /* connection state */ - x->x_clock = clock_new(x, (t_method)tcpclient_tick); - x->x_poll = clock_new(x, (t_method)tcpclient_poll); - x->x_fd = -1; - /* convert the bytes in the buffer to floats in a list */ - for (i = 0; i < MAX_UDP_RECEIVE; ++i) - { - x->x_msgoutbuf[i].a_type = A_FLOAT; - x->x_msgoutbuf[i].a_w.w_float = 0; - } - for (i = 0; i < 4; ++i) - { - x->x_addrbytes[i].a_type = A_FLOAT; - x->x_addrbytes[i].a_w.w_float = 0; - } - x->x_addr = 0L; - /* prepare child thread */ - if(pthread_attr_init(&x->x_threadattr) < 0) - post("%s: warning: could not prepare child thread", objName); - if(pthread_attr_setdetachstate(&x->x_threadattr, PTHREAD_CREATE_DETACHED) < 0) - post("%s: warning: could not prepare child thread", objName); - clock_delay(x->x_poll, 0); /* start polling the input */ - return (x); -} - -static void tcpclient_free(t_tcpclient *x) -{ - tcpclient_disconnect(x); - clock_free(x->x_poll); - clock_free(x->x_clock); -} - -#ifdef MSW -__declspec(dllexport) -#endif -void tcpclient_setup(void) -{ - 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") - , A_SYMBOL, A_FLOAT, 0); - class_addmethod(tcpclient_class, (t_method)tcpclient_disconnect, gensym("disconnect"), 0); - class_addmethod(tcpclient_class, (t_method)tcpclient_send, gensym("send"), A_GIMME, 0); - class_addmethod(tcpclient_class, (t_method)tcpclient_rcv, gensym("receive"), 0); - class_addmethod(tcpclient_class, (t_method)tcpclient_rcv, gensym("rcv"), 0); - class_addmethod(tcpclient_class, (t_method)tcpclient_dump, gensym("dump"), A_FLOAT, 0); -} - -/* end of x_net_tcp.c */ diff --git a/net/x_net_tcpreceive.c b/net/x_net_tcpreceive.c deleted file mode 100755 index 4cce77d..0000000 --- a/net/x_net_tcpreceive.c +++ /dev/null @@ -1,314 +0,0 @@ -/* x_net_tcpreceive.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. */ - -#include "m_pd.h" -#include "s_stuff.h" - -#ifdef MSW -#include -#include /* for socklen_t */ -#else -#include -#include -#include -#include -#include -#include -#endif - - -/* ----------------------------- tcpreceive ------------------------- */ - -static t_class *tcpreceive_class; - -#define MAX_UDP_RECEIVE 65536L // longer than data in maximum UDP packet -#define MAX_CONNECTIONS 128 // this is going to cause trouble down the line...:( - -typedef struct _tcpconnection -{ - long addr; - int socket; -} t_tcpconnection; - -typedef struct _tcpreceive -{ - t_object x_obj; - t_outlet *x_msgout; - t_outlet *x_addrout; - t_outlet *x_connectout; - int x_connectsocket; - int x_nconnections; - t_tcpconnection x_connection[MAX_CONNECTIONS]; - t_atom x_addrbytes[4]; - t_atom x_msgoutbuf[MAX_UDP_RECEIVE]; - char x_msginbuf[MAX_UDP_RECEIVE]; -} t_tcpreceive; - -#ifdef MSW -__declspec(dllexport) -#endif -void tcpreceive_setup(void); -static void tcpreceive_free(t_tcpreceive *x); -static void *tcpreceive_new(t_floatarg fportno); -static void tcpreceive_read(t_tcpreceive *x, int sockfd); -static void tcpreceive_connectpoll(t_tcpreceive *x); -static int tcpreceive_addconnection(t_tcpreceive * x, int fd, long addr); -static int tcpreceive_removeconnection(t_tcpreceive * x, int fd); -static void tcpreceive_closeall(t_tcpreceive *x); -static long tcpreceive_getconnection(t_tcpreceive * x, int fd); - -static void tcpreceive_read(t_tcpreceive *x, int sockfd) -{ - int i, read = 0; - long addr; - -// read = recvfrom(sockfd, x->x_msginbuf, MAX_UDP_RECEIVE, 0, (struct sockaddr *)&from, &fromlen); - read = recv(sockfd, x->x_msginbuf, MAX_UDP_RECEIVE, 0); -#ifdef DEBUG - post("tcpreceive_read: read %lu x->x_connectsocket = %d", - read, x->x_connectsocket); -#endif - if (read < 0) - { - sys_sockerror("tcpreceive_read: recv"); - sys_rmpollfn(sockfd); - sys_closesocket(sockfd); - tcpreceive_removeconnection(x, sockfd); - outlet_float(x->x_connectout, --x->x_nconnections); - } - else if (read == 0) - { - post("tcpreceive: EOF on socket %d\n", sockfd); - sys_rmpollfn(sockfd); - sys_closesocket(sockfd); - tcpreceive_removeconnection(x, sockfd); - outlet_float(x->x_connectout, --x->x_nconnections); - } - else if (read > 0) - { - for (i = 0; i < read; ++i) - { - /* convert the bytes in the buffer to floats in a list */ - x->x_msgoutbuf[i].a_w.w_float = (float)x->x_msginbuf[i]; - } - /* find sender's ip address and output it */ - addr = tcpreceive_getconnection(x, sockfd); - 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); - outlet_list(x->x_addrout, &s_list, 4L, x->x_addrbytes); - /* send the list out the outlet */ - if (read > 1) outlet_list(x->x_msgout, &s_list, read, x->x_msgoutbuf); - else outlet_float(x->x_msgout, x->x_msgoutbuf[0].a_w.w_float); - } -} - -static void *tcpreceive_new(t_floatarg fportno) -{ - t_tcpreceive *x; - struct sockaddr_in server; - int sockfd, portno = fportno; - int intarg, i; - - /* create a socket */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); -#ifdef DEBUG - post("tcpreceive_new: socket %d port %d", sockfd, portno); -#endif - if (sockfd < 0) - { - sys_sockerror("tcpreceive: socket"); - return (0); - } - server.sin_family = AF_INET; - server.sin_addr.s_addr = INADDR_ANY; - - /* ask OS to allow another Pd to repoen 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"); - /* 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"); - - /* assign server port number */ - server.sin_port = htons((u_short)portno); - - /* name the socket */ - if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) - { - sys_sockerror("tcpreceive: bind"); - sys_closesocket(sockfd); - return (0); - } - x = (t_tcpreceive *)pd_new(tcpreceive_class); - x->x_msgout = outlet_new(&x->x_obj, &s_anything); - x->x_addrout = outlet_new(&x->x_obj, &s_list); - x->x_connectout = outlet_new(&x->x_obj, &s_float); - /* clear the connection list */ - for (i = 0; i < MAX_CONNECTIONS; ++i) - { - x->x_connection[i].socket = -1; - x->x_connection[i].addr = 0L; - } - /* convert the bytes in the buffer to floats in a list */ - for (i = 0; i < MAX_UDP_RECEIVE; ++i) - { - x->x_msgoutbuf[i].a_type = A_FLOAT; - x->x_msgoutbuf[i].a_w.w_float = 0; - } - for (i = 0; i < 4; ++i) - { - x->x_addrbytes[i].a_type = A_FLOAT; - x->x_addrbytes[i].a_w.w_float = 0; - } - - /* streaming protocol */ - if (listen(sockfd, 5) < 0) - { - sys_sockerror("tcpreceive: listen"); - sys_closesocket(sockfd); - sockfd = -1; - } - else - { - sys_addpollfn(sockfd, (t_fdpollfn)tcpreceive_connectpoll, x); - } - x->x_connectsocket = sockfd; - x->x_nconnections = 0; - -//udp version... sys_addpollfn(x->x_connectsocket, (t_fdpollfn)tcpreceive_read, x); - return (x); -} - -/* tcpreceive_connectpoll checks for incoming connection requests on the original socket */ -/* a new socket is assigned */ -static void tcpreceive_connectpoll(t_tcpreceive *x) -{ - struct sockaddr_in from; - socklen_t fromlen = sizeof(from); - long addr; - int fd; - - fd = accept(x->x_connectsocket, (struct sockaddr *)&from, &fromlen); - if (fd < 0) post("tcpreceive: accept failed"); - else - { - // t_socketreceiver *y = socketreceiver_new((void *)x, - // (t_socketnotifier)tcpreceive_notify, - // 0, 0); - - /* get the sender's ip */ - addr = ntohl(from.sin_addr.s_addr); - if (tcpreceive_addconnection(x, fd, addr)) - { - sys_addpollfn(fd, (t_fdpollfn)tcpreceive_read, x); - 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); - outlet_list(x->x_addrout, &s_list, 4L, x->x_addrbytes); - } - else - { - error ("tcpreceive: Too many connections"); - sys_closesocket(fd); - } - } -} - -/* 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) -{ - int i; - for (i = 0; i < MAX_CONNECTIONS; ++i) - { - if (x->x_connection[i].socket == -1) - { - x->x_connection[i].socket = fd; - x->x_connection[i].addr = addr; - return 1; - } - } - return 0; -} - -/* tcpreceive_closeall closes all open sockets and deletes them from the list */ -static void tcpreceive_closeall(t_tcpreceive *x) -{ - int i; - - for (i = 0; ((i < MAX_CONNECTIONS) && (x->x_nconnections > 0)); ++i) - { - if (x->x_connection[i].socket != -1) - { - post ("tcpreceive: closing socket %d", x->x_connection[i].socket); - sys_rmpollfn(x->x_connection[i].socket); - sys_closesocket(x->x_connection[i].socket); - x->x_connection[i].socket = -1; - x->x_connection[i].addr = 0L; - outlet_float(x->x_connectout, --x->x_nconnections); - } - } -} - -/* tcpreceive_removeconnection tries to delete the socket fd from the list */ -/* returns 1 on success, else 0 */ -static int tcpreceive_removeconnection(t_tcpreceive *x, int fd) -{ - int i; - for (i = 0; i < MAX_CONNECTIONS; ++i) - { - if (x->x_connection[i].socket == fd) - { - x->x_connection[i].socket = -1; - x->x_connection[i].addr = 0L; - return 1; - } - } - return 0; -} - -/* tcpreceive_getconnection tries to find the socket fd in the list */ -/* returns addr on success, else 0 */ -static long tcpreceive_getconnection(t_tcpreceive *x, int fd) -{ - int i; - for (i = 0; i < MAX_CONNECTIONS; ++i) - { - if (x->x_connection[i].socket == fd) - return x->x_connection[i].addr; - } - 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_closeall(x); -} - -#ifdef MSW -__declspec(dllexport) -#endif -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); -} - -/* end x_net_tcpreceive.c */ - diff --git a/net/x_net_tcpsend.c b/net/x_net_tcpsend.c deleted file mode 100755 index cf8c33d..0000000 --- a/net/x_net_tcpsend.c +++ /dev/null @@ -1,222 +0,0 @@ -/* x_net_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" - -#ifdef MSW -#include -#else -#include -#include -#include -#include -#include -#include -#include -#endif - -static t_class *tcpsend_class; - -typedef struct _tcpsend -{ - t_object x_obj; - int x_fd; -} t_tcpsend; - -#ifdef MSW -__declspec(dllexport) -#endif -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) -{ - t_tcpsend *x = (t_tcpsend *)pd_new(tcpsend_class); - outlet_new(&x->x_obj, &s_float); - x->x_fd = -1; - return (x); -} - -static void tcpsend_connect(t_tcpsend *x, t_symbol *hostname, - t_floatarg fportno) -{ - struct sockaddr_in server; - struct hostent *hp; - int sockfd; - int portno = fportno; - int intarg; - - if (x->x_fd >= 0) - { - error("tcpsend: already connected"); - return; - } - - /* create a socket */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); -#ifdef DEBUG - fprintf(stderr, "tcpsend_connect: send socket %d\n", sockfd); -#endif - if (sockfd < 0) - { - 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) - { - 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"); - - memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); - - /* 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) - { - sys_sockerror("tcpsend: connecting stream socket"); - sys_closesocket(sockfd); - return; - } - x->x_fd = sockfd; - outlet_float(x->x_obj.ob_outlet, 1); -} - -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"); - } -} - -static void tcpsend_send(t_tcpsend *x, t_symbol *s, int argc, t_atom *argv) -{ - static char byte_buf[65536];// arbitrary maximum similar to max IP packet size - int i, d; - char c; - float f, e; - char *bp; - int length, sent; - int result; - static double lastwarntime; - static double pleasewarn; - double timebefore; - double timeafter; - int late; - -#ifdef DEBUG - post("s: %s", s->s_name); - post("argc: %d", argc); -#endif - for (i = 0; i < argc; ++i) - { - if (argv[i].a_type == A_FLOAT) - { - f = argv[i].a_w.w_float; - d = (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[i] = c; - } - else - { - error("tcpsend_send: item %d is not a float", i); - return; - } - } - - length = i; - 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"); -} - -static void tcpsend_free(t_tcpsend *x) -{ - tcpsend_disconnect(x); -} - -#ifdef MSW -__declspec(dllexport) -#endif -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); -} - -/* end x_net_tcpsend.c*/ diff --git a/net/x_net_tcpserver.c b/net/x_net_tcpserver.c deleted file mode 100755 index f6526c0..0000000 --- a/net/x_net_tcpserver.c +++ /dev/null @@ -1,619 +0,0 @@ -/* x_net_tcpserver.c Martin Peach 20060511 working version 20060512 */ -/* 20060515 works on linux too... */ -/* x_net_tcpserver.c is based on netserver: */ -/* -------------------------- netserver ------------------------------------- */ -/* */ -/* A server for bidirectional communication from within Pd. */ -/* Allows to send back data to specific clients connected to the server. */ -/* Written by Olaf Matthes */ -/* Get source at http://www.akustische-kunst.org/puredata/maxlib */ -/* */ -/* 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. */ -/* */ -/* Based on PureData by Miller Puckette and others. */ -/* */ -/* ---------------------------------------------------------------------------- */ -//define DEBUG - -#include "m_pd.h" -#include "m_imp.h" -#include "s_stuff.h" - -//#include -//#include -//#include -//#include -//#include -//#include -//#include -//#include -#if defined(UNIX) || defined(unix) -#include -#include -#include -#include -#include -#include -#include -#include -#define SOCKET_ERROR -1 -#else -//#include -//#include -#include -#endif - -#define MAX_CONNECT 32 /* maximum number of connections */ -#define INBUFSIZE 65536L /* was 4096: size of receiving data buffer */ -#define MAX_UDP_RECEIVE 65536L /* longer than data in maximum UDP packet */ - -/* ----------------------------- tcpserver ------------------------- */ - -static t_class *tcpserver_class; -static t_binbuf *inbinbuf; -static char objName[] = "tcpserver"; - -typedef void (*t_tcpserver_socketnotifier)(void *x); -typedef void (*t_tcpserver_socketreceivefn)(void *x, t_binbuf *b); - -typedef struct _tcpserver_socketreceiver -{ - unsigned char *sr_inbuf; - int sr_inhead; - int sr_intail; - void *sr_owner; - t_tcpserver_socketnotifier sr_notifier; - t_tcpserver_socketreceivefn sr_socketreceivefn; -} t_tcpserver_socketreceiver; - -typedef struct _tcpserver -{ - t_object x_obj; - t_outlet *x_msgout; - t_outlet *x_connectout; - t_outlet *x_sockout; - t_outlet *x_addrout; - t_symbol *x_host[MAX_CONNECT]; - t_int x_fd[MAX_CONNECT]; - u_long x_addr[MAX_CONNECT]; - t_tcpserver_socketreceiver *x_sr[MAX_CONNECT]; - t_atom x_addrbytes[4]; - t_int x_sock_fd; - t_int x_connectsocket; - t_int x_nconnections; - t_atom x_msgoutbuf[MAX_UDP_RECEIVE]; - char x_msginbuf[MAX_UDP_RECEIVE]; -} t_tcpserver; - -static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new(void *owner, t_tcpserver_socketnotifier notifier, - t_tcpserver_socketreceivefn socketreceivefn); -static int tcpserver_socketreceiver_doread(t_tcpserver_socketreceiver *x); -static void tcpserver_socketreceiver_read(t_tcpserver_socketreceiver *x, int fd); -static void tcpserver_socketreceiver_free(t_tcpserver_socketreceiver *x); -static void tcpserver_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv); -static void tcp_server_send_bytes(int sockfd, t_tcpserver *x, int argc, t_atom *argv); -static void tcpserver_client_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv); -static void tcpserver_broadcast(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv); -static void tcpserver_notify(t_tcpserver *x); -static void tcpserver_connectpoll(t_tcpserver *x); -static void tcpserver_print(t_tcpserver *x); -static void *tcpserver_new(t_floatarg fportno); -static void tcpserver_free(t_tcpserver *x); -#ifdef MSW -__declspec(dllexport) -#endif -void tcpserver_setup(void); - -static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new(void *owner, t_tcpserver_socketnotifier notifier, - t_tcpserver_socketreceivefn socketreceivefn) -{ - t_tcpserver_socketreceiver *x = (t_tcpserver_socketreceiver *)getbytes(sizeof(*x)); - if (!x) - { - error("%s_socketreceiver: unable to allocate %d bytes", objName, sizeof(*x)); - } - else - { - x->sr_inhead = x->sr_intail = 0; - x->sr_owner = owner; - x->sr_notifier = notifier; - x->sr_socketreceivefn = socketreceivefn; - if (!(x->sr_inbuf = malloc(INBUFSIZE))) - { - freebytes(x, sizeof(*x)); - x = NULL; - error("%s_socketreceiver: unable to allocate %d bytes", objName, INBUFSIZE); - } - } - return (x); -} - -/* this is in a separately called subroutine so that the buffer isn't - sitting on the stack while the messages are getting passed. */ -static int tcpserver_socketreceiver_doread(t_tcpserver_socketreceiver *x) -{ - char messbuf[INBUFSIZE]; - char *bp = messbuf; - int indx, i; - int inhead = x->sr_inhead; - int intail = x->sr_intail; - unsigned char c; - t_tcpserver *y = x->sr_owner; - unsigned char *inbuf = x->sr_inbuf; - - if (intail == inhead) return (0); -#ifdef DEBUG - post ("%s_socketreceiver_doread: intail=%d inhead=%d", objName, intail, inhead); -#endif - - for (indx = intail, i = 0; indx != inhead; indx = (indx+1)&(INBUFSIZE-1), ++i) - { - c = *bp++ = inbuf[indx]; - y->x_msgoutbuf[i].a_w.w_float = (float)c; - } - if (i > 1) outlet_list(y->x_msgout, &s_list, i, y->x_msgoutbuf); - else outlet_float(y->x_msgout, y->x_msgoutbuf[0].a_w.w_float); - - // intail = (indx+1)&(INBUFSIZE-1); - x->sr_inhead = inhead; - x->sr_intail = indx;//intail; - return (1); -} - -static void tcpserver_socketreceiver_read(t_tcpserver_socketreceiver *x, int fd) -{ - int readto = (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1); - int ret, i; - t_tcpserver *y = x->sr_owner; - - y->x_sock_fd = fd; - /* the input buffer might be full. If so, drop the whole thing */ - if (readto == x->sr_inhead) - { - post("%s: dropped message", objName); - x->sr_inhead = x->sr_intail = 0; - readto = INBUFSIZE; - } - else - { - ret = recv(fd, x->sr_inbuf + x->sr_inhead, - readto - x->sr_inhead, 0); - if (ret < 0) - { - sys_sockerror("tcpserver: recv"); - if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner); - sys_rmpollfn(fd); - sys_closesocket(fd); - } - else if (ret == 0) - { - post("%s: connection closed on socket %d", objName, fd); - if (x->sr_notifier) (*x->sr_notifier)(x->sr_owner); - sys_rmpollfn(fd); - sys_closesocket(fd); - } - else - { -#ifdef DEBUG - post ("%s_socketreceiver_read: ret = %d", objName, ret); -#endif - x->sr_inhead += ret; - if (x->sr_inhead >= INBUFSIZE) x->sr_inhead = 0; - /* output client's IP and socket no. */ - for(i = 0; i < y->x_nconnections; i++) /* search for corresponding IP */ - { - if(y->x_fd[i] == y->x_sock_fd) - { -// outlet_symbol(x->x_connectionip, x->x_host[i]); - /* find sender's ip address and output it */ - y->x_addrbytes[0].a_w.w_float = (y->x_addr[i] & 0xFF000000)>>24; - y->x_addrbytes[1].a_w.w_float = (y->x_addr[i] & 0x0FF0000)>>16; - y->x_addrbytes[2].a_w.w_float = (y->x_addr[i] & 0x0FF00)>>8; - y->x_addrbytes[3].a_w.w_float = (y->x_addr[i] & 0x0FF); - outlet_list(y->x_addrout, &s_list, 4L, y->x_addrbytes); - break; - } - } - outlet_float(y->x_sockout, y->x_sock_fd); /* the socket number */ - tcpserver_socketreceiver_doread(x); - } - } -} - -static void tcpserver_socketreceiver_free(t_tcpserver_socketreceiver *x) -{ - if (x != NULL) - { - free(x->sr_inbuf); - freebytes(x, sizeof(*x)); - } -} - -/* ---------------- main tcpserver (send) stuff --------------------- */ - -static void tcp_server_send_bytes(int client, t_tcpserver *x, int argc, t_atom *argv) -{ - static char byte_buf[MAX_UDP_RECEIVE];// arbitrary maximum similar to max IP packet size - int i, 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; - int sockfd = x->x_fd[client]; - - /* process & send data */ - if(sockfd >= 0) - { - for (i = 0; i < argc; ++i) - { - if (argv[i].a_type == A_FLOAT) - { - f = argv[i].a_w.w_float; - d = (int)f; - e = f - d; -#ifdef DEBUG - post("%s: argv[%d]: float:%f int:%d delta:%f", objName, i, f, d, e); -#endif - if (e != 0) - { - error("%s: item %d (%f) is not an integer", objName, i, f); - return; - } - if ((d < 0) || (d > 255)) - { - error("%s: item %d (%f) is not between 0 and 255", objName, i, f); - return; - } - c = (unsigned char)d; /* make sure it doesn't become negative; this only matters for post() */ -#ifdef DEBUG - post("%s: argv[%d]: %d", objName, i, c); -#endif - byte_buf[i] = c; - } - else - { - error("%s: item %d is not a float", objName, i); - return; - } - } - length = i; - if (length > 0) - { - for (bp = byte_buf, sent = 0; sent < length;) - { - timebefore = sys_getrealtime(); - result = send(sockfd, byte_buf, length-sent, 0); - timeafter = sys_getrealtime(); - late = (timeafter - timebefore > 0.005); - if (late || pleasewarn) - { - if (timeafter > lastwarntime + 2) - { - post("%s: send blocked %d msec", objName, - (int)(1000 * ((timeafter - timebefore) + pleasewarn))); - pleasewarn = 0; - lastwarntime = timeafter; - } - else if (late) pleasewarn += timeafter - timebefore; - } - if (result <= 0) - { - sys_sockerror("tcpserver: send"); - post("%s: could not send data to client %d", objName, client); - break; - } - else - { - sent += result; - bp += result; - } - } - } - } - else post("%s: not a valid socket number (%d)", objName, sockfd); -} - -/* send message to client using socket number */ -static void tcpserver_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) -{ - int i, sockfd; - int client = -1; - - if(x->x_nconnections < 0) - { - post("%s: no clients connected", objName); - return; - } - if(argc < 2) - { - post("%s: nothing to send", objName); - return; - } - /* get socket number of connection (first element in list) */ - if(argv[0].a_type == A_FLOAT) - { - sockfd = atom_getfloatarg(0, argc, argv); - for(i = 0; i < x->x_nconnections; i++) /* check if connection exists */ - { - if(x->x_fd[i] == sockfd) - { - client = i; /* the client we're sending to */ - break; - } - } - if(client == -1) - { - post("%s: no connection on socket %d", objName, sockfd); - return; - } - } - else - { - post("%s: no socket specified", objName); - return; - } - tcp_server_send_bytes(client, x, argc-1, &argv[1]); -} - -/* send message to client using client number - note that the client numbers might change in case a client disconnects! */ -/* clients start at 1 but our index starts at 0 */ -static void tcpserver_client_send(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) -{ - int client; - - if(x->x_nconnections < 0) - { - post("%s: no clients connected", objName); - return; - } - if(argc < 2) - { - post("%s: nothing to send", objName); - return; - } - /* get number of client (first element in list) */ - if(argv[0].a_type == A_FLOAT) - client = atom_getfloatarg(0, argc, argv); - else - { - post("%s: no client specified", objName); - return; - } - if (!((client > 0) && (client < MAX_CONNECT))) - { - post("%s: client %d out of range [1..%d]", objName, client, MAX_CONNECT); - return; - } - --client;/* zero based index*/ - tcp_server_send_bytes(client, x, argc-1, &argv[1]); -} - -/* broadcasts a message to all connected clients */ -static void tcpserver_broadcast(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv) -{ - int client; - - /* enumerate through the clients and send each the message */ - for(client = 0; client < x->x_nconnections; client++) /* check if connection exists */ - { - if(x->x_fd[client] >= 0) - { /* socket exists for this client */ - tcp_server_send_bytes(client, x, argc, argv); - break; - } - } -} - -/* ---------------- main tcpserver (receive) stuff --------------------- */ - -static void tcpserver_notify(t_tcpserver *x) -{ - int i, k; - - /* remove connection from list */ - for(i = 0; i < x->x_nconnections; i++) - { - if(x->x_fd[i] == x->x_sock_fd) - { - x->x_nconnections--; - post("%s: \"%s\" removed from list of clients", objName, x->x_host[i]->s_name); - x->x_host[i] = NULL; /* delete entry */ - x->x_fd[i] = -1; - tcpserver_socketreceiver_free(x->x_sr[i]); - x->x_sr[i] = NULL; - - /* rearrange list now: move entries to close the gap */ - for(k = i; k < x->x_nconnections; k++) - { - x->x_host[k] = x->x_host[k + 1]; - x->x_fd[k] = x->x_fd[k + 1]; - } - } - } - outlet_float(x->x_connectout, x->x_nconnections); -} - -static void tcpserver_connectpoll(t_tcpserver *x) -{ - struct sockaddr_in incomer_address; - int sockaddrl = (int) sizeof( struct sockaddr ); - int fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl); - int i; - - if (fd < 0) post("%s: accept failed", objName); - else - { - t_tcpserver_socketreceiver *y = tcpserver_socketreceiver_new((void *)x, - (t_tcpserver_socketnotifier)tcpserver_notify, NULL);/* MP tcpserver_doit isn't used I think...*/ - if (!y) - { -#ifdef MSW - closesocket(fd); -#else - close(fd); -#endif - return; - } - sys_addpollfn(fd, (t_fdpollfn)tcpserver_socketreceiver_read, y); - x->x_nconnections++; - i = x->x_nconnections - 1; - x->x_host[i] = gensym(inet_ntoa(incomer_address.sin_addr)); - x->x_fd[i] = fd; - x->x_sr[i] = y; - post("%s: accepted connection from %s on socket %d", - objName, x->x_host[i]->s_name, x->x_fd[i]); - outlet_float(x->x_connectout, x->x_nconnections); - outlet_float(x->x_sockout, x->x_fd[i]); /* the socket number */ - x->x_addr[i] = ntohl(incomer_address.sin_addr.s_addr); - x->x_addrbytes[0].a_w.w_float = (x->x_addr[i] & 0xFF000000)>>24; - x->x_addrbytes[1].a_w.w_float = (x->x_addr[i] & 0x0FF0000)>>16; - x->x_addrbytes[2].a_w.w_float = (x->x_addr[i] & 0x0FF00)>>8; - x->x_addrbytes[3].a_w.w_float = (x->x_addr[i] & 0x0FF); - outlet_list(x->x_addrout, &s_list, 4L, x->x_addrbytes); - } -} - -static void tcpserver_print(t_tcpserver *x) -{ - int i; - - if(x->x_nconnections > 0) - { - post("%s: %d open connections:", objName, x->x_nconnections); - for(i = 0; i < x->x_nconnections; i++) - { - post(" \"%s\" on socket %d", - x->x_host[i]->s_name, x->x_fd[i]); - } - } - else post("%s: no open connections", objName); -} - -static void *tcpserver_new(t_floatarg fportno) -{ - t_tcpserver *x; - int i; - struct sockaddr_in server; - int sockfd, portno = fportno; - - /* create a socket */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); -#ifdef DEBUG - post("%s: receive socket %d", objName, sockfd); -#endif - if (sockfd < 0) - { - sys_sockerror("tcpserver: socket"); - return (0); - } - server.sin_family = AF_INET; - server.sin_addr.s_addr = INADDR_ANY; -#ifdef IRIX - /* this seems to work only in IRIX but is unnecessary in - Linux. Not sure what NT needs in place of this. */ - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0) - post("setsockopt failed\n"); -#endif - /* assign server port number */ - server.sin_port = htons((u_short)portno); - /* name the socket */ - if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) - { - sys_sockerror("tcpserver: bind"); - sys_closesocket(sockfd); - return (0); - } - x = (t_tcpserver *)pd_new(tcpserver_class); - x->x_msgout = outlet_new(&x->x_obj, &s_anything); /* 1st outlet for received data */ - /* streaming protocol */ - if (listen(sockfd, 5) < 0) - { - sys_sockerror("tcpserver: listen"); - sys_closesocket(sockfd); - sockfd = -1; - } - else - { - sys_addpollfn(sockfd, (t_fdpollfn)tcpserver_connectpoll, x); - x->x_connectout = outlet_new(&x->x_obj, &s_float); /* 2nd outlet for number of connected clients */ - x->x_sockout = outlet_new(&x->x_obj, &s_float); /* 3rd outlet for socket number of current client */ - x->x_addrout = outlet_new(&x->x_obj, &s_list); /* 4th outlet for ip address of current client */ - inbinbuf = binbuf_new(); - } - x->x_connectsocket = sockfd; - x->x_nconnections = 0; - for(i = 0; i < MAX_CONNECT; i++) - { - x->x_fd[i] = -1; - x->x_sr[i] = NULL; - } - /* prepare to convert the bytes in the buffer to floats in a list */ - for (i = 0; i < MAX_UDP_RECEIVE; ++i) - { - x->x_msgoutbuf[i].a_type = A_FLOAT; - x->x_msgoutbuf[i].a_w.w_float = 0; - } - for (i = 0; i < 4; ++i) - { - x->x_addrbytes[i].a_type = A_FLOAT; - x->x_addrbytes[i].a_w.w_float = 0; - } - - return (x); -} - -static void tcpserver_free(t_tcpserver *x) -{ - int i; - - for(i = 0; i < MAX_CONNECT; i++) - { - if (x->x_fd[i] >= 0) - { - sys_rmpollfn(x->x_fd[i]); - sys_closesocket(x->x_fd[i]); - } - if (x->x_sr[i] != NULL) tcpserver_socketreceiver_free(x->x_sr[i]); - } - if (x->x_connectsocket >= 0) - { - sys_rmpollfn(x->x_connectsocket); - sys_closesocket(x->x_connectsocket); - } - - binbuf_free(inbinbuf); -} - -#ifdef MSW -__declspec(dllexport) -#endif -void tcpserver_setup(void) -{ - tcpserver_class = class_new(gensym(objName),(t_newmethod)tcpserver_new, (t_method)tcpserver_free, - sizeof(t_tcpserver), 0, A_DEFFLOAT, 0); - class_addmethod(tcpserver_class, (t_method)tcpserver_print, gensym("print"), 0); - class_addmethod(tcpserver_class, (t_method)tcpserver_send, gensym("send"), A_GIMME, 0); - class_addmethod(tcpserver_class, (t_method)tcpserver_client_send, gensym("client"), A_GIMME, 0); - class_addmethod(tcpserver_class, (t_method)tcpserver_broadcast, gensym("broadcast"), A_GIMME, 0); -} - -/* end of x_net_tcpserver.c */ diff --git a/net/x_net_udpreceive.c b/net/x_net_udpreceive.c deleted file mode 100755 index cef02b2..0000000 --- a/net/x_net_udpreceive.c +++ /dev/null @@ -1,162 +0,0 @@ -/* x_net_udpreceive.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. */ - -#include "m_pd.h" -#include "s_stuff.h" - -#ifdef MSW -#include -#include -#else -#include -#include -#include -#include -#include -#include -#endif - - -/* ----------------------------- udpreceive ------------------------- */ - -static t_class *udpreceive_class; - -#define MAX_UDP_RECEIVE 65536L // longer than data in maximum UDP packet - -typedef struct _udpreceive -{ - t_object x_obj; - t_outlet *x_msgout; - t_outlet *x_addrout; - int x_connectsocket; - t_atom x_addrbytes[4]; - t_atom x_msgoutbuf[MAX_UDP_RECEIVE]; - char x_msginbuf[MAX_UDP_RECEIVE]; -} t_udpreceive; - -#ifdef MSW -__declspec(dllexport) -#endif -void udpreceive_setup(void); -static void udpreceive_free(t_udpreceive *x); -static void *udpreceive_new(t_floatarg fportno); -static void udpreceive_read(t_udpreceive *x, int sockfd); - -static void udpreceive_read(t_udpreceive *x, int sockfd) -{ - int i, read = 0; - struct sockaddr_in from; - socklen_t fromlen = sizeof(from); - long addr; - - read = recvfrom(sockfd, x->x_msginbuf, MAX_UDP_RECEIVE, 0, (struct sockaddr *)&from, &fromlen); -#ifdef DEBUG - post("udpreceive_read: read %lu x->x_connectsocket = %d", - read, x->x_connectsocket); -#endif - /* get the sender's ip */ - addr = ntohl(from.sin_addr.s_addr); - 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); - outlet_list(x->x_addrout, &s_list, 4L, x->x_addrbytes); - - if (read < 0) - { - sys_sockerror("udpreceive_read"); - sys_closesocket(x->x_connectsocket); - return; - } - if (read > 0) - { - for (i = 0; i < read; ++i) - { - /* convert the bytes in the buffer to floats in a list */ - x->x_msgoutbuf[i].a_w.w_float = (float)x->x_msginbuf[i]; - } - /* send the list out the outlet */ - if (read > 1) outlet_list(x->x_msgout, &s_list, read, x->x_msgoutbuf); - else outlet_float(x->x_msgout, x->x_msgoutbuf[0].a_w.w_float); - } -} - -static void *udpreceive_new(t_floatarg fportno) -{ - t_udpreceive *x; - struct sockaddr_in server; - int sockfd, portno = fportno; - int intarg, i; - - /* create a socket */ - sockfd = socket(AF_INET, SOCK_DGRAM, 0); -#ifdef DEBUG - post("udpreceive_new: socket %d port %d", sockfd, portno); -#endif - if (sockfd < 0) - { - sys_sockerror("udpreceive: socket"); - return (0); - } - server.sin_family = AF_INET; - server.sin_addr.s_addr = INADDR_ANY; - - /* ask OS to allow another Pd to repoen this port after we close it. */ - intarg = 1; - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, - (char *)&intarg, sizeof(intarg)) < 0) - post("udpreceive: setsockopt (SO_REUSEADDR) failed"); - - /* assign server port number */ - server.sin_port = htons((u_short)portno); - - /* name the socket */ - if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) - { - sys_sockerror("udpreceive: bind"); - sys_closesocket(sockfd); - return (0); - } - x = (t_udpreceive *)pd_new(udpreceive_class); - x->x_msgout = outlet_new(&x->x_obj, &s_anything); - x->x_addrout = outlet_new(&x->x_obj, &s_list); - x->x_connectsocket = sockfd; - - /* convert the bytes in the buffer to floats in a list */ - for (i = 0; i < MAX_UDP_RECEIVE; ++i) - { - x->x_msgoutbuf[i].a_type = A_FLOAT; - x->x_msgoutbuf[i].a_w.w_float = 0; - } - for (i = 0; i < 4; ++i) - { - x->x_addrbytes[i].a_type = A_FLOAT; - x->x_addrbytes[i].a_w.w_float = 0; - } - sys_addpollfn(x->x_connectsocket, (t_fdpollfn)udpreceive_read, x); - return (x); -} - -static void udpreceive_free(t_udpreceive *x) -{ - if (x->x_connectsocket >= 0) - { - sys_rmpollfn(x->x_connectsocket); - sys_closesocket(x->x_connectsocket); - } -} - -#ifdef MSW -__declspec(dllexport) -#endif -void udpreceive_setup(void) -{ - udpreceive_class = class_new(gensym("udpreceive"), - (t_newmethod)udpreceive_new, (t_method)udpreceive_free, - sizeof(t_udpreceive), CLASS_NOINLET, A_DEFFLOAT, 0); -} - -/* end x_net_udpreceive.c */ - diff --git a/net/x_net_udpsend.c b/net/x_net_udpsend.c deleted file mode 100755 index 7b468f9..0000000 --- a/net/x_net_udpsend.c +++ /dev/null @@ -1,215 +0,0 @@ -/* x_net_udpsend.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 -#include -#ifdef MSW -#include -#else -#include -#include -#include -#include -#include -#endif - -static t_class *udpsend_class; - -typedef struct _udpsend -{ - t_object x_obj; - int x_fd; -} t_udpsend; - -#ifdef MSW -__declspec(dllexport) -#endif -void udpsend_setup(void); -static void udpsend_free(t_udpsend *x); -static void udpsend_send(t_udpsend *x, t_symbol *s, int argc, t_atom *argv); -static void udpsend_disconnect(t_udpsend *x); -static void udpsend_connect(t_udpsend *x, t_symbol *hostname, t_floatarg fportno); -static void *udpsend_new(void); - -static void *udpsend_new(void) -{ - t_udpsend *x = (t_udpsend *)pd_new(udpsend_class); - outlet_new(&x->x_obj, &s_float); - x->x_fd = -1; - return (x); -} - -static void udpsend_connect(t_udpsend *x, t_symbol *hostname, - t_floatarg fportno) -{ - struct sockaddr_in server; - struct hostent *hp; - int sockfd; - int portno = fportno; - - if (x->x_fd >= 0) - { - error("udpsend: already connected"); - return; - } - - /* create a socket */ - sockfd = socket(AF_INET, SOCK_DGRAM, 0); -#ifdef DEBUG - fprintf(stderr, "udpsend_connect: send socket %d\n", sockfd); -#endif - if (sockfd < 0) - { - sys_sockerror("udpsend: socket"); - return; - } - /* connect socket using hostname provided in command line */ - server.sin_family = AF_INET; - hp = gethostbyname(hostname->s_name); - if (hp == 0) - { - post("udpsend: bad host?\n"); - return; - } - memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length); - - /* assign client port number */ - server.sin_port = htons((u_short)portno); - - post("udpsend: connecting to port %d", portno); - /* try to connect. */ - if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) - { - sys_sockerror("udpsend: connecting stream socket"); - sys_closesocket(sockfd); - return; - } - x->x_fd = sockfd; - outlet_float(x->x_obj.ob_outlet, 1); -} - -static void udpsend_disconnect(t_udpsend *x) -{ - if (x->x_fd >= 0) - { - sys_closesocket(x->x_fd); - x->x_fd = -1; - outlet_float(x->x_obj.ob_outlet, 0); - } -} - -static void udpsend_send(t_udpsend *x, t_symbol *s, int argc, t_atom *argv) -{ - static char byte_buf[65536];// arbitrary maximum similar to max IP packet size - int i, d; - char c; - float f, e; - char *bp; - int length, sent; - int result; - static double lastwarntime; - static double pleasewarn; - double timebefore; - double timeafter; - int late; - -#ifdef DEBUG - post("s: %s", s->s_name); - post("argc: %d", argc); -#endif - for (i = 0; i < argc; ++i) - { - if (argv[i].a_type == A_FLOAT) - { - f = argv[i].a_w.w_float; - d = (int)f; - e = f - d; - if (e != 0) - { - error("udpsend_send: item %d (%f) is not an integer", i, f); - return; - } - c = (unsigned char)d; - if (c != d) - { - error("udpsend_send: item %d (%f) is not between 0 and 255", i, f); - return; - } -#ifdef DEBUG - post("udpsend_send: argv[%d]: %d", i, c); -#endif - byte_buf[i] = c; - } - else - { - error("udpsend_send: item %d is not a float", i); - return; - } - } - - length = i; - 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("udpsend blocked %d msec", - (int)(1000 * ((timeafter - timebefore) + pleasewarn))); - pleasewarn = 0; - lastwarntime = timeafter; - } - else if (late) pleasewarn += timeafter - timebefore; - } - if (result <= 0) - { - sys_sockerror("udpsend"); - udpsend_disconnect(x); - break; - } - else - { - sent += result; - bp += result; - } - } - } - else error("udpsend: not connected"); -} - -static void udpsend_free(t_udpsend *x) -{ - udpsend_disconnect(x); -} - -#ifdef MSW -__declspec(dllexport) -#endif -void udpsend_setup(void) -{ - udpsend_class = class_new(gensym("udpsend"), (t_newmethod)udpsend_new, - (t_method)udpsend_free, - sizeof(t_udpsend), 0, 0); - class_addmethod(udpsend_class, (t_method)udpsend_connect, - gensym("connect"), A_SYMBOL, A_FLOAT, 0); - class_addmethod(udpsend_class, (t_method)udpsend_disconnect, - gensym("disconnect"), 0); - class_addmethod(udpsend_class, (t_method)udpsend_send, gensym("send"), - A_GIMME, 0); -} - -/* end x_net_udpsend.c*/ - -- cgit v1.2.1