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