aboutsummaryrefslogtreecommitdiff
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
parent623fb91ea95294c80ad9748e8959cb7d86568143 (diff)
un-threaded receive
svn path=/trunk/externals/iem/iemnet/; revision=17543
-rw-r--r--Makefile4
-rw-r--r--iemnet.c130
-rw-r--r--iemnet.h97
-rw-r--r--iemnet_data.c202
-rw-r--r--iemnet_data.h14
-rw-r--r--iemnet_notify.c120
-rw-r--r--iemnet_receiver.c265
-rw-r--r--iemnet_sender.c161
-rw-r--r--tcpclient.c254
-rw-r--r--tcpreceive.c225
-rw-r--r--tcpsend.c90
-rw-r--r--tcpserver.c553
-rw-r--r--tests/sequence/01_server.pd118
-rw-r--r--udpclient.c172
-rw-r--r--udpreceive.c180
-rw-r--r--udpsend.c87
-rw-r--r--udpserver.c479
17 files changed, 1691 insertions, 1460 deletions
diff --git a/Makefile b/Makefile
index 4bb04bc..41ec52d 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ LIBRARY_NAME = iemnet
# objects, the matching .tcl file too
SOURCES = tcpserver.c tcpclient.c tcpsend.c tcpreceive.c udpreceive.c udpsend.c udpclient.c udpserver.c
-SHARED_SOURCES = iemnet.c iemnet_data.c iemnet_receiver.c iemnet_sender.c iemnet_notify.c
+SHARED_SOURCES = iemnet.c iemnet_data.c iemnet_receiver.c iemnet_sender.c
SHARED_HEADERS = iemnet_data.h iemnet.h
# list all pd objects (i.e. myobject.pd) files here, and their helpfiles will
@@ -231,6 +231,8 @@ ifeq (MINGW,$(findstring MINGW,$(UNAME)))
DISTBINDIR=$(DISTDIR)-$(OS)
endif
+-include Makefile.local
+
# in case somebody manually set the HELPPATCHES above
HELPPATCHES ?= $(SOURCES:.c=-help.pd) $(PDOBJECTS:.pd=-help.pd)
diff --git a/iemnet.c b/iemnet.c
index 8f3ba53..2ad4d70 100644
--- a/iemnet.c
+++ b/iemnet.c
@@ -1,7 +1,7 @@
/* iemnet
* this file provides core infrastructure for the iemnet-objects
*
- * copyright (c) 2010-2011 IOhannes m zmölnig, IEM
+ * copyright (c) 2010-2011 IOhannes m zmölnig, IEM
*/
/* This program is free software; you can redistribute it and/or */
@@ -15,9 +15,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/ */
/* */
#define DEBUGLEVEL
@@ -27,16 +26,37 @@
#include <pthread.h>
+/* close a socket properly */
+void iemnet__closesocket(int sockfd)
+{
+ if(sockfd >=0) {
+#ifndef SHUT_RDWR
+# define SHUT_RDWR 2
+#endif
+ int how=SHUT_RDWR;
+ int err = shutdown(sockfd,
+ how); /* needed on linux, since the recv won't shutdown on sys_closesocket() alone */
+ if(err) {
+ perror("iemnet:socket-shutdown");
+ }
+ sys_closesocket(sockfd);
+ }
+}
+
-void iemnet__addrout(t_outlet*status_outlet, t_outlet*address_outlet,
- long address, unsigned short port) {
+/* various functions to send data to output in a uniform way */
+void iemnet__addrout(t_outlet*status_outlet, t_outlet*address_outlet,
+ long address, unsigned short port)
+{
static t_atom addr[5];
static int firsttime=1;
if(firsttime) {
int i=0;
- for(i=0; i<5; i++)SETFLOAT(addr+i, 0);
+ for(i=0; i<5; i++) {
+ SETFLOAT(addr+i, 0);
+ }
firsttime=0;
}
@@ -46,29 +66,48 @@ void iemnet__addrout(t_outlet*status_outlet, t_outlet*address_outlet,
addr[3].a_w.w_float = (address & 0x0FF);
addr[4].a_w.w_float = port;
- if(status_outlet )outlet_anything(status_outlet , gensym("address"), 5, addr);
- if(address_outlet)outlet_list (address_outlet, gensym("list" ), 5, addr);
+ if(status_outlet ) {
+ outlet_anything(status_outlet , gensym("address"), 5, addr);
+ }
+ if(address_outlet) {
+ outlet_list (address_outlet, gensym("list" ), 5, addr);
+ }
}
-void iemnet__numconnout(t_outlet*status_outlet, t_outlet*numcon_outlet, int numconnections) {
+void iemnet__numconnout(t_outlet*status_outlet, t_outlet*numcon_outlet,
+ int numconnections)
+{
t_atom atom[1];
SETFLOAT(atom, numconnections);
- if(status_outlet)outlet_anything(status_outlet , gensym("connections"), 1, atom);
- if(numcon_outlet)outlet_float (numcon_outlet, numconnections);
+ if(status_outlet) {
+ outlet_anything(status_outlet , gensym("connections"), 1, atom);
+ }
+ if(numcon_outlet) {
+ outlet_float (numcon_outlet, numconnections);
+ }
}
-void iemnet__socketout(t_outlet*status_outlet, t_outlet*socket_outlet, int socketfd) {
+void iemnet__socketout(t_outlet*status_outlet, t_outlet*socket_outlet,
+ int socketfd)
+{
t_atom atom[1];
SETFLOAT(atom, socketfd);
- if(status_outlet)outlet_anything(status_outlet , gensym("socket"), 1, atom);
- if(socket_outlet)outlet_float (socket_outlet, socketfd);
+ if(status_outlet) {
+ outlet_anything(status_outlet , gensym("socket"), 1, atom);
+ }
+ if(socket_outlet) {
+ outlet_float (socket_outlet, socketfd);
+ }
}
-void iemnet__streamout(t_outlet*outlet, int argc, t_atom*argv, int stream) {
- if(NULL==outlet)return;
+void iemnet__streamout(t_outlet*outlet, int argc, t_atom*argv, int stream)
+{
+ if(NULL==outlet) {
+ return;
+ }
if(stream) {
while(argc-->0) {
@@ -85,7 +124,8 @@ typedef struct _names {
struct _names*next;
} t_iemnet_names;
static t_iemnet_names*namelist=0;
-static int iemnet__nametaken(const char*namestring) {
+static int iemnet__nametaken(const char*namestring)
+{
t_symbol*name=gensym(namestring);
t_iemnet_names*curname=namelist;
t_iemnet_names*lastname=curname;
@@ -102,16 +142,20 @@ static int iemnet__nametaken(const char*namestring) {
curname->name=name;
curname->next=0;
- if(lastname)
+ if(lastname) {
lastname->next=curname;
- else
+ } else {
namelist=curname;
+ }
return 0;
}
-int iemnet__register(const char*name) {
- if(iemnet__nametaken(name))return 0;
+int iemnet__register(const char*name)
+{
+ if(iemnet__nametaken(name)) {
+ return 0;
+ }
post("iemnet - networking with Pd: [%s]", name);
#ifdef LIBRARY_VERSION
post(" version "LIBRARY_VERSION"");
@@ -140,46 +184,52 @@ void udpserver_setup(void);
static int iemnet_debuglevel_=0;
static pthread_mutex_t debug_mtx = PTHREAD_MUTEX_INITIALIZER;
-void iemnet_debuglevel(void*x, t_float f) {
+void iemnet_debuglevel(void*x, t_float f)
+{
static int firsttime=1;
#ifdef IEMNET_HAVE_DEBUG
int debuglevel=(int)f;
- pthread_mutex_lock(&debug_mtx);
+ pthread_mutex_lock(&debug_mtx);
iemnet_debuglevel_=debuglevel;
- pthread_mutex_unlock(&debug_mtx);
+ pthread_mutex_unlock(&debug_mtx);
post("iemnet: setting debuglevel to %d", debuglevel);
#else
- if(firsttime)post("iemnet compiled without debug!");
+ if(firsttime) {
+ post("iemnet compiled without debug!");
+ }
#endif
firsttime=0;
}
-int iemnet_debug(int debuglevel, const char*file, unsigned int line, const char*function) {
+int iemnet_debug(int debuglevel, const char*file, unsigned int line,
+ const char*function)
+{
#ifdef IEMNET_HAVE_DEBUG
int debuglevel_=0;
- pthread_mutex_lock(&debug_mtx);
+ pthread_mutex_lock(&debug_mtx);
debuglevel_=iemnet_debuglevel_;
- pthread_mutex_unlock(&debug_mtx);
+ pthread_mutex_unlock(&debug_mtx);
if(debuglevel_ & debuglevel) {
- startpost("[%s:%d#%d] ", function, line, debuglevel);
+ startpost("[%s[%d]:%s#%d] ", file, line, function, debuglevel);
return 1;
}
#endif
return 0;
}
-IEMNET_EXTERN void iemnet_setup(void) {
+IEMNET_EXTERN void iemnet_setup(void)
+{
#ifdef _MSC_VER
- tcpclient_setup();
- tcpreceive_setup();
- tcpsend_setup();
- tcpserver_setup();
-
- udpclient_setup();
- udpreceive_setup();
- udpsend_setup();
- udpserver_setup();
+ tcpclient_setup();
+ tcpreceive_setup();
+ tcpsend_setup();
+ tcpserver_setup();
+
+ udpclient_setup();
+ udpreceive_setup();
+ udpsend_setup();
+ udpserver_setup();
#endif
}
diff --git a/iemnet.h b/iemnet.h
index 60cefa5..614b286 100644
--- a/iemnet.h
+++ b/iemnet.h
@@ -2,7 +2,7 @@
* iemnet
* networking for Pd
*
- * (c) 2010 IOhannes m zmölnig
+ * (c) 2010 IOhannes m zmölnig
* Institute of Electronic Music and Acoustics (IEM)
* University of Music and Dramatic Arts (KUG), Graz, Austria
*
@@ -23,9 +23,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/ */
/* */
/* ---------------------------------------------------------------------------- */
@@ -67,27 +66,42 @@ typedef struct _iemnet_sender t_iemnet_sender;
EXTERN_STRUCT _iemnet_sender;
/**
+ * user provided send function
+ * (defaults to just using send)
+ * this function is guaranteed to be called with a valid 'chunk',
+ * and the 'userdata' and 'sockfd' provided at sender-creation
+ */
+typedef int (*t_iemnet_sendfunction)(const void*userdata, int sockfd,
+ t_iemnet_chunk*chunk);
+
+/**
* create a sender to a given socket
*
* \param sock a previously opened socket
+ * \param sendfun a send()-implementation (or NULL, to use the default send/sendto based implementation)
+ * \param userdata pointer to optional userdata to be passsed to `sendfun`
+ * \param bool indicating whether this function is called from a subthread (1) or the mainthread (0)
* \return pointer to a sender object
* \note the socket must be writeable
*/
-t_iemnet_sender*iemnet__sender_create(int sock);
+t_iemnet_sender*iemnet__sender_create(int sock,
+ t_iemnet_sendfunction sendfun, const void*userdata,
+ int);
/**
* destroy a sender to a given socket
* destroying a sender will free all resources of the sender
*
* \param pointer to a sender object to be destroyed
+ * \param bool indicating whether this function is called from a subthread (1) or the mainthread (0)
*
* \note it will also close() the socket
*/
-void iemnet__sender_destroy(t_iemnet_sender*);
+void iemnet__sender_destroy(t_iemnet_sender*, int);
/**
* send data over a socket
*
- * \param pointer to a sender object
+ * \param pointer to a sender object
* \param pointer to a chunk of data to be sent
* \return the current fill state of the send buffer
*
@@ -98,7 +112,7 @@ int iemnet__sender_send(t_iemnet_sender*, t_iemnet_chunk*);
/**
* query the fill state of the send buffer
*
- * \param pointer to a sender object
+ * \param pointer to a sender object
* \return the current fill state of the send buffer
*/
int iemnet__sender_getsize(t_iemnet_sender*);
@@ -114,9 +128,11 @@ EXTERN_STRUCT _iemnet_receiver;
/**
* callback function for receiving
* whenever data arrives at the socket, a callback will be called synchronously
+ * if rawdata is NULL, this signifies that the socket has been closed
*/
-typedef void (*t_iemnet_receivecallback)(void*userdata,
- t_iemnet_chunk*rawdata);
+typedef void (*t_iemnet_receivecallback)(void*userdata
+ , t_iemnet_chunk*rawdata
+ );
/**
* create a receiver object
@@ -126,61 +142,40 @@ typedef void (*t_iemnet_receivecallback)(void*userdata,
* \param sock the (readable) socket to receive from
* \param data user data to be passed to callback
* \param callback a callback function that is called on the caller's side
+ * \param subthread bool indicating whether this function is called from a subthread (1) or the mainthread (0)
*
* \note the callback will be scheduled in the caller's thread with clock_delay()
*/
-t_iemnet_receiver*iemnet__receiver_create(int sock, void*data, t_iemnet_receivecallback callback);
+t_iemnet_receiver*iemnet__receiver_create(int sock, void*data,
+ t_iemnet_receivecallback callback, int subthread);
/**
* destroy a receiver at a given socket
* destroying a receiver will free all resources of the receiver
*
* \param pointer to a receiver object to be destroyed
+ * \param bool indicating whether this function is called from a subthread (1) or the mainthread (0)
*
* \note it will also close() the socket
*/
-void iemnet__receiver_destroy(t_iemnet_receiver*);
+void iemnet__receiver_destroy(t_iemnet_receiver*, int subthread);
/**
* query the fill state of the receive buffer
*
- * \param pointer to a receiver object
+ * \param pointer to a receiver object
* \return the current fill state of the receive buffer
*/
int iemnet__receiver_getsize(t_iemnet_receiver*);
-/**
- * opaque data type used for a notification server
- */
-#define t_iemnet_notifier struct _iemnet_notifier
-EXTERN_STRUCT _iemnet_notifier;
-t_iemnet_notifier*iemnet__notify_create(void);
-void iemnet__notify_destroy(t_iemnet_notifier*x);
+/* convenience functions */
/**
- * opaque data type used for a notification client
- */
-#define t_iemnet_notify struct _iemnet_notify
-EXTERN_STRUCT _iemnet_notify;
-void iemnet__notify_remove(t_iemnet_notify*notify);
-/**
- * callback function from main thread on notification
- */
-typedef void (*t_iemnet_notifun)(void *data);
-/**
- * register a new notification callback with the 'notifier' server.
- * on success, returns a notification client to be passed to iemnet__notify()
- * on failure, returns NULL
- */
-t_iemnet_notify*iemnet__notify_add(t_iemnet_notifier*notifier, t_iemnet_notifun fun, void*data);
-/**
- * tell mainthread that something happened with 'notify' client
- * (will call the callback associated to 'notify' asap)
+ * properly close a socket fd
+ *
+ * \param sock socket to close
*/
-void iemnet__notify(t_iemnet_notify*notify);
-
-
-/* convenience functions */
+void iemnet__closesocket(int fd);
/**
* output the address (IP, port)
@@ -194,7 +189,8 @@ void iemnet__notify(t_iemnet_notify*notify);
*
* \note the address will be output as a 5 element list, with the 1st 4 elements denoting the quads of the IP address (as bytes) and the last element the port
*/
-void iemnet__addrout(t_outlet*status_outlet, t_outlet*address_outlet, long address, unsigned short port);
+void iemnet__addrout(t_outlet*status_outlet, t_outlet*address_outlet,
+ long address, unsigned short port);
/**
* output the socket we received data from
@@ -205,7 +201,8 @@ void iemnet__addrout(t_outlet*status_outlet, t_outlet*address_outlet, long addre
* \param socket_outlet outlet for sockets only
* \param sockfd the socket
*/
-void iemnet__socketout(t_outlet*status_outlet, t_outlet*socket_outlet, int sockfd);
+void iemnet__socketout(t_outlet*status_outlet, t_outlet*socket_outlet,
+ int sockfd);
/**
* output the number of connections
@@ -216,7 +213,8 @@ void iemnet__socketout(t_outlet*status_outlet, t_outlet*socket_outlet, int sockf
* \param address_outlet outlet for numconnections only
* \param numconnections the number of connections
*/
-void iemnet__numconnout(t_outlet*status_outlet, t_outlet*numconn_outlet, int numconnections);
+void iemnet__numconnout(t_outlet*status_outlet, t_outlet*numconn_outlet,
+ int numconnections);
/**
* output a list as a stream (serialize)
@@ -275,7 +273,8 @@ int iemnet__register(const char*name);
#endif
void iemnet_debuglevel(void*,t_float);
-int iemnet_debug(int debuglevel, const char*file, unsigned int line, const char*function);
+int iemnet_debug(int debuglevel, const char*file, unsigned int line,
+ const char*function);
#define DEBUGMETHOD(c) class_addmethod(c, (t_method)iemnet_debuglevel, gensym("debug"), A_FLOAT, 0)
@@ -284,9 +283,13 @@ int iemnet_debug(int debuglevel, const char*file, unsigned int line, const char*
# undef DEBUG
# define DEBUG if(iemnet_debug(DEBUGLEVEL, __FILE__, __LINE__, __FUNCTION__))post
#else
-static void debug_dummy(const char *format, ...) {;}
+static void debug_dummy(const char *format, ...)
+{
+ ;
+}
# define DEBUG debug_dummy
#endif
+#define MARK() post("%s:%d [%s]", __FILE__, __LINE__, __FUNCTION__)
#endif /* INCLUDE_IEMNET_H_ */
diff --git a/iemnet_data.c b/iemnet_data.c
index 965a326..f0dea5f 100644
--- a/iemnet_data.c
+++ b/iemnet_data.c
@@ -4,7 +4,7 @@
* - wrappers for data "chunks"
* - queues
*
- * copyright (c) 2010 IOhannes m zmölnig, IEM
+ * copyright (c) 2010 IOhannes m zmölnig, IEM
*/
/* This program is free software; you can redistribute it and/or */
@@ -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/ */
/* */
#define DEBUGLEVEL 8
@@ -44,18 +43,27 @@
/* data handling */
-t_iemnet_floatlist*iemnet__floatlist_init(t_iemnet_floatlist*cl) {
+t_iemnet_floatlist*iemnet__floatlist_init(t_iemnet_floatlist*cl)
+{
unsigned int i;
- if(NULL==cl)return NULL;
- for(i=0; i<cl->size; i++)
+ if(NULL==cl) {
+ return NULL;
+ }
+ for(i=0; i<cl->size; i++) {
SETFLOAT((cl->argv+i), 0.f);
+ }
return cl;
}
-void iemnet__floatlist_destroy(t_iemnet_floatlist*cl) {
- if(NULL==cl)return;
- if(cl->argv) free(cl->argv);
+void iemnet__floatlist_destroy(t_iemnet_floatlist*cl)
+{
+ if(NULL==cl) {
+ return;
+ }
+ if(cl->argv) {
+ free(cl->argv);
+ }
cl->argv=NULL;
cl->argc=0;
cl->size=0;
@@ -63,9 +71,13 @@ void iemnet__floatlist_destroy(t_iemnet_floatlist*cl) {
free(cl);
}
-t_iemnet_floatlist*iemnet__floatlist_create(unsigned int size) {
- t_iemnet_floatlist*result=(t_iemnet_floatlist*)malloc(sizeof(t_iemnet_floatlist));
- if(NULL==result)return NULL;
+t_iemnet_floatlist*iemnet__floatlist_create(unsigned int size)
+{
+ t_iemnet_floatlist*result=(t_iemnet_floatlist*)malloc(sizeof(
+ t_iemnet_floatlist));
+ if(NULL==result) {
+ return NULL;
+ }
result->argv = (t_atom*)malloc(size*sizeof(t_atom));
if(NULL==result->argv) {
@@ -81,7 +93,9 @@ t_iemnet_floatlist*iemnet__floatlist_create(unsigned int size) {
return result;
}
-t_iemnet_floatlist*iemnet__floatlist_resize(t_iemnet_floatlist*cl, unsigned int size) {
+t_iemnet_floatlist*iemnet__floatlist_resize(t_iemnet_floatlist*cl,
+ unsigned int size)
+{
t_atom*tmp;
if (NULL==cl) {
return iemnet__floatlist_create(size);
@@ -93,7 +107,9 @@ t_iemnet_floatlist*iemnet__floatlist_resize(t_iemnet_floatlist*cl, unsigned int
}
tmp=(t_atom*)malloc(size*sizeof(t_atom));
- if(NULL==tmp) return NULL;
+ if(NULL==tmp) {
+ return NULL;
+ }
free(cl->argv);
@@ -105,10 +121,15 @@ t_iemnet_floatlist*iemnet__floatlist_resize(t_iemnet_floatlist*cl, unsigned int
return cl;
}
-void iemnet__chunk_destroy(t_iemnet_chunk*c) {
- if(NULL==c)return;
+void iemnet__chunk_destroy(t_iemnet_chunk*c)
+{
+ if(NULL==c) {
+ return;
+ }
- if(c->data)free(c->data);
+ if(c->data) {
+ free(c->data);
+ }
c->data=NULL;
c->size=0;
@@ -117,17 +138,26 @@ void iemnet__chunk_destroy(t_iemnet_chunk*c) {
}
-void iemnet__chunk_print(t_iemnet_chunk*c) {
+void iemnet__chunk_print(t_iemnet_chunk*c)
+{
unsigned int i=0;
startpost("chunk[%p:%d]", c, c?c->size:0);
- if(!c)return;
- for(i=0; i<c->size; i++)
+ if(!c) {
+ return;
+ }
+ for(i=0; i<c->size; i++) {
startpost(" %d", c->data[i]);
+ }
endpost();
}
-t_iemnet_chunk* iemnet__chunk_create_empty(int size) {
- t_iemnet_chunk*result=(t_iemnet_chunk*)malloc(sizeof(t_iemnet_chunk));
+t_iemnet_chunk* iemnet__chunk_create_empty(int size)
+{
+ t_iemnet_chunk*result=NULL;
+ if(size<1) {
+ return NULL;
+ }
+ result=(t_iemnet_chunk*)malloc(sizeof(t_iemnet_chunk));
if(result) {
result->size=size;
result->data=(unsigned char*)malloc(sizeof(unsigned char)*size);
@@ -142,12 +172,14 @@ t_iemnet_chunk* iemnet__chunk_create_empty(int size) {
result->addr=0L;
result->port=0;
+ result->family=AF_INET;
}
return result;
}
-t_iemnet_chunk* iemnet__chunk_create_data(int size, unsigned char*data) {
+t_iemnet_chunk* iemnet__chunk_create_data(int size, unsigned char*data)
+{
t_iemnet_chunk*result=iemnet__chunk_create_empty(size);
if(result) {
memcpy(result->data, data, result->size);
@@ -156,20 +188,25 @@ t_iemnet_chunk* iemnet__chunk_create_data(int size, unsigned char*data) {
}
t_iemnet_chunk* iemnet__chunk_create_dataaddr(int size,
- unsigned char*data,
- struct sockaddr_in*addr) {
+ unsigned char*data,
+ struct sockaddr_in*addr)
+{
t_iemnet_chunk*result=iemnet__chunk_create_data(size, data);
if(result && addr) {
result->addr = ntohl(addr->sin_addr.s_addr);
result->port = ntohs(addr->sin_port);
+ result->family = addr->sin_family;
}
return result;
}
-t_iemnet_chunk* iemnet__chunk_create_list(int argc, t_atom*argv) {
+t_iemnet_chunk* iemnet__chunk_create_list(int argc, t_atom*argv)
+{
int i;
t_iemnet_chunk*result=iemnet__chunk_create_empty(argc);
- if(NULL==result)return NULL;
+ if(NULL==result) {
+ return NULL;
+ }
for(i=0; i<argc; i++) {
unsigned char c = atom_getint(argv);
@@ -180,22 +217,32 @@ t_iemnet_chunk* iemnet__chunk_create_list(int argc, t_atom*argv) {
return result;
}
-t_iemnet_chunk*iemnet__chunk_create_chunk(t_iemnet_chunk*c) {
+t_iemnet_chunk*iemnet__chunk_create_chunk(t_iemnet_chunk*c)
+{
t_iemnet_chunk*result=NULL;
- if(NULL==c)return NULL;
+ if(NULL==c) {
+ return NULL;
+ }
result=iemnet__chunk_create_data(c->size, c->data);
- result->addr=c->addr;
- result->port=c->port;
-
+ if(result) {
+ result->addr=c->addr;
+ result->port=c->port;
+ }
return result;
}
-t_iemnet_floatlist*iemnet__chunk2list(t_iemnet_chunk*c, t_iemnet_floatlist*dest) {
+t_iemnet_floatlist*iemnet__chunk2list(t_iemnet_chunk*c,
+ t_iemnet_floatlist*dest)
+{
unsigned int i;
- if(NULL==c)return NULL;
+ if(NULL==c) {
+ return NULL;
+ }
dest=iemnet__floatlist_resize(dest, c->size);
- if(NULL==dest)return NULL;
+ if(NULL==dest) {
+ return NULL;
+ }
for(i=0; i<c->size; i++) {
dest->argv[i].a_w.w_float = c->data[i];
@@ -234,12 +281,14 @@ struct _iemnet_queue {
int used; // use counter, so queue_finish can wait for blocking accesses to finish
};
-static void queue_use_increment(t_iemnet_queue* _this) {
+static void queue_use_increment(t_iemnet_queue* _this)
+{
pthread_mutex_lock(&_this->usedmtx);
_this->used++;
pthread_mutex_unlock(&_this->usedmtx);
}
-static void queue_use_decrement(t_iemnet_queue* _this) {
+static void queue_use_decrement(t_iemnet_queue* _this)
+{
pthread_mutex_lock(&_this->usedmtx);
_this->used--;
pthread_cond_signal(&_this->usedcond);
@@ -250,19 +299,24 @@ static void queue_use_decrement(t_iemnet_queue* _this) {
* this will return the current queue size
*/
int queue_push(
- t_iemnet_queue* const _this,
- t_iemnet_chunk* const data
- ) {
+ t_iemnet_queue* const _this,
+ t_iemnet_chunk* const data
+)
+{
t_node* tail;
t_node* n=NULL;
int size=-1;
- if(NULL == _this)return size;
+ if(NULL == _this) {
+ return size;
+ }
pthread_mutex_lock(&_this->mtx);
size=_this->size;
pthread_mutex_unlock(&_this->mtx);
- if(NULL == data) return size;
+ if(NULL == data) {
+ return size;
+ }
n=(t_node*)malloc(sizeof(t_node));
@@ -294,18 +348,21 @@ int queue_push(
* OR the queue is "done" (in which case NULL is returned)
*/
t_iemnet_chunk* queue_pop_block(
- t_iemnet_queue* const _this
- ) {
+ t_iemnet_queue* const _this
+)
+{
t_node* head=0;
t_iemnet_chunk*data=0;
- if(NULL == _this)return NULL;
+ if(NULL == _this) {
+ return NULL;
+ }
queue_use_increment(_this);
pthread_mutex_lock(&_this->mtx);
/* if the queue is empty, wait */
- if(NULL == _this->head) {
+ while(NULL == _this->head) {
pthread_cond_wait(&_this->cond, &_this->mtx);
/* somebody signaled us, that we should do some work
* either the queue has been filled, or we are done...
@@ -320,11 +377,13 @@ t_iemnet_chunk* queue_pop_block(
head = _this->head;
/* update _this */
- if (! (_this->head = head->next)) {
- _this->tail = 0;
- }
- if(head && head->data) {
- _this->size-=head->data->size;
+ if(head) {
+ if (! (_this->head = head->next)) {
+ _this->tail = 0;
+ }
+ if(head->data) {
+ _this->size-=head->data->size;
+ }
}
pthread_mutex_unlock(&_this->mtx);
@@ -342,11 +401,14 @@ t_iemnet_chunk* queue_pop_block(
* (note that despite of the name this does block for synchronization)
*/
t_iemnet_chunk* queue_pop_noblock(
- t_iemnet_queue* const _this
- ) {
+ t_iemnet_queue* const _this
+)
+{
t_node* head=0;
t_iemnet_chunk*data=0;
- if(NULL == _this)return NULL;
+ if(NULL == _this) {
+ return NULL;
+ }
queue_use_increment(_this);
pthread_mutex_lock(&_this->mtx);
@@ -375,11 +437,13 @@ t_iemnet_chunk* queue_pop_noblock(
return data;
}
-t_iemnet_chunk* queue_pop(t_iemnet_queue* const _this) {
+t_iemnet_chunk* queue_pop(t_iemnet_queue* const _this)
+{
return queue_pop_block(_this);
}
-int queue_getsize(t_iemnet_queue* const _this) {
+int queue_getsize(t_iemnet_queue* const _this)
+{
int size=-1;
if(_this) {
pthread_mutex_lock(&_this->mtx);
@@ -388,9 +452,12 @@ int queue_getsize(t_iemnet_queue* const _this) {
}
return size;
}
-void queue_finish(t_iemnet_queue* q) {
+void queue_finish(t_iemnet_queue* q)
+{
DEBUG("queue_finish: %x", q);
- if(NULL==q) return;
+ if(NULL==q) {
+ return;
+ }
pthread_mutex_lock(&q->mtx);
q->done=1;
@@ -401,16 +468,20 @@ void queue_finish(t_iemnet_queue* q) {
/* wait until queue is no longer used */
pthread_mutex_lock(&q->usedmtx);
- while(q->used) pthread_cond_wait(&q->usedcond, &q->usedmtx);
+ while(q->used) {
+ pthread_cond_wait(&q->usedcond, &q->usedmtx);
+ }
pthread_mutex_unlock(&q->usedmtx);
DEBUG("queue_finished: %x", q);
}
-void queue_destroy(t_iemnet_queue* q) {
+void queue_destroy(t_iemnet_queue* q)
+{
t_iemnet_chunk*c=NULL;
- if(NULL==q)
+ if(NULL==q) {
return;
+ }
DEBUG("queue destroy %x", q);
queue_finish(q);
@@ -434,13 +505,16 @@ void queue_destroy(t_iemnet_queue* q) {
DEBUG("queue destroyed %x", q);
}
-t_iemnet_queue* queue_create(void) {
+t_iemnet_queue* queue_create(void)
+{
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
t_iemnet_queue*q=(t_iemnet_queue*)malloc(sizeof(t_iemnet_queue));
DEBUG("queue create %x", q);
- if(NULL==q)return NULL;
+ if(NULL==q) {
+ return NULL;
+ }
q->head = NULL;
q->tail = NULL;
diff --git a/iemnet_data.h b/iemnet_data.h
index f9a043c..80a8eed 100644
--- a/iemnet_data.h
+++ b/iemnet_data.h
@@ -2,7 +2,7 @@
* iemnet
* networking for Pd
*
- * (c) 2010 IOhannes m zmölnig
+ * (c) 2010 IOhannes m zmölnig
* Institute of Electronic Music and Acoustics (IEM)
* University of Music and Dramatic Arts (KUG), Graz, Austria
*
@@ -23,9 +23,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/ */
/* */
/* ---------------------------------------------------------------------------- */
@@ -67,6 +66,7 @@ typedef struct _iemnet_chunk {
long addr;
unsigned short port;
+ short family; // AF_INET, AF_INET6
} t_iemnet_chunk;
/**
@@ -103,7 +103,8 @@ t_iemnet_chunk*iemnet__chunk_create_data(int size, unsigned char*data);
* \param addr originating address (can be NULL)
* \return a new chunk that holds a copy of data
*/
-t_iemnet_chunk*iemnet__chunk_create_dataaddr(int size, unsigned char*data, struct sockaddr_in*addr);
+t_iemnet_chunk*iemnet__chunk_create_dataaddr(int size, unsigned char*data,
+ struct sockaddr_in*addr);
/**
* initialize a "chunk" (allocate memory,...) with given data
* receiver address will be set to 0
@@ -130,7 +131,8 @@ t_iemnet_chunk*iemnet__chunk_create_chunk(t_iemnet_chunk*source);
* \param dest the destination list
* \return the destination list if all went well, else NULL
*/
-t_iemnet_floatlist*iemnet__chunk2list(t_iemnet_chunk*c, t_iemnet_floatlist*dest);
+t_iemnet_floatlist*iemnet__chunk2list(t_iemnet_chunk*c,
+ t_iemnet_floatlist*dest);
/**
diff --git a/iemnet_notify.c b/iemnet_notify.c
deleted file mode 100644
index 6bf6a1b..0000000
--- a/iemnet_notify.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/* iemnet
- *
- * notify
- * notifies mai thread that new data has arrived
- *
- * copyright (c) 2012 IOhannes m zmölnig, IEM
- */
-
-/* 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., */
-/* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
-/* */
-
-#define DEBUGLEVEL 4
-
-#include "iemnet.h"
-#include "iemnet_data.h"
-
-/* for pipe() */
-#include <unistd.h>
-
-/* for printf() debugging */
-#include <stdio.h>
-
-struct _iemnet_notify {
- void*data;
- t_iemnet_notifun fun;
- struct _iemnet_notifier*parent;
- struct _iemnet_notify*next;
-};
-
-static t_iemnet_notify*pollqueue=NULL;
-
-struct _iemnet_notifier {
- int fd[2];
- struct _iemnet_notify*nodes;
-};
-
-static t_iemnet_notifier *masternotifier = NULL;
-
-/* notifies Pd that there is new data to fetch */
-void iemnet__notify(t_iemnet_notify*x) {
- write(masternotifier->fd[1], x, sizeof(x));
-}
-
-static void pollfun(void*x, int fd) {
- char buf[4096];
- int result=-1;
- t_iemnet_notify*q;
- result=read(fd, buf, sizeof(buf));
- for(q=pollqueue; q; q=q->next) {
- (q->fun)(q->data);
- }
-}
-
-static void iemnet__notifier_print(t_iemnet_notifier*x) {
- t_iemnet_notify*q;
- for(q=pollqueue; q; q=q->next) {
- printf("queue[%p]={fun:%p, data:%p, next:%p}\n", q, q->fun, q->data, q->next);
- }
-}
-t_iemnet_notifier*iemnet__notify_create(void) {
- if(masternotifier!=NULL)
- return masternotifier;
- masternotifier=(t_iemnet_notifier*)getbytes(sizeof(t_iemnet_notifier));
- if(!pipe(masternotifier->fd)) {
- sys_addpollfn(masternotifier->fd[0], pollfun, masternotifier);
- return masternotifier;
- }
- return NULL;
-}
-void iemnet__notify_destroy(t_iemnet_notifier*x) {
- // nada
-}
-
-t_iemnet_notify*iemnet__notify_add(t_iemnet_notifier*notifier, t_iemnet_notifun fun, void*data) {
- /* add the given receiver to the poll-queue
- * LATER: check whether it's already in there...
- */
- t_iemnet_notify*q=(t_iemnet_notify*)getbytes(sizeof(t_iemnet_notify));
- q->fun =fun;
- q->data=data;
- q->parent=notifier;
- q->next=pollqueue;
- pollqueue=q;
- //iemnet__notifier_print(notifier);
- return q;
-}
-void iemnet__notify_remove(t_iemnet_notify*x) {
- t_iemnet_notify*q=pollqueue;
- t_iemnet_notify*last=NULL;
- //iemnet__notifier_print(q->parent);
-
- for(q=pollqueue; q; q=q->next) {
- if(q == x) {
- if(last) {
- last->next=q->next;
- } else {
- pollqueue=q->next;
- }
- q->fun =NULL;
- q->data=NULL;
- q->next=NULL;
- freebytes(q, sizeof(*q));
- return;
- }
- last=q;
- }
-}
diff --git a/iemnet_receiver.c b/iemnet_receiver.c
index f9f3fa8..898bac8 100644
--- a/iemnet_receiver.c
+++ b/iemnet_receiver.c
@@ -2,9 +2,8 @@
*
* receiver
* receives data "chunks" from a socket
- * possibly threaded
*
- * copyright (c) 2010 IOhannes m zmölnig, IEM
+ * copyright (c) 2010-2015 IOhannes m zmölnig, IEM
*/
/* This program is free software; you can redistribute it and/or */
@@ -18,9 +17,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/ */
/* */
#define DEBUGLEVEL 4
@@ -28,258 +26,115 @@
#include "iemnet.h"
#include "iemnet_data.h"
-#include <string.h>
-#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
-#include <pthread.h>
-
#define INBUFSIZE 65536L /* was 4096: size of receiving data buffer */
struct _iemnet_receiver {
- pthread_t recthread;
int sockfd; /* owned outside; you must call iemnet__receiver_destroy() before freeing socket yourself */
void*userdata;
- t_iemnet_chunk*data;
t_iemnet_receivecallback callback;
- t_iemnet_queue*queue;
-
- int running;
- int keepreceiving;
-
- pthread_mutex_t running_mtx, keeprec_mtx;
- pthread_cond_t running_cond;
- t_iemnet_notify*notifier;
};
-static t_iemnet_notifier*receivenotifier=NULL;
-
-/* the workhorse of the family */
-static void*iemnet__receiver_readthread(void*arg) {
- unsigned int i=0;
- int result = 0;
- t_iemnet_receiver*receiver=(t_iemnet_receiver*)arg;
- int sockfd=receiver->sockfd;
- t_iemnet_queue*q=receiver->queue;
+static void pollfun(void*z, int fd)
+{
+ // read data from socket and call callback
+ t_iemnet_receiver*rec=(t_iemnet_receiver*)z;
unsigned char data[INBUFSIZE];
unsigned int size=INBUFSIZE;
+ t_iemnet_chunk*chunk=NULL;
+ int result = 0;
+ int local_errno = 0;
struct sockaddr_in from;
socklen_t fromlen = sizeof(from);
int recv_flags=0;
-
- struct timeval timout;
- fd_set readset;
- FD_ZERO(&readset);
- FD_SET(sockfd, &readset);
-
- for(i=0; i<size; i++)data[i]=0;
- receiver->running=1;
-
- pthread_mutex_lock (&receiver->running_mtx);
- pthread_cond_signal (&receiver->running_cond);
- pthread_mutex_unlock(&receiver->running_mtx);
-
- while(1) {
- t_iemnet_chunk*c=NULL;
- fd_set rs;
-
- pthread_mutex_lock(&receiver->keeprec_mtx);
- if(!receiver->keepreceiving) {
- pthread_mutex_unlock(&receiver->keeprec_mtx);
- break;
- }
- pthread_mutex_unlock(&receiver->keeprec_mtx);
-
- fromlen = sizeof(from);
- rs=readset;
- timout.tv_sec=0;
- timout.tv_usec=1000;
-
#ifdef MSG_DONTWAIT
- recv_flags|=MSG_DONTWAIT;
+ recv_flags|=MSG_DONTWAIT;
#endif
- select(sockfd+1, &rs, NULL, NULL,
- &timout);
- if (!FD_ISSET(sockfd, &rs))continue;
-
- DEBUG("select can read");
-
- //fprintf(stderr, "reading %d bytes...\n", size);
- //result = recv(sockfd, data, size, 0);
-
- result = recvfrom(sockfd, data, size, recv_flags, (struct sockaddr *)&from, &fromlen);
- //fprintf(stderr, "read %d bytes...\n", result);
- DEBUG("recfrom %d bytes: %p", result, data);
- c= iemnet__chunk_create_dataaddr(result, (result>0)?data:NULL, &from);
- DEBUG("pushing");
- queue_push(q, c);
- DEBUG("signalling");
- iemnet__notify(receiver->notifier);
-
-
- if(result<=0) break;
-
- DEBUG("rereceive");
- }
- // oha
- DEBUG("readthread loop termination: %d", result);
- //if(result>=0)iemnet_signalNewData(receiver);
-
- pthread_mutex_lock(&receiver->running_mtx);
- receiver->running=0;
- pthread_mutex_unlock(&receiver->running_mtx);
-
- DEBUG("read thread terminated");
- return NULL;
+ errno=0;
+ result = recvfrom(rec->sockfd, data, size, recv_flags,
+ (struct sockaddr *)&from, &fromlen);
+ local_errno=errno;
+ //fprintf(stderr, "read %d bytes...\n", result);
+ DEBUG("recvfrom %d bytes: %d %p %d", result, rec->sockfd, data, size);
+ DEBUG("errno=%d", local_errno);
+ chunk = iemnet__chunk_create_dataaddr(result, (result>0)?data:NULL, &from);
+
+ // call the callback with a NULL-chunk to signal a disconnect event.
+ (rec->callback)(rec->userdata, chunk);
+
+ iemnet__chunk_destroy(chunk);
}
-/* callback from Pd's main thread to fetch queued data */
-static void iemnet__receiver_tick(t_iemnet_receiver *x)
+t_iemnet_receiver*iemnet__receiver_create(int sock, void*userdata,
+ t_iemnet_receivecallback callback, int subthread)
{
- int running=0, keepreceiving=0;
- // received data
- t_iemnet_chunk*c=queue_pop_noblock(x->queue);
- DEBUG("tick got chunk %p", c);
-
- while(NULL!=c) {
- (x->callback)(x->userdata, c);
- iemnet__chunk_destroy(c);
- c=queue_pop_noblock(x->queue);
- }
- DEBUG("tick cleanup");
-
- pthread_mutex_lock(&x->running_mtx);
- running = x->running;
- pthread_mutex_unlock(&x->running_mtx);
-
- DEBUG("tick running %d", running);
- if(!running) {
- // read terminated
- pthread_mutex_lock(&x->keeprec_mtx);
- keepreceiving=x->keepreceiving;
- pthread_mutex_unlock(&x->keeprec_mtx);
-
- /* keepreceiving is set, if receiver is not yet in shutdown mode */
- if(keepreceiving)
- x->callback(x->userdata, NULL);
- }
- DEBUG("tick DONE");
-}
-
-int iemnet__receiver_getsize(t_iemnet_receiver*x) {
- int size=-1;
- if(x && x->queue)
- size=queue_getsize(x->queue);
-
- return size;
-}
-
-
-t_iemnet_receiver*iemnet__receiver_create(int sock, void*userdata, t_iemnet_receivecallback callback) {
- static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
- t_iemnet_receiver*rec=(t_iemnet_receiver*)malloc(sizeof(t_iemnet_receiver));
-
- if(NULL==receivenotifier)
- receivenotifier=iemnet__notify_create();
+ t_iemnet_receiver*rec=(t_iemnet_receiver*)malloc(sizeof(
+ t_iemnet_receiver));
DEBUG("create new receiver for 0x%X:%d", userdata, sock);
//fprintf(stderr, "new receiver for %d\t%x\t%x\n", sock, userdata, callback);
if(rec) {
- t_iemnet_chunk*data=NULL;
- int res=0;
-
- data=iemnet__chunk_create_empty(INBUFSIZE);
- if(NULL==data) {
- iemnet__receiver_destroy(rec);
- DEBUG("create receiver failed");
- return NULL;
- }
-
- rec->keepreceiving=1;
rec->sockfd=sock;
rec->userdata=userdata;
- rec->data=data;
rec->callback=callback;
- pthread_mutex_init(&rec->running_mtx , 0);
- pthread_mutex_init(&rec->keeprec_mtx , 0);
-
- pthread_cond_init(&rec->running_cond, 0);
-
- rec->running=1;
-
- rec->queue = queue_create();
- rec->notifier = iemnet__notify_add(receivenotifier, (t_iemnet_notifun)iemnet__receiver_tick, rec);
+ if(subthread) {
+ sys_lock();
+ }
+ sys_addpollfn(sock, pollfun, rec);
+ if(subthread) {
+ sys_unlock();
+ }
- /* start the recv thread */
- pthread_mutex_lock(&rec->running_mtx);
- res=pthread_create(&rec->recthread, 0, iemnet__receiver_readthread, rec);
- if(!res)pthread_cond_wait(&rec->running_cond, &rec->running_mtx);
- pthread_mutex_unlock(&rec->running_mtx);
}
//fprintf(stderr, "new receiver created\n");
return rec;
}
-
-void iemnet__receiver_destroy(t_iemnet_receiver*rec) {
- static int instance=0;
- int inst=instance++;
-
+void iemnet__receiver_destroy(t_iemnet_receiver*rec, int subthread)
+{
int sockfd;
- DEBUG("[%d] destroy receiver %x", inst, rec);
- if(NULL==rec)return;
- pthread_mutex_lock(&rec->keeprec_mtx);
- if(!rec->keepreceiving) {
- pthread_mutex_unlock(&rec->keeprec_mtx);
+ if(NULL==rec) {
return;
- }
- rec->keepreceiving=0;
- pthread_mutex_unlock(&rec->keeprec_mtx);
+ }
sockfd=rec->sockfd;
- pthread_join(rec->recthread, NULL);
- iemnet__notify_remove(rec->notifier);
-
- DEBUG("[%d] really destroying receiver %x -> %d", inst, rec, sockfd);
-
- if(sockfd>=0) {
- /* this doesn't alway make recvfrom() return!
- * - try polling
- * - try sending a signal with pthread_kill() ?
- */
-
- shutdown(sockfd, 2); /* needed on linux, since the recv won't shutdown on sys_closesocket() alone */
- sys_closesocket(sockfd);
+ if(subthread) {
+ sys_lock();
}
- DEBUG("[%d] closed socket %d", inst, sockfd);
-
- rec->sockfd=-1;
+ sys_rmpollfn(rec->sockfd);
- // empty the queue
- DEBUG("[%d] tick %d", inst, rec->running);
- iemnet__receiver_tick(rec);
- queue_destroy(rec->queue);
- DEBUG("[%d] tack", inst);
+ // FIXXME: read any remaining bytes from the socket
- if(rec->data)iemnet__chunk_destroy(rec->data);
+ if(subthread) {
+ sys_unlock();
+ }
- pthread_mutex_destroy(&rec->running_mtx);
- pthread_mutex_destroy(&rec->keeprec_mtx);
- pthread_cond_destroy(&rec->running_cond);
+ DEBUG("[%p] really destroying receiver %d", sockfd);
+ //iemnet__closesocket(sockfd);
+ DEBUG("[%p] closed socket %d", rec, sockfd);
+ rec->sockfd=-1;
rec->userdata=NULL;
- rec->data=NULL;
rec->callback=NULL;
- rec->queue=NULL;
free(rec);
rec=NULL;
- DEBUG("[%d] destroyed receiver", inst);
+}
+
+
+/* just dummy, since we don't maintain a queue any more */
+int iemnet__receiver_getsize(t_iemnet_receiver*x)
+{
+ if(x) {
+ return 0;
+ }
+ return -1;
}
diff --git a/iemnet_sender.c b/iemnet_sender.c
index 0e4f866..8cf1d14 100644
--- a/iemnet_sender.c
+++ b/iemnet_sender.c
@@ -4,7 +4,7 @@
* sends data "chunks" to a socket
* possibly threaded
*
- * copyright (c) 2010 IOhannes m zmölnig, IEM
+ * copyright (c) 2010 IOhannes m zmölnig, IEM
*/
/* This program is free software; you can redistribute it and/or */
@@ -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/ */
/* */
#define DEBUGLEVEL 2
@@ -54,11 +53,11 @@ static int debug_lockcount=0;
# define UNLOCK(x) pthread_mutex_unlock(x)
#endif
- /* draft:
- * - there is a sender thread for each open connection
- * - the main thread just adds chunks to each sender threads processing queue
- * - the sender thread tries to send the queue as fast as possible
- */
+/* draft:
+ * - there is a sender thread for each open connection
+ * - the main thread just adds chunks to each sender threads processing queue
+ * - the sender thread tries to send the queue as fast as possible
+ */
struct _iemnet_sender {
pthread_t thread;
@@ -68,62 +67,92 @@ struct _iemnet_sender {
int keepsending; // indicates whether we want to thread to continue or to terminate
int isrunning;
+ const void*userdata; /* user provided data */
+ t_iemnet_sendfunction sendfun; /* user provided send function */
+
pthread_mutex_t mtx; /* mutex to protect isrunning,.. */
};
/* the workhorse of the family */
-static int iemnet__sender_dosend(int sockfd, t_iemnet_queue*q) {
+
+static int iemnet__sender_defaultsend(const void*x, int sockfd,
+ t_iemnet_chunk*c)
+{
+ int result=-1;
+
struct sockaddr_in to;
socklen_t tolen = sizeof(to);
- t_iemnet_chunk*c=queue_pop_block(q);
- if(c) {
- unsigned char*data=c->data;
- unsigned int size=c->size;
-
- int result=-1;
+ unsigned char*data=c->data;
+ unsigned int size=c->size;
- // fprintf(stderr, "sending %d bytes at %x to %d\n", size, data, sockfd);
- if(c->port) {
- DEBUG("sending %d bytes to %x:%d", size, c->addr, c->port);
+ int flags = 0;
+#ifdef __linux__
+ flags |= MSG_NOSIGNAL;
+#endif
- to.sin_addr.s_addr=htonl(c->addr);
- to.sin_port =htons(c->port);
- result = sendto(sockfd, data, size, 0, (struct sockaddr *)&to, tolen);
- } else {
- DEBUG("sending %d bytes", size);
- result = send(sockfd, data, size, 0);
- }
- if(result<0) {
- // broken pipe
- return 0;
- }
+ // fprintf(stderr, "sending %d bytes at %x to %d\n", size, data, sockfd);
+ if(c->port) {
+ DEBUG("sending %d bytes to %x:%d @%d", size, c->addr, c->port, c->family);
- // shouldn't we do something with the result here?
- DEBUG("sent %d bytes", result);
- iemnet__chunk_destroy(c);
+ to.sin_addr.s_addr=htonl(c->addr);
+ to.sin_port =htons(c->port);
+ to.sin_family =c->family;
+ result = sendto(sockfd,
+ data, size, /* DATA */
+ flags, /* FLAGS */
+ (struct sockaddr *)&to, tolen); /* DESTADDR */
} else {
+ DEBUG("sending %d bytes", size);
+ result = send(sockfd,
+ data, size, /* DATA */
+ flags); /* FLAGS */
+ }
+ if(result<0) {
+ // broken pipe
return 0;
}
+
+ // shouldn't we do something with the result here?
+ DEBUG("sent %d bytes", result);
return 1;
}
-static void*iemnet__sender_sendthread(void*arg) {
+static void*iemnet__sender_sendthread(void*arg)
+{
t_iemnet_sender*sender=(t_iemnet_sender*)arg;
int sockfd=-1;
t_iemnet_queue*q=NULL;
+ t_iemnet_chunk*c=NULL;
+ t_iemnet_sendfunction dosend=iemnet__sender_defaultsend;
+ const void*userdata=NULL;
LOCK(&sender->mtx);
- sockfd=sender->sockfd;
q=sender->queue;
+ userdata=sender->userdata;
+ if(NULL!=sender->sendfun) {
+ dosend=sender->sendfun;
+ }
+
+ sockfd=sender->sockfd;
+
+
while(sender->keepsending) {
UNLOCK(&sender->mtx);
- if(!iemnet__sender_dosend(sockfd, q)){
- LOCK(&sender->mtx);
- break;
+
+ c=queue_pop_block(q);
+ if(c) {
+ if(!dosend(userdata, sockfd, c)) {
+ iemnet__chunk_destroy(c);
+
+ LOCK(&sender->mtx);
+ break;
+ }
+ iemnet__chunk_destroy(c);
+ c=NULL;
}
LOCK(&sender->mtx);
}
@@ -133,7 +162,8 @@ static void*iemnet__sender_sendthread(void*arg) {
return NULL;
}
-int iemnet__sender_send(t_iemnet_sender*s, t_iemnet_chunk*c) {
+int iemnet__sender_send(t_iemnet_sender*s, t_iemnet_chunk*c)
+{
t_iemnet_queue*q=0;
int size=-1;
LOCK (&s->mtx);
@@ -150,10 +180,11 @@ int iemnet__sender_send(t_iemnet_sender*s, t_iemnet_chunk*c) {
return size;
}
-void iemnet__sender_destroy(t_iemnet_sender*s) {
+void iemnet__sender_destroy(t_iemnet_sender*s, int subthread)
+{
int sockfd=-1;
/* simple protection against recursive calls:
- * s->keepsending is only set to "0" in here,
+ * s->keepsending is only set to "0" in here,
* so if it is false, we know that we are already being called
*/
DEBUG("destroy sender %x with queue %x (%d)", s, s->queue, s->keepsending);
@@ -178,11 +209,7 @@ void iemnet__sender_destroy(t_iemnet_sender*s) {
queue_finish(s->queue);
DEBUG("queue finished");
-
- if(sockfd>=0) {
- int err=shutdown(sockfd, 2); /* needed on linux, since the recv won't shutdown on sys_closesocket() alone */
- sys_closesocket(sockfd);
- }
+ //iemnet__closesocket(sockfd);
pthread_join(s->thread, NULL);
DEBUG("thread joined");
@@ -191,18 +218,23 @@ void iemnet__sender_destroy(t_iemnet_sender*s) {
pthread_mutex_destroy (&s->mtx);
memset(s, 0, sizeof(t_iemnet_sender));
+ s->sockfd = -1;
free(s);
s=NULL;
DEBUG("destroyed sender");
}
-t_iemnet_sender*iemnet__sender_create(int sock) {
+t_iemnet_sender*iemnet__sender_create(int sock,
+ t_iemnet_sendfunction sendfun, const void*userdata,
+ int subthread)
+{
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
- t_iemnet_sender*result=(t_iemnet_sender*)malloc(sizeof(t_iemnet_sender));
+ t_iemnet_sender*result=(t_iemnet_sender*)calloc(1,
+ sizeof(t_iemnet_sender));
int res=0;
DEBUG("create sender %x", result);
- if(NULL==result){
+ if(NULL==result) {
DEBUG("create sender failed");
return NULL;
}
@@ -211,23 +243,28 @@ t_iemnet_sender*iemnet__sender_create(int sock) {
result->sockfd = sock;
result->keepsending =1;
result->isrunning=1;
+ result->sendfun=sendfun;
+ result->userdata=userdata;
DEBUG("create_sender queue=%x", result->queue);
memcpy(&result->mtx , &mtx, sizeof(pthread_mutex_t));
res=pthread_create(&result->thread, 0, iemnet__sender_sendthread, result);
if(0==res) {
-
} else {
// something went wrong
+ queue_destroy(result->queue);
+ free(result);
+ return NULL;
}
DEBUG("created sender");
return result;
}
-int iemnet__sender_getlasterror(t_iemnet_sender*x) {
- x=NULL;
+/* coverity[param_set_but_not_used]: as x is there for potentially more specific implentations in the future */
+int iemnet__sender_getlasterror(t_iemnet_sender*x)
+{
#ifdef _WIN32
return WSAGetLastError();
#endif
@@ -235,27 +272,35 @@ int iemnet__sender_getlasterror(t_iemnet_sender*x) {
}
-int iemnet__sender_getsockopt(t_iemnet_sender*s, int level, int optname, void *optval, socklen_t*optlen) {
+int iemnet__sender_getsockopt(t_iemnet_sender*s, int level, int optname,
+ void *optval, socklen_t*optlen)
+{
int result=getsockopt(s->sockfd, level, optname, optval, optlen);
if(result!=0) {
- post("%s: getsockopt returned %d", __FUNCTION__, iemnet__sender_getlasterror(s));
+ post("%s: getsockopt returned %d", __FUNCTION__,
+ iemnet__sender_getlasterror(s));
}
return result;
}
-int iemnet__sender_setsockopt(t_iemnet_sender*s, int level, int optname, const void*optval, socklen_t optlen) {
+int iemnet__sender_setsockopt(t_iemnet_sender*s, int level, int optname,
+ const void*optval, socklen_t optlen)
+{
int result=setsockopt(s->sockfd, level, optname, optval, optlen);
if(result!=0) {
- post("%s: setsockopt returned %d", __FUNCTION__, iemnet__sender_getlasterror(s));
+ post("%s: setsockopt returned %d", __FUNCTION__,
+ iemnet__sender_getlasterror(s));
}
return result;
}
-int iemnet__sender_getsize(t_iemnet_sender*x) {
+int iemnet__sender_getsize(t_iemnet_sender*x)
+{
int size=-1;
- if(x && x->queue)
+ if(x && x->queue) {
size=queue_getsize(x->queue);
+ }
return size;
}
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 */
diff --git a/tcpreceive.c b/tcpreceive.c
index dc49d2d..a115a06 100644
--- a/tcpreceive.c
+++ b/tcpreceive.c
@@ -1,5 +1,5 @@
/* tcpreceive.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,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/ */
/* */
#define DEBUGLEVEL 1
@@ -33,14 +32,15 @@ static const char*objName="tcpreceive";
# include <netinet/tcp.h>
#endif
+#include <string.h>
+
/* ----------------------------- tcpreceive ------------------------- */
static t_class *tcpreceive_class;
#define MAX_CONNECTIONS 128 // this is going to cause trouble down the line...:(
-typedef struct _tcpconnection
-{
+typedef struct _tcpconnection {
long addr;
unsigned short port;
int socket;
@@ -48,8 +48,7 @@ typedef struct _tcpconnection
t_iemnet_receiver*receiver;
} t_tcpconnection;
-typedef struct _tcpreceive
-{
+typedef struct _tcpreceive {
t_object x_obj;
t_outlet *x_msgout;
t_outlet *x_addrout;
@@ -63,14 +62,17 @@ typedef struct _tcpreceive
int x_nconnections;
t_tcpconnection x_connection[MAX_CONNECTIONS];
- t_iemnet_floatlist *x_floatlist;
+ t_iemnet_floatlist *x_floatlist;
} t_tcpreceive;
-static int tcpreceive_find_socket(t_tcpreceive *x, int fd) {
+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;
+ if (x->x_connection[i].socket == fd) {
+ return i;
+ }
return -1;
}
@@ -82,14 +84,18 @@ static void tcpreceive_read_callback(void *w, t_iemnet_chunk*c)
t_tcpconnection*y=(t_tcpconnection*)w;
t_tcpreceive*x=NULL;
int index=-1;
- if(NULL==y || NULL==(x=y->owner))return;
+ if(NULL==y || NULL==(x=y->owner)) {
+ return;
+ }
index=tcpreceive_find_socket(x, y->socket);
if(index>=0) {
if(c) {
// TODO?: outlet info about connection
- x->x_floatlist=iemnet__chunk2list(c, x->x_floatlist); // gets 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); // gets destroyed in the dtor
+ iemnet__streamout(x->x_msgout, x->x_floatlist->argc, x->x_floatlist->argv,
+ x->x_serialize);
} else {
// disconnected
tcpreceive_disconnect(x, index);
@@ -99,25 +105,25 @@ static void tcpreceive_read_callback(void *w, t_iemnet_chunk*c)
/* 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_addconnection(t_tcpreceive *x, int fd, long addr,
+ unsigned short port)
{
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;
- x->x_connection[i].owner = x;
- x->x_connection[i].receiver=
- iemnet__receiver_create(fd,
- x->x_connection+i,
- tcpreceive_read_callback);
-
- return 1;
- }
+ 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;
+ x->x_connection[i].owner = x;
+ x->x_connection[i].receiver=
+ iemnet__receiver_create(fd,
+ x->x_connection+i,
+ tcpreceive_read_callback,
+ 0);
+
+ return 1;
}
+ }
return 0;
}
@@ -133,38 +139,31 @@ static void tcpreceive_connectpoll(t_tcpreceive *x)
int fd;
fd = accept(x->x_connectsocket, (struct sockaddr *)&from, &fromlen);
- if (fd < 0) error("[%s] accept failed", objName);
- 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))
- {
- x->x_nconnections++;
- outlet_float(x->x_connectout, x->x_nconnections);
- iemnet__addrout(x->x_statout, x->x_addrout, addr, port);
- }
- else
- {
- error ("[%s] Too many connections", objName);
- sys_closesocket(fd);
- }
+ if (fd < 0) {
+ error("[%s] accept failed", objName);
+ } else {
+ /* get the sender's ip */
+ addr = ntohl(from.sin_addr.s_addr);
+ port = ntohs(from.sin_port);
+ if (tcpreceive_addconnection(x, fd, addr, port)) {
+ x->x_nconnections++;
+ outlet_float(x->x_connectout, x->x_nconnections);
+ iemnet__addrout(x->x_statout, x->x_addrout, addr, port);
+ } else {
+ error ("[%s] Too many connections", objName);
+ iemnet__closesocket(fd);
}
+ }
}
static int tcpreceive_disconnect(t_tcpreceive *x, int id)
{
if(id>=0 && id < MAX_CONNECTIONS && x->x_connection[id].port>0) {
- iemnet__receiver_destroy(x->x_connection[id].receiver);
+ iemnet__receiver_destroy(x->x_connection[id].receiver, 0);
x->x_connection[id].receiver=NULL;
- sys_closesocket(x->x_connection[id].socket);
+ iemnet__closesocket(x->x_connection[id].socket);
x->x_connection[id].socket = -1;
x->x_connection[id].addr = 0L;
@@ -182,10 +181,9 @@ static void tcpreceive_disconnect_all(t_tcpreceive *x)
{
int i;
- for (i = 0; i < MAX_CONNECTIONS; i++)
- {
- tcpreceive_disconnect(x, i);
- }
+ for (i = 0; i < MAX_CONNECTIONS; i++) {
+ tcpreceive_disconnect(x, i);
+ }
}
@@ -196,13 +194,11 @@ static void tcpreceive_disconnect_all(t_tcpreceive *x)
static int tcpreceive_disconnect_socket(t_tcpreceive *x, int fd)
{
int i;
- for (i = 0; i < MAX_CONNECTIONS; ++i)
- {
- if (x->x_connection[i].socket == fd)
- {
- return tcpreceive_disconnect(x, i);
- }
+ for (i = 0; i < MAX_CONNECTIONS; ++i) {
+ if (x->x_connection[i].socket == fd) {
+ return tcpreceive_disconnect(x, i);
}
+ }
return 0;
}
@@ -214,6 +210,7 @@ static void tcpreceive_port(t_tcpreceive*x, t_floatarg fportno)
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) {
@@ -223,7 +220,7 @@ static void tcpreceive_port(t_tcpreceive*x, t_floatarg fportno)
/* cleanup any open ports */
if(sockfd>=0) {
sys_rmpollfn(sockfd);
- sys_closesocket(sockfd);
+ iemnet__closesocket(sockfd);
x->x_connectsocket=-1;
x->x_port=-1;
}
@@ -239,7 +236,7 @@ static void tcpreceive_port(t_tcpreceive*x, t_floatarg fportno)
#ifdef SO_REUSEADDR
intarg = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
- (char *)&intarg, sizeof(intarg))
+ (char *)&intarg, sizeof(intarg))
< 0) {
error("[%s]: setsockopt (SO_REUSEADDR) failed", objName);
}
@@ -247,7 +244,7 @@ static void tcpreceive_port(t_tcpreceive*x, t_floatarg fportno)
#ifdef SO_REUSEPORT
intarg = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT,
- (char *)&intarg, sizeof(intarg))
+ (char *)&intarg, sizeof(intarg))
< 0) {
error("[%s]: setsockopt (SO_REUSEPORT) failed", objName);
}
@@ -256,8 +253,9 @@ static void tcpreceive_port(t_tcpreceive*x, t_floatarg fportno)
/* Stream (TCP) sockets are set NODELAY */
intarg = 1;
if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,
- (char *)&intarg, sizeof(intarg)) < 0)
+ (char *)&intarg, sizeof(intarg)) < 0) {
post("[%s]: setsockopt (TCP_NODELAY) failed", objName);
+ }
server.sin_family = AF_INET;
@@ -265,30 +263,26 @@ static void tcpreceive_port(t_tcpreceive*x, t_floatarg fportno)
server.sin_port = htons((u_short)portno);
/* name the socket */
- if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0)
- {
- sys_sockerror("[tcpreceive] 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("[tcpreceive] bind failed");
+ iemnet__closesocket(sockfd);
+ sockfd = -1;
+ outlet_anything(x->x_statout, gensym("port"), 1, ap);
+ return;
+ }
/* streaming protocol */
- if (listen(sockfd, 5) < 0)
- {
- sys_sockerror("[tcpreceive] listen");
- sys_closesocket(sockfd);
- sockfd = -1;
- outlet_anything(x->x_statout, gensym("port"), 1, ap);
- return;
- }
- else
- {
- sys_addpollfn(sockfd,
- (t_fdpollfn)tcpreceive_connectpoll,
- x); // wait for new connections
- }
+ if (listen(sockfd, 5) < 0) {
+ sys_sockerror("[tcpreceive] listen");
+ iemnet__closesocket(sockfd);
+ sockfd = -1;
+ outlet_anything(x->x_statout, gensym("port"), 1, ap);
+ return;
+ } else {
+ sys_addpollfn(sockfd,
+ (t_fdpollfn)tcpreceive_connectpoll,
+ x); // wait for new connections
+ }
x->x_connectsocket = sockfd;
x->x_port = portno;
@@ -303,20 +297,24 @@ static void tcpreceive_port(t_tcpreceive*x, t_floatarg fportno)
outlet_anything(x->x_statout, gensym("port"), 1, ap);
}
-static void tcpreceive_serialize(t_tcpreceive *x, t_floatarg doit) {
+static void tcpreceive_serialize(t_tcpreceive *x, t_floatarg doit)
+{
x->x_serialize=doit;
}
static void tcpreceive_free(t_tcpreceive *x)
-{ /* is this ever called? */
- if (x->x_connectsocket >= 0)
- {
- sys_rmpollfn(x->x_connectsocket);
- sys_closesocket(x->x_connectsocket);
- }
+{
+ /* is this ever called? */
+ if (x->x_connectsocket >= 0) {
+ sys_rmpollfn(x->x_connectsocket);
+ iemnet__closesocket(x->x_connectsocket);
+ }
tcpreceive_disconnect_all(x);
- 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;
}
static void *tcpreceive_new(t_floatarg fportno)
@@ -338,12 +336,11 @@ static void *tcpreceive_new(t_floatarg fportno)
x->x_nconnections=0;
/* 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 < MAX_CONNECTIONS; ++i) {
+ x->x_connection[i].socket = -1;
+ x->x_connection[i].addr = 0L;
+ x->x_connection[i].port = 0;
+ }
x->x_floatlist=iemnet__floatlist_create(1024);
@@ -355,16 +352,20 @@ static void *tcpreceive_new(t_floatarg fportno)
IEMNET_EXTERN void tcpreceive_setup(void)
{
- if(!iemnet__register(objName))return;
+ if(!iemnet__register(objName)) {
+ return;
+ }
tcpreceive_class = class_new(gensym(objName),
- (t_newmethod)tcpreceive_new, (t_method)tcpreceive_free,
- sizeof(t_tcpreceive),
- 0,
- A_DEFFLOAT, 0);
-
- class_addmethod(tcpreceive_class, (t_method)tcpreceive_port, gensym("port"), A_DEFFLOAT, 0);
-
- class_addmethod(tcpreceive_class, (t_method)tcpreceive_serialize, gensym("serialize"), A_FLOAT, 0);
+ (t_newmethod)tcpreceive_new, (t_method)tcpreceive_free,
+ sizeof(t_tcpreceive),
+ 0,
+ A_DEFFLOAT, 0);
+
+ class_addmethod(tcpreceive_class, (t_method)tcpreceive_port,
+ gensym("port"), A_DEFFLOAT, 0);
+
+ class_addmethod(tcpreceive_class, (t_method)tcpreceive_serialize,
+ gensym("serialize"), A_FLOAT, 0);
DEBUGMETHOD(tcpreceive_class);
}
diff --git a/tcpsend.c b/tcpsend.c
index ae32f05..664137c 100644
--- a/tcpsend.c
+++ b/tcpsend.c
@@ -1,5 +1,5 @@
/* tcpsend.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,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/ */
/* */
#define DEBUGLEVEL 1
@@ -37,8 +36,7 @@ static const char objName[] = "tcpsend";
static t_class *tcpsend_class;
-typedef struct _tcpsend
-{
+typedef struct _tcpsend {
t_object x_obj;
int x_fd;
t_iemnet_sender*x_sender;
@@ -46,54 +44,55 @@ typedef struct _tcpsend
static void tcpsend_disconnect(t_tcpsend *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");
+ if (x->x_fd >= 0) {
+ if(x->x_sender) {
+ iemnet__sender_destroy(x->x_sender, 0);
}
+ x->x_sender=NULL;
+ iemnet__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;
+ memset(&server, 0, sizeof(server));
- if (x->x_fd >= 0)
- {
- error("tcpsend: already connected");
- return;
- }
+ if (x->x_fd >= 0) {
+ error("tcpsend: already connected");
+ return;
+ }
/* create a socket */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
DEBUG("send socket %d\n", sockfd);
- if (sockfd < 0)
- {
- sys_sockerror("tcpsend: socket");
- return;
- }
+ if (sockfd < 0) {
+ 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)
- {
- post("tcpsend: bad host?\n");
- return;
- }
+ if (hp == 0) {
+ 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)
+ (char *)&intarg, sizeof(intarg)) < 0) {
post("tcpsend: setsockopt (TCP_NODELAY) failed\n");
+ }
memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
@@ -102,15 +101,14 @@ static void tcpsend_connect(t_tcpsend *x, t_symbol *hostname,
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;
- }
+ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) {
+ sys_sockerror("tcpsend: connecting stream socket");
+ iemnet__closesocket(sockfd);
+ return;
+ }
x->x_fd = sockfd;
- x->x_sender=iemnet__sender_create(sockfd);
+ x->x_sender=iemnet__sender_create(sockfd, NULL, NULL, 0);
outlet_float(x->x_obj.ob_outlet, 1);
}
@@ -141,18 +139,20 @@ static void *tcpsend_new(void)
IEMNET_EXTERN void tcpsend_setup(void)
{
- if(!iemnet__register(objName))return;
- tcpsend_class = class_new(gensym(objName),
- (t_newmethod)tcpsend_new, (t_method)tcpsend_free,
- sizeof(t_tcpsend),
- 0, 0);
+ if(!iemnet__register(objName)) {
+ return;
+ }
+ tcpsend_class = class_new(gensym(objName),
+ (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);
+ gensym("connect"), A_SYMBOL, A_FLOAT, 0);
class_addmethod(tcpsend_class, (t_method)tcpsend_disconnect,
- gensym("disconnect"), 0);
+ gensym("disconnect"), 0);
class_addmethod(tcpsend_class, (t_method)tcpsend_send, gensym("send"),
- A_GIMME, 0);
+ A_GIMME, 0);
class_addlist(tcpsend_class, (t_method)tcpsend_send);
DEBUGMETHOD(tcpsend_class);
diff --git a/tcpserver.c b/tcpserver.c
index 59b6132..ca4f38e 100644
--- a/tcpserver.c
+++ b/tcpserver.c
@@ -1,5 +1,5 @@
/* tcpserver.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
*/
@@ -19,9 +19,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/ */
/* */
/* ---------------------------------------------------------------------------- */
@@ -30,6 +29,8 @@
#include "iemnet.h"
#include "iemnet_data.h"
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#define MAX_CONNECT 32 /* maximum number of connections */
@@ -38,45 +39,48 @@
static t_class *tcpserver_class;
static const char objName[] = "tcpserver";
-typedef struct _tcpserver_socketreceiver
-{
+typedef struct _tcpserver_socketreceiver {
struct _tcpserver *sr_owner;
long sr_host;
unsigned short sr_port;
- t_int sr_fd;
+ int sr_fd;
t_iemnet_sender*sr_sender;
t_iemnet_receiver*sr_receiver;
} t_tcpserver_socketreceiver;
-typedef struct _tcpserver
-{
+typedef struct _tcpserver {
t_object x_obj;
t_outlet *x_msgout;
t_outlet *x_connectout;
t_outlet *x_sockout; // legacy
t_outlet *x_addrout; // legacy
- t_outlet *x_statout;
+ t_outlet *x_statout;
int x_serialize;
t_tcpserver_socketreceiver *x_sr[MAX_CONNECT]; /* socket per connection */
- t_int x_nconnections;
+ unsigned int x_nconnections;
- t_int x_connectsocket; /* socket waiting for new connections */
- t_int x_port;
+ int
+ x_connectsocket; /* socket waiting for new connections */
+ int x_port;
- int x_defaulttarget; /* the default connection to send to; 0=broadcast; >0 use this client; <0 exclude this client */
- t_iemnet_floatlist *x_floatlist;
+ int
+ x_defaulttarget; /* the default connection to send to; 0=broadcast; >0 use this client; <0 exclude this client */
+ t_iemnet_floatlist *x_floatlist;
} t_tcpserver;
static void tcpserver_receive_callback(void*x, t_iemnet_chunk*);
-static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new(t_tcpserver *owner, int sockfd, struct sockaddr_in*addr)
+static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new(
+ t_tcpserver *owner, int sockfd, struct sockaddr_in*addr)
{
- t_tcpserver_socketreceiver *x = (t_tcpserver_socketreceiver *)getbytes(sizeof(*x));
+ t_tcpserver_socketreceiver *x = (t_tcpserver_socketreceiver *)getbytes(
+ sizeof(*x));
if(NULL==x) {
- error("%s_socketreceiver: unable to allocate %d bytes", objName, (int)sizeof(*x));
+ error("%s_socketreceiver: unable to allocate %d bytes", objName,
+ (int)sizeof(*x));
return NULL;
} else {
x->sr_owner=owner;
@@ -86,8 +90,9 @@ static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new(t_tcpserver *own
x->sr_host=ntohl(addr->sin_addr.s_addr);
x->sr_port=ntohs(addr->sin_port);
- x->sr_sender=iemnet__sender_create(sockfd);
- x->sr_receiver=iemnet__receiver_create(sockfd, x, tcpserver_receive_callback);
+ x->sr_sender=iemnet__sender_create(sockfd, NULL, NULL, 0);
+ x->sr_receiver=iemnet__receiver_create(sockfd, x,
+ tcpserver_receive_callback, 0);
}
return (x);
}
@@ -95,40 +100,41 @@ static t_tcpserver_socketreceiver *tcpserver_socketreceiver_new(t_tcpserver *own
static void tcpserver_socketreceiver_free(t_tcpserver_socketreceiver *x)
{
DEBUG("freeing %x", x);
- if (x != NULL)
- {
- int sockfd=x->sr_fd;
- t_iemnet_sender*sender=x->sr_sender;
- t_iemnet_receiver*receiver=x->sr_receiver;
-
- x->sr_owner=NULL;
- x->sr_sender=NULL;
- x->sr_receiver=NULL;
-
- x->sr_fd=-1;
-
-
- if(sender) iemnet__sender_destroy(sender);
- if(receiver)iemnet__receiver_destroy(receiver);
-
- sys_closesocket(sockfd);
-
-
- freebytes(x, sizeof(*x));
+ if (x != NULL) {
+ int sockfd=x->sr_fd;
+ t_iemnet_sender*sender=x->sr_sender;
+ t_iemnet_receiver*receiver=x->sr_receiver;
+
+ x->sr_owner=NULL;
+ x->sr_sender=NULL;
+ x->sr_receiver=NULL;
+
+ x->sr_fd=-1;
+
+
+ if(sender) {
+ iemnet__sender_destroy(sender, 0);
+ }
+ if(receiver) {
+ iemnet__receiver_destroy(receiver, 0);
}
+
+ iemnet__closesocket(sockfd);
+
+
+ freebytes(x, sizeof(*x));
+ }
DEBUG("freeed %x", x);
}
static int tcpserver_socket2index(t_tcpserver*x, int sockfd)
{
- int i=0;
- for(i = 0; i < x->x_nconnections; i++) /* check if connection exists */
- {
- if(x->x_sr[i]->sr_fd == sockfd)
- {
- return i;
- }
- }
+ unsigned int i=0;
+ for(i = 0; i < x->x_nconnections; i++) { /* check if connection exists */
+ if(x->x_sr[i]->sr_fd == sockfd) {
+ return i;
+ }
+ }
return -1;
}
@@ -138,28 +144,27 @@ static int tcpserver_socket2index(t_tcpserver*x, int sockfd)
*/
static int tcpserver_fixindex(t_tcpserver*x, int client)
{
- if(x->x_nconnections <= 0)
- {
- pd_error(x, "[%s]: no clients connected", objName);
- return -1;
- }
-
- if (!((client > 0) && (client <= x->x_nconnections)))
- {
- pd_error(x, "[%s] client %d out of range [1..%d]", objName, client, (int)(x->x_nconnections));
- return -1;
- }
+ if(x->x_nconnections <= 0) {
+ pd_error(x, "[%s]: no clients connected", objName);
+ return -1;
+ }
+
+ if (!((client > 0) && (client <= x->x_nconnections))) {
+ pd_error(x, "[%s] client %d out of range [1..%d]", objName, client,
+ (int)(x->x_nconnections));
+ return -1;
+ }
return (client-1);
}
/* ---------------- tcpserver info ---------------------------- */
-static void tcpserver_info_client(t_tcpserver *x, int client)
+static void tcpserver_info_client(t_tcpserver *x, unsigned int client)
{
// "client <id> <socket> <IP> <port>"
// "bufsize <id> <insize> <outsize>"
static t_atom output_atom[4];
- if(x&&x->x_sr&&x->x_sr[client]) {
+ if(x&&client<MAX_CONNECT&&x->x_sr[client]) {
int sockfd = x->x_sr[client]->sr_fd;
unsigned short port = x->x_sr[client]->sr_port;
long address = x->x_sr[client]->sr_host;
@@ -168,7 +173,7 @@ static void tcpserver_info_client(t_tcpserver *x, int client)
int insize =iemnet__receiver_getsize(x->x_sr[client]->sr_receiver);
int outsize=iemnet__sender_getsize (x->x_sr[client]->sr_sender );
- snprintf(hostname, MAXPDSTRING-1, "%d.%d.%d.%d",
+ snprintf(hostname, MAXPDSTRING-1, "%d.%d.%d.%d",
(unsigned char)((address & 0xFF000000)>>24),
(unsigned char)((address & 0x0FF0000)>>16),
(unsigned char)((address & 0x0FF00)>>8),
@@ -190,7 +195,8 @@ static void tcpserver_info_client(t_tcpserver *x, int client)
}
-static void tcpserver_info(t_tcpserver *x) {
+static void tcpserver_info(t_tcpserver *x)
+{
static t_atom output_atom[4];
int sockfd=x->x_connectsocket;
@@ -218,25 +224,26 @@ static void tcpserver_info(t_tcpserver *x) {
}
-static void tcpserver_info_connection(t_tcpserver *x, t_tcpserver_socketreceiver*y)
+static void tcpserver_info_connection(t_tcpserver *x,
+ t_tcpserver_socketreceiver*y)
{
iemnet__addrout(x->x_statout, x->x_addrout, y->sr_host, y->sr_port);
outlet_float(x->x_sockout, y->sr_fd);
}
/* ---------------- main tcpserver (send) stuff --------------------- */
-static void tcpserver_disconnect_socket(t_tcpserver *x, t_floatarg fsocket);
-static void tcpserver_send_bytes(t_tcpserver*x, int client, t_iemnet_chunk*chunk)
+static void tcpserver_disconnect_socket(t_tcpserver *x,
+ t_floatarg fsocket);
+
+static void tcpserver_send_bytes_client(t_tcpserver*x,
+ t_tcpserver_socketreceiver*sr, int client, t_iemnet_chunk*chunk)
{
- DEBUG("send_bytes to %x -> %x[%d]", x, x->x_sr, client);
- if(x->x_sr)DEBUG("client %X", x->x_sr[client]);
- if(x && x->x_sr && x->x_sr[client]) {
+ if(sr) {
t_atom output_atom[3];
int size=-1;
- t_iemnet_sender*sender=sender=x->x_sr[client]->sr_sender;
- int sockfd = x->x_sr[client]->sr_fd;
-
+ t_iemnet_sender*sender=sr->sr_sender;
+ int sockfd = sr->sr_fd;
if(sender) {
size=iemnet__sender_send(sender, chunk);
}
@@ -244,7 +251,7 @@ static void tcpserver_send_bytes(t_tcpserver*x, int client, t_iemnet_chunk*chunk
SETFLOAT(&output_atom[0], client+1);
SETFLOAT(&output_atom[1], size);
SETFLOAT(&output_atom[2], sockfd);
- outlet_anything( x->x_statout, gensym("sent"), 3, output_atom);
+ outlet_anything( x->x_statout, gensym("sendbuffersize"), 3, output_atom);
if(size<0) {
// disconnected!
@@ -253,74 +260,119 @@ static void tcpserver_send_bytes(t_tcpserver*x, int client, t_iemnet_chunk*chunk
}
}
+static void tcpserver_send_bytes(t_tcpserver*x, int client,
+ t_iemnet_chunk*chunk)
+{
+ t_tcpserver_socketreceiver*sr=NULL;
+ if(x&&client<MAX_CONNECT) {
+ sr=x->x_sr[client];
+ }
+ DEBUG("send_bytes to %p[%d] -> %p", x, client, sr);
+ tcpserver_send_bytes_client(x, sr, client, chunk);
+}
+/* send the chunk to all non-null clients */
+static void tcpserver_send_bytes_clients(t_tcpserver*x,
+ t_tcpserver_socketreceiver**sr, unsigned int nsr, t_iemnet_chunk*chunk)
+{
+ unsigned int i=0;
+ for(i=0; i<nsr; i++) {
+ tcpserver_send_bytes_client(x, sr[i], i, chunk);
+ }
+}
/* broadcasts a message to all connected clients but the given one */
-static void tcpserver_send_butclient(t_tcpserver *x, int but, int argc, t_atom *argv)
+static void tcpserver_send_butclient(t_tcpserver *x, unsigned int but,
+ int argc, t_atom *argv)
{
- int client=0;
- t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv);
+ unsigned int client=0;
+ t_iemnet_chunk*chunk=NULL;
+ t_tcpserver_socketreceiver**sr=NULL;
+ if(!x || !x->x_nconnections) {
+ return;
+ }
- /* enumerate through the clients and send each the message */
- for(client = 0; client < x->x_nconnections; client++) /* check if connection exists */
- {
- /* socket exists for this client */
- if(client!=but)tcpserver_send_bytes(x, client, chunk);
- }
+ chunk=iemnet__chunk_create_list(argc, argv);
+ sr=(t_tcpserver_socketreceiver**)calloc(x->x_nconnections,
+ sizeof(t_tcpserver_socketreceiver*));
+
+ for(client=0; client<x->x_nconnections; client++) {
+ sr[client]=x->x_sr[client];
+ }
+
+ if(but<x->x_nconnections) {
+ sr[but]=NULL;
+ }
+
+ tcpserver_send_bytes_clients(x, sr, x->x_nconnections, chunk);
+
+ free(sr);
iemnet__chunk_destroy(chunk);
}
/* sends a message to a given client */
-static void tcpserver_send_toclient(t_tcpserver *x, int client, int argc, t_atom *argv)
+static void tcpserver_send_toclient(t_tcpserver *x, unsigned int client,
+ int argc, t_atom *argv)
{
t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv);
tcpserver_send_bytes(x, client, chunk);
iemnet__chunk_destroy(chunk);
}
-
-
/* send message to client using client number
note that the client numbers might change in case a client disconnects! */
/* clients start at 1 but our index starts at 0 */
-static void tcpserver_send_client(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv)
+static void tcpserver_send_client(t_tcpserver *x, t_symbol *s, int argc,
+ t_atom *argv)
{
int client=0;
-
- if (argc > 0)
- {
- client=tcpserver_fixindex(x, atom_getint(argv));
- if(client<0)return;
- if(argc==1) {
- tcpserver_info_client(x, client);
- } else {
- tcpserver_send_toclient(x, client, argc-1, argv+1);
- }
+
+ if (argc > 0) {
+ client=tcpserver_fixindex(x, atom_getint(argv));
+ if(client<0) {
return;
}
- else
- {
- for(client=0; client<x->x_nconnections; client++)
- tcpserver_info_client(x, client);
+ if(argc==1) {
+ tcpserver_info_client(x, client);
+ } else {
+ tcpserver_send_toclient(x, client, argc-1, argv+1);
+ }
+ return;
+ } else {
+ unsigned int client;
+ for(client=0; client<x->x_nconnections; client++) {
+ tcpserver_info_client(x, client);
}
+ }
}
/* broadcasts a message to all connected clients */
-static void tcpserver_broadcast(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv)
+static void tcpserver_broadcast(t_tcpserver *x, t_symbol *s, int argc,
+ t_atom *argv)
{
- int client;
- t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv);
+ unsigned int client=0;
+ t_iemnet_chunk*chunk=NULL;
+ t_tcpserver_socketreceiver**sr=NULL;
+ if(!x || !x->x_nconnections) {
+ return;
+ }
- /* enumerate through the clients and send each the message */
- for(client = 0; client < x->x_nconnections; client++) /* check if connection exists */
- {
- /* socket exists for this client */
- tcpserver_send_bytes(x, client, chunk);
- }
+ chunk=iemnet__chunk_create_list(argc, argv);
+ sr=(t_tcpserver_socketreceiver**)calloc(x->x_nconnections,
+ sizeof(t_tcpserver_socketreceiver*));
+
+ for(client=0; client<x->x_nconnections; client++) {
+ sr[client]=x->x_sr[client];
+ }
+
+ tcpserver_send_bytes_clients(x, sr, x->x_nconnections, chunk);
+
+ free(sr);
iemnet__chunk_destroy(chunk);
}
/* broadcasts a message to all connected clients */
-static void tcpserver_broadcastbut(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv)
+static void tcpserver_broadcastbut(t_tcpserver *x, t_symbol *s, int argc,
+ t_atom *argv)
{
int but=-1;
//int client=0;
@@ -329,32 +381,48 @@ static void tcpserver_broadcastbut(t_tcpserver *x, t_symbol *s, int argc, t_atom
if(argc<2) {
return;
}
- if((but=tcpserver_fixindex(x, atom_getint(argv)))<0)return;
+ if((but=tcpserver_fixindex(x, atom_getint(argv)))<0) {
+ return;
+ }
tcpserver_send_butclient(x, but, argc-1, argv+1);
}
-static void tcpserver_defaultsend(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv)
+static void tcpserver_defaultsend(t_tcpserver *x, t_symbol *s, int argc,
+ t_atom *argv)
{
int client=-1;
int sockfd=x->x_defaulttarget;
- if(0==sockfd)
- tcpserver_broadcast(x, s, argc, argv);
- else if(sockfd>0) {
+ if(sockfd>0) {
client=tcpserver_socket2index(x, sockfd);
- tcpserver_send_toclient(x, client, argc, argv);
+ if(client>=0) {
+ tcpserver_send_toclient(x, client, argc, argv);
+ return;
+ }
+ pd_error(x, "[%s] illegal socket %d, switching to broadcast mode", objName,
+ sockfd);
+ x->x_defaulttarget=0;
} else if(sockfd<0) {
client=tcpserver_socket2index(x, -sockfd);
- tcpserver_send_butclient(x, client, argc, argv);
+ if(client>=0) {
+ tcpserver_send_butclient(x, client, argc, argv);
+ return;
+ }
+ pd_error(x, "[%s] illegal !ocket %d, switching to broadcast mode", objName,
+ sockfd);
+ x->x_defaulttarget=0;
}
+
+ tcpserver_broadcast(x, s, argc, argv);
}
static void tcpserver_defaulttarget(t_tcpserver *x, t_floatarg f)
{
int sockfd=0;
int rawclient=f;
- int client=(rawclient<0)?(-rawclient):rawclient;
+ unsigned int client=(rawclient<0)?(-rawclient):rawclient;
if(client > x->x_nconnections) {
- error("[%s] target %d out of range [0..%d]", objName, client, (int)(x->x_nconnections));
+ error("[%s] target %d out of range [0..%d]", objName, client,
+ (int)(x->x_nconnections));
return;
}
@@ -363,7 +431,9 @@ static void tcpserver_defaulttarget(t_tcpserver *x, t_floatarg f)
sockfd=x->x_sr[client-1]->sr_fd;
}
- if(rawclient<0)sockfd=-sockfd;
+ if(rawclient<0) {
+ sockfd=-sockfd;
+ }
x->x_defaulttarget=sockfd;
}
@@ -376,43 +446,42 @@ static void tcpserver_targetsocket(t_tcpserver *x, t_floatarg f)
/* send message to client using socket number */
-static void tcpserver_send_socket(t_tcpserver *x, t_symbol *s, int argc, t_atom *argv)
+static void tcpserver_send_socket(t_tcpserver *x, t_symbol *s, int argc,
+ t_atom *argv)
{
int client = -1;
t_iemnet_chunk*chunk=NULL;
if(argc) {
client = tcpserver_socket2index(x, atom_getint(argv));
- if(client<0)return;
+ if(client<0) {
+ return;
+ }
} else {
pd_error(x, "%s_send: no socket specified", objName);
return;
}
/* get socket number of connection (first element in list) */
- if(argc && argv->a_type == A_FLOAT)
- {
- int sockfd=atom_getint(argv);
- client = tcpserver_socket2index(x, sockfd);
- if(client < 0)
- {
- post("%s_send: no connection on socket %d", objName, sockfd);
- return;
- }
- }
- else
- {
- post("%s_send: no socket specified", objName);
+ if(argc && argv->a_type == A_FLOAT) {
+ int sockfd=atom_getint(argv);
+ client = tcpserver_socket2index(x, sockfd);
+ if(client < 0) {
+ post("%s_send: no connection on socket %d", objName, sockfd);
return;
}
-
+ } else {
+ post("%s_send: no socket specified", objName);
+ return;
+ }
+
chunk=iemnet__chunk_create_list(argc-1, argv+1);
tcpserver_send_bytes(x, client, chunk);
iemnet__chunk_destroy(chunk);
}
-static void tcpserver_disconnect(t_tcpserver *x, int client)
+static void tcpserver_disconnect(t_tcpserver *x, unsigned int client)
{
- int k;
+ unsigned int k;
DEBUG("disconnect %x %d", x, client);
tcpserver_info_connection(x, x->x_sr[client]);
@@ -420,10 +489,9 @@ static void tcpserver_disconnect(t_tcpserver *x, int client)
x->x_sr[client]=NULL;
/* rearrange list now: move entries to close the gap */
- for(k = client; k < x->x_nconnections; k++)
- {
- x->x_sr[k] = x->x_sr[k + 1];
- }
+ for(k = client; k < x->x_nconnections; k++) {
+ x->x_sr[k] = x->x_sr[k + 1];
+ }
x->x_sr[k + 1]=NULL;
x->x_nconnections--;
@@ -437,7 +505,9 @@ static void tcpserver_disconnect_client(t_tcpserver *x, t_floatarg fclient)
{
int client = tcpserver_fixindex(x, fclient);
- if(client<0)return;
+ if(client<0) {
+ return;
+ }
tcpserver_disconnect(x, client);
}
@@ -446,8 +516,9 @@ static void tcpserver_disconnect_client(t_tcpserver *x, t_floatarg fclient)
static void tcpserver_disconnect_socket(t_tcpserver *x, t_floatarg fsocket)
{
int id=tcpserver_socket2index(x, (int)fsocket);
- if(id>=0)
+ if(id>=0) {
tcpserver_disconnect_client(x, id+1);
+ }
}
@@ -455,23 +526,28 @@ static void tcpserver_disconnect_socket(t_tcpserver *x, t_floatarg fsocket)
/* disconnect a client by socket */
static void tcpserver_disconnect_all(t_tcpserver *x)
{
- int id=x->x_nconnections;
- while(--id>=0) {
+ unsigned int id;
+ for(id=0; id<x->x_nconnections; id++) {
tcpserver_disconnect(x, id);
}
}
/* ---------------- main tcpserver (receive) stuff --------------------- */
-static void tcpserver_receive_callback(void *y0,
- t_iemnet_chunk*c) {
+static void tcpserver_receive_callback(void *y0,
+ t_iemnet_chunk*c)
+{
t_tcpserver_socketreceiver *y=(t_tcpserver_socketreceiver*)y0;
t_tcpserver*x=NULL;
- if(NULL==y || NULL==(x=y->sr_owner))return;
-
+ if(NULL==y || NULL==(x=y->sr_owner)) {
+ return;
+ }
+
if(c) {
tcpserver_info_connection(x, y);
- 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
int sockfd=y->sr_fd;
@@ -486,25 +562,33 @@ static void tcpserver_connectpoll(t_tcpserver *x)
{
struct sockaddr_in incomer_address;
socklen_t sockaddrl = sizeof( struct sockaddr );
- int fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl);
+ int fd = accept(x->x_connectsocket,
+ (struct sockaddr*)&incomer_address, &sockaddrl);
int i;
- if (fd < 0) post("%s: accept failed", objName);
- else
- {
- t_tcpserver_socketreceiver *y = tcpserver_socketreceiver_new((void *)x, fd, &incomer_address);
- if (!y)
- {
- sys_closesocket(fd);
- return;
- }
- x->x_nconnections++;
- i = x->x_nconnections - 1;
- x->x_sr[i] = y;
-
- tcpserver_info_connection(x, y);
+ if (fd < 0) {
+ post("%s: accept failed", objName);
+ } else {
+ t_tcpserver_socketreceiver *y = NULL;
+ if(x->x_nconnections>=MAX_CONNECT) {
+ pd_error(x, "%s: cannot handle more than %d connections, dropping",
+ objName, x->x_nconnections);
+ iemnet__closesocket(fd);
}
+
+ y = tcpserver_socketreceiver_new((void *)x, fd, &incomer_address);
+ if (!y) {
+ iemnet__closesocket(fd);
+ return;
+ }
+ x->x_nconnections++;
+ i = x->x_nconnections - 1;
+ x->x_sr[i] = y;
+
+ tcpserver_info_connection(x, y);
+ }
+
outlet_float(x->x_connectout, x->x_nconnections);
}
@@ -515,6 +599,8 @@ static void tcpserver_port(t_tcpserver*x, t_floatarg fportno)
struct sockaddr_in server;
socklen_t serversize=sizeof(server);
int sockfd = x->x_connectsocket;
+ memset(&server, 0, sizeof(server));
+
SETFLOAT(ap, -1);
if(x->x_port == portno) {
return;
@@ -523,14 +609,16 @@ static void tcpserver_port(t_tcpserver*x, t_floatarg fportno)
/* cleanup any open ports */
if(sockfd>=0) {
sys_rmpollfn(sockfd);
- sys_closesocket(sockfd);
+ iemnet__closesocket(sockfd);
x->x_connectsocket=-1;
x->x_port=-1;
}
-
sockfd = socket(AF_INET, SOCK_STREAM, 0);
-
+ if(sockfd<0) {
+ sys_sockerror("[tcpserver]: cannot create TCP/IP socket");
+ return;
+ }
server.sin_family = AF_INET;
@@ -540,27 +628,24 @@ static void tcpserver_port(t_tcpserver*x, t_floatarg fportno)
/* assign server port number */
server.sin_port = htons((u_short)portno);
/* name the socket */
- if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0)
- {
- sys_sockerror("tcpserver: bind");
- sys_closesocket(sockfd);
- outlet_anything(x->x_statout, gensym("port"), 1, ap);
- return;
- }
+ if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0) {
+ sys_sockerror("tcpserver: bind");
+ iemnet__closesocket(sockfd);
+ outlet_anything(x->x_statout, gensym("port"), 1, ap);
+ return;
+ }
/* streaming protocol */
- if (listen(sockfd, 5) < 0)
- {
- sys_sockerror("tcpserver: listen");
- sys_closesocket(sockfd);
- sockfd = -1;
- outlet_anything(x->x_statout, gensym("port"), 1, ap);
- return;
- }
- else
- {
- sys_addpollfn(sockfd, (t_fdpollfn)tcpserver_connectpoll, x); // wait for new connections
- }
+ if (listen(sockfd, 5) < 0) {
+ sys_sockerror("tcpserver: listen");
+ iemnet__closesocket(sockfd);
+ sockfd = -1;
+ outlet_anything(x->x_statout, gensym("port"), 1, ap);
+ return;
+ } else {
+ sys_addpollfn(sockfd, (t_fdpollfn)tcpserver_connectpoll,
+ x); // wait for new connections
+ }
x->x_connectsocket = sockfd;
x->x_port = portno;
@@ -576,7 +661,8 @@ static void tcpserver_port(t_tcpserver*x, t_floatarg fportno)
outlet_anything(x->x_statout, gensym("port"), 1, ap);
}
-static void tcpserver_serialize(t_tcpserver *x, t_floatarg doit) {
+static void tcpserver_serialize(t_tcpserver *x, t_floatarg doit)
+{
x->x_serialize=doit;
}
@@ -589,10 +675,12 @@ static void *tcpserver_new(t_floatarg fportno)
x = (t_tcpserver *)pd_new(tcpserver_class);
x->x_msgout = outlet_new(&x->x_obj, 0); /* 1st outlet for received data */
- x->x_connectout = outlet_new(&x->x_obj, gensym("float")); /* 2nd outlet for number of connected clients */
+ x->x_connectout = outlet_new(&x->x_obj,
+ gensym("float")); /* 2nd outlet for number of connected clients */
x->x_sockout = outlet_new(&x->x_obj, gensym("float"));
x->x_addrout = outlet_new(&x->x_obj, gensym("list" ));
- x->x_statout = outlet_new(&x->x_obj, 0);/* 5th outlet for everything else */
+ x->x_statout = outlet_new(&x->x_obj,
+ 0);/* 5th outlet for everything else */
x->x_serialize=1;
@@ -600,14 +688,13 @@ static void *tcpserver_new(t_floatarg fportno)
x->x_port = -1;
x->x_nconnections = 0;
- for(i = 0; i < MAX_CONNECT; i++)
- {
- x->x_sr[i] = NULL;
- }
+ for(i = 0; i < MAX_CONNECT; i++) {
+ x->x_sr[i] = NULL;
+ }
x->x_defaulttarget=0;
-
-
+
+
x->x_floatlist=iemnet__floatlist_create(1024);
tcpserver_port(x, fportno);
@@ -619,46 +706,60 @@ static void tcpserver_free(t_tcpserver *x)
{
int i;
- for(i = 0; i < MAX_CONNECT; i++)
- {
- if (NULL!=x->x_sr[i]) {
- DEBUG("[%s] free %x", objName, x);
- tcpserver_socketreceiver_free(x->x_sr[i]);
- x->x_sr[i]=NULL;
- }
+ for(i = 0; i < MAX_CONNECT; i++) {
+ if (NULL!=x->x_sr[i]) {
+ DEBUG("[%s] free %x", objName, x);
+ tcpserver_socketreceiver_free(x->x_sr[i]);
+ x->x_sr[i]=NULL;
}
- if (x->x_connectsocket >= 0)
- {
- sys_rmpollfn(x->x_connectsocket);
- sys_closesocket(x->x_connectsocket);
- }
- if(x->x_floatlist)iemnet__floatlist_destroy(x->x_floatlist);x->x_floatlist=NULL;
+ }
+ if (x->x_connectsocket >= 0) {
+ sys_rmpollfn(x->x_connectsocket);
+ iemnet__closesocket(x->x_connectsocket);
+ }
+ if(x->x_floatlist) {
+ iemnet__floatlist_destroy(x->x_floatlist);
+ }
+ x->x_floatlist=NULL;
}
IEMNET_EXTERN void tcpserver_setup(void)
{
- if(!iemnet__register(objName))return;
+ if(!iemnet__register(objName)) {
+ return;
+ }
- tcpserver_class = class_new(gensym(objName),(t_newmethod)tcpserver_new, (t_method)tcpserver_free,
+ tcpserver_class = class_new(gensym(objName),(t_newmethod)tcpserver_new,
+ (t_method)tcpserver_free,
sizeof(t_tcpserver), 0, A_DEFFLOAT, 0);
- class_addmethod(tcpserver_class, (t_method)tcpserver_disconnect_client, gensym("disconnectclient"), A_DEFFLOAT, 0);
- class_addmethod(tcpserver_class, (t_method)tcpserver_disconnect_socket, gensym("disconnectsocket"), A_DEFFLOAT, 0);
- class_addmethod(tcpserver_class, (t_method)tcpserver_disconnect_all, gensym("disconnect"), 0);
-
- class_addmethod(tcpserver_class, (t_method)tcpserver_send_socket, gensym("send"), A_GIMME, 0);
- class_addmethod(tcpserver_class, (t_method)tcpserver_send_client, gensym("client"), A_GIMME, 0);
-
- class_addmethod(tcpserver_class, (t_method)tcpserver_broadcast, gensym("broadcast"), A_GIMME, 0);
-
- class_addmethod(tcpserver_class, (t_method)tcpserver_defaulttarget, gensym("target"), A_DEFFLOAT, 0);
- class_addmethod(tcpserver_class, (t_method)tcpserver_targetsocket, gensym("targetsocket"), A_DEFFLOAT, 0);
+ class_addmethod(tcpserver_class, (t_method)tcpserver_disconnect_client,
+ gensym("disconnectclient"), A_DEFFLOAT, 0);
+ class_addmethod(tcpserver_class, (t_method)tcpserver_disconnect_socket,
+ gensym("disconnectsocket"), A_DEFFLOAT, 0);
+ class_addmethod(tcpserver_class, (t_method)tcpserver_disconnect_all,
+ gensym("disconnect"), 0);
+
+ class_addmethod(tcpserver_class, (t_method)tcpserver_send_socket,
+ gensym("send"), A_GIMME, 0);
+ class_addmethod(tcpserver_class, (t_method)tcpserver_send_client,
+ gensym("client"), A_GIMME, 0);
+
+ class_addmethod(tcpserver_class, (t_method)tcpserver_broadcast,
+ gensym("broadcast"), A_GIMME, 0);
+
+ class_addmethod(tcpserver_class, (t_method)tcpserver_defaulttarget,
+ gensym("target"), A_DEFFLOAT, 0);
+ class_addmethod(tcpserver_class, (t_method)tcpserver_targetsocket,
+ gensym("targetsocket"), A_DEFFLOAT, 0);
class_addlist (tcpserver_class, (t_method)tcpserver_defaultsend);
- class_addmethod(tcpserver_class, (t_method)tcpserver_serialize, gensym("serialize"), A_FLOAT, 0);
+ class_addmethod(tcpserver_class, (t_method)tcpserver_serialize,
+ gensym("serialize"), A_FLOAT, 0);
- class_addmethod(tcpserver_class, (t_method)tcpserver_port, gensym("port"), A_DEFFLOAT, 0);
+ class_addmethod(tcpserver_class, (t_method)tcpserver_port, gensym("port"),
+ A_DEFFLOAT, 0);
class_addbang (tcpserver_class, (t_method)tcpserver_info);
DEBUGMETHOD(tcpserver_class);
diff --git a/tests/sequence/01_server.pd b/tests/sequence/01_server.pd
index 8e84863..200e97b 100644
--- a/tests/sequence/01_server.pd
+++ b/tests/sequence/01_server.pd
@@ -1,59 +1,59 @@
-#N canvas 219 165 438 532 10;
-#X obj 71 256 tcpserver 9999;
-#X obj 71 278 t b;
-#X obj 71 300 i;
-#X obj 115 326 + 1;
-#X obj 115 348 % 255;
-#X obj 250 252 loadbang;
-#X msg 71 388 broadcast \$1;
-#X obj 71 429 list append;
-#X obj 250 274 f 1024;
-#X obj 250 296 t b f b;
-#X obj 250 438 list prepend;
-#X obj 273 319 until;
-#X obj 273 341 f 255;
-#X obj 273 363 list prepend;
-#X obj 273 385 t l l;
-#X msg 106 276 bang;
-#X msg 321 250 bang;
-#X obj 71 451 list trim;
-#X obj 23 229 t a;
-#X text 27 43 responds to any data from the client by sending pack
-a stream consisting of a header and a dummy payload.;
-#X text 31 84 the dummy payload is a number of 0xFF bytes;
-#X obj 71 322 t f f;
-#X text 32 99 the header is a single byte counting up from 0..254 (and
-wrapping around);
-#X floatatom 166 305 5 0 0 0 - - -;
-#X obj 152 169 route sent;
-#X obj 152 191 unpack 0 0 0;
-#X floatatom 186 225 0 0 0 0 - - -;
-#X floatatom 221 211 5 0 0 0 - - -;
-#X connect 0 0 1 0;
-#X connect 0 4 24 0;
-#X connect 1 0 2 0;
-#X connect 2 0 21 0;
-#X connect 3 0 4 0;
-#X connect 4 0 2 1;
-#X connect 5 0 8 0;
-#X connect 6 0 7 0;
-#X connect 7 0 17 0;
-#X connect 8 0 9 0;
-#X connect 9 0 10 0;
-#X connect 9 1 11 0;
-#X connect 10 0 7 1;
-#X connect 11 0 12 0;
-#X connect 12 0 13 0;
-#X connect 13 0 14 0;
-#X connect 14 0 10 1;
-#X connect 14 1 13 1;
-#X connect 15 0 1 0;
-#X connect 16 0 8 0;
-#X connect 17 0 18 0;
-#X connect 18 0 0 0;
-#X connect 21 0 6 0;
-#X connect 21 1 3 0;
-#X connect 23 0 3 1;
-#X connect 24 0 25 0;
-#X connect 25 1 26 0;
-#X connect 25 2 27 0;
+#N canvas 219 165 438 532 10;
+#X obj 71 256 tcpserver 9999;
+#X obj 71 278 t b;
+#X obj 71 300 i;
+#X obj 115 326 + 1;
+#X obj 115 348 % 255;
+#X obj 250 252 loadbang;
+#X msg 71 388 broadcast \$1;
+#X obj 71 429 list append;
+#X obj 250 274 f 1024;
+#X obj 250 296 t b f b;
+#X obj 250 438 list prepend;
+#X obj 273 319 until;
+#X obj 273 341 f 255;
+#X obj 273 363 list prepend;
+#X obj 273 385 t l l;
+#X msg 106 276 bang;
+#X msg 321 250 bang;
+#X obj 71 451 list trim;
+#X obj 23 229 t a;
+#X text 27 43 responds to any data from the client by sending pack
+a stream consisting of a header and a dummy payload.;
+#X text 31 84 the dummy payload is a number of 0xFF bytes;
+#X obj 71 322 t f f;
+#X text 32 99 the header is a single byte counting up from 0..254 (and
+wrapping around);
+#X floatatom 166 305 5 0 0 0 - - -;
+#X obj 152 169 route sent;
+#X obj 152 191 unpack 0 0 0;
+#X floatatom 186 225 0 0 0 0 - - -;
+#X floatatom 221 211 5 0 0 0 - - -;
+#X connect 0 0 1 0;
+#X connect 0 4 24 0;
+#X connect 1 0 2 0;
+#X connect 2 0 21 0;
+#X connect 3 0 4 0;
+#X connect 4 0 2 1;
+#X connect 5 0 8 0;
+#X connect 6 0 7 0;
+#X connect 7 0 17 0;
+#X connect 8 0 9 0;
+#X connect 9 0 10 0;
+#X connect 9 1 11 0;
+#X connect 10 0 7 1;
+#X connect 11 0 12 0;
+#X connect 12 0 13 0;
+#X connect 13 0 14 0;
+#X connect 14 0 10 1;
+#X connect 14 1 13 1;
+#X connect 15 0 1 0;
+#X connect 16 0 8 0;
+#X connect 17 0 18 0;
+#X connect 18 0 0 0;
+#X connect 21 0 6 0;
+#X connect 21 1 3 0;
+#X connect 23 0 3 1;
+#X connect 24 0 25 0;
+#X connect 25 1 26 0;
+#X connect 25 2 27 0;
diff --git a/udpclient.c b/udpclient.c
index 4ebca84..b643fdc 100644
--- a/udpclient.c
+++ b/udpclient.c
@@ -1,5 +1,5 @@
/* udpclient.c
- * copyright (c) 2010 IOhannes m zmölnig, IEM
+ * copyright (c) 2010 IOhannes m zmölnig, IEM
*/
/* */
@@ -16,9 +16,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/ */
/* */
/* ---------------------------------------------------------------------------- */
@@ -34,8 +33,7 @@ static t_class *udpclient_class;
static const char objName[] = "udpclient";
-typedef struct _udpclient
-{
+typedef struct _udpclient {
t_object x_obj;
t_clock *x_clock;
t_outlet *x_msgout;
@@ -58,7 +56,7 @@ typedef struct _udpclient
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_udpclient;
@@ -68,47 +66,43 @@ static void udpclient_receive_callback(void *x, t_iemnet_chunk*);
/* connection handling */
-static void *udpclient_child_connect(void *w)
+static void *udpclient_doconnect(t_udpclient*x, int subthread)
{
- t_udpclient *x = (t_udpclient*) w;
-
struct sockaddr_in server;
struct hostent *hp;
int sockfd;
int broadcast = 1;/* nonzero is true */
+ memset(&server, 0, sizeof(server));
- if (x->x_sender)
- {
- error("[%s] already connected", objName);
- return (x);
- }
+ if (x->x_sender) {
+ error("[%s] already connected", objName);
+ return (x);
+ }
/* create a socket */
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
DEBUG("send socket %d\n", sockfd);
- if (sockfd < 0)
- {
- sys_sockerror("udpclient: socket");
- return (x);
- }
+ if (sockfd < 0) {
+ sys_sockerror("udpclient: socket");
+ return (x);
+ }
/* Based on zmoelnig's patch 2221504:
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);
- }
+ if( 0 != setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
+ (const void *)&broadcast, sizeof(broadcast))) {
+ error("[%s] couldn't switch to broadcast mode", objName);
+ }
#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 (hp == 0) {
+ error("[%s] bad host '%s'?", objName, x->x_hostname);
+ return (x);
+ }
memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
/* assign client port number */
@@ -116,23 +110,29 @@ static void *udpclient_child_connect(void *w)
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");
- sys_closesocket(sockfd);
- return (x);
- }
+ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) {
+ sys_sockerror("udpclient: connecting stream socket");
+ iemnet__closesocket(sockfd);
+ return (x);
+ }
x->x_fd = sockfd;
x->x_addr = ntohl(*(long *)hp->h_addr);
- x->x_sender=iemnet__sender_create(sockfd);
- x->x_receiver=iemnet__receiver_create(sockfd, x, udpclient_receive_callback);
+ x->x_sender=iemnet__sender_create(sockfd, NULL, NULL, subthread);
+ x->x_receiver=iemnet__receiver_create(sockfd, x,
+ 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);
@@ -141,38 +141,54 @@ static void udpclient_tick(t_udpclient *x)
static void udpclient_disconnect(t_udpclient *x)
{
- if (x->x_fd >= 0)
- {
+ 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); x->x_receiver=NULL;
- if(x->x_sender)iemnet__sender_destroy(x->x_sender); x->x_sender=NULL;
-
- sys_closesocket(x->x_fd);
- x->x_fd = -1;
- x->x_connectstate = 0;
- outlet_float(x->x_connectout, 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);
}
- else pd_error(x, "[%s] not connected", objName);
+ x->x_sender=NULL;
+
+ iemnet__closesocket(x->x_fd);
+ x->x_fd = -1;
+ x->x_connectstate = 0;
+ outlet_float(x->x_connectout, 0);
+ } else {
+ pd_error(x, "[%s] not connected", objName);
+ }
}
-static void udpclient_connect(t_udpclient *x, t_symbol *hostname, t_floatarg fportno)
+static void udpclient_connect(t_udpclient *x, t_symbol *hostname,
+ t_floatarg fportno)
{
- if(x->x_fd>=0)udpclient_disconnect(x);
+ if(x->x_fd>=0) {
+ udpclient_disconnect(x);
+ }
/* 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;
+#if 0
/* start child thread */
- if(pthread_create(&x->x_threadid, &x->x_threadattr, udpclient_child_connect, x) < 0)
+ 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)
+static void udpclient_send(t_udpclient *x, t_symbol *s, int argc,
+ t_atom *argv)
{
int size=0;
t_atom output_atom;
@@ -185,16 +201,20 @@ static void udpclient_send(t_udpclient *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);
}
-static void udpclient_receive_callback(void*y, t_iemnet_chunk*c) {
+static void udpclient_receive_callback(void*y, t_iemnet_chunk*c)
+{
t_udpclient *x=(t_udpclient*)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); // 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 {
// disconnected
DEBUG("disconnected");
@@ -211,8 +231,10 @@ 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_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_fd = -1;
x->x_addr = 0L;
@@ -226,11 +248,14 @@ static void *udpclient_new(void)
x->x_floatlist=iemnet__floatlist_create(1024);
/* prepare child thread */
- if(pthread_attr_init(&x->x_threadattr) < 0)
+ 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)
+ }
+ if(pthread_attr_setdetachstate(&x->x_threadattr,
+ PTHREAD_CREATE_DETACHED) < 0) {
verbose(1, "[%s] warning: could not prepare child thread", objName);
-
+ }
+
return (x);
}
@@ -238,20 +263,31 @@ static void *udpclient_new(void)
static void udpclient_free(t_udpclient *x)
{
udpclient_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;
+ 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;
}
IEMNET_EXTERN void udpclient_setup(void)
{
- if(!iemnet__register(objName))return;
+ if(!iemnet__register(objName)) {
+ return;
+ }
udpclient_class = class_new(gensym(objName), (t_newmethod)udpclient_new,
(t_method)udpclient_free,
sizeof(t_udpclient), 0, A_DEFFLOAT, 0);
- class_addmethod(udpclient_class, (t_method)udpclient_connect, gensym("connect")
+ class_addmethod(udpclient_class, (t_method)udpclient_connect,
+ gensym("connect")
, A_SYMBOL, A_FLOAT, 0);
- class_addmethod(udpclient_class, (t_method)udpclient_disconnect, gensym("disconnect"), 0);
- class_addmethod(udpclient_class, (t_method)udpclient_send, gensym("send"), A_GIMME, 0);
+ class_addmethod(udpclient_class, (t_method)udpclient_disconnect,
+ gensym("disconnect"), 0);
+ class_addmethod(udpclient_class, (t_method)udpclient_send, gensym("send"),
+ A_GIMME, 0);
class_addlist(udpclient_class, (t_method)udpclient_send);
DEBUGMETHOD(udpclient_class);
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);
}
diff --git a/udpsend.c b/udpsend.c
index 7def6cf..620f7c0 100644
--- a/udpsend.c
+++ b/udpsend.c
@@ -1,5 +1,5 @@
/* udpsend.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,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/ */
/* */
#define DEBUGLEVEL 1
@@ -32,44 +31,42 @@ static const char objName[] = "udpsend";
static t_class *udpsend_class;
-typedef struct _udpsend
-{
+typedef struct _udpsend {
t_object x_obj;
t_iemnet_sender*x_sender;
} t_udpsend;
static void udpsend_connect(t_udpsend *x, t_symbol *hostname,
- t_floatarg fportno)
+ t_floatarg fportno)
{
struct sockaddr_in server;
int sockfd;
int portno = fportno;
int broadcast = 1;/* nonzero is true */
+ memset(&server, 0, sizeof(server));
- if (x->x_sender)
- {
- error("[%s] already connected", objName);
- return;
- }
+ if (x->x_sender) {
+ error("[%s] already connected", objName);
+ return;
+ }
/* create a socket */
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
DEBUG("send socket %d\n", sockfd);
- if (sockfd < 0)
- {
- sys_sockerror("[udpsend] socket");
- return;
- }
+ if (sockfd < 0) {
+ sys_sockerror("[udpsend] socket");
+ return;
+ }
/* Based on zmoelnig's patch 2221504:
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);
- }
+ if( 0 != setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
+ (const void *)&broadcast, sizeof(broadcast))) {
+ error("[%s] couldn't switch to broadcast mode", objName);
+ }
#endif /* SO_BROADCAST */
-
+
/* connect socket using hostname provided in command line */
server.sin_family = AF_INET;
@@ -82,20 +79,19 @@ static void udpsend_connect(t_udpsend *x, t_symbol *hostname,
} else {
struct addrinfo * res;
for (res = addr; res != NULL; res = res->ai_next) {
- struct sockaddr_in *sa = (struct sockaddr_in *) res->ai_addr;
- int len = res->ai_addrlen;
- // memcpy((char *)&server.sin_addr, (char *)res->ai_addr, hp->h_length);
- // LATER check how to do that...
+ struct sockaddr_in *sa = (struct sockaddr_in *) res->ai_addr;
+ int len = res->ai_addrlen;
+ // memcpy((char *)&server.sin_addr, (char *)res->ai_addr, hp->h_length);
+ // LATER check how to do that...
}
}
freeaddrinfo(addr);
#else
struct hostent *hp = gethostbyname(hostname->s_name);
- if (hp == 0)
- {
- error("[%s] bad host '%s'?", objName, hostname->s_name);
- return;
- }
+ if (hp == 0) {
+ error("[%s] bad host '%s'?", objName, hostname->s_name);
+ return;
+ }
memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
#endif
} while(0);
@@ -105,20 +101,19 @@ static void udpsend_connect(t_udpsend *x, t_symbol *hostname,
DEBUG("connecting to port %d", portno);
/* try to connect. */
- if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
- {
- sys_sockerror("[udpsend] connecting stream socket");
- sys_closesocket(sockfd);
- return;
- }
- x->x_sender=iemnet__sender_create(sockfd);
+ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0) {
+ sys_sockerror("[udpsend] connecting stream socket");
+ iemnet__closesocket(sockfd);
+ return;
+ }
+ x->x_sender=iemnet__sender_create(sockfd, NULL, NULL, 0);
outlet_float(x->x_obj.ob_outlet, 1);
}
static void udpsend_disconnect(t_udpsend *x)
{
if(x->x_sender) {
- iemnet__sender_destroy(x->x_sender);
+ iemnet__sender_destroy(x->x_sender, 0);
x->x_sender=NULL;
outlet_float(x->x_obj.ob_outlet, 0);
}
@@ -150,18 +145,20 @@ static void *udpsend_new(void)
IEMNET_EXTERN void udpsend_setup(void)
{
- if(!iemnet__register(objName))return;
+ if(!iemnet__register(objName)) {
+ return;
+ }
udpsend_class = class_new(gensym(objName), (t_newmethod)udpsend_new,
- (t_method)udpsend_free,
- sizeof(t_udpsend), 0, 0);
+ (t_method)udpsend_free,
+ sizeof(t_udpsend), 0, 0);
class_addmethod(udpsend_class, (t_method)udpsend_connect,
- gensym("connect"), A_SYMBOL, A_FLOAT, 0);
+ gensym("connect"), A_SYMBOL, A_FLOAT, 0);
class_addmethod(udpsend_class, (t_method)udpsend_disconnect,
- gensym("disconnect"), 0);
+ gensym("disconnect"), 0);
class_addmethod(udpsend_class, (t_method)udpsend_send, gensym("send"),
- A_GIMME, 0);
+ A_GIMME, 0);
class_addlist(udpsend_class, (t_method)udpsend_send);
DEBUGMETHOD(udpsend_class);
}
diff --git a/udpserver.c b/udpserver.c
index 93bf10b..df4b389 100644
--- a/udpserver.c
+++ b/udpserver.c
@@ -2,7 +2,7 @@
*
* listens on a UDP-socket for bi-directional communication
*
- * 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
*/
@@ -22,9 +22,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/ */
/* */
/* ---------------------------------------------------------------------------- */
@@ -32,6 +31,7 @@
#include "iemnet.h"
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#define MAX_CONNECT 32 /* maximum number of connections */
@@ -40,8 +40,7 @@
static t_class *udpserver_class;
static const char objName[] = "udpserver";
-typedef struct _udpserver_sender
-{
+typedef struct _udpserver_sender {
struct _udpserver *sr_owner;
long sr_host;
@@ -50,8 +49,7 @@ typedef struct _udpserver_sender
t_iemnet_sender*sr_sender;
} t_udpserver_sender;
-typedef struct _udpserver
-{
+typedef struct _udpserver {
t_object x_obj;
t_outlet *x_msgout;
t_outlet *x_connectout;
@@ -62,19 +60,24 @@ typedef struct _udpserver
t_udpserver_sender *x_sr[MAX_CONNECT]; /* socket per connection */
t_int x_nconnections;
- t_int x_connectsocket; /* socket waiting for new connections */
+ t_int
+ x_connectsocket; /* socket waiting for new connections */
t_int x_port;
- unsigned char x_accept; /* whether we accept new connections or not */
+ unsigned char
+ x_accept; /* whether we accept new connections or not */
- int x_defaulttarget; /* the default connection to send to; 0=broadcast; >0 use this client; <0 exclude this client */
+ int
+ x_defaulttarget; /* the default connection to send to; 0=broadcast; >0 use this client; <0 exclude this client */
t_iemnet_receiver *x_receiver;
t_iemnet_floatlist *x_floatlist;
} t_udpserver;
-static t_udpserver_sender *udpserver_sender_new(t_udpserver *owner, unsigned long host, unsigned short port)
+static t_udpserver_sender *udpserver_sender_new(t_udpserver *owner,
+ unsigned long host, unsigned short port)
{
- t_udpserver_sender *x = (t_udpserver_sender *)malloc(sizeof(t_udpserver_sender));
+ t_udpserver_sender *x = (t_udpserver_sender *)malloc(sizeof(
+ t_udpserver_sender));
if(NULL==x) {
error("%s_sender: unable to allocate %d bytes", objName, (int)sizeof(*x));
return NULL;
@@ -87,7 +90,7 @@ static t_udpserver_sender *udpserver_sender_new(t_udpserver *owner, unsigned lo
x->sr_host=host; //ntohl(addr->sin_addr.s_addr);
x->sr_port=port; //ntohs(addr->sin_port);
- x->sr_sender=iemnet__sender_create(sockfd);
+ x->sr_sender=iemnet__sender_create(sockfd, NULL, NULL, 0);
}
return (x);
}
@@ -95,39 +98,40 @@ static t_udpserver_sender *udpserver_sender_new(t_udpserver *owner, unsigned lo
static void udpserver_sender_free(t_udpserver_sender *x)
{
DEBUG("freeing %x", x);
- if (x != NULL)
- {
- int sockfd=x->sr_fd;
- t_iemnet_sender*sender=x->sr_sender;
-
- x->sr_owner=NULL;
- x->sr_sender=NULL;
+ if (x != NULL) {
+ int sockfd=x->sr_fd;
+ t_iemnet_sender*sender=x->sr_sender;
- x->sr_fd=-1;
+ x->sr_owner=NULL;
+ x->sr_sender=NULL;
- free(x);
+ x->sr_fd=-1;
- if(sender) iemnet__sender_destroy(sender);
+ free(x);
- sys_closesocket(sockfd);
+ if(sender) {
+ iemnet__sender_destroy(sender, 0);
}
+
+ iemnet__closesocket(sockfd);
+ }
+ /* coverity[pass_freed_arg]: this is merely for debugging printout */
DEBUG("freeed %x", x);
}
-static t_udpserver_sender* udpserver_sender_copy(t_udpserver_sender*x) {
+static t_udpserver_sender* udpserver_sender_copy(t_udpserver_sender*x)
+{
return udpserver_sender_new(x->sr_owner,x->sr_host, x->sr_port);
}
static int udpserver_socket2index(t_udpserver*x, int sockfd)
{
int i=0;
- for(i = 0; i < x->x_nconnections; i++) /* check if connection exists */
- {
- if(x->x_sr[i]->sr_fd == sockfd)
- {
- return i;
- }
+ for(i = 0; i < x->x_nconnections; i++) { /* check if connection exists */
+ if(x->x_sr[i]->sr_fd == sockfd) {
+ return i;
}
+ }
return -1;
}
@@ -137,35 +141,42 @@ static int udpserver_socket2index(t_udpserver*x, int sockfd)
*/
static int udpserver_fixindex(t_udpserver*x, int client)
{
- if(x->x_nconnections <= 0)
- {
- pd_error(x, "[%s]: no clients connected", objName);
- return -1;
- }
+ if(x->x_nconnections <= 0) {
+ pd_error(x, "[%s]: no clients connected", objName);
+ return -1;
+ }
- if (!((client > 0) && (client <= x->x_nconnections)))
- {
- pd_error(x, "[%s] client %d out of range [1..%d]", objName, client, (int)(x->x_nconnections));
- return -1;
- }
+ if (!((client > 0) && (client <= x->x_nconnections))) {
+ pd_error(x, "[%s] client %d out of range [1..%d]", objName, client,
+ (int)(x->x_nconnections));
+ return -1;
+ }
return (client-1);
}
/* returns 1 if addr1==addr2, 0 otherwise */
-static int equal_addr(unsigned long host1, unsigned short port1, unsigned long host2, unsigned short port2) {
+static int equal_addr(unsigned long host1, unsigned short port1,
+ unsigned long host2, unsigned short port2)
+{
return (
- ((port1 == port2) &&
- (host1 == host2))
- );
+ ((port1 == port2) &&
+ (host1 == host2))
+ );
}
-static int udpserver__find_sender(t_udpserver*x, unsigned long host, unsigned short port) {
+static int udpserver__find_sender(t_udpserver*x, unsigned long host,
+ unsigned short port)
+{
int i=0;
for(i=0; i<x->x_nconnections; i++) {
- if(NULL==x->x_sr[i])return -1;
- if(equal_addr(host, port, x->x_sr[i]->sr_host, x->x_sr[i]->sr_port))return i;
+ if(NULL==x->x_sr[i]) {
+ return -1;
+ }
+ if(equal_addr(host, port, x->x_sr[i]->sr_host, x->x_sr[i]->sr_port)) {
+ return i;
+ }
}
return -1;
}
@@ -175,11 +186,13 @@ static int udpserver__find_sender(t_udpserver*x, unsigned long host, unsigned s
* if not, add it to the list of registered senders
*/
static t_udpserver_sender* udpserver_sender_add(t_udpserver*x,
- unsigned long host, unsigned short port )
+ unsigned long host, unsigned short port )
{
int id=-1;
- if(!x->x_accept)return NULL;
+ if(!x->x_accept) {
+ return NULL;
+ }
id=udpserver__find_sender(x, host, port);
DEBUG("%X:%d -> %d", host, port, id);
@@ -217,9 +230,10 @@ static t_udpserver_sender* udpserver_sender_add(t_udpserver*x,
return NULL;
}
-static void udpserver_sender_remove(t_udpserver*x, int id) {
- if(id>=0 && id<x->x_nconnections && x->x_sr[id]) {
- int i;
+static void udpserver_sender_remove(t_udpserver*x, unsigned int id)
+{
+ if(id<x->x_nconnections && x->x_sr[id]) {
+ unsigned int i;
t_udpserver_sender* sdr=x->x_sr[id];
udpserver_sender_free(sdr);
@@ -235,15 +249,13 @@ static void udpserver_sender_remove(t_udpserver*x, int id) {
}
-
-
/* ---------------- udpserver info ---------------------------- */
static void udpserver_info_client(t_udpserver *x, int client)
{
// "client <id> <socket> <IP> <port>"
// "bufsize <id> <insize> <outsize>"
static t_atom output_atom[4];
- if(x&&x->x_sr&&x->x_sr[client]) {
+ if(x&&client<MAX_CONNECT&&x->x_sr[client]) {
int sockfd = x->x_sr[client]->sr_fd;
unsigned short port = x->x_sr[client]->sr_port;
long address = x->x_sr[client]->sr_host;
@@ -256,8 +268,8 @@ static void udpserver_info_client(t_udpserver *x, int client)
(unsigned char)((address & 0xFF000000)>>24),
(unsigned char)((address & 0x0FF0000)>>16),
(unsigned char)((address & 0x0FF00)>>8),
- (unsigned char)((address & 0x0FF))
- );
+ (unsigned char)((address & 0x0FF))
+ );
hostname[MAXPDSTRING-1]=0;
SETFLOAT (output_atom+0, client+1);
@@ -275,7 +287,8 @@ static void udpserver_info_client(t_udpserver *x, int client)
}
-static void udpserver_info(t_udpserver *x) {
+static void udpserver_info(t_udpserver *x)
+{
static t_atom output_atom[4];
int sockfd=x->x_connectsocket;
@@ -287,10 +300,11 @@ static void udpserver_info(t_udpserver *x) {
error("[%s] no valid sock", objName);
}
-
if(x->x_port<=0) {
struct sockaddr_in server;
socklen_t serversize=sizeof(server);
+ memset(&server, 0, sizeof(server));
+
if(!getsockname(sockfd, (struct sockaddr *)&server, &serversize)) {
x->x_port=ntohs(server.sin_port);
port=x->x_port;
@@ -311,16 +325,20 @@ static void udpserver_info_connection(t_udpserver *x, t_udpserver_sender*y)
}
/* ---------------- main udpserver (send) stuff --------------------- */
-static void udpserver_disconnect_socket(t_udpserver *x, t_floatarg fsocket);
-static void udpserver_send_bytes(t_udpserver*x, int client, t_iemnet_chunk*chunk)
+static void udpserver_disconnect_socket(t_udpserver *x,
+ t_floatarg fsocket);
+static void udpserver_send_bytes(t_udpserver*x, unsigned int client,
+ t_iemnet_chunk*chunk)
{
DEBUG("send_bytes to %x -> %x[%d]", x, x->x_sr, client);
- if(x->x_sr)DEBUG("client %X", x->x_sr[client]);
- if(x && x->x_sr && x->x_sr[client]) {
+ if(client<MAX_CONNECT) {
+ DEBUG("client %X", x->x_sr[client]);
+ }
+ if(x && client<MAX_CONNECT && x->x_sr[client]) {
t_atom output_atom[3];
int size=0;
- t_iemnet_sender*sender=sender=x->x_sr[client]->sr_sender;
+ t_iemnet_sender*sender=x->x_sr[client]->sr_sender;
int sockfd = x->x_sr[client]->sr_fd;
chunk->addr=x->x_sr[client]->sr_host;
@@ -333,7 +351,7 @@ static void udpserver_send_bytes(t_udpserver*x, int client, t_iemnet_chunk*chunk
SETFLOAT(&output_atom[0], client+1);
SETFLOAT(&output_atom[1], size);
SETFLOAT(&output_atom[2], sockfd);
- outlet_anything( x->x_statout, gensym("sent"), 3, output_atom);
+ outlet_anything( x->x_statout, gensym("sendbuffersize"), 3, output_atom);
if(size<0) {
// disconnected!
@@ -345,21 +363,25 @@ static void udpserver_send_bytes(t_udpserver*x, int client, t_iemnet_chunk*chunk
/* broadcasts a message to all connected clients but the given one */
-static void udpserver_send_butclient(t_udpserver *x, int but, int argc, t_atom *argv)
+static void udpserver_send_butclient(t_udpserver *x, unsigned int but,
+ int argc, t_atom *argv)
{
- int client=0;
+ unsigned int client=0;
t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv);
/* enumerate through the clients and send each the message */
- for(client = 0; client < x->x_nconnections; client++) /* check if connection exists */
- {
- /* socket exists for this client */
- if(client!=but)udpserver_send_bytes(x, client, chunk);
+ for(client = 0; client < x->x_nconnections;
+ client++) { /* check if connection exists */
+ /* socket exists for this client */
+ if(client!=but) {
+ udpserver_send_bytes(x, client, chunk);
}
+ }
iemnet__chunk_destroy(chunk);
}
/* sends a message to a given client */
-static void udpserver_send_toclient(t_udpserver *x, int client, int argc, t_atom *argv)
+static void udpserver_send_toclient(t_udpserver *x, unsigned int client,
+ int argc, t_atom *argv)
{
t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv);
udpserver_send_bytes(x, client, chunk);
@@ -371,71 +393,91 @@ static void udpserver_send_toclient(t_udpserver *x, int client, int argc, t_atom
/* send message to client using client number
note that the client numbers might change in case a client disconnects! */
/* clients start at 1 but our index starts at 0 */
-static void udpserver_send_client(t_udpserver *x, t_symbol *s, int argc, t_atom *argv)
+static void udpserver_send_client(t_udpserver *x, t_symbol *s, int argc,
+ t_atom *argv)
{
int client=0;
- if (argc > 0)
- {
- client=udpserver_fixindex(x, atom_getint(argv));
- if(client<0)return;
- if(argc==1) {
- udpserver_info_client(x, client);
- } else {
- udpserver_send_toclient(x, client, argc-1, argv+1);
- }
+ if (argc > 0) {
+ client=udpserver_fixindex(x, atom_getint(argv));
+ if(client<0) {
return;
}
- else
- {
- for(client=0; client<x->x_nconnections; client++)
- udpserver_info_client(x, client);
+ if(argc==1) {
+ udpserver_info_client(x, client);
+ } else {
+ udpserver_send_toclient(x, client, argc-1, argv+1);
+ }
+ return;
+ } else {
+ for(client=0; client<x->x_nconnections; client++) {
+ udpserver_info_client(x, client);
}
+ }
}
/* broadcasts a message to all connected clients */
-static void udpserver_broadcast(t_udpserver *x, t_symbol *s, int argc, t_atom *argv)
+static void udpserver_broadcast(t_udpserver *x, t_symbol *s, int argc,
+ t_atom *argv)
{
- int client;
+ unsigned int client;
t_iemnet_chunk*chunk=iemnet__chunk_create_list(argc, argv);
DEBUG("broadcasting to %d clients", x->x_nconnections);
/* enumerate through the clients and send each the message */
- for(client = 0; client < x->x_nconnections; client++) /* check if connection exists */
- {
- /* socket exists for this client */
- udpserver_send_bytes(x, client, chunk);
- }
+ for(client = 0; client < x->x_nconnections;
+ client++) { /* check if connection exists */
+ /* socket exists for this client */
+ udpserver_send_bytes(x, client, chunk);
+ }
iemnet__chunk_destroy(chunk);
}
/* broadcasts a message to all connected clients */
-static void udpserver_broadcastbut(t_udpserver *x, t_symbol *s, int argc, t_atom *argv)
+static void udpserver_broadcastbut(t_udpserver *x, t_symbol *s, int argc,
+ t_atom *argv)
{
- int but=-1;
+ int but;
if(argc<2) {
return;
}
- if((but=udpserver_fixindex(x, atom_getint(argv)))<0)return;
+ if((but=udpserver_fixindex(x, atom_getint(argv)))<0) {
+ return;
+ }
udpserver_send_butclient(x, but, argc-1, argv+1);
}
-static void udpserver_defaultsend(t_udpserver *x, t_symbol *s, int argc, t_atom *argv)
+static void udpserver_defaultsend(t_udpserver *x, t_symbol *s, int argc,
+ t_atom *argv)
{
int client=-1;
int sockfd=x->x_defaulttarget;
DEBUG("sending to sockfd: %d", sockfd);
- if(0==sockfd)
- udpserver_broadcast(x, s, argc, argv);
- else if(sockfd>0) {
+ if(sockfd>0) {
client=udpserver_socket2index(x, sockfd);
- udpserver_send_toclient(x, client, argc, argv);
+ if(client<0) {
+ pd_error(x, "[%s] illegal socket %d, switching to broadcast mode", objName,
+ sockfd);
+ x->x_defaulttarget=0;
+ } else {
+ udpserver_send_toclient(x, client, argc, argv);
+ return;
+ }
} else if(sockfd<0) {
client=udpserver_socket2index(x, -sockfd);
- udpserver_send_butclient(x, client, argc, argv);
+ if(client<0) {
+ pd_error(x, "[%s] illegal !socket %d, switching to broadcast mode",
+ objName, sockfd);
+ x->x_defaulttarget=0;
+ } else {
+ udpserver_send_butclient(x, client, argc, argv);
+ return;
+ }
}
+
+ udpserver_broadcast(x, s, argc, argv);
}
static void udpserver_defaulttarget(t_udpserver *x, t_floatarg f)
{
@@ -444,7 +486,8 @@ static void udpserver_defaulttarget(t_udpserver *x, t_floatarg f)
int client=(rawclient<0)?(-rawclient):rawclient;
if(client > x->x_nconnections) {
- error("[%s] target %d out of range [0..%d]", objName, client, (int)(x->x_nconnections));
+ error("[%s] target %d out of range [0..%d]", objName, client,
+ (int)(x->x_nconnections));
return;
}
@@ -453,7 +496,9 @@ static void udpserver_defaulttarget(t_udpserver *x, t_floatarg f)
sockfd=x->x_sr[client-1]->sr_fd;
}
- if(rawclient<0)sockfd=-sockfd;
+ if(rawclient<0) {
+ sockfd=-sockfd;
+ }
x->x_defaulttarget=sockfd;
}
@@ -466,55 +511,62 @@ static void udpserver_targetsocket(t_udpserver *x, t_floatarg f)
/* send message to client using socket number */
-static void udpserver_send_socket(t_udpserver *x, t_symbol *s, int argc, t_atom *argv)
+static void udpserver_send_socket(t_udpserver *x, t_symbol *s, int argc,
+ t_atom *argv)
{
int client = -1;
t_iemnet_chunk*chunk=NULL;
if(argc) {
client = udpserver_socket2index(x, atom_getint(argv));
- if(client<0)return;
+ if(client<0) {
+ return;
+ }
} else {
pd_error(x, "%s_send: no socket specified", objName);
return;
}
/* get socket number of connection (first element in list) */
- if(argc && argv->a_type == A_FLOAT)
- {
- int sockfd=atom_getint(argv);
- client = udpserver_socket2index(x, sockfd);
- if(client < 0)
- {
- error("[%s]: no connection on socket %d", objName, sockfd);
- return;
- }
- }
- else
- {
- error("[%s]: no socket specified", objName);
+ if(argc && argv->a_type == A_FLOAT) {
+ int sockfd=atom_getint(argv);
+ client = udpserver_socket2index(x, sockfd);
+ if(client < 0) {
+ error("[%s]: no connection on socket %d", objName, sockfd);
return;
}
+ } else {
+ error("[%s]: no socket specified", objName);
+ return;
+ }
chunk=iemnet__chunk_create_list(argc-1, argv+1);
udpserver_send_bytes(x, client, chunk);
iemnet__chunk_destroy(chunk);
}
-static void udpserver_disconnect(t_udpserver *x, int client)
+static void udpserver_disconnect(t_udpserver *x, unsigned int client)
{
- t_udpserver_sender*sdr;
+ t_udpserver_sender*sdr=NULL;
int conns;
DEBUG("disconnect %x %d", x, client);
- if(client<0 || client >= x->x_nconnections)return;
+ if(client >= x->x_nconnections) {
+ return;
+ }
- sdr=udpserver_sender_copy(x->x_sr[client]);
+ sdr = (t_udpserver_sender *)calloc(1, sizeof(t_udpserver_sender));
+ if(sdr) {
+ sdr->sr_host=x->x_sr[client]->sr_host;
+ sdr->sr_port=x->x_sr[client]->sr_port;
+ }
udpserver_sender_remove(x, client);
conns=x->x_nconnections;
-
- udpserver_info_connection(x, sdr);
+ if(sdr) {
+ udpserver_info_connection(x, sdr);
+ free(sdr);
+ }
outlet_float(x->x_connectout, conns);
}
@@ -524,7 +576,9 @@ static void udpserver_disconnect_client(t_udpserver *x, t_floatarg fclient)
{
int client = udpserver_fixindex(x, fclient);
- if(client<0)return;
+ if(client<0) {
+ return;
+ }
udpserver_disconnect(x, client);
}
@@ -533,8 +587,9 @@ static void udpserver_disconnect_client(t_udpserver *x, t_floatarg fclient)
static void udpserver_disconnect_socket(t_udpserver *x, t_floatarg fsocket)
{
int id=udpserver_socket2index(x, (int)fsocket);
- if(id>=0)
+ if(id>=0) {
udpserver_disconnect_client(x, id+1);
+ }
}
@@ -542,22 +597,26 @@ static void udpserver_disconnect_socket(t_udpserver *x, t_floatarg fsocket)
/* disconnect a client by socket */
static void udpserver_disconnect_all(t_udpserver *x)
{
- int id=x->x_nconnections;
- while(--id>=0) {
+ unsigned int id;
+ for(id=0; id<x->x_nconnections; id++) {
udpserver_disconnect(x, id);
}
}
/* whether we should accept new connections */
-static void udpserver_accept(t_udpserver *x, t_float f) {
+static void udpserver_accept(t_udpserver *x, t_float f)
+{
x->x_accept=(unsigned char)f;
}
/* ---------------- main udpserver (receive) stuff --------------------- */
-static void udpserver_receive_callback(void *y, t_iemnet_chunk*c) {
+static void udpserver_receive_callback(void *y, t_iemnet_chunk*c)
+{
t_udpserver*x=(t_udpserver*)y;
- if(NULL==y)return;
+ if(NULL==y) {
+ return;
+ }
if(c) {
int conns = x->x_nconnections;
@@ -567,13 +626,15 @@ static void udpserver_receive_callback(void *y, t_iemnet_chunk*c) {
DEBUG("added new sender from %d", c->port);
if(sdr) {
udpserver_info_connection(x, sdr);
- x->x_floatlist=iemnet__chunk2list(c, x->x_floatlist); // gets destroyed in the dtor
+ x->x_floatlist=iemnet__chunk2list(c,
+ x->x_floatlist); // gets destroyed in the dtor
/* here we might have a reentrancy problem */
if(conns!=x->x_nconnections) {
outlet_float(x->x_connectout, x->x_nconnections);
}
- outlet_list(x->x_msgout, gensym("list"), x->x_floatlist->argc, x->x_floatlist->argv);
+ outlet_list(x->x_msgout, gensym("list"), x->x_floatlist->argc,
+ x->x_floatlist->argv);
}
} else {
// disconnection never happens with a connectionless protocol like UDP
@@ -592,28 +653,28 @@ static void udpserver_connectpoll(t_udpserver *x)
// TODO: provide a way to not accept connection
// idea: add a message "accept $1" to turn off/on acceptance of new connections
- fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl);
+ fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address,
+ &sockaddrl);
bug("connectpoll");
- if (fd < 0) error("[%s] accept failed", objName);
- else
- {
- unsigned long host = ntohl(incomer_address.sin_addr.s_addr);
- unsigned short port = ntohs(incomer_address.sin_port);
-
- t_udpserver_sender *y = udpserver_sender_new(x, host, port);
- if (!y)
- {
- sys_closesocket(fd);
- return;
- }
- x->x_nconnections++;
- i = x->x_nconnections - 1;
- x->x_sr[i] = y;
+ if (fd < 0) {
+ error("[%s] accept failed", objName);
+ } else {
+ unsigned long host = ntohl(incomer_address.sin_addr.s_addr);
+ unsigned short port = ntohs(incomer_address.sin_port);
- udpserver_info_connection(x, y);
+ t_udpserver_sender *y = udpserver_sender_new(x, host, port);
+ if (!y) {
+ iemnet__closesocket(fd);
+ return;
}
+ x->x_nconnections++;
+ i = x->x_nconnections - 1;
+ x->x_sr[i] = y;
+
+ udpserver_info_connection(x, y);
+ }
outlet_float(x->x_connectout, x->x_nconnections);
}
@@ -625,6 +686,8 @@ static void udpserver_port(t_udpserver*x, t_floatarg fportno)
struct sockaddr_in server;
socklen_t serversize=sizeof(server);
int sockfd = x->x_connectsocket;
+ memset(&server, 0, sizeof(server));
+
SETFLOAT(ap, -1);
if(x->x_port == portno) {
return;
@@ -633,14 +696,17 @@ static void udpserver_port(t_udpserver*x, t_floatarg fportno)
/* cleanup any open ports */
if(sockfd>=0) {
//sys_rmpollfn(sockfd);
- sys_closesocket(sockfd);
+ iemnet__closesocket(sockfd);
x->x_connectsocket=-1;
x->x_port=-1;
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
-
+ if(sockfd<0) {
+ sys_sockerror("[udpserver]: cannot create UDP socket");
+ return;
+ }
server.sin_family = AF_INET;
@@ -650,17 +716,17 @@ static void udpserver_port(t_udpserver*x, t_floatarg fportno)
/* assign server port number */
server.sin_port = htons((u_short)portno);
/* name the socket */
- if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0)
- {
- sys_sockerror("udpserver: bind");
- sys_closesocket(sockfd);
- outlet_anything(x->x_statout, gensym("port"), 1, ap);
- return;
- }
+ if (bind(sockfd, (struct sockaddr *)&server, serversize) < 0) {
+ sys_sockerror("udpserver: bind");
+ iemnet__closesocket(sockfd);
+ outlet_anything(x->x_statout, gensym("port"), 1, ap);
+ return;
+ }
x->x_receiver=iemnet__receiver_create(sockfd,
- x,
- udpserver_receive_callback);
+ x,
+ udpserver_receive_callback,
+ 0);
x->x_connectsocket = sockfd;
x->x_port = portno;
@@ -684,19 +750,20 @@ static void *udpserver_new(t_floatarg fportno)
x = (t_udpserver *)pd_new(udpserver_class);
x->x_msgout = outlet_new(&x->x_obj, 0); /* 1st outlet for received data */
- x->x_connectout = outlet_new(&x->x_obj, gensym("float")); /* 2nd outlet for number of connected clients */
+ x->x_connectout = outlet_new(&x->x_obj,
+ gensym("float")); /* 2nd outlet for number of connected clients */
x->x_sockout = outlet_new(&x->x_obj, gensym("float"));
x->x_addrout = outlet_new(&x->x_obj, gensym("list" ));
- x->x_statout = outlet_new(&x->x_obj, 0);/* 5th outlet for everything else */
+ x->x_statout = outlet_new(&x->x_obj,
+ 0);/* 5th outlet for everything else */
x->x_connectsocket = -1;
x->x_port = -1;
x->x_nconnections = 0;
- for(i = 0; i < MAX_CONNECT; i++)
- {
- x->x_sr[i] = NULL;
- }
+ for(i = 0; i < MAX_CONNECT; i++) {
+ x->x_sr[i] = NULL;
+ }
x->x_defaulttarget=0;
x->x_floatlist=iemnet__floatlist_create(1024);
@@ -712,45 +779,59 @@ static void udpserver_free(t_udpserver *x)
{
int i;
- for(i = 0; i < MAX_CONNECT; i++)
- {
- if (NULL!=x->x_sr[i]) {
- DEBUG("[%s] free %x", objName, x);
- udpserver_sender_free(x->x_sr[i]);
- x->x_sr[i]=NULL;
- }
- }
- if (x->x_connectsocket >= 0)
- {
- //sys_rmpollfn(x->x_connectsocket);
- sys_closesocket(x->x_connectsocket);
+ for(i = 0; i < MAX_CONNECT; i++) {
+ if (NULL!=x->x_sr[i]) {
+ DEBUG("[%s] free %x", objName, x);
+ udpserver_sender_free(x->x_sr[i]);
+ x->x_sr[i]=NULL;
}
- if(x->x_floatlist)iemnet__floatlist_destroy(x->x_floatlist);x->x_floatlist=NULL;
+ }
+ if (x->x_connectsocket >= 0) {
+ //sys_rmpollfn(x->x_connectsocket);
+ iemnet__closesocket(x->x_connectsocket);
+ }
+ if(x->x_floatlist) {
+ iemnet__floatlist_destroy(x->x_floatlist);
+ }
+ x->x_floatlist=NULL;
}
IEMNET_EXTERN void udpserver_setup(void)
{
- if(!iemnet__register(objName))return;
+ if(!iemnet__register(objName)) {
+ return;
+ }
error("[%s] does not work yet", objName);
- udpserver_class = class_new(gensym(objName),(t_newmethod)udpserver_new, (t_method)udpserver_free,
+ udpserver_class = class_new(gensym(objName),(t_newmethod)udpserver_new,
+ (t_method)udpserver_free,
sizeof(t_udpserver), 0, A_DEFFLOAT, 0);
- class_addmethod(udpserver_class, (t_method)udpserver_disconnect_client, gensym("disconnectclient"), A_DEFFLOAT, 0);
- class_addmethod(udpserver_class, (t_method)udpserver_disconnect_socket, gensym("disconnectsocket"), A_DEFFLOAT, 0);
- class_addmethod(udpserver_class, (t_method)udpserver_disconnect_all, gensym("disconnect"), 0);
-
- class_addmethod(udpserver_class, (t_method)udpserver_accept, gensym("accept"), A_FLOAT, 0);
-
- class_addmethod(udpserver_class, (t_method)udpserver_send_socket, gensym("send"), A_GIMME, 0);
- class_addmethod(udpserver_class, (t_method)udpserver_send_client, gensym("client"), A_GIMME, 0);
-
- class_addmethod(udpserver_class, (t_method)udpserver_broadcast, gensym("broadcast"), A_GIMME, 0);
-
- class_addmethod(udpserver_class, (t_method)udpserver_defaulttarget, gensym("target"), A_DEFFLOAT, 0);
- class_addmethod(udpserver_class, (t_method)udpserver_targetsocket, gensym("targetsocket"), A_DEFFLOAT, 0);
+ class_addmethod(udpserver_class, (t_method)udpserver_disconnect_client,
+ gensym("disconnectclient"), A_DEFFLOAT, 0);
+ class_addmethod(udpserver_class, (t_method)udpserver_disconnect_socket,
+ gensym("disconnectsocket"), A_DEFFLOAT, 0);
+ class_addmethod(udpserver_class, (t_method)udpserver_disconnect_all,
+ gensym("disconnect"), 0);
+
+ class_addmethod(udpserver_class, (t_method)udpserver_accept,
+ gensym("accept"), A_FLOAT, 0);
+
+ class_addmethod(udpserver_class, (t_method)udpserver_send_socket,
+ gensym("send"), A_GIMME, 0);
+ class_addmethod(udpserver_class, (t_method)udpserver_send_client,
+ gensym("client"), A_GIMME, 0);
+
+ class_addmethod(udpserver_class, (t_method)udpserver_broadcast,
+ gensym("broadcast"), A_GIMME, 0);
+
+ class_addmethod(udpserver_class, (t_method)udpserver_defaulttarget,
+ gensym("target"), A_DEFFLOAT, 0);
+ class_addmethod(udpserver_class, (t_method)udpserver_targetsocket,
+ gensym("targetsocket"), A_DEFFLOAT, 0);
class_addlist (udpserver_class, (t_method)udpserver_defaultsend);
- class_addmethod(udpserver_class, (t_method)udpserver_port, gensym("port"), A_DEFFLOAT, 0);
+ class_addmethod(udpserver_class, (t_method)udpserver_port, gensym("port"),
+ A_DEFFLOAT, 0);
class_addbang (udpserver_class, (t_method)udpserver_info);
DEBUGMETHOD(udpserver_class);