예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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 ;
		
}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
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;
}
예제 #7
0
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;
}
예제 #8
0
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;
}
예제 #9
0
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;
}