aboutsummaryrefslogtreecommitdiff
path: root/udpclient.c
diff options
context:
space:
mode:
Diffstat (limited to 'udpclient.c')
-rw-r--r--udpclient.c156
1 files changed, 65 insertions, 91 deletions
diff --git a/udpclient.c b/udpclient.c
index b643fdc..d35dd3c 100644
--- a/udpclient.c
+++ b/udpclient.c
@@ -1,5 +1,5 @@
/* udpclient.c
- * copyright (c) 2010 IOhannes m zmölnig, IEM
+ * copyright © 2010-2015 IOhannes m zmölnig, IEM
*/
/* */
@@ -32,10 +32,8 @@
static t_class *udpclient_class;
static const char objName[] = "udpclient";
-
typedef struct _udpclient {
t_object x_obj;
- t_clock *x_clock;
t_outlet *x_msgout;
t_outlet *x_addrout;
t_outlet *x_connectout;
@@ -44,26 +42,21 @@ typedef struct _udpclient {
t_iemnet_sender*x_sender;
t_iemnet_receiver*x_receiver;
-
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
-
+ u_short x_port; // port we're sending to
+ u_short x_sendport; // port we're sending from
- /* multithread stuff */
- pthread_t x_threadid; /* id of child thread */
- pthread_attr_t x_threadattr; /* attributes of child thread */
+ long x_addr; // address we're connected to as 32bit int
t_iemnet_floatlist *x_floatlist;
} t_udpclient;
+/* forward declarations */
static void udpclient_receive_callback(void *x, t_iemnet_chunk*);
-
-
/* connection handling */
static void *udpclient_doconnect(t_udpclient*x, int subthread)
@@ -75,43 +68,55 @@ static void *udpclient_doconnect(t_udpclient*x, int subthread)
memset(&server, 0, sizeof(server));
if (x->x_sender) {
- error("[%s] already connected", objName);
+ iemnet_log(x, IEMNET_ERROR, "already connected");
return (x);
}
+ /* connect socket using hostname provided in command line */
+ hp = gethostbyname(x->x_hostname);
+ if (hp == 0) {
+ iemnet_log(x, IEMNET_ERROR, "bad host '%s'?", x->x_hostname);
+ return (x);
+ }
+ server.sin_family = AF_INET;
+
/* create a socket */
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
DEBUG("send socket %d\n", sockfd);
if (sockfd < 0) {
- sys_sockerror("udpclient: socket");
+ iemnet_log(x, IEMNET_ERROR, "unable to create socket");
+ sys_sockerror("socket");
return (x);
}
- /* Based on zmoelnig's patch 2221504:
- Enable sending of broadcast messages (if hostname is a broadcast address)*/
+ /* Enable sending of broadcast messages (if hostname is a broadcast address) */
#ifdef SO_BROADCAST
if( 0 != setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
(const void *)&broadcast, sizeof(broadcast))) {
- error("[%s] couldn't switch to broadcast mode", objName);
+ iemnet_log(x, IEMNET_ERROR, "unable to switch to broadcast mode");
+ sys_sockerror("setsockopt");
}
#endif /* SO_BROADCAST */
- /* connect socket using hostname provided in command line */
- server.sin_family = AF_INET;
- hp = gethostbyname(x->x_hostname);
- if (hp == 0) {
- error("[%s] bad host '%s'?", objName, x->x_hostname);
- return (x);
+ if(x->x_sendport>0) {
+ server.sin_family = AF_INET;
+ server.sin_port = htons(x->x_sendport);
+ server.sin_addr.s_addr = INADDR_ANY;
+ if (bind(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) {
+ iemnet_log(x, IEMNET_ERROR, "unable to bind with sending port %d (continuing with random port)", x->x_sendport);
+ sys_sockerror("bind");
+ }
}
- memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
+ /* try to connect. */
/* assign client port number */
- server.sin_port = htons((u_short)x->x_port);
+ memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
+ server.sin_port = htons(x->x_port);
+ DEBUG("connecting to %s:%d", x->x_hostname, x->x_port);
- DEBUG("connecting to port %d", x->x_port);
- /* try to connect. */
if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) {
- sys_sockerror("udpclient: connecting stream socket");
+ iemnet_log(x, IEMNET_ERROR, "unable to connect to stream socket");
+ sys_sockerror("connect");
iemnet__closesocket(sockfd);
return (x);
}
@@ -123,48 +128,41 @@ static void *udpclient_doconnect(t_udpclient*x, int subthread)
udpclient_receive_callback, subthread);
x->x_connectstate = 1;
-
- clock_delay(x->x_clock, 0);
- return (x);
-}
-static void *udpclient_child_connect(void *w)
-{
- t_udpclient *x = (t_udpclient*) w;
- udpclient_doconnect(x, 1);
- return x;
-}
-static void udpclient_tick(t_udpclient *x)
-{
outlet_float(x->x_connectout, 1);
+ return (x);
}
-
-static void udpclient_disconnect(t_udpclient *x)
+static int udpclient_do_disconnect(t_udpclient *x)
{
- if (x->x_fd >= 0) {
-
- DEBUG("disconnect %x %x", x->x_sender, x->x_receiver);
- if(x->x_receiver) {
- iemnet__receiver_destroy(x->x_receiver, 0);
- }
- x->x_receiver=NULL;
- if(x->x_sender) {
- iemnet__sender_destroy(x->x_sender, 0);
- }
- x->x_sender=NULL;
+ DEBUG("disconnect %x %x", x->x_sender, x->x_receiver);
+ if(x->x_receiver) {
+ iemnet__receiver_destroy(x->x_receiver, 0);
+ }
+ x->x_receiver=NULL;
+ if(x->x_sender) {
+ iemnet__sender_destroy(x->x_sender, 0);
+ }
+ x->x_sender=NULL;
- iemnet__closesocket(x->x_fd);
- x->x_fd = -1;
- x->x_connectstate = 0;
- outlet_float(x->x_connectout, 0);
+ x->x_connectstate = 0;
+ if (x->x_fd < 0) {
+ return 0;
+ }
+ iemnet__closesocket(x->x_fd);
+ x->x_fd = -1;
+ return 1;
+}
+static void udpclient_disconnect(t_udpclient *x) {
+ if(!udpclient_do_disconnect(x)) {
+ iemnet_log(x, IEMNET_ERROR, "not connected");
} else {
- pd_error(x, "[%s] not connected", objName);
+ outlet_float(x->x_connectout, 0);
}
}
-
static void udpclient_connect(t_udpclient *x, t_symbol *hostname,
- t_floatarg fportno)
+ t_floatarg fportno,
+ t_floatarg fsndportno)
{
if(x->x_fd>=0) {
udpclient_disconnect(x);
@@ -173,20 +171,12 @@ static void udpclient_connect(t_udpclient *x, t_symbol *hostname,
to the child thread that establishes the connection */
x->x_hostname = hostname->s_name;
x->x_port = fportno;
+ x->x_sendport = (fsndportno>0)?fsndportno:0;
x->x_connectstate = 0;
-#if 0
- /* start child thread */
- if(pthread_create(&x->x_threadid, &x->x_threadattr,
- udpclient_child_connect, x) < 0) {
- error("%s: could not create new thread", objName);
- }
-#else
udpclient_doconnect(x, 0);
-#endif
}
/* sending/receiving */
-
static void udpclient_send(t_udpclient *x, t_symbol *s, int argc,
t_atom *argv)
{
@@ -212,7 +202,7 @@ static void udpclient_receive_callback(void*y, t_iemnet_chunk*c)
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); // gets destroyed in the dtor
+ x->x_floatlist); /* gets destroyed in the dtor */
outlet_list(x->x_msgout, gensym("list"),x->x_floatlist->argc,
x->x_floatlist->argv);
} else {
@@ -229,12 +219,12 @@ static void udpclient_receive_callback(void*y, t_iemnet_chunk*c)
static void *udpclient_new(void)
{
t_udpclient *x = (t_udpclient *)pd_new(udpclient_class);
- x->x_msgout = outlet_new(&x->x_obj, 0); /* received data */
+ 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 */
+ gensym("float")); /* connection state */
x->x_statusout = outlet_new(&x->x_obj,
- 0);/* last outlet for everything else */
+ 0); /* last outlet for everything else */
x->x_fd = -1;
x->x_addr = 0L;
@@ -243,30 +233,14 @@ static void *udpclient_new(void)
x->x_sender=NULL;
x->x_receiver=NULL;
- x->x_clock = clock_new(x, (t_method)udpclient_tick);
-
x->x_floatlist=iemnet__floatlist_create(1024);
- /* prepare child thread */
- if(pthread_attr_init(&x->x_threadattr) < 0) {
- verbose(1, "[%s] warning: could not prepare child thread", objName);
- }
- if(pthread_attr_setdetachstate(&x->x_threadattr,
- PTHREAD_CREATE_DETACHED) < 0) {
- verbose(1, "[%s] warning: could not prepare child thread", objName);
- }
-
-
return (x);
}
static void udpclient_free(t_udpclient *x)
{
- udpclient_disconnect(x);
- if(x->x_clock) {
- clock_free(x->x_clock);
- }
- x->x_clock=NULL;
+ udpclient_do_disconnect(x);
if(x->x_floatlist) {
iemnet__floatlist_destroy(x->x_floatlist);
}
@@ -283,7 +257,7 @@ IEMNET_EXTERN void udpclient_setup(void)
sizeof(t_udpclient), 0, A_DEFFLOAT, 0);
class_addmethod(udpclient_class, (t_method)udpclient_connect,
gensym("connect")
- , A_SYMBOL, A_FLOAT, 0);
+ , A_SYMBOL, A_FLOAT, A_DEFFLOAT, 0);
class_addmethod(udpclient_class, (t_method)udpclient_disconnect,
gensym("disconnect"), 0);
class_addmethod(udpclient_class, (t_method)udpclient_send, gensym("send"),