aboutsummaryrefslogtreecommitdiff
path: root/udpreceive.c
diff options
context:
space:
mode:
authorIOhannes m zmölnig <zmoelnig@users.sourceforge.net>2015-08-31 22:11:51 +0000
committerIOhannes m zmölnig <zmoelnig@users.sourceforge.net>2015-08-31 22:11:51 +0000
commitc5e0079ae1323ad4c35d28f83ce732bb3820c46a (patch)
tree9768e681d9f4905cd04f4a3e4b84a6865a2454b3 /udpreceive.c
parent623fb91ea95294c80ad9748e8959cb7d86568143 (diff)
un-threaded receive
svn path=/trunk/externals/iem/iemnet/; revision=17543
Diffstat (limited to 'udpreceive.c')
-rw-r--r--udpreceive.c180
1 files changed, 122 insertions, 58 deletions
diff --git a/udpreceive.c b/udpreceive.c
index e2a1c30..5fc092e 100644
--- a/udpreceive.c
+++ b/udpreceive.c
@@ -1,5 +1,5 @@
/* udpreceive.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) Miller Puckette
*/
@@ -18,22 +18,21 @@
/* 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/ */
#define DEBUGLEVEL 1
static const char objName[] = "udpreceive";
#include "iemnet.h"
+#include <string.h>
/* ----------------------------- udpreceive ------------------------- */
static t_class *udpreceive_class;
-typedef struct _udpreceive
-{
+typedef struct _udpreceive {
t_object x_obj;
t_outlet *x_msgout;
t_outlet *x_addrout;
@@ -42,80 +41,84 @@ typedef struct _udpreceive
int x_connectsocket;
int x_port;
t_iemnet_receiver*x_receiver;
- t_iemnet_floatlist *x_floatlist;
+ t_iemnet_floatlist *x_floatlist;
+
+ int x_reuseport, x_reuseaddr;
} t_udpreceive;
-static void udpreceive_read_callback(void*y, t_iemnet_chunk*c) {
+static void udpreceive_read_callback(void*y, t_iemnet_chunk*c)
+{
t_udpreceive*x=(t_udpreceive*)y;
if(c) {
iemnet__addrout(x->x_statout, x->x_addrout, c->addr, c->port);
- x->x_floatlist=iemnet__chunk2list(c, x->x_floatlist); // gets destroyed in the dtor
- outlet_list(x->x_msgout, gensym("list"), x->x_floatlist->argc, x->x_floatlist->argv);
+ x->x_floatlist=iemnet__chunk2list(c,
+ x->x_floatlist); // gets destroyed in the dtor
+ outlet_list(x->x_msgout, gensym("list"), x->x_floatlist->argc,
+ x->x_floatlist->argv);
} else {
post("[%s] nothing received", objName);
}
}
-static void udpreceive_port(t_udpreceive*x, t_floatarg fportno)
+static int udpreceive_setport(t_udpreceive*x, unsigned short portno)
{
- static t_atom ap[1];
- int portno = fportno;
struct sockaddr_in server;
socklen_t serversize=sizeof(server);
int sockfd = x->x_connectsocket;
int intarg;
+ memset(&server, 0, sizeof(server));
- SETFLOAT(ap, -1);
if(x->x_port == portno) {
- return;
+ return 1;
}
/* cleanup any open ports */
if(sockfd>=0) {
- iemnet__receiver_destroy(x->x_receiver);
+ iemnet__receiver_destroy(x->x_receiver, 0);
x->x_connectsocket=-1;
x->x_port=-1;
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd<0) {
- error("[%s]: unable to create socket", objName);
- return;
+ pd_error(x, "[%s]: unable to create socket", objName);
+ return 0;
}
/* ask OS to allow another Pd to reopen this port after we close it. */
#ifdef SO_REUSEADDR
- intarg = 1;
- if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
- (char *)&intarg, sizeof(intarg))
- < 0) {
- error("[%s]: setsockopt (SO_REUSEADDR) failed", objName);
+ if(x->x_reuseaddr) {
+ intarg = 1;
+ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
+ (void *)&intarg, sizeof(intarg))
+ < 0) {
+ pd_error(x, "[%s]: setsockopt (SO_REUSEADDR) failed", objName);
+ }
}
#endif /* SO_REUSEADDR */
#ifdef SO_REUSEPORT
- intarg = 1;
- if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT,
- (char *)&intarg, sizeof(intarg))
- < 0) {
- error("[%s]: setsockopt (SO_REUSEPORT) failed", objName);
+ if(x->x_reuseport) {
+ intarg = 1;
+ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT,
+ (void *)&intarg, sizeof(intarg))
+ < 0) {
+ pd_error(x, "[%s]: setsockopt (SO_REUSEPORT) failed", objName);
+ }
}
#endif /* SO_REUSEPORT */
-
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons((u_short)portno);
/* name the socket */
- if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0)
- {
- sys_sockerror("[udpreceive] bind failed");
- sys_closesocket(sockfd);
- sockfd = -1;
- outlet_anything(x->x_statout, gensym("port"), 1, ap);
- return;
- }
+ if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0) {
+ sys_sockerror("[udpreceive] bind failed");
+ iemnet__closesocket(sockfd);
+ sockfd = -1;
+ return 0;
+ }
x->x_connectsocket = sockfd;
x->x_port = portno;
@@ -126,54 +129,115 @@ static void udpreceive_port(t_udpreceive*x, t_floatarg fportno)
}
x->x_receiver=iemnet__receiver_create(sockfd,
- x,
- udpreceive_read_callback);
+ x,
+ udpreceive_read_callback,
+ 0);
+ return 1;
+}
+
+static void udpreceive_port(t_udpreceive*x, t_symbol*s, int argc,
+ t_atom*argv)
+{
+ t_atom ap[1];
+ if(argc) {
+ if(argc>1 || A_FLOAT != argv->a_type) {
+ pd_error(x, "[%s] usage: port [<portnum>]", objName);
+ return;
+ }
+ SETFLOAT(ap, -1);
+ if(!udpreceive_setport(x, atom_getint(argv))) {
+ outlet_anything(x->x_statout, gensym("port"), 1, ap);
+ }
+ }
SETFLOAT(ap, x->x_port);
outlet_anything(x->x_statout, gensym("port"), 1, ap);
}
+static void udpreceive_optionI(t_udpreceive*x, t_symbol*s, int argc,
+ t_atom*argv)
+{
+ int*reuse=NULL;
+ if(gensym("reuseport")==s) {
+ reuse=&x->x_reuseport;
+ }
+ if(gensym("reuseaddr")==s) {
+ reuse=&x->x_reuseaddr;
+ }
+
+ if(!reuse) {
+ pd_error(x, "[%s]: unknown option '%s'", objName, s->s_name);
+ return;
+ }
+ if(argc) {
+ if(1==argc && A_FLOAT == argv->a_type) {
+ *reuse=atom_getint(argv);
+ return;
+ } else {
+ pd_error(x, "[%s] usage: %s [<val>]", objName, s->s_name);
+ return;
+ }
+ } else {
+ t_atom ap[1];
+ SETFLOAT(ap, *reuse);
+ outlet_anything(x->x_statout, s, 1, ap);
+ }
+}
static void *udpreceive_new(t_floatarg fportno)
{
- t_udpreceive*x = (t_udpreceive *)pd_new(udpreceive_class);
+ t_udpreceive*x = (t_udpreceive *)pd_new(udpreceive_class);
+
+ x->x_msgout = outlet_new(&x->x_obj, 0);
+ x->x_addrout = outlet_new(&x->x_obj, gensym("list"));
+ x->x_statout = outlet_new(&x->x_obj, 0);
- x->x_msgout = outlet_new(&x->x_obj, 0);
- x->x_addrout = outlet_new(&x->x_obj, gensym("list"));
- x->x_statout = outlet_new(&x->x_obj, 0);
+ x->x_connectsocket = -1;
+ x->x_port = -1;
+ x->x_receiver = NULL;
- x->x_connectsocket = -1;
- x->x_port = -1;
- x->x_receiver = NULL;
+ x->x_reuseaddr = 1;
+ x->x_reuseport = 0;
- x->x_floatlist=iemnet__floatlist_create(1024);
+ x->x_floatlist=iemnet__floatlist_create(1024);
- udpreceive_port(x, fportno);
+ udpreceive_setport(x, fportno);
- return (x);
+ return (x);
}
static void udpreceive_free(t_udpreceive *x)
{
- iemnet__receiver_destroy(x->x_receiver);
+ iemnet__receiver_destroy(x->x_receiver, 0);
x->x_connectsocket=0;
outlet_free(x->x_msgout);
outlet_free(x->x_addrout);
outlet_free(x->x_statout);
- if(x->x_floatlist)iemnet__floatlist_destroy(x->x_floatlist);x->x_floatlist=NULL;
+ if(x->x_floatlist) {
+ iemnet__floatlist_destroy(x->x_floatlist);
+ }
+ x->x_floatlist=NULL;
}
IEMNET_EXTERN void udpreceive_setup(void)
{
- if(!iemnet__register(objName))return;
- udpreceive_class = class_new(gensym(objName),
- (t_newmethod)udpreceive_new, (t_method)udpreceive_free,
- sizeof(t_udpreceive), 0, A_DEFFLOAT, 0);
-
- class_addmethod(udpreceive_class, (t_method)udpreceive_port,
- gensym("port"), A_DEFFLOAT, 0);
+ if(!iemnet__register(objName)) {
+ return;
+ }
+ udpreceive_class = class_new(gensym(objName),
+ (t_newmethod)udpreceive_new, (t_method)udpreceive_free,
+ sizeof(t_udpreceive), 0, A_DEFFLOAT, 0);
+
+ class_addmethod(udpreceive_class, (t_method)udpreceive_port,
+ gensym("port"), A_GIMME, 0);
+
+ /* options for opening new sockets */
+ class_addmethod(udpreceive_class, (t_method)udpreceive_optionI,
+ gensym("reuseaddr"), A_GIMME, 0);
+ class_addmethod(udpreceive_class, (t_method)udpreceive_optionI,
+ gensym("reuseport"), A_GIMME, 0);
DEBUGMETHOD(udpreceive_class);
}