aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIOhannes m zmölnig <zmoelnig@users.sourceforge.net>2010-03-25 08:28:36 +0000
committerIOhannes m zmölnig <zmoelnig@users.sourceforge.net>2010-03-25 08:28:36 +0000
commit29f2b2b9168fd2d45ec5a2699dab2e5ab44ad10b (patch)
tree770ebdbbadfa11757fb4bd10f4deec3f4ef7e49b
parent4da2a3bb1ad4e821e03d5776c0eb7492f0a9d5fe (diff)
most of the tcp-objects seem to work now;
performance increase as measured until now is great :-) svn path=/trunk/externals/iem/iemnet/; revision=13265
-rw-r--r--iemnet.c26
-rw-r--r--tcpclient.c13
-rw-r--r--tcpreceive.c481
-rw-r--r--tcpsend.c318
-rw-r--r--tcpserver.c39
5 files changed, 368 insertions, 509 deletions
diff --git a/iemnet.c b/iemnet.c
index 5c739c7..7586c7a 100644
--- a/iemnet.c
+++ b/iemnet.c
@@ -4,8 +4,6 @@
#include "iemnet.h"
-#include "s_stuff.h"
-
#include <string.h>
#include <stdio.h>
#include <errno.h>
@@ -488,7 +486,7 @@ int iemnet__sender_setsockopt(t_iemnet_sender*s, int level, int optname, const v
struct _iemnet_receiver {
pthread_t thread;
int sockfd; /* owned outside; you must call iemnet__receiver_destroy() before freeing socket yourself */
- void*owner;
+ void*userdata;
t_iemnet_chunk*data;
t_iemnet_receivecallback callback;
t_queue*queue;
@@ -542,20 +540,20 @@ static void iemnet__receiver_tick(t_iemnet_receiver *x)
t_iemnet_chunk*c=queue_pop_noblock(x->queue);
while(NULL!=c) {
x->flist = iemnet__chunk2list(c, x->flist);
- (x->callback)(x->owner, x->sockfd, x->flist->argc, x->flist->argv);
+ (x->callback)(x->userdata, x->flist->argc, x->flist->argv);
iemnet__chunk_destroy(c);
c=queue_pop_noblock(x->queue);
}
if(!x->running) {
// read terminated
- x->callback(x->owner, x->sockfd, 0, NULL);
+ x->callback(x->userdata, 0, NULL);
}
}
-t_iemnet_receiver*iemnet__receiver_create(int sock, void*owner, t_iemnet_receivecallback callback) {
+t_iemnet_receiver*iemnet__receiver_create(int sock, void*userdata, t_iemnet_receivecallback callback) {
t_iemnet_receiver*rec=(t_iemnet_receiver*)getbytes(sizeof(t_iemnet_receiver));
- //fprintf(stderr, "new receiver for %d\t%x\t%x\n", sock, owner, callback);
+ //fprintf(stderr, "new receiver for %d\t%x\t%x\n", sock, userdata, callback);
if(rec) {
t_iemnet_chunk*data=iemnet__chunk_create_empty(INBUFSIZE);
int res=0;
@@ -564,7 +562,7 @@ t_iemnet_receiver*iemnet__receiver_create(int sock, void*owner, t_iemnet_receive
return NULL;
}
rec->sockfd=sock;
- rec->owner=owner;
+ rec->userdata=userdata;
rec->data=data;
rec->callback=callback;
rec->flist=iemnet__floatlist_create(1024);
@@ -590,7 +588,7 @@ void iemnet__receiver_destroy(t_iemnet_receiver*rec) {
rec->sockfd=0;
pthread_join(rec->thread, NULL);
- rec->owner=NULL;
+ rec->userdata=NULL;
rec->data=NULL;
rec->callback=NULL;
rec->clock=NULL;
@@ -609,15 +607,17 @@ void iemnet__receiver_destroy(t_iemnet_receiver*rec) {
#ifdef _MSC_VER
- void tcpclient_setup(void);
- void tcpserver_setup(void);
+void tcpclient_setup(void);
+void tcpserver_setup(void);
+void tcpsend_setup(void);
#endif
IEMNET_EXTERN void iemnet_setup(void) {
#ifdef _MSC_VER
- tcpclient_setup();
- tcpserver_setup();
+ tcpclient_setup();
+ tcpserver_setup();
+ tcpserver_setup();
#endif
}
diff --git a/tcpclient.c b/tcpclient.c
index c0c89ef..c7bffe2 100644
--- a/tcpclient.c
+++ b/tcpclient.c
@@ -25,21 +25,8 @@
/* ---------------------------------------------------------------------------- */
#include "iemnet.h"
-
-#include "s_stuff.h"
-
-#ifdef _WIN32
-#else
-# include <netdb.h> /* gethostbyname, htons... */
-#endif
-
#include <string.h>
-
- //#include <sys/types.h>
- //#include <sys/socket.h>
-
-
#include <pthread.h>
diff --git a/tcpreceive.c b/tcpreceive.c
index 418e77b..502cbf7 100644
--- a/tcpreceive.c
+++ b/tcpreceive.c
@@ -1,332 +1,297 @@
-/* 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 _WIN32
-#include <winsock2.h>
-#include <ws2tcpip.h> /* for socklen_t */
-#else
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <netdb.h>
-#include <stdio.h>
-#endif
+/* tcpreceive.c
+ * copyright (c) 2010 IOhannes m zmlnig, IEM
+ * copyright (c) 2006-2010 Martin Peach
+ * copyright (c) Miller Puckette
+ */
+
+/* */
+/* A client for unidirectional communication from within Pd. */
+/* */
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* */
+
+#include "iemnet.h"
+#ifndef _WIN32
+# include <netinet/tcp.h>
+#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;
- unsigned short port;
- int socket;
+ long addr;
+ unsigned short port;
+ int socket;
+ struct _tcpreceive*owner;
+ t_iemnet_receiver*receiver;
} 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[5];
- t_atom x_msgoutbuf[MAX_UDP_RECEIVE];
- char x_msginbuf[MAX_UDP_RECEIVE];
+ 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[5];
} t_tcpreceive;
-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, unsigned short port);
-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 unsigned short tcpreceive_getconnectionport(t_tcpreceive * x, int fd);
-
-static void tcpreceive_read(t_tcpreceive *x, int sockfd)
-{
- int i, read = 0;
- long addr;
- unsigned short port;
-// 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);
- port = tcpreceive_getconnectionport(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);
- x->x_addrbytes[4].a_w.w_float = port;
- outlet_list(x->x_addrout, &s_list, 5L, 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 int tcpreceive_find_socket(t_tcpreceive *x, int fd) {
+ int i;
+ for (i = 0; i < MAX_CONNECTIONS; ++i)
+ if (x->x_connection[i].socket == fd)return i;
+
+ return -1;
}
-static void *tcpreceive_new(t_floatarg fportno)
+static int tcpreceive_disconnect(t_tcpreceive *x, int id);
+
+static void tcpreceive_read_callback(t_tcpconnection *y, int argc, t_atom*argv)
{
- t_tcpreceive *x;
- struct sockaddr_in server;
- int sockfd, portno = fportno;
- int intarg, i;
+ t_tcpreceive*x=NULL;
+ if(NULL==y || NULL==(x=y->owner))return;
+ int index=tcpreceive_find_socket(x, y->socket);
+ if(index>=0) {
- /* 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;
- x->x_connection[i].port = 0;
- }
- /* 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 < 5; ++i)
- {
- x->x_addrbytes[i].a_type = A_FLOAT;
- x->x_addrbytes[i].a_w.w_float = 0;
+ if(argc) {
+ // outlet info about connection
+ outlet_list(x->x_msgout, gensym("list"), argc, argv);
+ } else {
+ // disconnected
+ int sockfd=y->socket;
+ tcpreceive_disconnect(x, index);
}
+ }
- /* streaming protocol */
- if (listen(sockfd, 5) < 0)
- {
- sys_sockerror("tcpreceive: listen");
- sys_closesocket(sockfd);
- sockfd = -1;
- }
- else
+}
+
+
+/* tcpreceive_addconnection tries to add the socket fd to the list */
+/* returns 1 on success, else 0 */
+static int tcpreceive_addconnection(t_tcpreceive *x, int fd, long addr, unsigned short port)
+{
+ int i;
+ for (i = 0; i < MAX_CONNECTIONS; ++i)
{
- sys_addpollfn(sockfd, (t_fdpollfn)tcpreceive_connectpoll, x);
+ if (x->x_connection[i].socket == -1)
+ {
+ x->x_connection[i].socket = fd;
+ x->x_connection[i].addr = addr;
+ x->x_connection[i].port = port;
+ x->x_connection[i].owner = x;
+ x->x_connection[i].receiver=
+ iemnet__receiver_create(fd,
+ x->x_connection+i,
+ (t_iemnet_receivecallback)tcpreceive_read_callback);
+
+ return 1;
+ }
}
- x->x_connectsocket = sockfd;
- x->x_nconnections = 0;
-
-//udp version... sys_addpollfn(x->x_connectsocket, (t_fdpollfn)tcpreceive_read, x);
- return (x);
+ return 0;
}
+
/* 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;
- unsigned short port;
- int fd;
-
- fd = accept(x->x_connectsocket, (struct sockaddr *)&from, &fromlen);
- if (fd < 0) post("tcpreceive: accept failed");
- else
+ struct sockaddr_in from;
+ socklen_t fromlen = sizeof(from);
+ long addr;
+ unsigned short port;
+ 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);
- port = ntohs(from.sin_port);
- if (tcpreceive_addconnection(x, fd, addr, port))
- {
- 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);
- x->x_addrbytes[4].a_w.w_float = port;
- outlet_list(x->x_addrout, &s_list, 5L, x->x_addrbytes);
+ // 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);
+ port = ntohs(from.sin_port);
+ if (tcpreceive_addconnection(x, fd, addr, port))
+ {
+ outlet_float(x->x_connectout, ++x->x_nconnections);
+ x->x_addrbytes[0].a_w.w_float = (addr & 0xFF000000)>>24;
+ x->x_addrbytes[1].a_w.w_float = (addr & 0x0FF0000)>>16;
+ x->x_addrbytes[2].a_w.w_float = (addr & 0x0FF00)>>8;
+ x->x_addrbytes[3].a_w.w_float = (addr & 0x0FF);
+ x->x_addrbytes[4].a_w.w_float = port;
+ outlet_list(x->x_addrout, &s_list, 5L, x->x_addrbytes);
}
- else
+ else
{
- error ("tcpreceive: Too many connections");
- sys_closesocket(fd);
+ 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, unsigned short port)
+
+static int tcpreceive_disconnect(t_tcpreceive *x, int id)
{
- 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;
- x->x_connection[i].port = port;
- return 1;
- }
- }
- return 0;
+ if(id>=0 && id < MAX_CONNECTIONS && x->x_connection[id].port>0) {
+ iemnet__receiver_destroy(x->x_connection[id].receiver);
+ x->x_connection[id].receiver=NULL;
+
+ sys_closesocket(x->x_connection[id].socket);
+ x->x_connection[id].socket = -1;
+
+ x->x_connection[id].addr = 0L;
+ x->x_connection[id].port = 0;
+ x->x_nconnections--;
+ outlet_float(x->x_connectout, x->x_nconnections);
+ return 1;
+ }
+
+ return 0;
}
/* tcpreceive_closeall closes all open sockets and deletes them from the list */
-static void tcpreceive_closeall(t_tcpreceive *x)
+static void tcpreceive_disconnect_all(t_tcpreceive *x)
{
- int i;
+ int i;
- for (i = 0; ((i < MAX_CONNECTIONS) && (x->x_nconnections > 0)); ++i)
+ for (i = 0; i < MAX_CONNECTIONS; 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;
- x->x_connection[i].port = 0;
- outlet_float(x->x_connectout, --x->x_nconnections);
- }
+ tcpreceive_disconnect(x, i);
}
}
+
+
+
/* 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)
+static int tcpreceive_disconnect_socket(t_tcpreceive *x, int fd)
{
- int i;
- for (i = 0; i < MAX_CONNECTIONS; ++i)
+ int i;
+ for (i = 0; i < MAX_CONNECTIONS; ++i)
{
- if (x->x_connection[i].socket == fd)
+ if (x->x_connection[i].socket == fd)
{
- x->x_connection[i].socket = -1;
- x->x_connection[i].addr = 0L;
- x->x_connection[i].port = 0;
- return 1;
+ return tcpreceive_disconnect(x, i);
}
}
- return 0;
+ return 0;
}
-/* tcpreceive_getconnectionport tries to find the socket fd in the list */
-/* returns port on success, else 0 */
-static u_short tcpreceive_getconnectionport(t_tcpreceive *x, int fd)
-{
- int i;
- for (i = 0; i < MAX_CONNECTIONS; ++i)
+static void tcpreceive_free(t_tcpreceive *x)
+{ /* is this ever called? */
+ if (x->x_connectsocket >= 0)
{
- if (x->x_connection[i].socket == fd)
- return x->x_connection[i].port;
+ sys_rmpollfn(x->x_connectsocket);
+ sys_closesocket(x->x_connectsocket);
}
- return 0;
+ tcpreceive_disconnect_all(x);
}
-/* 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)
+static void *tcpreceive_new(t_floatarg fportno)
{
- int i;
- for (i = 0; i < MAX_CONNECTIONS; ++i)
+ 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)
{
- if (x->x_connection[i].socket == fd)
- return x->x_connection[i].addr;
+ sys_sockerror("tcpreceive: socket");
+ return (0);
}
- return 0;
-}
+ server.sin_family = AF_INET;
+ server.sin_addr.s_addr = INADDR_ANY;
-static void tcpreceive_free(t_tcpreceive *x)
-{ /* is this ever called? */
- if (x->x_connectsocket >= 0)
+ /* 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_rmpollfn(x->x_connectsocket);
- sys_closesocket(x->x_connectsocket);
+ sys_sockerror("tcpreceive: bind");
+ sys_closesocket(sockfd);
+ return (0);
}
- tcpreceive_closeall(x);
+ 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;
+ x->x_connection[i].port = 0;
+ }
+ for (i = 0; i < 5; ++i)
+ {
+ SETFLOAT(x->x_addrbytes+i, 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;
+
+ return (x);
}
+
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);
+ 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/tcpsend.c b/tcpsend.c
index b576eae..98ac620 100644
--- a/tcpsend.c
+++ b/tcpsend.c
@@ -1,254 +1,156 @@
-/* tcpsend.c 20060424 Martin Peach did it based on x_net.c. x_net.c header follows: */
-/* Copyright (c) 1997-1999 Miller Puckette.
-* For information on usage and redistribution, and for a DISCLAIMER OF ALL
-* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
-
-/* network */
-
-#include "m_pd.h"
-#include "s_stuff.h"
-#include <stdio.h>
+/* tcpsend.c
+ * copyright (c) 2010 IOhannes m zmlnig, IEM
+ * copyright (c) 2006-2010 Martin Peach
+ * copyright (c) Miller Puckette
+ */
+
+/* */
+/* A client for unidirectional communication from within Pd. */
+/* */
+/* This program is free software; you can redistribute it and/or */
+/* modify it under the terms of the GNU General Public License */
+/* as published by the Free Software Foundation; either version 2 */
+/* of the License, or (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
+/* GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program; if not, write to the Free Software */
+/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* */
+
+
+#include "iemnet.h"
#include <string.h>
-#ifdef _WIN32
-#include <winsock2.h>
-#else
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <netdb.h>
+#ifndef _WIN32
+# include <netinet/tcp.h>
#endif
+
static t_class *tcpsend_class;
typedef struct _tcpsend
{
- t_object x_obj;
- int x_fd;
+ t_object x_obj;
+ int x_fd;
+ t_iemnet_sender*x_sender;
} t_tcpsend;
-void tcpsend_setup(void);
-static void tcpsend_free(t_tcpsend *x);
-static void tcpsend_send(t_tcpsend *x, t_symbol *s, int argc, t_atom *argv);
-static void tcpsend_disconnect(t_tcpsend *x);
-static void tcpsend_connect(t_tcpsend *x, t_symbol *hostname, t_floatarg fportno);
-static void *tcpsend_new(void);
-
-static void *tcpsend_new(void)
+static void tcpsend_disconnect(t_tcpsend *x)
{
- t_tcpsend *x = (t_tcpsend *)pd_new(tcpsend_class);
- outlet_new(&x->x_obj, &s_float);
- x->x_fd = -1;
- return (x);
+ if (x->x_fd >= 0)
+ {
+ if(x->x_sender)iemnet__sender_destroy(x->x_sender); x->x_sender=NULL;
+ sys_closesocket(x->x_fd);
+ x->x_fd = -1;
+ outlet_float(x->x_obj.ob_outlet, 0);
+ post("tcpsend: disconnected");
+ }
}
+
+
static void tcpsend_connect(t_tcpsend *x, t_symbol *hostname,
- t_floatarg fportno)
+ t_floatarg fportno)
{
- struct sockaddr_in server;
- struct hostent *hp;
- int sockfd;
- int portno = fportno;
- int intarg;
+ struct sockaddr_in server;
+ struct hostent *hp;
+ int sockfd;
+ int portno = fportno;
+ int intarg;
- if (x->x_fd >= 0)
+ if (x->x_fd >= 0)
{
- error("tcpsend: already connected");
- return;
+ error("tcpsend: already connected");
+ return;
}
- /* create a socket */
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ /* create a socket */
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
#ifdef DEBUG
- fprintf(stderr, "tcpsend_connect: send socket %d\n", sockfd);
+ fprintf(stderr, "tcpsend_connect: send socket %d\n", sockfd);
#endif
- if (sockfd < 0)
+ if (sockfd < 0)
{
- sys_sockerror("tcpsend: socket");
- return;
+ sys_sockerror("tcpsend: socket");
+ return;
}
- /* connect socket using hostname provided in command line */
- server.sin_family = AF_INET;
- hp = gethostbyname(hostname->s_name);
- if (hp == 0)
+ /* connect socket using hostname provided in command line */
+ server.sin_family = AF_INET;
+ hp = gethostbyname(hostname->s_name);
+ if (hp == 0)
{
- post("tcpsend: bad host?\n");
- return;
+ post("tcpsend: bad host?\n");
+ return;
}
- /* for stream (TCP) sockets, specify "nodelay" */
- intarg = 1;
- if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
- (char *)&intarg, sizeof(intarg)) < 0)
- post("tcpsend: setsockopt (TCP_NODELAY) failed\n");
+ /* for stream (TCP) sockets, specify "nodelay" */
+ intarg = 1;
+ if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&intarg, sizeof(intarg)) < 0)
+ post("tcpsend: setsockopt (TCP_NODELAY) failed\n");
- memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
+ memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
- /* assign client port number */
- server.sin_port = htons((u_short)portno);
+ /* assign client port number */
+ server.sin_port = htons((u_short)portno);
- post("tcpsend: connecting to port %d", portno);
- /* try to connect. */
- if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
+ post("tcpsend: connecting to port %d", portno);
+ /* try to connect. */
+ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
{
- sys_sockerror("tcpsend: connecting stream socket");
- sys_closesocket(sockfd);
- return;
+ sys_sockerror("tcpsend: connecting stream socket");
+ sys_closesocket(sockfd);
+ return;
}
- x->x_fd = sockfd;
- outlet_float(x->x_obj.ob_outlet, 1);
-}
+ x->x_fd = sockfd;
-static void tcpsend_disconnect(t_tcpsend *x)
-{
- if (x->x_fd >= 0)
- {
- sys_closesocket(x->x_fd);
- x->x_fd = -1;
- outlet_float(x->x_obj.ob_outlet, 0);
- post("tcpsend: disconnected");
- }
+ x->x_sender=iemnet__sender_create(sockfd);
+
+ outlet_float(x->x_obj.ob_outlet, 1);
}
static void tcpsend_send(t_tcpsend *x, t_symbol *s, int argc, t_atom *argv)
{
-#define BYTE_BUF_LEN 65536 // arbitrary maximum similar to max IP packet size
- static char byte_buf[BYTE_BUF_LEN];
- int i, j;
- unsigned int d;
- unsigned char c;
- float f, e;
- char *bp;
- int length, sent;
- int result;
- static double lastwarntime;
- static double pleasewarn;
- double timebefore;
- double timeafter;
- int late;
- char fpath[FILENAME_MAX];
- FILE *fptr;
-
-#ifdef DEBUG
- post("s: %s", s->s_name);
- post("argc: %d", argc);
-#endif
- for (i = j = 0; i < argc; ++i)
- {
- if (argv[i].a_type == A_FLOAT)
- {
- f = argv[i].a_w.w_float;
- d = (unsigned int)f;
- e = f - d;
- if (e != 0)
- {
- error("tcpsend_send: item %d (%f) is not an integer", i, f);
- return;
- }
- c = (unsigned char)d;
- if (c != d)
- {
- error("tcpsend_send: item %d (%f) is not between 0 and 255", i, f);
- return;
- }
-#ifdef DEBUG
- post("tcpsend_send: argv[%d]: %d", i, c);
-#endif
- byte_buf[j++] = c;
- }
- else if (argv[i].a_type == A_SYMBOL)
- {
-
- atom_string(&argv[i], fpath, FILENAME_MAX);
-#ifdef DEBUG
- post ("tcpsend fname: %s", fpath);
-#endif
- fptr = fopen(fpath, "rb");
- if (fptr == NULL)
- {
- post("tcpsend: unable to open \"%s\"", fpath);
- return;
- }
- rewind(fptr);
-#ifdef DEBUG
- post("tcpsend: d is %d", d);
-#endif
- while ((d = fgetc(fptr)) != EOF)
- {
- byte_buf[j++] = (char)(d & 0x0FF);
-#ifdef DEBUG
- post("tcpsend: byte_buf[%d] = %d", j-1, byte_buf[j-1]);
-#endif
- if (j >= BYTE_BUF_LEN)
- {
- post ("tcpsend: file too long, truncating at %lu", BYTE_BUF_LEN);
- break;
- }
- }
- fclose(fptr);
- fptr = NULL;
- post("tcpsend: read \"%s\" length %d byte%s", fpath, j, ((d==1)?"":"s"));
- }
- else
- {
- error("tcpsend_send: item %d is not a float or a file name", i);
- return;
- }
- }
-
- length = j;
- if ((x->x_fd >= 0) && (length > 0))
- {
- for (bp = byte_buf, sent = 0; sent < length;)
- {
- timebefore = sys_getrealtime();
- result = send(x->x_fd, byte_buf, length-sent, 0);
- timeafter = sys_getrealtime();
- late = (timeafter - timebefore > 0.005);
- if (late || pleasewarn)
- {
- if (timeafter > lastwarntime + 2)
- {
- post("tcpsend blocked %d msec",
- (int)(1000 * ((timeafter - timebefore) + pleasewarn)));
- pleasewarn = 0;
- lastwarntime = timeafter;
- }
- else if (late) pleasewarn += timeafter - timebefore;
- }
- if (result <= 0)
- {
- sys_sockerror("tcpsend");
- tcpsend_disconnect(x);
- break;
- }
- else
- {
- sent += result;
- bp += result;
- }
- }
- }
- else error("tcpsend: not connected");
+ int size=0;
+ t_iemnet_sender*sender=x->x_sender;
+ t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv);
+ if(sender && chunk) {
+ size=iemnet__sender_send(sender, chunk);
+ }
+ iemnet__chunk_destroy(chunk);
}
static void tcpsend_free(t_tcpsend *x)
{
- tcpsend_disconnect(x);
+ tcpsend_disconnect(x);
+}
+
+static void *tcpsend_new(void)
+{
+ t_tcpsend *x = (t_tcpsend *)pd_new(tcpsend_class);
+ outlet_new(&x->x_obj, &s_float);
+ x->x_fd = -1;
+ return (x);
}
void tcpsend_setup(void)
{
- tcpsend_class = class_new(gensym("tcpsend"), (t_newmethod)tcpsend_new,
- (t_method)tcpsend_free,
- sizeof(t_tcpsend), 0, 0);
- class_addmethod(tcpsend_class, (t_method)tcpsend_connect,
- gensym("connect"), A_SYMBOL, A_FLOAT, 0);
- class_addmethod(tcpsend_class, (t_method)tcpsend_disconnect,
- gensym("disconnect"), 0);
- class_addmethod(tcpsend_class, (t_method)tcpsend_send, gensym("send"),
- A_GIMME, 0);
- class_addlist(tcpsend_class, (t_method)tcpsend_send);
+ tcpsend_class = class_new(gensym("tcpsend"),
+ (t_newmethod)tcpsend_new, (t_method)tcpsend_free,
+ sizeof(t_tcpsend),
+ 0, 0);
+
+ class_addmethod(tcpsend_class, (t_method)tcpsend_connect,
+ gensym("connect"), A_SYMBOL, A_FLOAT, 0);
+ class_addmethod(tcpsend_class, (t_method)tcpsend_disconnect,
+ gensym("disconnect"), 0);
+ class_addmethod(tcpsend_class, (t_method)tcpsend_send, gensym("send"),
+ A_GIMME, 0);
+ class_addlist(tcpsend_class, (t_method)tcpsend_send);
}
/* end tcpsend.c */
diff --git a/tcpserver.c b/tcpserver.c
index e84eb10..8e99eb7 100644
--- a/tcpserver.c
+++ b/tcpserver.c
@@ -27,12 +27,8 @@
//#define DEBUG
#include "iemnet.h"
-#include "s_stuff.h"
-
-#if defined(UNIX) || defined(unix)
+#ifndef _WIN32
# include <arpa/inet.h>
-#else
-# include <winsock2.h>
#endif
@@ -45,6 +41,8 @@ static char objName[] = "tcpserver";
typedef struct _tcpserver_socketreceiver
{
+ struct _tcpserver *sr_owner;
+
t_symbol *sr_host;
t_int sr_fd;
t_iemnet_sender*sr_sender;
@@ -66,20 +64,22 @@ typedef struct _tcpserver
t_atom x_addrbytes[4];
} t_tcpserver;
-static void tcpserver_receive_callback(t_tcpserver *x, int sockfd, int argc, t_atom*argv);
+static void tcpserver_receive_callback(t_tcpserver_socketreceiver*x, int argc, t_atom*argv);
-static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new(void *owner, int sockfd, t_symbol*host)
+static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new(t_tcpserver *owner, int sockfd, t_symbol*host)
{
t_tcpserver_socketreceiver *x = (t_tcpserver_socketreceiver *)getbytes(sizeof(*x));
if(NULL==x) {
error("%s_socketreceiver: unable to allocate %d bytes", objName, sizeof(*x));
return NULL;
} else {
- x->sr_host=host;
- x->sr_fd=sockfd;
+ x->sr_owner=owner;
+
+ x->sr_host=host;
+ x->sr_fd=sockfd;
- x->sr_sender=iemnet__sender_create(sockfd);
- x->sr_receiver=iemnet__receiver_create(sockfd, owner, (t_iemnet_receivecallback)tcpserver_receive_callback);
+ x->sr_sender=iemnet__sender_create(sockfd);
+ x->sr_receiver=iemnet__receiver_create(sockfd, x, (t_iemnet_receivecallback)tcpserver_receive_callback);
}
return (x);
}
@@ -93,6 +93,11 @@ static void tcpserver_socketreceiver_free(t_tcpserver_socketreceiver *x)
sys_closesocket(x->sr_fd);
+ x->sr_owner=NULL;
+ x->sr_sender=NULL;
+ x->sr_receiver=NULL;
+ x->sr_fd=-1;
+
freebytes(x, sizeof(*x));
}
}
@@ -294,16 +299,16 @@ static void tcpserver_disconnect_all(t_tcpserver *x)
}
}
-
-
-
-
/* ---------------- main tcpserver (receive) stuff --------------------- */
-static void tcpserver_receive_callback(t_tcpserver *x, int sockfd, int argc, t_atom*argv) {
- if(argc) {
+static void tcpserver_receive_callback(t_tcpserver_socketreceiver *y, int argc, t_atom*argv) {
+ t_tcpserver*x=NULL;
+ if(NULL==y || NULL==(x=y->sr_owner))return;
+
+ if(argc) {
outlet_list(x->x_msgout, gensym("list"), argc, argv);
} else {
// disconnected
+ int sockfd=y->sr_fd;
tcpserver_disconnect_socket(x, sockfd);
}