/* iemnet * * receiver * receives data "chunks" from a socket * * copyright © 2010-2015 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, see */ /* http://www.gnu.org/licenses/ */ /* */ #define DEBUGLEVEL 4 #include "iemnet.h" #include "iemnet_data.h" #include #include #define INBUFSIZE 65536L /* was 4096: size of receiving data buffer */ struct _iemnet_receiver { int sockfd; /* owned outside; you must call iemnet__receiver_destroy() before freeing socket yourself */ void*userdata; t_iemnet_receivecallback callback; }; 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; #ifdef MSG_DONTWAIT recv_flags|=MSG_DONTWAIT; #endif 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); } t_iemnet_receiver*iemnet__receiver_create(int sock, void*userdata, t_iemnet_receivecallback callback, int subthread) { 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) { rec->sockfd=sock; rec->userdata=userdata; rec->callback=callback; if(subthread) { sys_lock(); } sys_addpollfn(sock, pollfun, rec); if(subthread) { sys_unlock(); } } //fprintf(stderr, "new receiver created\n"); return rec; } void iemnet__receiver_destroy(t_iemnet_receiver*rec, int subthread) { int sockfd; if(NULL==rec) { return; } sockfd=rec->sockfd; if(subthread) { sys_lock(); } sys_rmpollfn(rec->sockfd); // FIXXME: read any remaining bytes from the socket if(subthread) { sys_unlock(); } DEBUG("[%p] really destroying receiver %d", sockfd); DEBUG("[%p] closed socket %d", rec, sockfd); rec->sockfd=-1; rec->userdata=NULL; rec->callback=NULL; free(rec); rec=NULL; } /* 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; }