/** @brief Close an unicast connection and delete the client * * @param unicast_vars the unicast parameters * @param fds The polling file descriptors * @param Socket The socket of the client we want to disconnect */ void unicast_close_connection(unicast_parameters_t *unicast_vars, fds_t *fds, int Socket) { int actual_fd; actual_fd=0; //We find the FD correspondig to this client while((actual_fd<fds->pfdsnum) && (fds->pfds[actual_fd].fd!=Socket)) actual_fd++; if(actual_fd==fds->pfdsnum) { log_message( log_module, MSG_ERROR,"close connection : we did't find the file descriptor this should never happend, please contact\n"); actual_fd=0; //We find the FD correspondig to this client while(actual_fd<fds->pfdsnum) { log_message( log_module, MSG_ERROR,"fds->pfds[actual_fd].fd %d Socket %d \n", fds->pfds[actual_fd].fd,Socket); actual_fd++; } return; } log_message( log_module, MSG_FLOOD,"We close the connection\n"); //We delete the client unicast_del_client(unicast_vars, unicast_vars->fd_info[actual_fd].client); //We move the last fd to the actual/deleted one, and decrease the number of fds by one fds->pfds[actual_fd].fd = fds->pfds[fds->pfdsnum-1].fd; fds->pfds[actual_fd].events = fds->pfds[fds->pfdsnum-1].events; fds->pfds[actual_fd].revents = fds->pfds[fds->pfdsnum-1].revents; //we move the file descriptor information unicast_vars->fd_info[actual_fd] = unicast_vars->fd_info[fds->pfdsnum-1]; //last one set to 0 for poll() fds->pfds[fds->pfdsnum-1].fd=0; fds->pfds[fds->pfdsnum-1].events=POLLIN|POLLPRI; fds->pfds[fds->pfdsnum-1].revents=0; //We clear it to avoid nasty bugs ... fds->pfdsnum--; fds->pfds=realloc(fds->pfds,(fds->pfdsnum+1)*sizeof(struct pollfd)); if (fds->pfds==NULL) { log_message( log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); } unicast_vars->fd_info=realloc(unicast_vars->fd_info,(fds->pfdsnum)*sizeof(unicast_fd_info_t)); if (unicast_vars->fd_info==NULL) { log_message( log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); } log_message( log_module, MSG_FLOOD,"Number of clients : %d\n", unicast_vars->client_number); }
/** @brief Handle an "event" on the unicast file descriptors * If the event is on an already open client connection, it handle the message * If the event is on the master connection, it accepts the new connection * If the event is on a channel specific socket, it accepts the new connection and starts streaming * */ int unicast_handle_fd_event(unicast_parameters_t *unicast_vars, fds_t *fds, mumudvb_channel_t *channels, int number_of_channels, strength_parameters_t *strengthparams, auto_p_t *auto_p, void *cam_p, void *scam_vars) { int iRet; //We look what happened for which connection int actual_fd; for(actual_fd=1;actual_fd<fds->pfdsnum;actual_fd++) { iRet=0; if((fds->pfds[actual_fd].revents&POLLHUP)&&(unicast_vars->fd_info[actual_fd].type==UNICAST_CLIENT)) { log_message( log_module, MSG_DEBUG,"We've got a POLLHUP. Actual_fd %d socket %d we close the connection \n", actual_fd, fds->pfds[actual_fd].fd ); unicast_close_connection(unicast_vars,fds,fds->pfds[actual_fd].fd); //We check if we hage to parse fds->pfds[actual_fd].revents (the last fd moved to the actual one) if(fds->pfds[actual_fd].revents) actual_fd--;//Yes, we force the loop to see it } if((fds->pfds[actual_fd].revents&POLLIN)||(fds->pfds[actual_fd].revents&POLLPRI)) { if((unicast_vars->fd_info[actual_fd].type==UNICAST_MASTER)|| (unicast_vars->fd_info[actual_fd].type==UNICAST_LISTEN_CHANNEL)) { //Event on the master connection or listenin channel //New connection, we accept the connection log_message( log_module, MSG_FLOOD,"New client\n"); int tempSocket; unicast_client_t *tempClient; //we accept the incoming connection tempClient=unicast_accept_connection(unicast_vars, fds->pfds[actual_fd].fd); if(tempClient!=NULL) { tempSocket=tempClient->Socket; fds->pfdsnum++; fds->pfds=realloc(fds->pfds,(fds->pfdsnum+1)*sizeof(struct pollfd)); if (fds->pfds==NULL) { log_message( log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return -1; } //We poll the new socket fds->pfds[fds->pfdsnum-1].fd = tempSocket; fds->pfds[fds->pfdsnum-1].events = POLLIN | POLLPRI | POLLHUP; //We also poll the deconnections fds->pfds[fds->pfdsnum-1].revents = 0; fds->pfds[fds->pfdsnum].fd = 0; fds->pfds[fds->pfdsnum].events = POLLIN | POLLPRI; fds->pfds[fds->pfdsnum].revents = 0; //Information about the descriptor unicast_vars->fd_info=realloc(unicast_vars->fd_info,(fds->pfdsnum)*sizeof(unicast_fd_info_t)); if (unicast_vars->fd_info==NULL) { log_message( log_module, MSG_ERROR,"Problem with realloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); set_interrupted(ERROR_MEMORY<<8); return -1; } //client connection unicast_vars->fd_info[fds->pfdsnum-1].type=UNICAST_CLIENT; unicast_vars->fd_info[fds->pfdsnum-1].channel=-1; unicast_vars->fd_info[fds->pfdsnum-1].client=tempClient; log_message( log_module, MSG_FLOOD,"Number of clients : %d\n", unicast_vars->client_number); if(unicast_vars->fd_info[actual_fd].type==UNICAST_LISTEN_CHANNEL) { //Event on a channel connection, we open a new socket for this client and //we store the wanted channel for when we will get the GET log_message( log_module, MSG_DEBUG,"Connection on a channel socket the client will get the channel %d\n", unicast_vars->fd_info[actual_fd].channel); tempClient->askedChannel=unicast_vars->fd_info[actual_fd].channel; } } } else if(unicast_vars->fd_info[actual_fd].type==UNICAST_CLIENT) { //Event on a client connectio i.e. the client asked something log_message( log_module, MSG_FLOOD,"New message for socket %d\n", fds->pfds[actual_fd].fd); iRet=unicast_handle_message(unicast_vars,unicast_vars->fd_info[actual_fd].client, channels, number_of_channels, strengthparams, auto_p, cam_p, scam_vars); if (iRet==-2 ) //iRet==-2 --> 0 received data or error, we close the connection { unicast_close_connection(unicast_vars,fds,fds->pfds[actual_fd].fd); //We check if we hage to parse fds->pfds[actual_fd].revents (the last fd moved to the actual one) if(fds->pfds[actual_fd].revents) actual_fd--;//Yes, we force the loop to see it again } } else { log_message( log_module, MSG_WARN,"File descriptor with bad type, please contact\n Debug information : actual_fd %d unicast_vars->fd_info[actual_fd].type %d\n", actual_fd, unicast_vars->fd_info[actual_fd].type); } } } return 0; }
/** * 操作系统级抽象线程 */ OSThread::OSThread(OSThreadStartFunc start_proc, void* start_parm) { pd_initialize(); set_start_proc(start_proc); set_start_parm(start_parm); set_interrupted(false); }