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; }
/*! * \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); } } }
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; }
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 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; }
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; }
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); }
static int aelsub_exec(struct ast_channel *chan, const char *vdata) { char buf[256], *data = ast_strdupa(vdata); struct ast_app *gosub = pbx_findapp("Gosub"); AST_DECLARE_APP_ARGS(args, AST_APP_ARG(name); AST_APP_ARG(args); );
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; }
/*! \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; }
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; }
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); }
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; }
static int execif_exec(struct cw_channel *chan, int argc, char **argv) { int res=0; struct localuser *u; struct cw_app *app = NULL; if (argc < 2 || !argv[0][0] || !argv[1][0]) { cw_log(LOG_ERROR, "Syntax: %s\n", execif_syntax); return -1; } LOCAL_USER_ADD(u); if (cw_true(argv[0])) { if ((app = pbx_findapp(argv[1]))) { res = pbx_exec_argv(chan, app, argc - 2, argv + 2); } else { cw_log(LOG_WARNING, "Count not find application! (%s)\n", argv[1]); res = -1; } } ALL_DONE(u,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 ; }
/*! * \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; }
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; }
/*! * \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; }
/*! * \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; }
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; }