From 4fa185a5450d9ec1516aa159f4e9dbc1c77a0839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Wed, 7 Apr 2010 14:29:34 +0000 Subject: first working prototype - still loads of problems the socket outlet doesn't make any sense (remove it?) disconnecting kills the receiver thread! svn path=/trunk/externals/iem/iemnet/; revision=13392 --- udpserver.c | 136 +++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 88 insertions(+), 48 deletions(-) diff --git a/udpserver.c b/udpserver.c index 7e52f21..de3a287 100644 --- a/udpserver.c +++ b/udpserver.c @@ -35,7 +35,7 @@ static t_class *udpserver_class; static const char objName[] = "udpserver"; -typedef struct _udpserver_socketreceiver +typedef struct _udpserver_sender { struct _udpserver *sr_owner; @@ -43,19 +43,18 @@ typedef struct _udpserver_socketreceiver unsigned short sr_port; t_int sr_fd; t_iemnet_sender*sr_sender; - t_iemnet_receiver*sr_receiver; -} t_udpserver_socketreceiver; +} t_udpserver_sender; typedef struct _udpserver { 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_msgout; + t_outlet *x_connectout; + t_outlet *x_sockout; // legacy + t_outlet *x_addrout; // legacy + t_outlet *x_statout; - t_udpserver_socketreceiver *x_sr[MAX_CONNECT]; /* socket per connection */ + t_udpserver_sender *x_sr[MAX_CONNECT]; /* socket per connection */ t_int x_nconnections; t_int x_connectsocket; /* socket waiting for new connections */ @@ -63,58 +62,55 @@ typedef struct _udpserver 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_udpserver; + t_iemnet_receiver *x_receiver; -static void udpserver_receive_callback(void*x, t_iemnet_chunk*,int argc, t_atom*argv); + t_iemnet_floatlist *x_floatlist; +} t_udpserver; -static t_udpserver_socketreceiver *udpserver_socketreceiver_new(t_udpserver *owner, int sockfd, struct sockaddr_in*addr) +static t_udpserver_sender *udpserver_sender_new(t_udpserver *owner, unsigned long host, unsigned short port) { - t_udpserver_socketreceiver *x = (t_udpserver_socketreceiver *)getbytes(sizeof(*x)); + t_udpserver_sender *x = (t_udpserver_sender *)getbytes(sizeof(*x)); if(NULL==x) { - error("%s_socketreceiver: unable to allocate %d bytes", objName, sizeof(*x)); + error("%s_sender: unable to allocate %d bytes", objName, sizeof(*x)); return NULL; } else { + int sockfd = owner->x_connectsocket; x->sr_owner=owner; x->sr_fd=sockfd; - x->sr_host=ntohl(addr->sin_addr.s_addr); - x->sr_port=ntohs(addr->sin_port); + 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_receiver=iemnet__receiver_create(sockfd, x, udpserver_receive_callback); } return (x); } -static void udpserver_socketreceiver_free(t_udpserver_socketreceiver *x) +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; - t_iemnet_receiver*receiver=x->sr_receiver; - - x->sr_owner=NULL; x->sr_sender=NULL; - x->sr_receiver=NULL; x->sr_fd=-1; freebytes(x, sizeof(*x)); if(sender) iemnet__sender_destroy(sender); - if(receiver)iemnet__receiver_destroy(receiver); sys_closesocket(sockfd); } DEBUG("freeed %x", x); } + + static int udpserver_socket2index(t_udpserver*x, int sockfd) { int i=0; @@ -149,6 +145,48 @@ static int udpserver_fixindex(t_udpserver*x, int client) } +/* returns 1 if addr1==addr2, 0 otherwise */ +static int equal_addr(unsigned long host1, unsigned short port1, unsigned long host2, unsigned short port2) { + return ( + ((port1 == port2) && + (host1 == host2)) + ); +} + + +static int udpserver__find_sender(t_udpserver*x, unsigned long host, unsigned short port) { + int i=0; + for(i=0; ix_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; + } + return -1; +} + +/** + * check whether the sender is already registered + * if not, add it to the list of registered senders + */ +static void udpserver_sender_add(t_udpserver*x, unsigned long host, unsigned short port ) +{ + int id=udpserver__find_sender(x, host, port); + DEBUG("%X:%d -> %d", host, port, id); + if(id<0) { + id=x->x_nconnections; + /* an unknown address! add it */ + if(idx_sr[id]=udpserver_sender_new(x, host, port); + DEBUG("new sender[%d]= %x", id, x->x_sr[id]); + x->x_nconnections++; + } else { + // oops, no more senders! + } + } +} + + + + /* ---------------- udpserver info ---------------------------- */ static void udpserver_info_client(t_udpserver *x, int client) { @@ -161,7 +199,7 @@ static void udpserver_info_client(t_udpserver *x, int client) long address = x->x_sr[client]->sr_host; char hostname[MAXPDSTRING]; - int insize =iemnet__receiver_getsize(x->x_sr[client]->sr_receiver); + int insize =iemnet__receiver_getsize(x->x_receiver); int outsize=iemnet__sender_getsize (x->x_sr[client]->sr_sender ); snprintf(hostname, MAXPDSTRING-1, "%d.%d.%d.%d", @@ -215,10 +253,10 @@ static void udpserver_info(t_udpserver *x) { } -static void udpserver_info_connection(t_udpserver *x, t_udpserver_socketreceiver*y) +static void udpserver_info_connection(t_udpserver *x, t_udpserver_sender*y) { iemnet__addrout(x->x_statout, x->x_addrout, y->sr_host, y->sr_port); - outlet_float(x->x_sockout, y->sr_fd); + // outlet_float(x->x_sockout, y->sr_fd); } /* ---------------- main udpserver (send) stuff --------------------- */ @@ -234,6 +272,9 @@ static void udpserver_send_bytes(t_udpserver*x, int client, t_iemnet_chunk*chunk t_iemnet_sender*sender=sender=x->x_sr[client]->sr_sender; int sockfd = x->x_sr[client]->sr_fd; + chunk->addr=x->x_sr[client]->sr_host; + chunk->port=x->x_sr[client]->sr_port; + if(sender) { size=iemnet__sender_send(sender, chunk); } @@ -414,7 +455,7 @@ static void udpserver_disconnect(t_udpserver *x, int client) DEBUG("disconnect %x %d", x, client); udpserver_info_connection(x, x->x_sr[client]); - udpserver_socketreceiver_free(x->x_sr[client]); + udpserver_sender_free(x->x_sr[client]); x->x_sr[client]=NULL; /* rearrange list now: move entries to close the gap */ @@ -425,7 +466,6 @@ static void udpserver_disconnect(t_udpserver *x, int client) x->x_sr[k + 1]=NULL; x->x_nconnections--; - outlet_float(x->x_connectout, x->x_nconnections); } @@ -460,23 +500,19 @@ static void udpserver_disconnect_all(t_udpserver *x) } /* ---------------- main udpserver (receive) stuff --------------------- */ -static void udpserver_receive_callback(void *y0, - t_iemnet_chunk*c, - int argc, t_atom*argv) { - t_udpserver_socketreceiver *y=(t_udpserver_socketreceiver*)y0; - t_udpserver*x=NULL; - if(NULL==y || NULL==(x=y->sr_owner))return; - - if(argc) { +static void udpserver_receive_callback(void *y, t_iemnet_chunk*c) { + t_udpserver*x=(t_udpserver*)y; + if(NULL==y)return; + + if(c) { udpserver_info_connection(x, y); - iemnet__streamout(x->x_msgout, argc, argv); + udpserver_sender_add(x, 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); } else { - // disconnected - int sockfd=y->sr_fd; - udpserver_disconnect_socket(x, sockfd); + // disconnection never happens with a connectionless protocol like UDP + pd_error(x, "[%s] received disconnection event", objName); } - - // error("[%s]: %d bytes in %d packets", objName, bytecount, packetcount); } static void udpserver_connectpoll(t_udpserver *x) @@ -486,10 +522,15 @@ static void udpserver_connectpoll(t_udpserver *x) int fd = accept(x->x_connectsocket, (struct sockaddr*)&incomer_address, &sockaddrl); int i; + post("connectpoll"); + if (fd < 0) error("[%s] accept failed", objName); else { - t_udpserver_socketreceiver *y = udpserver_socketreceiver_new((void *)x, fd, &incomer_address); + 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); @@ -549,7 +590,6 @@ static void udpserver_port(t_udpserver*x, t_floatarg fportno) x, udpserver_receive_callback); - x->x_connectsocket = sockfd; x->x_port = portno; @@ -577,7 +617,6 @@ static void *udpserver_new(t_floatarg fportno) 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_connectsocket = -1; x->x_port = -1; x->x_nconnections = 0; @@ -588,6 +627,7 @@ static void *udpserver_new(t_floatarg fportno) } x->x_defaulttarget=0; + x->x_floatlist=iemnet__floatlist_create(1024); udpserver_port(x, fportno); @@ -602,7 +642,7 @@ static void udpserver_free(t_udpserver *x) { if (NULL!=x->x_sr[i]) { DEBUG("[%s] free %x", objName, x); - udpserver_socketreceiver_free(x->x_sr[i]); + udpserver_sender_free(x->x_sr[i]); x->x_sr[i]=NULL; } } @@ -611,6 +651,7 @@ static void udpserver_free(t_udpserver *x) sys_rmpollfn(x->x_connectsocket); sys_closesocket(x->x_connectsocket); } + if(x->x_floatlist)iemnet__floatlist_destroy(x->x_floatlist);x->x_floatlist=NULL; } IEMNET_EXTERN void udpserver_setup(void) @@ -633,7 +674,6 @@ IEMNET_EXTERN void udpserver_setup(void) 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_addbang (udpserver_class, (t_method)udpserver_info); } -- cgit v1.2.1