aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIOhannes m zmölnig <zmoelnig@users.sourceforge.net>2015-09-01 14:30:10 +0000
committerIOhannes m zmölnig <zmoelnig@users.sourceforge.net>2015-09-01 14:30:10 +0000
commitf628926f7ff2d494667bc14bc5d0cbcba02de5db (patch)
treeaaacb3d74b256d2fd4f736e7bedab1529c340303
parentc5e0079ae1323ad4c35d28f83ce732bb3820c46a (diff)
allow setting of local port
svn path=/trunk/externals/iem/iemnet/; revision=17544
-rw-r--r--udpclient-help.pd71
-rw-r--r--udpclient.c156
2 files changed, 103 insertions, 124 deletions
diff --git a/udpclient-help.pd b/udpclient-help.pd
index 18e6d3c..6cf60a6 100644
--- a/udpclient-help.pd
+++ b/udpclient-help.pd
@@ -1,35 +1,35 @@
-#N canvas 0 34 988 533 12;
-#X msg 96 97 disconnect;
-#X floatatom 255 351 3 0 0 0 - - -;
-#X floatatom 284 351 3 0 0 0 - - -;
-#X floatatom 311 351 3 0 0 0 - - -;
-#X floatatom 336 351 3 0 0 0 - - -;
+#N canvas 4 49 1100 592 12;
+#X msg 116 117 disconnect;
+#X floatatom 255 351 3 0 0 0 - - -, f 3;
+#X floatatom 284 351 3 0 0 0 - - -, f 3;
+#X floatatom 311 351 3 0 0 0 - - -, f 3;
+#X floatatom 336 351 3 0 0 0 - - -, f 3;
#X text 219 351 from;
#X obj 275 307 tgl 15 0 empty empty connected 18 7 0 8 -24198 -241291
--1 1 1;
-#X text 187 21 connect with an IP address and port number;
+-1 0 1;
+#X text 197 21 connect with an IP address and port number;
#X text 44 257 See also:;
#X msg 21 22 connect 127.0.0.1 9997;
-#X text 364 156 semicolon-terminated string for netserver or netreceive
+#X text 414 176 semicolon-terminated string for netserver or netreceive
;
-#X text 302 182 'send' prefix is optional;
+#X text 322 202 'send' prefix is optional;
#X obj 235 412 spigot;
#X obj 274 389 tgl 15 0 empty empty enable_print 18 7 0 8 -24198 -241291
--1 1 1;
-#X floatatom 772 190 9 0 0 0 - - -;
+-1 0 1;
+#X floatatom 872 280 9 0 0 0 - - -, f 9;
#X text 40 399 2010/03/01 Martin Peach;
-#X text 418 440 Attempting to print long messages can hang Pd!;
-#X obj 772 166 route sent;
-#X text 844 190 sent bytes;
-#X floatatom 772 347 3 0 0 0 - - -;
-#X floatatom 826 347 3 0 0 0 - - -;
-#X floatatom 799 347 3 0 0 0 - - -;
-#X obj 772 268 route address;
-#X obj 772 296 unpack f f f f f;
-#X floatatom 853 347 3 0 0 0 - - -;
-#X floatatom 881 321 6 0 0 0 - - -;
-#X text 879 347 ip;
-#X text 927 320 port;
+#X text 438 440 Attempting to print long messages can hang Pd!;
+#X obj 872 256 route sent;
+#X text 944 280 sent bytes;
+#X floatatom 872 437 3 0 0 0 - - -, f 3;
+#X floatatom 926 437 3 0 0 0 - - -, f 3;
+#X floatatom 899 437 3 0 0 0 - - -, f 3;
+#X obj 872 358 route address;
+#X obj 872 386 unpack f f f f f;
+#X floatatom 953 437 3 0 0 0 - - -, f 3;
+#X floatatom 981 411 6 0 0 0 - - -, f 6;
+#X text 979 437 ip;
+#X text 1027 430 port;
#X obj 520 344 spigot;
#X obj 559 321 tgl 15 0 empty empty enable_print 18 7 0 8 -24198 -241291
-1 0 1;
@@ -43,21 +43,25 @@ net objects. all information is available via outlet#4 as well!;
#X obj 235 441 print udpclient:received;
#X obj 520 373 print udpclient:status;
#X obj 255 328 unpack f f f f f;
-#X floatatom 364 351 6 0 0 0 - - -;
-#X msg 128 129 send 47 116 101 115 116 32 104 101 108 108 111 10;
-#X msg 156 157 send 51 49 32 97 98 99 59 10;
-#X text 482 128 /test hello (OSC message);
-#X text 308 255 udpclient can be used for a bi-directional connection
+#X floatatom 364 351 6 0 0 0 - - -, f 6;
+#X msg 148 149 send 47 116 101 115 116 32 104 101 108 108 111 10;
+#X msg 176 177 send 51 49 32 97 98 99 59 10;
+#X text 552 148 /test hello (OSC message);
+#X text 312 255 udpclient can be used for a bi-directional connection
;
-#X msg 183 184 97 98 99 100 10;
+#X msg 203 204 97 98 99 100 10;
#X msg 47 48 connect swisstime.ethz.ch 13;
-#X text 527 14 udpclient can connect to a server and send and receive
+#X text 547 14 udpclient can connect to a server and send and receive
messages as lists of bytes. Any integer value between 0 and 255 can
be transmitted or received.;
#X obj 295 281 s \$0.udpclient.o4;
#X obj 520 298 r \$0.udpclient.o4;
-#X obj 772 142 r \$0.udpclient.o4;
-#X obj 772 242 r \$0.udpclient.o4;
+#X obj 872 232 r \$0.udpclient.o4;
+#X obj 872 332 r \$0.udpclient.o4;
+#X msg 74 75 connect 127.0.0.1 7999 7999;
+#X text 303 67 optional second argument to set the local port (where
+we receive the returning messages) \; default is to choose any available
+port.;
#X connect 0 0 35 0;
#X connect 9 0 35 0;
#X connect 12 0 36 0;
@@ -87,3 +91,4 @@ be transmitted or received.;
#X connect 48 0 28 0;
#X connect 49 0 17 0;
#X connect 50 0 22 0;
+#X connect 51 0 35 0;
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"),