Esempio n. 1
0
static int exec_exec(struct ast_channel *chan, void *data)
{
	int res=0;
	struct ast_module_user *u;
	char *s, *appname, *endargs, args[MAXRESULT] = "";
	struct ast_app *app;

	u = ast_module_user_add(chan);

	/* Check and parse arguments */
	if (data) {
		s = ast_strdupa(data);
		appname = strsep(&s, "(");
		if (s) {
			endargs = strrchr(s, ')');
			if (endargs)
				*endargs = '\0';
			pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
		}
		if (appname) {
			app = pbx_findapp(appname);
			if (app) {
				res = pbx_exec(chan, app, args);
			} else {
				ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
				res = -1;
			}
		}
	}

	ast_module_user_remove(u);
	return res;
}
Esempio n. 2
0
static int exec_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	char *s, *appname, *endargs, args[MAXRESULT];
	struct ast_app *app;

	if (ast_strlen_zero(data))
		return 0;

	s = ast_strdupa(data);
	args[0] = 0;
	appname = strsep(&s, "(");
	if (s) {
		endargs = strrchr(s, ')');
		if (endargs)
			*endargs = '\0';
		pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
	}
	if (appname) {
		app = pbx_findapp(appname);
		if (app) {
			res = pbx_exec(chan, app, args);
		} else {
			ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
			res = -1;
		}
	}

	return res;
}
Esempio n. 3
0
/*!
 * \internal
 * \brief Check if Monitor needs to be started on a channel.
 * \since 12.0.0
 *
 * \param chan The bridge considers this channel the caller.
 * \param peer The bridge considers this channel the callee.
 *
 * \return Nothing
 */
static void bridge_check_monitor(struct ast_channel *chan, struct ast_channel *peer)
{
	const char *value;
	const char *monitor_args = NULL;
	struct ast_channel *monitor_chan = NULL;

	ast_channel_lock(chan);
	value = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR");
	if (!ast_strlen_zero(value)) {
		monitor_args = ast_strdupa(value);
		monitor_chan = chan;
	}
	ast_channel_unlock(chan);
	if (!monitor_chan) {
		ast_channel_lock(peer);
		value = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR");
		if (!ast_strlen_zero(value)) {
			monitor_args = ast_strdupa(value);
			monitor_chan = peer;
		}
		ast_channel_unlock(peer);
	}
	if (monitor_chan) {
		struct ast_app *monitor_app;

		monitor_app = pbx_findapp("Monitor");
		if (monitor_app) {
			pbx_exec(monitor_chan, monitor_app, monitor_args);
		}
	}
}
Esempio n. 4
0
static int tryexec_exec(struct ast_channel *chan, void *data)
{
	int res=0;
	struct localuser *u;
	char *s, *appname, *endargs, args[MAXRESULT] = "";
	struct ast_app *app;

	LOCAL_USER_ADD(u);

	/* Check and parse arguments */
	if (data) {
		s = ast_strdupa(data);
		appname = strsep(&s, "(");
		if (s) {
			endargs = strrchr(s, ')');
			if (endargs)
				*endargs = '\0';
			pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
		}
		if (appname) {
			app = pbx_findapp(appname);
			if (app) {
				res = pbx_exec(chan, app, args);
				pbx_builtin_setvar_helper(chan, "TRYSTATUS", res ? "FAILED" : "SUCCESS");
			} else {
				ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
				pbx_builtin_setvar_helper(chan, "TRYSTATUS", "NOAPP");
			}
		}
	}

	LOCAL_USER_REMOVE(u);
	return 0;
}
static int SQLiteSwitch_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, int newstack, const char *data)
{
	struct ast_app *app;
	int res = 0;
	extension_cache *cache;
	char key[ARRAY_SIZE];
	time_t now;
	char app_data[1024];
	

	time(&now);
	//ast_log(LOG_NOTICE, "SQLiteSwitch_exec: con: %s, exten: %s, pri: %d, cid: %s, data: %s\n", context, exten, priority, callerid ? callerid : "<unknown>", data);

	snprintf(key, ARRAY_SIZE, "%s.%s", exten, context);
	memset(&app_data,0,sizeof(app_data) - 1);

	ast_verbose(VERBOSE_PREFIX_2 "SQLiteSwitch_exec lookup [%s]: ",key);
	cache = (extension_cache *) sqlite3HashFind(&extens,key,strlen(key));
	ast_verbose("%s\n",cache ? "match" : "fail");

	if (cache) {
		app = pbx_findapp(cache->app_name[priority]);
		if (app) {
			pbx_substitute_variables_helper(chan, cache->app_data[priority], app_data, sizeof(app_data) - 1);
			ast_verbose(VERBOSE_PREFIX_2 "SQLiteSwitch_exec: call app %s(%s)\n",cache->app_name[priority],app_data);
			res = pbx_exec(chan, app,app_data,1);
		}
		else {
			ast_log(LOG_WARNING, "application %s not registered\n",cache->app_name[priority]);
			res = -1;
		}
	}
		
	return res;
}
Esempio n. 6
0
static void bridge_stasis_run_cb(struct ast_channel *chan, void *data)
{
    RAII_VAR(char *, app_name, NULL, ast_free);
    struct ast_app *app_stasis;

    /* Take ownership of the swap_app memory from the datastore */
    app_name = app_get_replace_channel_app(chan);
    if (!app_name) {
        ast_log(LOG_ERROR, "Failed to get app name for %s (%p)\n", ast_channel_name(chan), chan);
        return;
    }

    /* find Stasis() */
    app_stasis = pbx_findapp("Stasis");
    if (!app_stasis) {
        ast_log(LOG_WARNING, "Could not find application (Stasis)\n");
        return;
    }

    if (ast_check_hangup_locked(chan)) {
        /* channel hungup, don't run Stasis() */
        return;
    }

    /* run Stasis() */
    pbx_exec(chan, app_stasis, app_name);
}
Esempio n. 7
0
static int tryexec_exec(struct ast_channel *chan, const char *data)
{
	int res = 0;
	char *s, *appname, *endargs;
	struct ast_app *app;
	struct ast_str *args = NULL;

	if (ast_strlen_zero(data))
		return 0;

	s = ast_strdupa(data);
	appname = strsep(&s, "(");
	if (s) {
		endargs = strrchr(s, ')');
		if (endargs)
			*endargs = '\0';
		if ((args = ast_str_create(16))) {
			ast_str_substitute_variables(&args, 0, chan, s);
		}
	}
	if (appname) {
		app = pbx_findapp(appname);
		if (app) {
			res = pbx_exec(chan, app, args ? ast_str_buffer(args) : NULL);
			pbx_builtin_setvar_helper(chan, "TRYSTATUS", res ? "FAILED" : "SUCCESS");
		} else {
			ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
			pbx_builtin_setvar_helper(chan, "TRYSTATUS", "NOAPP");
		}
	}

	ast_free(args);
	return 0;
}
Esempio n. 8
0
static int checkMax(struct ast_channel *chan, struct roomdetails *dtmfmatch)
{
	int res=0;
    	struct ast_app *app;
	char getvar[30]="AstVar";
	char roomno[30]="";
	char maxusers[30]="";
	char currentusers[30]="";
	char prompt[50]="";
	char arg[255]="";

    	strcpy(maxusers,dtmfmatch->maxusers);
	strcpy(roomno,dtmfmatch->roomno);
    	strcat(arg,roomno);
    	strcat(arg,",");
	strcat(arg,getvar);

	if(!(app = pbx_findapp(ConfAppCount))) {
		ast_log(LOG_WARNING, "Invalid participant count application: %s\n", ConfAppCount);
		return -1;
	}
 	res = pbx_exec(chan, app, arg);
   	strcpy(currentusers, pbx_builtin_getvar_helper(chan, getvar));
	if(atoi(currentusers) < atoi(maxusers)){
	ast_log(LOG_NOTICE, "Currentusers: %i\n", atoi(currentusers));
		if(atoi(currentusers)>0){
			strcpy(prompt,"conf-thereare");
			if (!ast_streamfile(chan, "conf-thereare", chan->language)){
				res = ast_waitstream(chan,"");
				ast_stopstream(chan);
				
				if (!ast_say_number(chan, (atoi(currentusers)), AST_DIGIT_ANY, chan->language, (char *) NULL)){
					res = ast_waitstream(chan,"");
					ast_stopstream(chan);
				}
				if (!ast_streamfile(chan, "conf-otherinparty", chan->language)){
					res = ast_waitstream(chan,"");
					ast_stopstream(chan);
				}
			}
		}
		res=1;
	}
	else{
        	ast_log(LOG_NOTICE, "Maximum users exeeded, Current users in room: %s\n",currentusers);
        	strcpy(prompt, "conf-locked");
        	if (!ast_streamfile(chan, prompt, chan->language)){
        		res = ast_waitstream(chan,"");
			ast_stopstream(chan);
		}
		res=-1;
	}
	return res;
}
/*! \brief Thread which dials and executes upon answer */
static void *ari_originate_dial(void *data)
{
	struct ast_dial *dial = data;
	struct ari_origination *origination = ast_dial_get_user_data(dial);
	enum ast_dial_result res;

	res = ast_dial_run(dial, NULL, 0);
	if (res != AST_DIAL_RESULT_ANSWERED) {
		goto end;
	}

	if (!ast_strlen_zero(origination->appdata)) {
		struct ast_app *app = pbx_findapp("Stasis");

		if (app) {
			ast_verb(4, "Launching Stasis(%s) on %s\n", origination->appdata,
				ast_channel_name(ast_dial_answered(dial)));
			pbx_exec(ast_dial_answered(dial), app, origination->appdata);
		} else {
			ast_log(LOG_WARNING, "No such application 'Stasis'\n");
		}
	} else {
		struct ast_channel *answered = ast_dial_answered(dial);

		if (!ast_strlen_zero(origination->context)) {
			ast_channel_context_set(answered, origination->context);
		}

		if (!ast_strlen_zero(origination->exten)) {
			ast_channel_exten_set(answered, origination->exten);
		}

		if (origination->priority > 0) {
			ast_channel_priority_set(answered, origination->priority);
		}

		if (ast_pbx_run(answered)) {
			ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(answered));
		} else {
			/* PBX will have taken care of hanging up, so we steal the answered channel so dial doesn't do it */
			ast_dial_answered_steal(dial);
		}
	}

end:
	ast_dial_destroy(dial);
	ast_free(origination);
	return NULL;
}
Esempio n. 10
0
/*! \brief Thread used for running the Stasis application */
static void *snoop_stasis_thread(void *obj)
{
	RAII_VAR(struct stasis_app_snoop *, snoop, obj, ao2_cleanup);
	struct ast_app *stasis = pbx_findapp("Stasis");

	if (!stasis) {
		ast_hangup(snoop->chan);
		return NULL;
	}

	pbx_exec(snoop->chan, stasis, ast_str_buffer(snoop->app));

	ast_hangup(snoop->chan);

	return NULL;
}
Esempio n. 11
0
static int enterConf(struct ast_channel *chan, struct roomdetails *dtmfmatch)
{
        int res=0;
        /* char *prompt; */
	char prompt[50]="";
        struct ast_app *app;
	char arg2[255]="";
	char roomno2[80]="";
	char roomtype2[30]="";
	char recordfile[100]="conf-recordings/";

        strcpy(roomno2,dtmfmatch->roomno);
	strcpy(roomtype2,dtmfmatch->roomtype);
	strcpy(arg2, roomno2);

	strcat(arg2, ",");
	strcat(arg2, roomtype2);
	strcat(arg2, ",");

	strcat(recordfile, dtmfmatch->roomno);
	strcat(recordfile, "-");
	strcat(recordfile, dtmfmatch->bookid);

        ast_log(LOG_NOTICE, "Roomtype: %s\n", arg2);
	pbx_builtin_setvar_helper(chan, "MEETME_RECORDINGFILE", recordfile);
  
	if(strchr(dtmfmatch->aFlags, 'r'))
	{
		strcpy(prompt,"conf-call-recorded");
		if (!ast_streamfile(chan, prompt, chan->language)){
			res = ast_waitstream(chan,"");
			ast_stopstream(chan);
		}
	}
        if(!(app=pbx_findapp(ConfApp))){
		ast_log(LOG_WARNING, "Invalid conferencing application: %s\n", ConfApp);
		return -1;
	}
        res = pbx_exec(chan, app, arg2);

	return 1;
}
Esempio n. 12
0
static int execif_exec(struct ast_channel *chan, void *data) {
	int res=0;
	struct localuser *u;
	char *myapp = NULL;
	char *mydata = NULL;
	char *expr = NULL;
	struct ast_app *app = NULL;

	LOCAL_USER_ADD(u);

	expr = ast_strdupa(data);
	if (!expr) {
		ast_log(LOG_ERROR, "Out of memory\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	if ((myapp = strchr(expr,'|'))) {
		*myapp = '\0';
		myapp++;
		if ((mydata = strchr(myapp,'|'))) {
			*mydata = '\0';
			mydata++;
		} else
			mydata = "";

		if (pbx_checkcondition(expr)) { 
			if ((app = pbx_findapp(myapp))) {
				res = pbx_exec(chan, app, mydata, 1);
			} else {
				ast_log(LOG_WARNING, "Count not find application! (%s)\n", myapp);
				res = -1;
			}
		}
	} else {
		ast_log(LOG_ERROR,"Invalid Syntax.\n");
		res = -1;
	}
		
	ALL_DONE(u,res);
}
Esempio n. 13
0
static int execif_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct ast_module_user *u;
	char *myapp = NULL;
	char *mydata = NULL;
	char *expr = NULL;
	struct ast_app *app = NULL;

	u = ast_module_user_add(chan);

	expr = ast_strdupa(data);

	if ((myapp = strchr(expr,'|'))) {
		*myapp = '\0';
		myapp++;
		if ((mydata = strchr(myapp,'|'))) {
			*mydata = '\0';
			mydata++;
		} else
			mydata = "";

		if (pbx_checkcondition(expr)) { 
			if ((app = pbx_findapp(myapp))) {
				res = pbx_exec(chan, app, mydata);
			} else {
				ast_log(LOG_WARNING, "Could not find application! (%s)\n", myapp);
				res = -1;
			}
		}
	} else {
		ast_log(LOG_ERROR,"Invalid Syntax.\n");
		res = -1;
	}
		
	ast_module_user_remove(u);

	return res;
}
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 ;
		
}
Esempio n. 15
0
static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int confflags)
{
	struct ast_conference *prev=NULL, *cur;
	struct ast_conf_user *user = malloc(sizeof(struct ast_conf_user));
	int fd;
	struct zt_confinfo ztc;
	struct ast_frame *f;
	struct ast_channel *c;
	struct ast_frame fr;
	int outfd;
	int ms;
	int nfds;
	int res;
	int flags;
	int retryzap;
	int origfd;
	int musiconhold = 0;
	int firstpass = 0;
	int origquiet;
	int ret = -1;
	int x;
	int menu_active = 0;
	int using_pseudo = 0;

	struct ast_app *app;
	char *agifile;
	char *agifiledefault = "conf-background.agi";
	char meetmesecs[30] = "";
	char exitcontext[AST_MAX_EXTENSION] = "";
	int dtmf;

	ZT_BUFFERINFO bi;
	char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
	char *buf = __buf + AST_FRIENDLY_OFFSET;
	
	if (!user) {
		ast_log(LOG_ERROR, "Out of memory\n");
		return(ret);
	}
	memset(user, 0, sizeof(struct ast_conf_user));

	user->user_no = 0; /* User number 0 means starting up user! (dead - not in the list!) */

	time(&user->jointime);

	if (conf->locked) {
		/* Sorry, but this confernce is locked! */	
		if (!ast_streamfile(chan, "conf-locked", chan->language))
			ast_waitstream(chan, "");
		goto outrun;
	}
	conf->users++;
	if (confflags & CONFFLAG_MARKEDUSER)
		conf->markedusers++;
      
   	ast_mutex_lock(&conflock);
	if (conf->firstuser == NULL) {
		/* Fill the first new User struct */
		user->user_no = 1;
		user->nextuser = NULL;
		user->prevuser = NULL;
		conf->firstuser = user;
		conf->lastuser = user;
	} else {
		/* Fill the new user struct */	
		user->user_no = conf->lastuser->user_no + 1; 
		user->prevuser = conf->lastuser;
		user->nextuser = NULL;
		if (conf->lastuser->nextuser != NULL) {
			ast_log(LOG_WARNING, "Error in User Management!\n");
			ast_mutex_unlock(&conflock);
			goto outrun;
		} else {
			conf->lastuser->nextuser = user;
			conf->lastuser = user;
		}
	}
	user->chan = chan;
	user->userflags = confflags;
	user->adminflags = 0;
	ast_mutex_unlock(&conflock);
	origquiet = confflags & CONFFLAG_QUIET;
	if (confflags & CONFFLAG_EXIT_CONTEXT) {
		if ((agifile = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) 
			strncpy(exitcontext, agifile, sizeof(exitcontext) - 1);
		else if (!ast_strlen_zero(chan->macrocontext)) 
			strncpy(exitcontext, chan->macrocontext, sizeof(exitcontext) - 1);
		else
			strncpy(exitcontext, chan->context, sizeof(exitcontext) - 1);
	}
	while((confflags & CONFFLAG_WAITMARKED) && (conf->markedusers == 0)) {
		confflags &= ~CONFFLAG_QUIET;
		confflags |= origquiet;
		/* XXX Announce that we're waiting on the conference lead to join */
		if (!(confflags & CONFFLAG_QUIET)) {
			res = ast_streamfile(chan, "vm-dialout", chan->language);
			if (!res)
				res = ast_waitstream(chan, "");
		} else
			res = 0;
		/* If we're waiting with hold music, set to silent mode */
		if (!res) {
			confflags |= CONFFLAG_QUIET;
			ast_moh_start(chan, NULL);
			res = ast_safe_sleep_conditional(chan, 60000, confnonzero, conf);
			ast_moh_stop(chan);
		}
		if (res < 0) {
			ast_log(LOG_DEBUG, "Got hangup on '%s' already\n", chan->name);
			goto outrun;
		}
	}
	
	if (!(confflags & CONFFLAG_QUIET) && conf->users == 1) {
		if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) {
			if (ast_waitstream(chan, "") < 0)
				goto outrun;
		} else
			goto outrun;
	}

	/* Set it into linear mode (write) */
	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
		ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name);
		goto outrun;
	}

	/* Set it into linear mode (read) */
	if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
		ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name);
		goto outrun;
	}
	ast_indicate(chan, -1);
	retryzap = strcasecmp(chan->type, "Zap");
zapretry:
	origfd = chan->fds[0];
	if (retryzap) {
		fd = open("/dev/zap/pseudo", O_RDWR);
		if (fd < 0) {
			ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
			goto outrun;
		}
		using_pseudo = 1;
		/* Make non-blocking */
		flags = fcntl(fd, F_GETFL);
		if (flags < 0) {
			ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno));
			close(fd);
			goto outrun;
		}
		if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
			ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno));
			close(fd);
			goto outrun;
		}
		/* Setup buffering information */
		memset(&bi, 0, sizeof(bi));
		bi.bufsize = CONF_SIZE/2;
		bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
		bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
		bi.numbufs = 4;
		if (ioctl(fd, ZT_SET_BUFINFO, &bi)) {
			ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno));
			close(fd);
			goto outrun;
		}
		x = 1;
		if (ioctl(fd, ZT_SETLINEAR, &x)) {
			ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno));
			close(fd);
			goto outrun;
		}
		nfds = 1;
	} else {
		/* XXX Make sure we're not running on a pseudo channel XXX */
		fd = chan->fds[0];
		nfds = 0;
	}
	memset(&ztc, 0, sizeof(ztc));
	/* Check to see if we're in a conference... */
	ztc.chan = 0;	
	if (ioctl(fd, ZT_GETCONF, &ztc)) {
		ast_log(LOG_WARNING, "Error getting conference\n");
		close(fd);
		goto outrun;
	}
	if (ztc.confmode) {
		/* Whoa, already in a conference...  Retry... */
		if (!retryzap) {
			ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n");
			retryzap = 1;
			goto zapretry;
		}
	}
	memset(&ztc, 0, sizeof(ztc));
	/* Add us to the conference */
	ztc.chan = 0;	
	ztc.confno = conf->zapconf;
	if (confflags & CONFFLAG_MONITOR)
		ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER;
	else if (confflags & CONFFLAG_TALKER)
		ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
	else 
		ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;

	if (ioctl(fd, ZT_SETCONF, &ztc)) {
		ast_log(LOG_WARNING, "Error setting conference\n");
		close(fd);
		goto outrun;
	}
	ast_log(LOG_DEBUG, "Placed channel %s in ZAP conf %d\n", chan->name, conf->zapconf);

	manager_event(EVENT_FLAG_CALL, "MeetmeJoin", 
			"Channel: %s\r\n"
			"Uniqueid: %s\r\n"
			"Meetme: %s\r\n"
			"Usernum: %i\r\n",
			chan->name, chan->uniqueid, conf->confno, user->user_no);

	if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) {
		firstpass = 1;
		if (!(confflags & CONFFLAG_QUIET))
			conf_play(conf, ENTER);
	}

	if (confflags & CONFFLAG_AGI) {

		/* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND)
		  or use default filename of conf-background.agi */

		agifile = pbx_builtin_getvar_helper(chan,"MEETME_AGI_BACKGROUND");
		if (!agifile)
			agifile = agifiledefault;

		if (!strcasecmp(chan->type,"Zap")) {
			/*  Set CONFMUTE mode on Zap channel to mute DTMF tones */
			x = 1;
			ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
		}
		/* Find a pointer to the agi app and execute the script */
		app = pbx_findapp("agi");
		if (app) {
			ret = pbx_exec(chan, app, agifile, 1);
		} else {
			ast_log(LOG_WARNING, "Could not find application (agi)\n");
			ret = -2;
		}
		if (!strcasecmp(chan->type,"Zap")) {
			/*  Remove CONFMUTE mode on Zap channel */
			x = 0;
			ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
		}
	} else {
		if (!strcasecmp(chan->type,"Zap") && (confflags & CONFFLAG_STARMENU)) {
			/*  Set CONFMUTE mode on Zap channel to mute DTMF tones when the menu is enabled */
			x = 1;
			ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
		}	
		for(;;) {
			outfd = -1;
			ms = -1;
			c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
			
			/* Update the struct with the actual confflags */
			user->userflags = confflags;
			
			/* trying to add moh for single person conf */
			if (confflags & CONFFLAG_MOH) {
				if (conf->users == 1) {
					if (musiconhold == 0) {
						ast_moh_start(chan, NULL);
						musiconhold = 1;
					} 
				} else {
					if (musiconhold) {
						ast_moh_stop(chan);
						musiconhold = 0;
					}
				}
			}
			
			/* Leave if the last marked user left */
			if (conf->markedusers == 0 && confflags & CONFFLAG_MARKEDEXIT) {
				ret = -1;
				break;
			}
	
			/* Check if the admin changed my modes */
			if (user->adminflags) {			
				/* Set the new modes */
				if ((user->adminflags & ADMINFLAG_MUTED) && (ztc.confmode & ZT_CONF_TALKER)) {
					ztc.confmode ^= ZT_CONF_TALKER;
					if (ioctl(fd, ZT_SETCONF, &ztc)) {
						ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
						ret = -1;
						break;
					}
				}
				if (!(user->adminflags & ADMINFLAG_MUTED) && !(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) {
					ztc.confmode |= ZT_CONF_TALKER;
					if (ioctl(fd, ZT_SETCONF, &ztc)) {
						ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
						ret = -1;
						break;
					}
				}
				if (user->adminflags & ADMINFLAG_KICKME) {
					//You have been kicked.
					if (!ast_streamfile(chan, "conf-kicked", chan->language))
						ast_waitstream(chan, "");
					ret = 0;
					break;
				}
			} else if (!(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) {
				ztc.confmode |= ZT_CONF_TALKER;
				if (ioctl(fd, ZT_SETCONF, &ztc)) {
					ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
					ret = -1;
					break;
				}
			}

			if (c) {
				if (c->fds[0] != origfd) {
					if (using_pseudo) {
						/* Kill old pseudo */
						close(fd);
					}
					ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n");
					retryzap = 0;
					using_pseudo = 0;
					goto zapretry;
				}
				f = ast_read(c);
				if (!f) 
					break;
				if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT)) {
					char tmp[2];
					tmp[0] = f->subclass;
					tmp[1] = '\0';
					if (ast_exists_extension(chan, exitcontext, tmp, 1, chan->callerid)) {
						strncpy(chan->context, exitcontext, sizeof(chan->context) - 1);
						strncpy(chan->exten, tmp, sizeof(chan->exten) - 1);
						chan->priority = 0;
						ret = 0;
						break;
					}
				} else if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) {
					ret = 0;
					break;
				} else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) {
					if (musiconhold) {
			   			ast_moh_stop(chan);
					}
					if ((confflags & CONFFLAG_ADMIN)) {
						/* Admin menu */
						if (!menu_active) {
							menu_active = 1;
							/* Record this sound! */
							if (!ast_streamfile(chan, "conf-adminmenu", chan->language))
								dtmf = ast_waitstream(chan, AST_DIGIT_ANY);
							else
								dtmf = 0;
						} else 
							dtmf = f->subclass;
						if (dtmf) {
							switch(dtmf) {
								case '1': /* Un/Mute */
									menu_active = 0;
		 							if (ztc.confmode & ZT_CONF_TALKER) {
	 						       		ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
	 						       		confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER;
									} else {
										ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
										confflags ^= CONFFLAG_MONITOR | CONFFLAG_TALKER;
									}
									if (ioctl(fd, ZT_SETCONF, &ztc)) {
										ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
										ret = -1;
										break;
									}
									if (ztc.confmode & ZT_CONF_TALKER) {
										if (!ast_streamfile(chan, "conf-unmuted", chan->language))
											ast_waitstream(chan, "");
									} else {
										if (!ast_streamfile(chan, "conf-muted", chan->language))
											ast_waitstream(chan, "");
									}
									break;
								case '2': /* Un/Lock the Conference */
									menu_active = 0;
									if (conf->locked) {
										conf->locked = 0;
										if (!ast_streamfile(chan, "conf-unlockednow", chan->language))
											ast_waitstream(chan, "");
									} else {
										conf->locked = 1;
										if (!ast_streamfile(chan, "conf-lockednow", chan->language))
											ast_waitstream(chan, "");
									}
									break;
								default:
									menu_active = 0;
									/* Play an error message! */
									if (!ast_streamfile(chan, "conf-errormenu", chan->language))
										ast_waitstream(chan, "");
									break;
							}
						}
					} else {
						/* User menu */
						if (!menu_active) {
							menu_active = 1;
							/* Record this sound! */
							if (!ast_streamfile(chan, "conf-usermenu", chan->language))
								dtmf = ast_waitstream(chan, AST_DIGIT_ANY);
							else
								dtmf = 0;
						} else 
							dtmf = f->subclass;
						if (dtmf) {
							switch(dtmf) {
								case '1': /* Un/Mute */
									menu_active = 0;
		 							if (ztc.confmode & ZT_CONF_TALKER) {
	 						       		ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
	 						       		confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER;
									} else if (!(user->adminflags & ADMINFLAG_MUTED)) {
										ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
										confflags ^= CONFFLAG_MONITOR | CONFFLAG_TALKER;
									}
									if (ioctl(fd, ZT_SETCONF, &ztc)) {
										ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
										ret = -1;
										break;
									}
									if (ztc.confmode & ZT_CONF_TALKER) {
										if (!ast_streamfile(chan, "conf-unmuted", chan->language))
											ast_waitstream(chan, "");
									} else {
										if (!ast_streamfile(chan, "conf-muted", chan->language))
											ast_waitstream(chan, "");
									}
									break;
								default:
									menu_active = 0;
									/* Play an error message! */
									if (!ast_streamfile(chan, "conf-errormenu", chan->language))
										ast_waitstream(chan, "");
									break;
							}
						}
					}
					if (musiconhold) {
			   			ast_moh_start(chan, NULL);
					}
				} else if (using_pseudo) {
					if (f->frametype == AST_FRAME_VOICE) {
						if (f->subclass == AST_FORMAT_SLINEAR) {
							/* Carefully write */
							careful_write(fd, f->data, f->datalen);
						} else
							ast_log(LOG_WARNING, "Huh?  Got a non-linear (%d) frame in the conference\n", f->subclass);
					}
				}
				ast_frfree(f);
			} else if (outfd > -1) {
				res = read(outfd, buf, CONF_SIZE);
				if (res > 0) {
					memset(&fr, 0, sizeof(fr));
					fr.frametype = AST_FRAME_VOICE;
					fr.subclass = AST_FORMAT_SLINEAR;
					fr.datalen = res;
					fr.samples = res/2;
					fr.data = buf;
					fr.offset = AST_FRIENDLY_OFFSET;
					if (ast_write(chan, &fr) < 0) {
						ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno));
						/* break; */
					}
				} else 
					ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno));
			}
		}
	}
	if (using_pseudo)
		close(fd);
	else {
		/* Take out of conference */
		/* Add us to the conference */
		ztc.chan = 0;	
		ztc.confno = 0;
		ztc.confmode = 0;
		if (ioctl(fd, ZT_SETCONF, &ztc)) {
			ast_log(LOG_WARNING, "Error setting conference\n");
		}
	}
	if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN))
		conf_play(conf, LEAVE);

outrun:
	ast_mutex_lock(&conflock);
	if (user->user_no) { /* Only cleanup users who really joined! */
		manager_event(EVENT_FLAG_CALL, "MeetmeLeave", 
			"Channel: %s\r\n"
			"Uniqueid: %s\r\n"
			"Meetme: %s\r\n"
			"Usernum: %i\r\n",
			chan->name, chan->uniqueid, conf->confno, user->user_no);
		prev = NULL;
		conf->users--;
		if (confflags & CONFFLAG_MARKEDUSER) 
			conf->markedusers--;
		cur = confs;
		if (!conf->users) {
			/* No more users -- close this one out */
			while(cur) {
				if (cur == conf) {
					if (prev)
						prev->next = conf->next;
					else
						confs = conf->next;
					break;
				}
				prev = cur;
				cur = cur->next;
			}
			if (!cur) 
				ast_log(LOG_WARNING, "Conference not found\n");
			if (conf->chan)
				ast_hangup(conf->chan);
			else
				close(conf->fd);
			free(conf);
		} else {
			/* Remove the user struct */ 
			if (user == conf->firstuser) {
				if (user->nextuser) {
					/* There is another entry */
					user->nextuser->prevuser = NULL;
				} else {
					/* We are the only entry */
					conf->lastuser = NULL;
				}
				/* In either case */
				conf->firstuser = user->nextuser;
			} else if (user == conf->lastuser){
				if (user->prevuser)
					user->prevuser->nextuser = NULL;
				else
					ast_log(LOG_ERROR, "Bad bad bad!  We're the last, not the first, but nobody before us??\n");
				conf->lastuser = user->prevuser;
			} else {
				if (user->nextuser)
					user->nextuser->prevuser = user->prevuser;
				else
					ast_log(LOG_ERROR, "Bad! Bad! Bad! user->nextuser is NULL but we're not the end!\n");
				if (user->prevuser)
					user->prevuser->nextuser = user->nextuser;
				else
					ast_log(LOG_ERROR, "Bad! Bad! Bad! user->prevuser is NULL but we're not the beginning!\n");
			}
		}
		/* Return the number of seconds the user was in the conf */
		snprintf(meetmesecs, sizeof(meetmesecs), "%i", (int) (time(NULL) - user->jointime));
		pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs);
	}
	free(user);
	ast_mutex_unlock(&conflock);
	return ret;
}
Esempio n. 16
0
/*!
 * \brief [lua_CFunction] This function is part of the 'application' metatable
 * and is used to execute applications similar to pbx_exec() (for access from
 * lua, don't call directly)
 *
 * \param L the lua_State to use
 * \return nothing
 *
 * This funciton is executed as the '()' operator for apps accessed through the
 * 'app' table.
 *
 * \code
 * app.playback('demo-congrats')
 * \endcode
 */
static int lua_pbx_exec(lua_State *L)
{
	int res, nargs = lua_gettop(L);
	const char *data = "";
	char *app_name, *context, *exten;
	char tmp[80], tmp2[80], tmp3[LUA_EXT_DATA_SIZE];
	int priority, autoservice;
	struct ast_app *app;
	struct ast_channel *chan;

	lua_getfield(L, 1, "name");
	app_name = ast_strdupa(lua_tostring(L, -1));
	lua_pop(L, 1);
	
	if (!(app = pbx_findapp(app_name))) {
		lua_pushstring(L, "application '");
		lua_pushstring(L, app_name);
		lua_pushstring(L, "' not found");
		lua_concat(L, 3);
		return lua_error(L);
	}
	

	lua_getfield(L, LUA_REGISTRYINDEX, "channel");
	chan = lua_touserdata(L, -1);
	lua_pop(L, 1);
	
	context = ast_strdupa(ast_channel_context(chan));
	exten = ast_strdupa(ast_channel_exten(chan));
	priority = ast_channel_priority(chan);
	
	lua_concat_args(L, 2, nargs);
	data = lua_tostring(L, -1);

	ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\")\n",
			exten, context, priority,
			term_color(tmp, app_name, COLOR_BRCYAN, 0, sizeof(tmp)),
			term_color(tmp2, ast_channel_name(chan), COLOR_BRMAGENTA, 0, sizeof(tmp2)),
			term_color(tmp3, data, COLOR_BRMAGENTA, 0, sizeof(tmp3)));

	lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
	autoservice = lua_toboolean(L, -1);
	lua_pop(L, 1);

	if (autoservice)
		ast_autoservice_stop(chan);

	res = pbx_exec(chan, app, data);

	lua_pop(L, 1); /* pop data */
	data = "";

	if (autoservice)
		ast_autoservice_start(chan);

	/* error executing an application, report it */
	if (res) {
		lua_pushinteger(L, res);
		return lua_error(L);
	}

	if (strcmp(context, ast_channel_context(chan))) {
		lua_pushstring(L, context);
		lua_pushstring(L, ast_channel_context(chan));
		lua_pushliteral(L, "context");
	} else if (strcmp(exten, ast_channel_exten(chan))) {
		lua_pushstring(L, exten);
		lua_pushstring(L, ast_channel_exten(chan));
		lua_pushliteral(L, "exten");
	} else if (priority != ast_channel_priority(chan)) {
		lua_pushinteger(L, priority);
		lua_pushinteger(L, ast_channel_priority(chan));
		lua_pushliteral(L, "priority");
	} else {
		/* no goto - restore the original position back
		 * to lua state, in case this was a recursive dialplan
		 * call (a dialplan application re-entering dialplan) */
		lua_update_registry(L, context, exten, priority);
		return 0;
	}

	/* goto detected - construct error message */
	lua_insert(L, -3);
													
	lua_pushliteral(L, " changed from ");							    
	lua_insert(L, -3);									       
													 
	lua_pushliteral(L, " to ");								      
	lua_insert(L, -2);									       
													 
	lua_concat(L, 5);										
													 
	ast_debug(2, "Goto detected: %s\n", lua_tostring(L, -1));					
	lua_pop(L, 1);										   
													 
	/* let the lua engine know it needs to return control to the pbx */			      
	lua_pushinteger(L, LUA_GOTO_DETECTED);							   
	lua_error(L);

	return 0;
}
Esempio n. 17
0
/*!
 * \brief [lua_CFunction] This function is part of the 'application' metatable
 * and is used to execute applications similar to pbx_exec() (for access from
 * lua, don't call directly)
 *
 * \param L the lua_State to use
 * \return nothing
 *
 * This funciton is executed as the '()' operator for apps accessed through the
 * 'app' table.
 *
 * \code
 * app.playback('demo-congrats')
 * \endcode
 */
static int lua_pbx_exec(lua_State *L)
{
	int res, nargs = lua_gettop(L);
	char data[LUA_EXT_DATA_SIZE] = "";
	char *data_next = data, *app_name;
	char *context, *exten;
	char tmp[80], tmp2[80], tmp3[LUA_EXT_DATA_SIZE];
	int priority, autoservice;
	size_t data_left = sizeof(data);
	struct ast_app *app;
	struct ast_channel *chan;
	
	lua_getfield(L, 1, "name");
	app_name = ast_strdupa(lua_tostring(L, -1));
	lua_pop(L, 1);
	
	if (!(app = pbx_findapp(app_name))) {
		lua_pushstring(L, "application '");
		lua_pushstring(L, app_name);
		lua_pushstring(L, "' not found");
		lua_concat(L, 3);
		return lua_error(L);
	}
	

	lua_getfield(L, LUA_REGISTRYINDEX, "channel");
	chan = lua_touserdata(L, -1);
	lua_pop(L, 1);
	
	
	lua_getfield(L, LUA_REGISTRYINDEX, "context");
	context = ast_strdupa(lua_tostring(L, -1));
	lua_pop(L, 1);
	
	lua_getfield(L, LUA_REGISTRYINDEX, "exten");
	exten = ast_strdupa(lua_tostring(L, -1));
	lua_pop(L, 1);
	
	lua_getfield(L, LUA_REGISTRYINDEX, "priority");
	priority = lua_tointeger(L, -1);
	lua_pop(L, 1);


	if (nargs > 1) {
		int i;

		if (!lua_isnil(L, 2))
			ast_build_string(&data_next, &data_left, "%s", luaL_checkstring(L, 2));

		for (i = 3; i <= nargs; i++) {
			if (lua_isnil(L, i))
				ast_build_string(&data_next, &data_left, ",");
			else
				ast_build_string(&data_next, &data_left, ",%s", luaL_checkstring(L, i));
		}
	}
	
	ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\")\n",
			exten, context, priority,
			term_color(tmp, app_name, COLOR_BRCYAN, 0, sizeof(tmp)),
			term_color(tmp2, chan->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
			term_color(tmp3, data, COLOR_BRMAGENTA, 0, sizeof(tmp3)));

	lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
	autoservice = lua_toboolean(L, -1);
	lua_pop(L, 1);

	if (autoservice)
		ast_autoservice_stop(chan);

	res = pbx_exec(chan, app, data);
	
	if (autoservice)
		ast_autoservice_start(chan);

	/* error executing an application, report it */
	if (res) {
		lua_pushinteger(L, res);
		return lua_error(L);
	}
	return 0;
}
Esempio n. 18
0
/*!
 * \brief [lua_CFunction] This function is part of the 'application' metatable
 * and is used to execute applications similar to pbx_exec() (for access from
 * lua, don't call directly)
 *
 * \param L the lua_State to use
 * \return nothing
 *
 * This funciton is executed as the '()' operator for apps accessed through the
 * 'app' table.
 *
 * \code
 * app.playback('demo-congrats')
 * \endcode
 */
static int lua_pbx_exec(lua_State *L)
{
	int res, nargs = lua_gettop(L);
	const char *data = "";
	char *app_name, *context, *exten;
	char tmp[80], tmp2[80], tmp3[LUA_EXT_DATA_SIZE];
	int priority, autoservice;
	struct ast_app *app;
	struct ast_channel *chan;

	lua_getfield(L, 1, "name");
	app_name = ast_strdupa(lua_tostring(L, -1));
	lua_pop(L, 1);
	
	if (!(app = pbx_findapp(app_name))) {
		lua_pushstring(L, "application '");
		lua_pushstring(L, app_name);
		lua_pushstring(L, "' not found");
		lua_concat(L, 3);
		return lua_error(L);
	}
	

	lua_getfield(L, LUA_REGISTRYINDEX, "channel");
	chan = lua_touserdata(L, -1);
	lua_pop(L, 1);
	
	
	lua_getfield(L, LUA_REGISTRYINDEX, "context");
	context = ast_strdupa(lua_tostring(L, -1));
	lua_pop(L, 1);
	
	lua_getfield(L, LUA_REGISTRYINDEX, "exten");
	exten = ast_strdupa(lua_tostring(L, -1));
	lua_pop(L, 1);
	
	lua_getfield(L, LUA_REGISTRYINDEX, "priority");
	priority = lua_tointeger(L, -1);
	lua_pop(L, 1);

	lua_concat_args(L, 2, nargs);
	data = lua_tostring(L, -1);

	ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\")\n",
			exten, context, priority,
			term_color(tmp, app_name, COLOR_BRCYAN, 0, sizeof(tmp)),
			term_color(tmp2, chan->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
			term_color(tmp3, data, COLOR_BRMAGENTA, 0, sizeof(tmp3)));

	lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
	autoservice = lua_toboolean(L, -1);
	lua_pop(L, 1);

	if (autoservice)
		ast_autoservice_stop(chan);

	res = pbx_exec(chan, app, data);

	lua_pop(L, 1); /* pop data */
	data = "";

	if (autoservice)
		ast_autoservice_start(chan);

	/* error executing an application, report it */
	if (res) {
		lua_pushinteger(L, res);
		return lua_error(L);
	}

	lua_detect_goto(L);

	return 0;
}
Esempio n. 19
0
static int page_exec(struct ast_channel *chan, void *data)
{
	struct ast_module_user *u;
	char *options, *tech, *resource, *tmp;
	char meetmeopts[88], originator[AST_CHANNEL_NAME];
	struct ast_flags flags = { 0 };
	unsigned int confid = ast_random();
	struct ast_app *app;
	int res = 0, pos = 0, i = 0;
	struct ast_dial *dials[MAX_DIALS];

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "This application requires at least one argument (destination(s) to page)\n");
		return -1;
	}

	u = ast_module_user_add(chan);

	if (!(app = pbx_findapp("MeetMe"))) {
		ast_log(LOG_WARNING, "There is no MeetMe application available!\n");
		ast_module_user_remove(u);
		return -1;
	};

	options = ast_strdupa(data);

	ast_copy_string(originator, chan->name, sizeof(originator));
	if ((tmp = strchr(originator, '-')))
		*tmp = '\0';

	tmp = strsep(&options, "|");
	if (options)
		ast_app_parse_options(page_opts, &flags, NULL, options);

	snprintf(meetmeopts, sizeof(meetmeopts), "MeetMe|%ud|%s%sqxdw(5)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m"),
		(ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );

	/* Go through parsing/calling each device */
	while ((tech = strsep(&tmp, "&"))) {
		struct ast_dial *dial = NULL;

		/* don't call the originating device */
		if (!strcasecmp(tech, originator))
			continue;

		/* If no resource is available, continue on */
		if (!(resource = strchr(tech, '/'))) {
			ast_log(LOG_WARNING, "Incomplete destination '%s' supplied.\n", tech);
			continue;
		}

		*resource++ = '\0';

		/* Create a dialing structure */
		if (!(dial = ast_dial_create())) {
			ast_log(LOG_WARNING, "Failed to create dialing structure.\n");
			continue;
		}

		/* Append technology and resource */
		ast_dial_append(dial, tech, resource);

		/* Set ANSWER_EXEC as global option */
		ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, meetmeopts);

		/* Run this dial in async mode */
		ast_dial_run(dial, chan, 1);

		/* Put in our dialing array */
		dials[pos++] = dial;
	}

	if (!ast_test_flag(&flags, PAGE_QUIET)) {
		res = ast_streamfile(chan, "beep", chan->language);
		if (!res)
			res = ast_waitstream(chan, "");
	}

	if (!res) {
		snprintf(meetmeopts, sizeof(meetmeopts), "%ud|A%s%sqxd", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t"), 
			(ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
		pbx_exec(chan, app, meetmeopts);
	}

	/* Go through each dial attempt cancelling, joining, and destroying */
	for (i = 0; i < pos; i++) {
		struct ast_dial *dial = dials[i];

		/* We have to wait for the async thread to exit as it's possible Meetme won't throw them out immediately */
		ast_dial_join(dial);

		/* Hangup all channels */
		ast_dial_hangup(dial);

		/* Destroy dialing structure */
		ast_dial_destroy(dial);
	}

	ast_module_user_remove(u);

	return -1;
}