aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Peach <mrpeach@users.sourceforge.net>2006-08-24 06:51:16 +0000
committerMartin Peach <mrpeach@users.sourceforge.net>2006-08-24 06:51:16 +0000
commitad3e4ced602b5ec7b1005635342e8f338c6bd2fa (patch)
tree13bb689b21951fb41ae9282a7a51073c2f0160fa
parent59fe72b56dd0b97625a8061304b257269c00d790 (diff)
Renamed files without x_net_ prefix.
Removed extra copies of tcpserver and tcpclient svn path=/trunk/externals/mrpeach/; revision=5726
-rwxr-xr-xnet/tcpclient.c (renamed from net/x_net_tcp_client.c)0
-rwxr-xr-xnet/tcpreceive.c (renamed from net/x_net_tcpreceive.c)0
-rwxr-xr-xnet/tcpsend.c (renamed from net/x_net_tcpsend.c)0
-rwxr-xr-xnet/tcpserver.c (renamed from net/x_net_tcpserver.c)0
-rwxr-xr-xnet/udpreceive.c (renamed from net/x_net_udpreceive.c)0
-rwxr-xr-xnet/udpsend.c (renamed from net/x_net_udpsend.c)0
-rwxr-xr-xnet/x_net_tcp_server.c600
-rwxr-xr-xnet/x_net_tcpclient.c443
8 files changed, 0 insertions, 1043 deletions
diff --git a/net/x_net_tcp_client.c b/net/tcpclient.c
index 366d421..366d421 100755
--- a/net/x_net_tcp_client.c
+++ b/net/tcpclient.c
diff --git a/net/x_net_tcpreceive.c b/net/tcpreceive.c
index 4cce77d..4cce77d 100755
--- a/net/x_net_tcpreceive.c
+++ b/net/tcpreceive.c
diff --git a/net/x_net_tcpsend.c b/net/tcpsend.c
index cf8c33d..cf8c33d 100755
--- a/net/x_net_tcpsend.c
+++ b/net/tcpsend.c
diff --git a/net/x_net_tcpserver.c b/net/tcpserver.c
index f6526c0..f6526c0 100755
--- a/net/x_net_tcpserver.c
+++ b/net/tcpserver.c
diff --git a/net/x_net_udpreceive.c b/net/udpreceive.c
index cef02b2..cef02b2 100755
--- a/net/x_net_udpreceive.c
+++ b/net/udpreceive.c
diff --git a/net/x_net_udpsend.c b/net/udpsend.c
index 7b468f9..7b468f9 100755
--- a/net/x_net_udpsend.c
+++ b/net/udpsend.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 <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 "m_imp.h"
-#include "s_stuff.h"
-
-//#include <sys/types.h>
-//#include <stdarg.h>
-//#include <signal.h>
-//#include <fcntl.h>
-//#include <errno.h>
-//#include <string.h>
-//#include <stdio.h>
-//#include <pthread.h>
-#if defined(UNIX) || defined(unix)
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/time.h>
-#define SOCKET_ERROR -1
-#else
-//#include <io.h>
-//#include <fcntl.h>
-#include <winsock2.h>
-#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 <stdio.h>
-#include <sys/types.h>
-#include <string.h>
-#include <pthread.h>
-#if defined(UNIX) || defined(unix)
-#include <sys/socket.h>
-#include <sys/errno.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <unistd.h>
-#define SOCKET_ERROR -1
-#else
-#include <winsock2.h>
-#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 */