/*! \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;
}
Exemplo n.º 2
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;
}