int member_exec( struct ast_channel* chan, void* data ) { int left = 0 ; int res; struct ast_conference *conf = NULL; struct ast_conf_member *member = NULL; struct ast_frame *f = NULL; struct ast_app *app = NULL; ast_log( AST_CONF_DEBUG, "Launching NConference %s\n", "$Revision: 2325 $" ) ; // make sure we have a channel to process if ( chan == NULL ) { ast_log( LOG_NOTICE, "member channel has closed\n" ) ; return -1 ; } if (chan->_state != AST_STATE_UP) if ( (res = ast_answer( chan )) ) { ast_log( LOG_ERROR, "unable to answer call\n" ) ; return -1 ; } member = create_member( chan, (const char*)( data ) ) ; // unable to create member, return an error if ( member == NULL ) { ast_log( LOG_ERROR, "unable to create member\n" ) ; return -1 ; } // // setup Openpbx read/write formats // //ast_log( AST_CONF_DEBUG, // "CHANNEL INFO, CHANNEL => %s, DNID => %s, CALLER_ID => %s, ANI => %s\n", // chan->name, chan->cid.cid_dnid, chan->cid.cid_num, chan->cid.cid_ani ) ; ast_log( AST_CONF_DEBUG, "CHANNEL CODECS, CHANNEL => %s, NATIVE => %d, READ => %d, WRITE => %d\n", chan->name, chan->nativeformats, member->read_format, member->write_format ) ; if ( ast_set_read_format( chan, member->read_format ) < 0 ) { ast_log( LOG_ERROR, "unable to set read format.\n" ) ; delete_member( member ) ; return -1 ; } // for right now, we'll send everything as slinear if ( ast_set_write_format( chan, member->write_format ) < 0 ) { ast_log( LOG_ERROR, "unable to set write format.\n" ) ; delete_member( member ) ; return -1 ; } // // setup a conference for the new member // conf = start_conference( member ) ; if ( conf == NULL ) { ast_log( LOG_ERROR, "unable to setup member conference\n" ) ; delete_member( member) ; return -1 ; } else { if (conf->is_locked && (member->type != MEMBERTYPE_MASTER) ) { if (strlen(conf->pin) == 0 || strncmp(conf->pin,member->pin,sizeof(conf->pin)) ) { /* Conference is Locked and an invalid PIN was entered */ remove_member(conf, member); return -2 ; } } else { member->conf = conf; if ( member->type == MEMBERTYPE_MASTER ) conf->auto_destroy = member->auto_destroy; } } if ( member->type == MEMBERTYPE_MASTER ) { conf->auto_destroy = member->auto_destroy; if ( strlen( member->pin ) > 0 ) { strncpy(conf->pin,member->pin,sizeof(conf->pin)); ast_log( AST_CONF_DEBUG, "Conference pin set to => %s\n", conf->pin ) ; } } // // process loop for new member ( this runs in it's own thread // ast_log( AST_CONF_DEBUG, "begin member event loop, channel => %s\n", chan->name ) ; // Add user to monitor if (member->monitor) { const char * const monitorfilename = pbx_builtin_getvar_helper(chan, "MONITOR_FILENAME"); if (monitorfilename) { ast_monitor_start(chan, NULL, monitorfilename, 1); } else if (chan->cdr) { ast_monitor_start(chan, NULL, chan->cdr->uniqueid, 1); } else { char tmpid[256]; snprintf(tmpid, sizeof(tmpid), "chan-%x", rand()); ast_monitor_start(chan, NULL, tmpid, 1); } if (member->monitor_join) { ast_monitor_setjoinfiles(chan, 1); } } // Run AGI script if (member->agi) { char * agi = pbx_builtin_getvar_helper(chan, "AGI_CONF_JOIN"); if (agi) { app = pbx_findapp("agi"); if (app) { pbx_exec(chan, app, agi, 1); } } else { ast_log(LOG_WARNING, "AGI requested, but AGI_CONF_JOIN missing.\n"); } conf->agi = 1 ; } // Activate the generator for the channel. res = ast_conf_member_genactivate( member ); if ( !res ) { member->force_remove_flag = 1; ast_log( AST_CONF_DEBUG, "member marked for removal => %s\n", chan->name ) ; } //Play the join info messages if (!member->force_remove_flag && !member->quiet_mode && !member->mute_incoming_sounds) { if (ast_strlen_zero(member->intro_sounds)) { conference_queue_sound( member, "conf-youareinconfnum" ); conference_queue_number( member, member->id ); } } // The member at the very beginningis speaking member->is_speaking = 1 ; // tell conference_exec we're ready for frames member->active_flag = 1 ; //Main loop. while ( !member->force_remove_flag || member->soundq != NULL ) { #ifdef SOLARIS struct timespec rqtp; rqtp.tv_sec = 0; rqtp.tv_nsec = 1000000; if (nanosleep(&rqtp, (struct timespec *) NULL) == -1) { ast_log(LOG_NOTICE, "Nanosleep timer errored.\n"); } #else usleep(1000); #endif //-----------------// // INCOMING FRAMES // //-----------------// if ( member->force_remove_flag == 1 ) { // break to the loop break; } // wait for an event on this channel int waittime = ( member->framelen == 0 ) ? AST_CONF_WAITFOR_TIME : member->framelen; left = ast_waitfor( chan, waittime ) ; if ( left < 0 ) { // an error occured ast_log( LOG_NOTICE, "an error occured waiting for a frame, channel => %s, error => %d\n", chan->name, left ) ; } else if ( left == 0 ) { // No frame avalaible member->lostframecount ++; // We have lost a frame. // In this case, we queue some silence // Sothat if we keep loosing frames, // there will be no glitching in the conference. // Set the speaking state to 0. if ( member->lostframecount == 1 ) { queue_incoming_silent_frame(member,1); } member->is_speaking = 0; } else if ( left > 0 ) { // a frame has come in before the latency timeout // was reached, so we process the frame // let's reset the lost frame count if ( member->lostframecount ) { member->lostframecount = 0; // If vad is not enabled, then set the speaking state back to 1 if ( !member->enable_vad ) member->is_speaking = 1; } f = ast_read( chan ) ; if ( f == NULL ) { ast_log( AST_CONF_DEBUG, "unable to read from channel, channel => %s. Got Hangup.\n", chan->name ) ; queue_incoming_silent_frame(member,5); member->is_speaking = 0; break ; } else { /* ast_log( AST_CONF_DEBUG, "Read (PRE dsp), channel => %s, datalen: %d samplefreq: %ld len: %ld samples %d class: %d\n", chan->name, f->datalen, member->samplefreq, f->len, f->samples, f->subclass) ; */ #if 0 == 1 if ( member->samplefreq == 0 && f->samples != 0 ) { if ( ( f->len == 0 ) && ( f->datalen == 320 ) && ( f->samples == 160 ) ) member->framelen = 20; // This is probably chan_zap not setting the correct len. else member->framelen = f->len; // frame length in milliseconds member->datalen = f->datalen; // frame length in milliseconds member->samples = f->samples; // number of samples in framelen member->samplefreq = (int)(member->samples/member->framelen)*1000; // calculated sample frequency ast_log( AST_CONF_DEBUG, "MEMBER FRAME DATA: datalen %d samples %d len(ms) %ld, offset: %d \n", f->datalen, f->samples, f->len, f->offset ); } if ( ( (member->framelen != f->len ) && ( f->len !=0 ) ) || ( (member->samples != f->samples ) && ( f->samples !=0 ) && ( f->len !=0 ) ) ) { ast_log( AST_CONF_DEBUG, "FRAME CHANGE : samples %d len(ms) %ld\n", f->samples, f->len ); ast_log( AST_CONF_DEBUG, "FRAME SHOULDBE: samples %d len(ms) %ld\n", member->samples, member->framelen ); if (member->samples == 0 ) { member->framelen = f->len; // frame length in milliseconds member->datalen = f->datalen; // frame length in milliseconds member->samples = f->samples; // number of samples in framelen member->samplefreq = (int) ( f->samples/f->len)*1000; // calculated sample frequency } } #endif member->framelen = f->datalen; // This fix is for chan_zap // Chan_zap NEVER sets framelen value. // Probably when adding support to 16Khz we should add a check for this. if ( ( member->framelen == 0 ) && ( member->datalen == 320 ) && ( member->samples == 160 ) ) member->framelen = 20; } } // actually process the frame. res = process_incoming(member, f); if (member->force_remove_flag) member->remove_flag = 1 ; } // Run AGI script if (member->agi) { char * agi = pbx_builtin_getvar_helper(chan, "AGI_CONF_LEAVE"); if (agi) { app = pbx_findapp("agi"); if (app) { pbx_exec(chan, app, agi, 1); } } else { ast_log(LOG_WARNING, "AGI requested, but AGI_CONF_LEAVE missing.\n"); } } if (conf->agi) handle_conf_agi_end(conf->name, member); member->remove_flag = 1 ; ast_log( AST_CONF_DEBUG, "end member event loop, time_entered => %ld - removal: %d\n", member->time_entered.tv_sec, member->remove_flag ) ; //ast_log( AST_CONF_DEBUG, "Deactivating generator - Channel => %s\n", member->chan->name ) ; ast_generator_deactivate(chan); if (member->hangup_go_on) { ast_log(AST_CONF_DEBUG, "Hangup go on!\n"); return 0; } return -1 ; }
int member_exec( struct cw_channel* chan, int argc, char **argv ) { int left = 0 ; int res; struct cw_conference *conf = NULL; struct cw_conf_member *member = NULL; struct cw_frame *f = NULL; cw_log( CW_CONF_DEBUG, "Launching NConference %s\n", "$Revision: 5349 $" ) ; if (chan->_state != CW_STATE_UP) if ( (res = cw_answer( chan )) ) { cw_log( LOG_ERROR, "unable to answer call\n" ) ; return -1 ; } member = create_member( chan, argc, argv ) ; // unable to create member, return an error if ( member == NULL ) { cw_log( LOG_ERROR, "unable to create member\n" ) ; return -1 ; } // // setup CallWeaver read/write formats // cw_log(CW_CONF_DEBUG, "CHANNEL INFO, CHANNEL => %s, DNID => %s, CALLER_ID => %s, ANI => %s\n", chan->name ? chan->name : "----", chan->cid.cid_dnid ? chan->cid.cid_dnid : "----", chan->cid.cid_num ? chan->cid.cid_num : "----", chan->cid.cid_ani ? chan->cid.cid_ani : "----"); cw_log(CW_CONF_DEBUG, "CHANNEL CODECS, CHANNEL => %s, NATIVE => %d, READ => %d, WRITE => %d\n", chan->name, chan->nativeformats, member->read_format, member->write_format); if ( cw_set_read_format( chan, member->read_format ) < 0 ) { cw_log( LOG_ERROR, "unable to set read format.\n" ) ; delete_member( member ) ; return -1 ; } // for right now, we'll send everything as slinear if ( cw_set_write_format( chan, member->write_format ) < 0 ) { cw_log( LOG_ERROR, "unable to set write format.\n" ) ; delete_member( member ) ; return -1 ; } // // setup a conference for the new member // conf = start_conference( member ) ; if ( conf == NULL ) { cw_log( LOG_ERROR, "unable to setup member conference\n" ) ; delete_member( member) ; return -1 ; } else { if (conf->is_locked && (member->type != MEMBERTYPE_MASTER) ) { if ( strcmp(conf->pin,member->pin) ) { conference_queue_sound(member,"conf-locked"); conf_play_soundqueue( member ); member->force_remove_flag = 1 ; } } else { member->conf = conf; if ( member->type == MEMBERTYPE_MASTER ) conf->auto_destroy = member->auto_destroy; } } if ( member->type == MEMBERTYPE_MASTER ) { conf->auto_destroy = member->auto_destroy; if ( strlen( member->pin ) > 0 ) { strncpy(conf->pin,member->pin,sizeof(conf->pin)); cw_log( CW_CONF_DEBUG, "Conference pin set to => %s\n", conf->pin ) ; } } // // process loop for new member ( this runs in it's own thread // cw_log( CW_CONF_DEBUG, "begin member event loop, channel => %s\n", chan->name ) ; // Activate the generator for the channel. res = cw_conf_member_genactivate( member ); if ( !res ) { member->force_remove_flag = 1; cw_log( CW_CONF_DEBUG, "member marked for removal => %s\n", chan->name ) ; } //Play the join info messages if (!member->force_remove_flag && !member->quiet_mode) { conference_queue_sound( member, "conf-youareinconfnum" ); conference_queue_number( member, member->id ); } // The member at the very beginningis speaking member->is_speaking = 1 ; // tell conference_exec we're ready for frames member->active_flag = 1 ; //Main loop. while ( !member->force_remove_flag || member->soundq != NULL ) { usleep(1000); // make sure we have a channel to process if ( chan == NULL ) { cw_log( LOG_NOTICE, "member channel has closed\n" ) ; break ; } //-----------------// // INCOMING FRAMES // //-----------------// if ( member->force_remove_flag == 1 ) { // break to the loop break; } // wait for an event on this channel int waittime = ( member->framelen == 0 ) ? CW_CONF_WAITFOR_TIME : member->framelen; left = cw_waitfor( chan, waittime ) ; f = NULL; if ( left < 0 ) { // an error occured cw_log( LOG_NOTICE, "an error occured waiting for a frame, channel => %s, error => %d\n", chan->name, left ) ; } else if ( left == 0 ) { // No frame avalaible member->lostframecount ++; // We have lost a frame. // In this case, we queue some silence // Sothat if we keep loosing frames, // there will be no glitching in the conference. // Set the speaking state to 0. if ( member->lostframecount == 1 ) { queue_incoming_silent_frame(member,1); } member->is_speaking = 0; } else if ( left > 0 ) { // a frame has come in before the latency timeout // was reached, so we process the frame // let's reset the lost frame count if ( member->lostframecount ) { member->lostframecount = 0; // If vad is not enabled, then set the speaking state back to 1 if ( !member->enable_vad ) member->is_speaking = 1; } f = cw_read( chan ) ; if ( f == NULL ) { cw_log( CW_CONF_DEBUG, "unable to read from channel, channel => %s. Got Hangup.\n", chan->name ) ; queue_incoming_silent_frame(member,5); member->is_speaking = 0; break ; } else { /* cw_log( CW_CONF_DEBUG, "Read (PRE dsp), channel => %s, datalen: %d samplefreq: %ld len: %ld samples %d class: %d\n", chan->name, f->datalen, member->samplefreq, f->len, f->samples, f->subclass) ; */ if ( member->samplefreq == 0 && f->samples != 0 ) { if ( ( f->len == 0 ) && ( f->datalen == 320 ) && ( f->samples == 160 ) ) member->framelen = 20; // This is probably chan_zap not setting the correct len. else member->framelen = f->len; // frame length in milliseconds member->datalen = f->datalen; // frame length in milliseconds member->samples = f->samples; // number of samples in framelen member->samplefreq = (int)(member->samples/member->framelen)*1000; // calculated sample frequency cw_log( CW_CONF_DEBUG, "MEMBER FRAME DATA: datalen %d samples %d len(ms) %ld, offset: %d \n", f->datalen, f->samples, f->len, f->offset ); /* // Try to initialize the smoother, only once queue_incoming_silent_frame(member); if ( member->smooth_size_in < 0 ) { member->smooth_size_in = f->samples ; cw_log( CW_CONF_DEBUG, "Initializing Smooother.\n"); member->inSmoother = cw_smoother_new(member->smooth_size_in); if ( member->inSmoother == NULL ) cw_log( CW_CONF_DEBUG, "Smoother initialization failed\n"); } */ } if ( ( (member->framelen != f->len ) && ( f->len !=0 ) ) || ( (member->samples != f->samples ) && ( f->samples !=0 ) && ( f->len !=0 ) ) ) { cw_log( CW_CONF_DEBUG, "FRAME CHANGE : samples %d len(ms) %ld\n", f->samples, f->len ); cw_log( CW_CONF_DEBUG, "FRAME SHOULDBE: samples %d len(ms) %ld\n", member->samples, member->framelen ); if (member->samples == 0 ) { member->framelen = f->len; // frame length in milliseconds member->datalen = f->datalen; // frame length in milliseconds member->samples = f->samples; // number of samples in framelen member->samplefreq = (int) ( f->samples/f->len)*1000; // calculated sample frequency } } // This fix is for chan_zap // Chan_zap NEVER sets framelen value. // Probably when adding support to 16Khz we should add a check for this. if ( ( member->framelen == 0 ) && ( member->datalen == 320 ) && ( member->samples == 160 ) ) member->framelen = 20; } } // actually process the frame. res = process_incoming(member, f); if (member->force_remove_flag) member->remove_flag = 1 ; } // // clean up // if ( member != NULL ) member->remove_flag = 1 ; cw_log( CW_CONF_DEBUG, "end member event loop, time_entered => %ld - removal: %d\n", member->time_entered.tv_sec, member->remove_flag ) ; //cw_log( CW_CONF_DEBUG, "Deactivating generator - Channel => %s\n", member->chan->name ) ; cw_generator_deactivate(chan); return -1 ; }
static void handle_add_request( GROUP_LIST* groups, char* msg, char* ip , unsigned short port_number){ unsigned short len; int packet_header_offset; char* group_name; GROUP_T *group; GROUP_T* new_group; MEMBER_T* new_member; packet_header_offset = sizeof(unsigned short) + sizeof(char); memcpy(&len, msg, sizeof(unsigned short)); len = ntohs(len); group_name = (char*) malloc( sizeof(char) * (len + 1)); // len + 1 bytes including the '\0' if(!group_name){ /* * Server is out of memory.Send a negative reply.We only need to change * the \type field of the packet's header */ msg[2] = ADD_REPLY_NEGATIVE; return ; } // copy group name from the packet strncpy( group_name, msg + packet_header_offset, len ); group_name[len] = '\0'; new_member = create_member(ip , port_number); if( !new_member){ // not enough memory free(group_name); msg[2] = ADD_REPLY_NEGATIVE; return; } group = get_group_by_name(groups, group_name); if(!group){ /* * No such group.First create a new members list and add the new member to the * list.Then create a new group and add it to the groups' list */ int flag; MEMBER_LIST* member_list = create_member_list(); if( !member_list){ free(group_name); free(new_member); msg[2] = ADD_REPLY_NEGATIVE; return ; } // add member to the list flag = add_member(member_list,new_member); if( !flag){ // not added free(member_list); free(new_member); free(group_name); msg[2] = ADD_REPLY_NEGATIVE; return ; } // now create a new group and add it to the groups list new_group = create_group( group_name, member_list); if( !new_group){ free(new_member); free(member_list); free(group_name); msg[2] = ADD_REPLY_NEGATIVE; return; } // add it to the groups' list add_group(groups, new_group); msg[2] = ADD_REPLY_POSITIVE; return; } else{ // group is found.Add the member to the group add_member( group->members, new_member); // positive reply msg[2] = ADD_REPLY_POSITIVE; } free(group_name); return ; }