static int changrab_exec(struct cw_channel *chan, int argc, char **argv) { int res=0; struct localuser *u; struct cw_channel *newchan; struct cw_channel *oldchan; struct cw_frame *f; struct cw_bridge_config config; if (argc < 1 || argc > 2) { cw_log(LOG_ERROR, "Syntax: %s\n", changrab_syntax); return -1; } if ((oldchan = my_cw_get_channel_by_name_locked(argv[0]))) { cw_mutex_unlock(&oldchan->lock); } else { cw_log(LOG_WARNING, "No Such Channel: %s\n", argv[0]); return -1; } if (argc > 1) { if (oldchan->_bridge && strchr(argv[1], 'b')) oldchan = oldchan->_bridge; if (strchr(argv[1],'r') && oldchan->_state == CW_STATE_UP) return -1; } LOCAL_USER_ADD(u); newchan = cw_channel_alloc(0); snprintf(newchan->name, sizeof (newchan->name), "ChanGrab/%s",oldchan->name); newchan->readformat = oldchan->readformat; newchan->writeformat = oldchan->writeformat; cw_channel_masquerade(newchan, oldchan); if((f = cw_read(newchan))) { cw_fr_free(f); memset(&config,0,sizeof(struct cw_bridge_config)); cw_set_flag(&(config.features_callee), CW_FEATURE_REDIRECT); cw_set_flag(&(config.features_caller), CW_FEATURE_REDIRECT); if(newchan->_state != CW_STATE_UP) { cw_answer(newchan); } chan->appl = "Bridged Call"; res = cw_bridge_call(chan, newchan, &config); cw_hangup(newchan); } LOCAL_USER_REMOVE(u); return res ? 0 : -1; }
static int sayunixtime_exec(struct cw_channel *chan, int argc, char **argv) { struct timeval tv; time_t unixtime; struct localuser *u; char *format; int res=0; if (argc > 3) { cw_log(LOG_ERROR, "Syntax: %s\n", sayunixtime_syntax); return -1; } LOCAL_USER_ADD(u); if (argc < 1 || !(unixtime = (time_t)atol(argv[0]))) { tv = cw_tvnow(); unixtime = (time_t)tv.tv_sec; } if (argc > 2 && argv[2][0]) { format = argv[2]; } else if (!strcasecmp(chan->language, "da")) { format = "A dBY HMS"; } else if (!strcasecmp(chan->language, "de")) { format = "A dBY HMS"; } else { format = "ABdY 'digits/at' IMp"; } if (chan->_state != CW_STATE_UP) res = cw_answer(chan); if (!res) res = cw_say_date_with_format(chan, unixtime, CW_DIGIT_ANY, chan->language, format, (argc > 1 && argv[1][0] ? argv[1] : NULL)); LOCAL_USER_REMOVE(u); return res; }
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 int pipe_exec(struct cw_channel *chan, int argc, char **argv) { int res=0; struct localuser *u; int fds[2]; int ms = -1; int pid = -1; int owriteformat; int oreadformat; int timeout = 2000; struct timeval last; struct cw_frame *f; struct myframe { struct cw_frame f; char offset[CW_FRIENDLY_OFFSET]; short frdata[160]; } myf; last.tv_usec = 0; last.tv_sec = 0; if (argc < 2 || argc > 3) { cw_log(LOG_ERROR, "Syntax: %s\n", pipe_syntax); return -1; } LOCAL_USER_ADD(u); if (pipe(fds)) { cw_log(LOG_WARNING, "Unable to create pipe\n"); LOCAL_USER_REMOVE(u); return -1; } // MOC: Setting non blocking doesn't seem to change anything // flags = fcntl(fds[1], F_GETFL); // fcntl(fds[1], F_SETFL, flags | O_NONBLOCK); // flags = fcntl(fds[0], F_GETFL); // fcntl(fds[0], F_SETFL, flags | O_NONBLOCK); cw_stopstream(chan); if (chan->_state != CW_STATE_UP) res = cw_answer(chan); if (res) { close(fds[0]); close(fds[1]); cw_log(LOG_WARNING, "Answer failed!\n"); LOCAL_USER_REMOVE(u); return -1; } oreadformat = chan->readformat; res = cw_set_read_format(chan, CW_FORMAT_SLINEAR); owriteformat = chan->writeformat; res += cw_set_write_format(chan, CW_FORMAT_SLINEAR); if (res < 0) { close(fds[0]); close(fds[1]); cw_log(LOG_WARNING, "Unable to set write format to signed linear\n"); LOCAL_USER_REMOVE(u); return -1; } res = pipeencode(argv[1], argv[2], fds[0], fds[1]); if (res >= 0) { last = cw_tvnow(); last.tv_sec += 1; pid = res; for (;;) { /* Wait for audio, and stream */ if (argv[0][0] == '0') { /* START WRITE TO FD */ ms = cw_waitfor(chan, 10); if (ms < 0) { cw_log(LOG_DEBUG, "Hangup detected\n"); res = -1; break; } else if (ms > 0) { f = cw_read(chan); if (!f) { cw_log(LOG_DEBUG, "Null frame == hangup() detected\n"); res = -1; break; } if (f->frametype == CW_FRAME_DTMF) { cw_log(LOG_DEBUG, "User pressed a key\n"); cw_fr_free(f); res = 0; break; } if (f->frametype == CW_FRAME_VOICE) { res = write(fds[1], f->data, f->datalen); if (res < 0) { if (errno != EAGAIN) { cw_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno)); cw_fr_free(f); res = -1; break; } } } cw_fr_free(f); } /* END WRITE TO FD */ } else { /* START WRITE CHANNEL */ ms = cw_tvdiff_ms(last, cw_tvnow()); if (ms <= 0) { res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout); if (res > 0) { cw_fr_init_ex(&myf.f, CW_FRAME_VOICE, CW_FORMAT_SLINEAR, __PRETTY_FUNCTION__); myf.f.datalen = res; myf.f.samples = res/sizeof(int16_t); myf.f.offset = CW_FRIENDLY_OFFSET; myf.f.data = myf.frdata; if (cw_write(chan, &myf.f) < 0) { res = -1; break; } } else { cw_log(LOG_DEBUG, "No more stream\n"); res = 0; break; } last = cw_tvadd(last, cw_samp2tv(myf.f.samples, 8000)); } else { ms = cw_waitfor(chan, ms); if (ms < 0) { cw_log(LOG_DEBUG, "Hangup detected\n"); res = -1; break; } if (ms) { f = cw_read(chan); if (!f) { cw_log(LOG_DEBUG, "Null frame == hangup() detected\n"); res = -1; break; } if (f->frametype == CW_FRAME_DTMF) { cw_log(LOG_DEBUG, "User pressed a key\n"); cw_fr_free(f); res = 0; break; } cw_fr_free(f); } } /* END WRITE CHANNEL */ } } } close(fds[0]); close(fds[1]); LOCAL_USER_REMOVE(u); if (pid > -1) kill(pid, SIGKILL); if (!res && oreadformat) cw_set_read_format(chan, oreadformat); if (!res && owriteformat) cw_set_write_format(chan, owriteformat); return res; }
static int record_exec(struct cw_channel *chan, int argc, char **argv) { int res = 0; int count = 0; int percentflag = 0; char *ext = NULL; int i = 0; char tmp[256]; struct cw_filestream *s = '\0'; struct localuser *u; struct cw_frame *f = NULL; struct cw_dsp *sildet = NULL; /* silence detector dsp */ int totalsilence = 0; int dspsilence = 0; int silence = 0; /* amount of silence to allow */ int gotsilence = 0; /* did we timeout for silence? */ int maxduration = 0; /* max duration of recording in milliseconds */ int gottimeout = 0; /* did we timeout for maxduration exceeded? */ int option_skip = 0; int option_noanswer = 0; int option_append = 0; int terminator = '#'; int option_quiet = 0; int rfmt = 0; int flags; if (argc < 1 || argc > 4 || !argv[0][0]) { cw_log(LOG_ERROR, "Syntax: %s\n", record_syntax); return -1; } LOCAL_USER_ADD(u); if (strstr(argv[0], "%d")) percentflag = 1; ext = strrchr(argv[0], '.'); /* to support filename with a . in the filename, not format */ if (!ext) ext = strchr(argv[0], ':'); if (ext) { *ext = '\0'; ext++; } if (!ext) { cw_log(LOG_WARNING, "No extension specified to filename!\n"); LOCAL_USER_REMOVE(u); return -1; } if (argc > 1) { silence = atoi(argv[1]); if (silence > 0) silence *= 1000; else if (silence < 0) silence = 0; } if (argc > 2) { maxduration = atoi(argv[2]); if (maxduration > 0) maxduration *= 1000; else if (maxduration < 0) maxduration = 0; } if (argc > 3) { /* Retain backwards compatibility with old style options */ if (!strcasecmp(argv[3], "skip")) option_skip = 1; else if (!strcasecmp(argv[3], "noanswer")) option_noanswer = 1; else { if (strchr(argv[3], 's')) option_skip = 1; if (strchr(argv[3], 'n')) option_noanswer = 1; if (strchr(argv[3], 'a')) option_append = 1; if (strchr(argv[3], 't')) terminator = '*'; if (strchr(argv[3], 'q')) option_quiet = 1; } } /* done parsing */ /* these are to allow the use of the %d in the config file for a wild card of sort to create a new file with the inputed name scheme */ if (percentflag) { char *piece[100]; int pieces; /* Separate each piece out by the format specifier */ pieces = cw_separate_app_args(argv[0], '%', arraysize(piece), piece); do { int tmplen; /* First piece has no leading percent, so it's copied verbatim */ cw_copy_string(tmp, piece[0], sizeof(tmp)); tmplen = strlen(tmp); for (i = 1; i < pieces; i++) { if (piece[i][0] == 'd') { /* Substitute the count */ snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "%d", count); tmplen += strlen(tmp + tmplen); } else if (tmplen + 2 < sizeof(tmp)) { /* Unknown format specifier - just copy it verbatim */ tmp[tmplen++] = '%'; tmp[tmplen++] = piece[i][0]; } /* Copy the remaining portion of the piece */ cw_copy_string(tmp + tmplen, &(piece[i][1]), sizeof(tmp) - tmplen); } count++; } while ( cw_fileexists(tmp, ext, chan->language) != -1 ); pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp); } else strncpy(tmp, argv[0], sizeof(tmp)-1); /* end of routine mentioned */ if (chan->_state != CW_STATE_UP) { if (option_skip) { /* At the user's option, skip if the line is not up */ LOCAL_USER_REMOVE(u); return 0; } else if (!option_noanswer) { /* Otherwise answer unless we're supposed to record while on-hook */ res = cw_answer(chan); } } if (!res) { if (!option_quiet) { /* Some code to play a nice little beep to signify the start of the record operation */ res = cw_streamfile(chan, "beep", chan->language); if (!res) { res = cw_waitstream(chan, ""); } else { cw_log(LOG_WARNING, "cw_streamfile failed on %s\n", chan->name); } cw_stopstream(chan); } /* The end of beep code. Now the recording starts */ if (silence > 0) { rfmt = chan->readformat; res = cw_set_read_format(chan, CW_FORMAT_SLINEAR); if (res < 0) { cw_log(LOG_WARNING, "Unable to set to linear mode, giving up\n"); LOCAL_USER_REMOVE(u); return -1; } sildet = cw_dsp_new(); if (!sildet) { cw_log(LOG_WARNING, "Unable to create silence detector :(\n"); LOCAL_USER_REMOVE(u); return -1; } cw_dsp_set_threshold(sildet, 256); } flags = option_append ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY; s = cw_writefile( tmp, ext, NULL, flags , 0, 0644); if (s) { int waitres; /* Request a video update */ cw_indicate(chan, CW_CONTROL_VIDUPDATE); if (maxduration <= 0) maxduration = -1; while ((waitres = cw_waitfor(chan, maxduration)) > -1) { if (maxduration > 0) { if (waitres == 0) { gottimeout = 1; break; } maxduration = waitres; } f = cw_read(chan); if (!f) { res = -1; break; } if (f->frametype == CW_FRAME_VOICE) { res = cw_writestream(s, f); if (res) { cw_log(LOG_WARNING, "Problem writing frame\n"); cw_fr_free(f); break; } if (silence > 0) { dspsilence = 0; cw_dsp_silence(sildet, f, &dspsilence); if (dspsilence) { totalsilence = dspsilence; } else { totalsilence = 0; } if (totalsilence > silence) { /* Ended happily with silence */ cw_fr_free(f); gotsilence = 1; break; } } } if (f->frametype == CW_FRAME_VIDEO) { res = cw_writestream(s, f); if (res) { cw_log(LOG_WARNING, "Problem writing frame\n"); cw_fr_free(f); break; } } if ((f->frametype == CW_FRAME_DTMF) && (f->subclass == terminator)) { cw_fr_free(f); break; } cw_fr_free(f); } if (!f) { cw_log(LOG_DEBUG, "Got hangup\n"); res = -1; } if (gotsilence) { cw_stream_rewind(s, silence-1000); cw_truncstream(s); } else if (!gottimeout) { /* Strip off the last 1/4 second of it */ cw_stream_rewind(s, 250); cw_truncstream(s); } cw_closestream(s); } else cw_log(LOG_WARNING, "Could not create file %s\n", tmp); } else cw_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name); if ((silence > 0) && rfmt) { res = cw_set_read_format(chan, rfmt); if (res) cw_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); if (sildet) cw_dsp_free(sildet); } LOCAL_USER_REMOVE(u); return res; }
static int fax_exec(struct cw_channel *chan, int argc, char **argv) { fax_state_t fax; t38_terminal_state_t t38; t30_state_t *t30; const char *file_name; int res = 0; int ready; int calling_party; int verbose; struct localuser *u; int original_read_fmt; int original_write_fmt; /* Basic initial checkings */ if (chan == NULL) { cw_log(LOG_WARNING, "Fax transmit channel is NULL. Giving up.\n"); return -1; } /* Make sure they are initialized to zero */ memset(&fax, 0, sizeof(fax)); memset(&t38, 0, sizeof(t38)); if (argc < 1 || argc > 4) { cw_log(LOG_ERROR, "Syntax: %s\n", fax_syntax); return -1; } /* Resetting channel variables related to T38 */ pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", ""); pbx_builtin_setvar_helper(chan, "FAXPAGES", ""); pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", ""); pbx_builtin_setvar_helper(chan, "FAXBITRATE", ""); pbx_builtin_setvar_helper(chan, "PHASEESTATUS", ""); pbx_builtin_setvar_helper(chan, "PHASEESTRING", ""); /* Parsing parameters */ calling_party = FALSE; verbose = FALSE; file_name = argv[0]; while (argv++, --argc) { if (strcmp(argv[0], "caller") == 0) { calling_party = TRUE; } else if (strcmp(argv[0], "debug") == 0) { verbose = TRUE; } } /* Done parsing */ LOCAL_USER_ADD(u); if (chan->_state != CW_STATE_UP) { /* Shouldn't need this, but checking to see if channel is already answered * Theoretically the PBX should already have answered before running the app */ res = cw_answer(chan); if (!res) { cw_log(LOG_DEBUG, "Could not answer channel '%s'\n", chan->name); //LOCAL_USER_REMOVE(u); //return res; } } /* Setting read and write formats */ original_read_fmt = chan->readformat; if (original_read_fmt != CW_FORMAT_SLINEAR) { res = cw_set_read_format(chan, CW_FORMAT_SLINEAR); if (res < 0) { cw_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n"); LOCAL_USER_REMOVE(u); return -1; } } original_write_fmt = chan->writeformat; if (original_write_fmt != CW_FORMAT_SLINEAR) { res = cw_set_write_format(chan, CW_FORMAT_SLINEAR); if (res < 0) { cw_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n"); res = cw_set_read_format(chan, original_read_fmt); if (res) cw_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); LOCAL_USER_REMOVE(u); return -1; } } /* This is the main loop */ ready = TRUE; if (chan->t38_status == T38_NEGOTIATED) t30 = t38_terminal_get_t30_state(&t38); else t30 = fax_get_t30_state(&fax); while (ready && ready_to_talk(chan)) { if (ready && chan->t38_status != T38_NEGOTIATED) { t30 = fax_get_t30_state(&fax); ready = fax_audio(chan, &fax, file_name, calling_party, verbose); } if (ready && chan->t38_status == T38_NEGOTIATED) { t30 = t38_terminal_get_t30_state(&t38); ready = fax_t38(chan, &t38, file_name, calling_party, verbose); } if (chan->t38_status != T38_NEGOTIATING) ready = FALSE; // 1 loop is enough. This could be useful if we want to turn from udptl to RTP later. } t30_terminate(t30); fax_release(&fax); t38_terminal_release(&t38); /* Restoring initial channel formats. */ if (original_read_fmt != CW_FORMAT_SLINEAR) { if ((res = cw_set_read_format(chan, original_read_fmt))) cw_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); } if (original_write_fmt != CW_FORMAT_SLINEAR) { if ((res = cw_set_write_format(chan, original_write_fmt))) cw_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name); } return ready; }
static int visdn_ppp_exec(struct cw_channel *chan, int argc, char **argv) { struct visdn_chan *visdn_chan; const char **nargv; struct localuser *u; struct cw_frame *f; int res=-1; LOCAL_USER_ADD(u); if (chan->_state != CW_STATE_UP) cw_answer(chan); cw_mutex_lock(&chan->lock); if (strcmp(chan->type, "VISDN")) { cw_log(LOG_WARNING, "Only VISDN channels may be connected to" " this application\n"); cw_mutex_unlock(&chan->lock); return -1; } visdn_chan = chan->tech_pvt; if (!strlen(visdn_chan->visdn_chanid)) { cw_log(LOG_WARNING, "vISDN crossconnector channel ID not present\n"); cw_mutex_unlock(&chan->lock); return -1; } nargv = alloca((2 + argc + 3 + 1) * sizeof(nargv[0])); nargv[0] = PPP_EXEC; nargv[1] = "nodetach"; memcpy(nargv + 2, argc, argv * sizeof(argv[0])); nargv[2 + argc + 0] = "plugin"; nargv[2 + argc + 1] = "visdn.so"; nargv[2 + argc + 2] = visdn_chan->visdn_chanid; nargv[2 + argc + 3] = NULL; cw_mutex_unlock(&chan->lock); #if 0 int i; for (i=0;i<argc;i++) { cw_log(LOG_NOTICE, "Arg %d: %s\n", i, argv[i]); } #endif signal(SIGCHLD, SIG_DFL); pid_t pid = spawn_ppp(chan, nargv); if (pid < 0) { cw_log(LOG_WARNING, "Failed to spawn pppd\n"); return -1; } while(cw_waitfor(chan, -1) > -1) { f = cw_read(chan); if (!f) { cw_log(LOG_NOTICE, "Channel '%s' hungup." " Signalling PPP at %d to die...\n", chan->name, pid); kill(pid, SIGTERM); break; } cw_fr_free(f); int status; res = wait4(pid, &status, WNOHANG, NULL); if (res < 0) { cw_log(LOG_WARNING, "wait4 returned %d: %s\n", res, strerror(errno)); break; } else if (res > 0) { if (option_verbose > 2) { if (WIFEXITED(status)) { cw_verbose(VERBOSE_PREFIX_3 "PPP on %s terminated with status %d\n", chan->name, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { cw_verbose(VERBOSE_PREFIX_3 "PPP on %s terminated with signal %d\n", chan->name, WTERMSIG(status)); } else { cw_verbose(VERBOSE_PREFIX_3 "PPP on %s terminated weirdly.\n", chan->name); } } break; } } LOCAL_USER_REMOVE(u); return res; }
int cw_control_streamfile(struct cw_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms) { long elapsed = 0, last_elapsed = 0; char *breaks = NULL; char *end = NULL; int blen = 2; int res; if (stop) blen += strlen(stop); if (pause) blen += strlen(pause); if (restart) blen += strlen(restart); if (blen > 2) { breaks = alloca(blen + 1); breaks[0] = '\0'; if (stop) strcat(breaks, stop); if (pause) strcat(breaks, pause); if (restart) strcat(breaks, restart); } if (chan->_state != CW_STATE_UP) res = cw_answer(chan); if (chan) cw_stopstream(chan); if (file) { if ((end = strchr(file,':'))) { if (!strcasecmp(end, ":end")) { *end = '\0'; end++; } } } for (;;) { struct timeval started = cw_tvnow(); if (chan) cw_stopstream(chan); res = cw_streamfile(chan, file, chan->language); if (!res) { if (end) { cw_seekstream(chan->stream, 0, SEEK_END); end=NULL; } res = 1; if (elapsed) { cw_stream_fastforward(chan->stream, elapsed); last_elapsed = elapsed - 200; } if (res) res = cw_waitstream_fr(chan, breaks, fwd, rev, skipms); else break; } if (res < 1) break; /* We go at next loop if we got the restart char */ if (restart && strchr(restart, res)) { cw_log(LOG_DEBUG, "we'll restart the stream here at next loop\n"); elapsed=0; /* To make sure the next stream will start at beginning */ continue; } if (pause != NULL && strchr(pause, res)) { elapsed = cw_tvdiff_ms(cw_tvnow(), started) + last_elapsed; for(;;) { if (chan) cw_stopstream(chan); res = cw_waitfordigit(chan, 1000); if (res == 0) continue; else if (res == -1 || strchr(pause, res) || (stop && strchr(stop, res))) break; } if (res == *pause) { res = 0; continue; } } if (res == -1) break; /* if we get one of our stop chars, return it to the calling function */ if (stop && strchr(stop, res)) { /* res = 0; */ break; } } if (chan) cw_stopstream(chan); return res; }
static int privacy_exec (struct cw_channel *chan, int argc, char **argv) { char phone[30]; struct localuser *u; struct cw_config *cfg; char *s; int res=0; int retries; int maxretries = 3; int minlength = 10; int x; LOCAL_USER_ADD (u); if (!cw_strlen_zero(chan->cid.cid_num)) { if (option_verbose > 2) cw_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n"); pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS"); } else { /*Answer the channel if it is not already*/ if (chan->_state != CW_STATE_UP) { res = cw_answer(chan); if (res) { pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAIL"); LOCAL_USER_REMOVE(u); return 0; } } /*Read in the config file*/ cfg = cw_config_load(PRIV_CONFIG); /*Play unidentified call*/ res = cw_safe_sleep(chan, 1000); if (!res) res = cw_streamfile(chan, "privacy-unident", chan->language); if (!res) res = cw_waitstream(chan, ""); if (cfg && (s = cw_variable_retrieve(cfg, "general", "maxretries"))) { if (sscanf(s, "%d", &x) == 1) { maxretries = x; } else { cw_log(LOG_WARNING, "Invalid max retries argument\n"); } } if (cfg && (s = cw_variable_retrieve(cfg, "general", "minlength"))) { if (sscanf(s, "%d", &x) == 1) { minlength = x; } else { cw_log(LOG_WARNING, "Invalid min length argument\n"); } } /*Ask for 10 digit number, give 3 attempts*/ for (retries = 0; retries < maxretries; retries++) { if (!res ) res = cw_app_getdata(chan, "privacy-prompt", phone, sizeof(phone), 0); if (res < 0) break; /*Make sure we get at least our minimum of digits*/ if (strlen(phone) >= minlength ) break; else { res = cw_streamfile(chan, "privacy-incorrect", chan->language); if (!res) res = cw_waitstream(chan, ""); } } /*Got a number, play sounds and send them on their way*/ if ((retries < maxretries) && res == 1 ) { res = cw_streamfile(chan, "privacy-thankyou", chan->language); if (!res) res = cw_waitstream(chan, ""); cw_set_callerid (chan, phone, "Privacy Manager", NULL); if (option_verbose > 2) cw_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s\n",phone); pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS"); } else { /* Flag Failure */ pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAIL"); } if (cfg) cw_config_destroy(cfg); } LOCAL_USER_REMOVE (u); return 0; }