/*! \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; }
static void *app_control_dial(struct stasis_app_control *control, struct ast_channel *chan, void *data) { RAII_VAR(struct ast_dial *, dial, ast_dial_create(), ast_dial_destroy); RAII_VAR(struct stasis_app_control_dial_data *, dial_data, data, ast_free); enum ast_dial_result res; char *tech, *resource; struct ast_channel *new_chan; struct ast_bridge *bridge; tech = dial_data->endpoint; if (!(resource = strchr(tech, '/'))) { return NULL; } *resource++ = '\0'; if (!dial) { ast_log(LOG_ERROR, "Failed to create dialing structure.\n"); return NULL; } if (ast_dial_append(dial, tech, resource) < 0) { ast_log(LOG_ERROR, "Failed to add %s/%s to dialing structure.\n", tech, resource); return NULL; } ast_dial_set_global_timeout(dial, dial_data->timeout); res = ast_dial_run(dial, NULL, 0); if (res != AST_DIAL_RESULT_ANSWERED || !(new_chan = ast_dial_answered_steal(dial))) { return NULL; } if (!(bridge = ast_bridge_basic_new())) { ast_log(LOG_ERROR, "Failed to create basic bridge.\n"); return NULL; } if (ast_bridge_impart(bridge, new_chan, NULL, NULL, AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { ast_hangup(new_chan); } else { stasis_app_control_add_channel_to_bridge(control, bridge); } return NULL; }
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; }