コード例 #1
0
int start_profiling(void)
{
	struct app_list_t *app = NULL;
	const struct app_info_t *app_info = NULL;
	int res = 0;

	app_info = app_info_get_first(&app);
	if (app_info == NULL) {
		LOGE("No app info found\n");
		return -1;
	}
	// remove previous screen capture files
	remove_indir(SCREENSHOT_DIR);
	if (mkdir(SCREENSHOT_DIR, 0777) == -1 && errno != EEXIST) {
		GETSTRERROR(errno, buf);
		LOGW("Failed to create directory for screenshot : %s\n", buf);
	}

	set_label_for_all(SCREENSHOT_DIR);

	if (samplingStart() < 0) {
		LOGE("Cannot start sampling\n");
		res = -1;
		goto exit;
	}

	if (IS_OPT_SET(FL_RECORDING))
		add_input_events();

	while (app_info != NULL) {
		if (exec_app(app_info)) {
			LOGE("Cannot exec app\n");
			res = -1;
			goto recording_stop;
		}
		app_info = app_info_get_next(&app);
	}

	if (start_app_launch_timer(get_apps_to_run()) < 0) {
		res = -1;
		goto recording_stop;
	}

	goto exit;

 recording_stop:
	if (IS_OPT_SET(FL_RECORDING))
		del_input_events();
	samplingStop();

 exit:
	LOGI("return %d\n", res);
	return res;
}
コード例 #2
0
/* This is where we actually charge the guy 
  This can be called anytime a call is in progress or at the end of a call before the session is destroyed */
static switch_status_t do_billing(switch_core_session_t *session)
{
	/* FS vars we will use */
	switch_channel_t *channel;
	switch_caller_profile_t *profile;

	/* Local vars */
	nibble_data_t *nibble_data;
	switch_time_t ts = switch_micro_time_now();
	double billamount;
	char date[80] = "";
	char *uuid;
	switch_size_t retsize;
	switch_time_exp_t tm;
	const char *billrate;
	const char *billincrement;
	const char *billaccount;
	double nobal_amt = globals.nobal_amt;
	double lowbal_amt = globals.lowbal_amt;
	double balance;

	if (!session) {
		/* Why are we here? */
		return SWITCH_STATUS_SUCCESS;
	}

	uuid = switch_core_session_get_uuid(session);

	/* Get channel var */
	if (!(channel = switch_core_session_get_channel(session))) {
		return SWITCH_STATUS_SUCCESS;
	}

	/* Variables kept in FS but relevant only to this module */
	billrate = switch_channel_get_variable(channel, "nibble_rate");
	billincrement = switch_channel_get_variable(channel, "nibble_increment");
	billaccount = switch_channel_get_variable(channel, "nibble_account");
	
	if (!zstr(switch_channel_get_variable(channel, "nobal_amt"))) {
		nobal_amt = atof(switch_channel_get_variable(channel, "nobal_amt"));
	}
	
	if (!zstr(switch_channel_get_variable(channel, "lowbal_amt"))) {
		lowbal_amt = atof(switch_channel_get_variable(channel, "lowbal_amt"));
	}
	
	/* Return if there's no billing information on this session */
	if (!billrate || !billaccount) {
		return SWITCH_STATUS_SUCCESS;
	}

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Attempting to bill at $%s per minute to account %s\n", billrate,
					  billaccount);

	/* Get caller profile info from channel */
	profile = switch_channel_get_caller_profile(channel);

	if (!profile || !profile->times) {
		/* No caller profile (why would this happen?) */
		return SWITCH_STATUS_SUCCESS;
	}

	if (profile->times->answered < 1) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Not billing %s - call is not in answered state\n", billaccount);

		/* See if this person has enough money left to continue the call */
		balance = get_balance(billaccount, channel);
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Comparing %f to hangup balance of %f\n", balance, nobal_amt);
		if (balance <= nobal_amt) {
			/* Not enough money - reroute call to nobal location */
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Balance of %f fell below allowed amount of %f! (Account %s)\n",
							  balance, nobal_amt, billaccount);

			transfer_call(session, globals.nobal_action);
		}

		return SWITCH_STATUS_SUCCESS;
	}

	/* Lock this session's data for this module while we tinker with it */
	if (globals.mutex) {
		switch_mutex_lock(globals.mutex);
	}

	/* Get our nibble data var. This will be NULL if it's our first call here for this session */
	nibble_data = (nibble_data_t *) switch_channel_get_private(channel, "_nibble_data_");

	/* Are we in paused mode? If so, we don't do anything here - go back! */
	if (nibble_data && (nibble_data->pausets > 0)) {
		if (globals.mutex) {
			switch_mutex_unlock(globals.mutex);
		}
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Received heartbeat, but we're paused - ignoring\n");
		return SWITCH_STATUS_SUCCESS;
	}

	/* Have we done any billing on this channel yet? If no, set up vars for doing so */
	if (!nibble_data) {
		nibble_data = switch_core_session_alloc(session, sizeof(*nibble_data));
		memset(nibble_data, 0, sizeof(*nibble_data));

		/* Setup new billing data (based on call answer time, in case this module started late with active calls) */
		nibble_data->lastts = profile->times->answered;	/* Set the initial answer time to match when the call was really answered */
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Beginning new billing on %s\n", uuid);
	}

	switch_time_exp_lt(&tm, nibble_data->lastts);
	switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%d seconds passed since last bill time of %s\n",
					  (int) ((ts - nibble_data->lastts) / 1000000), date);

	if ((ts - nibble_data->lastts) >= 0) {
		/* If billincrement is set we bill by it and not by time elapsed */
		if (!(switch_strlen_zero(billincrement))) {
			switch_time_t chargedunits = (ts - nibble_data->lastts) / 1000000 <= atol(billincrement) ? atol(billincrement) * 1000000 : (switch_time_t)(ceil((ts - nibble_data->lastts) / (atol(billincrement) * 1000000.0))) * atol(billincrement) * 1000000;
			billamount = (atof(billrate) / 1000000 / 60) * chargedunits - nibble_data->bill_adjustments;
			/* Account for the prepaid amount */
			nibble_data->lastts += chargedunits;
		} else {		
			/* Convert billrate into microseconds and multiply by # of microseconds that have passed since last *successful* bill */
			billamount = (atof(billrate) / 1000000 / 60) * ((ts - nibble_data->lastts)) - nibble_data->bill_adjustments;
			/* Update the last time we billed */
			nibble_data->lastts = ts;
		}

		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Billing $%f to %s (Call: %s / %f so far)\n", billamount, billaccount,
						  uuid, nibble_data->total);

		/* DO ODBC BILLING HERE and reset counters if it's successful! */
		if (bill_event(billamount, billaccount, channel) == SWITCH_STATUS_SUCCESS) {
			/* Increment total cost */
			nibble_data->total += billamount;

			/* Reset manual billing adjustments from pausing */
			nibble_data->bill_adjustments = 0;

			/* Update channel variable with current billing */
			switch_channel_set_variable_printf(channel, "nibble_total_billed", "%f", nibble_data->total);
		} else {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failed to log to database!\n");
		}
	} else {
		if (switch_strlen_zero(billincrement))
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Just tried to bill %s negative minutes! That should be impossible.\n", uuid);
	}

	/* Save this location */
	if (channel) {
		switch_channel_set_private(channel, "_nibble_data_", nibble_data);

		/* don't verify balance and transfer to nobal if we're done with call */
		if (switch_channel_get_state(channel) != CS_REPORTING && switch_channel_get_state(channel) != CS_HANGUP) {
			
			balance = get_balance(billaccount, channel);
			
			/* See if we've achieved low balance */
			if (!nibble_data->lowbal_action_executed && balance <= lowbal_amt) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Balance of %f fell below low balance amount of %f! (Account %s)\n",
								  balance, lowbal_amt, billaccount);

				if (exec_app(session, globals.lowbal_action) != SWITCH_STATUS_SUCCESS)
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Low balance action didn't execute\n");
				else
					nibble_data->lowbal_action_executed = 1;
			}

			/* See if this person has enough money left to continue the call */
			if (balance <= nobal_amt) {
				/* Not enough money - reroute call to nobal location */
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Balance of %f fell below allowed amount of %f! (Account %s)\n",
								  balance, nobal_amt, billaccount);

				/* IMPORTANT: Billing must be paused before the transfer occurs! This prevents infinite loops, since the transfer will result */
				/* in nibblebill checking the call again in the routing process for an allowed balance! */
				/* If you intend to give the user the option to re-up their balance, you must clear & resume billing once the balance is updated! */
				nibblebill_pause(session);
				transfer_call(session, globals.nobal_action);
			}
		}
	}


	/* Done changing - release lock */
	if (globals.mutex) {
		switch_mutex_unlock(globals.mutex);
	}

	/* Go check if this call is allowed to continue */

	return SWITCH_STATUS_SUCCESS;
}
コード例 #3
0
static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *caller_profile, switch_xml_t xexten, 
					   switch_caller_extension_t **extension, const char *exten_name, int recur)
{
	switch_xml_t xcond, xaction, xexpression, xregex;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	int proceed = 0, save_proceed = 0;
	char *expression_expanded = NULL, *field_expanded = NULL;
	switch_regex_t *re = NULL, *save_re = NULL;
	int offset = 0;
	const char *tmp, *tzoff = NULL, *tzname = NULL, *req_nesta = NULL;
	char nbuf[128] = "";
	int req_nest = 1;
	char space[MAX_RECUR_SPACE] = "";
	const char *orig_exten_name = exten_name;

	check_tz();

	if (!exten_name) {
		exten_name = "_anon_";
	}

	if (!orig_exten_name) {
		orig_exten_name = "_anon_";
	}


	if (recur) {
		int i, j = 0, k = 0;

		if (recur > MAX_RECUR) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Recursion LIMIT!\n");
			return 0;
		}

		switch_snprintf(nbuf, sizeof(nbuf), "%s_recur_%d", exten_name, recur);
		exten_name = nbuf;
		
		space[j++] = '|';

		for (i = 0; i < recur; i++) {
			for (k = 0; k < RECUR_SPACE; k++) {
				if (i == recur-1 && k == RECUR_SPACE-1) {
					space[j++] = ' ';
				} else {
					space[j++] = '-';
				}
			}
		}
		
		if ((req_nesta = switch_xml_attr(xexten, "require-nested"))) {
			req_nest = switch_true(req_nesta);
		}

		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, 
						  "%sDialplan: Processing recursive conditions level:%d [%s] require-nested=%s\n", space,
						  recur, exten_name, req_nest ? "TRUE" : "FALSE");

	} else {
		if ((tmp = switch_xml_attr(xexten, "name"))) {
			exten_name = tmp;
		}
	}


	for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) {
		char *field = NULL;
		char *do_break_a = NULL;
		char *expression = NULL, *save_expression = NULL, *save_field_data = NULL;
		char *regex_rule = NULL;
		const char *field_data = NULL;
		int ovector[30];
		switch_bool_t anti_action = SWITCH_TRUE;
		break_t do_break_i = BREAK_ON_FALSE;
		int time_match;

		check_tz();
		time_match = switch_xml_std_datetime_check(xcond, tzoff ? &offset : NULL, tzname);

		switch_safe_free(field_expanded);
		switch_safe_free(expression_expanded);

		field = (char *) switch_xml_attr(xcond, "field");


		if ((do_break_a = (char *) switch_xml_attr(xcond, "break"))) {
			if (!strcasecmp(do_break_a, "on-true")) {
				do_break_i = BREAK_ON_TRUE;
			} else if (!strcasecmp(do_break_a, "on-false")) {
				do_break_i = BREAK_ON_FALSE;
			} else if (!strcasecmp(do_break_a, "always")) {
				do_break_i = BREAK_ALWAYS;
			} else if (!strcasecmp(do_break_a, "never")) {
				do_break_i = BREAK_NEVER;
			} else {
				do_break_a = NULL;
			}
		}


		if (switch_xml_child(xcond, "condition")) {
			if (!(proceed = parse_exten(session, caller_profile, xcond, extension, orig_exten_name, recur + 1))) {
				if (do_break_i == BREAK_NEVER) {
					continue;
				}
				goto done;
			}
		}
		
		if (time_match == 1) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
							  "%sDialplan: %s Date/Time Match (PASS) [%s] break=%s\n", space,
							  switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false");
			anti_action = SWITCH_FALSE;
			proceed = 1;
		} else if (time_match == 0) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
							  "%sDialplan: %s Date/TimeMatch (FAIL) [%s] break=%s\n", space,
							  switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false");
		}
		
		
		if ((regex_rule = (char *) switch_xml_attr(xcond, "regex"))) {
			int all = !strcasecmp(regex_rule, "all");
			int xor = !strcasecmp(regex_rule, "xor");
			int pass = 0;
			int fail = 0;
			int total = 0;

			switch_channel_del_variable_prefix(channel, "DP_REGEX_MATCH");

			for (xregex = switch_xml_child(xcond, "regex"); xregex; xregex = xregex->next) {
				check_tz();
				time_match = switch_xml_std_datetime_check(xregex, tzoff ? &offset : NULL, tzname);
				
				if (time_match == 1) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
									  "%sDialplan: %s Date/Time Match (PASS) [%s]\n", space,
									  switch_channel_get_name(channel), exten_name);
					anti_action = SWITCH_FALSE;
				} else if (time_match == 0) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
									  "%sDialplan: %s Date/TimeMatch (FAIL) [%s]\n", space,
									  switch_channel_get_name(channel), exten_name);
				}


				if ((xexpression = switch_xml_child(xregex, "expression"))) {
					expression = switch_str_nil(xexpression->txt);
				} else {
					expression = (char *) switch_xml_attr_soft(xregex, "expression");
				}
				
				if ((expression_expanded = switch_channel_expand_variables(channel, expression)) == expression) {
					expression_expanded = NULL;
				} else {
					expression = expression_expanded;
				}
				
				total++;
				
				field = (char *) switch_xml_attr(xregex, "field");
				
				if (field) {
					if (strchr(field, '$')) {
						if ((field_expanded = switch_channel_expand_variables(channel, field)) == field) {
							field_expanded = NULL;
							field_data = field;
						} else {
							field_data = field_expanded;
						}
					} else {
						field_data = switch_caller_get_field_by_name(caller_profile, field);
					}
					if (!field_data) {
						field_data = "";
					}
					
					if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
										  "%sDialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ match=%s\n", space,
										  switch_channel_get_name(channel), exten_name, field, field_data, expression, all ? "all" : "any");
						pass++;
						if (!all && !xor) break;
					} else {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
										  "%sDialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ match=%s\n", space,
										  switch_channel_get_name(channel), exten_name, field, field_data, expression, all ? "all" : "any");
						fail++;
						if (all && !xor) break;
					}
				} else if (time_match == -1) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
									  "%sDialplan: %s Absolute Condition [%s] match=%s\n", space,
									  switch_channel_get_name(channel), exten_name, all ? "all" : "any");
					pass++;
					proceed = 1;
					if (!all && !xor) break;
				} else if (time_match == 1) {
					pass++;
					proceed = 1;
					if (!all && !xor) break;
				}
				
				if (field && strchr(expression, '(')) {
					char var[256];
					switch_snprintf(var, sizeof(var), "DP_REGEX_MATCH_%d", total);

					switch_channel_set_variable(channel, var, NULL);
					switch_capture_regex(re, proceed, field_data, ovector, var, switch_regex_set_var_callback, session);
					
					switch_safe_free(save_expression);
					switch_safe_free(save_field_data);
					switch_regex_safe_free(save_re);
					
					
					save_expression = strdup(expression);
					save_field_data = strdup(field_data);
					save_re = re;
					save_proceed = proceed;
					
					re = NULL;
				}

				switch_regex_safe_free(re);

				switch_safe_free(field_expanded);
				switch_safe_free(expression_expanded);
				
			}

			if (xor) {
				if (pass == 1) {
					anti_action = SWITCH_FALSE;
				}
			} else {
				if ((all && !fail) || (!all && pass)) {
					anti_action = SWITCH_FALSE; 
				}
			}

			switch_safe_free(field_expanded);
			switch_safe_free(expression_expanded);
			
		} else {
			if ((xexpression = switch_xml_child(xcond, "expression"))) {
				expression = switch_str_nil(xexpression->txt);
			} else {
				expression = (char *) switch_xml_attr_soft(xcond, "expression");
			}

			if ((expression_expanded = switch_channel_expand_variables(channel, expression)) == expression) {
				expression_expanded = NULL;
			} else {
				expression = expression_expanded;
			}
			
			if (field) {
				if (strchr(field, '$')) {
					if ((field_expanded = switch_channel_expand_variables(channel, field)) == field) {
						field_expanded = NULL;
						field_data = field;
					} else {
						field_data = field_expanded;
					}
				} else {
					field_data = switch_caller_get_field_by_name(caller_profile, field);
				}
				if (!field_data) {
					field_data = "";
				}

				if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
									  "%sDialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n", space,
									  switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
					anti_action = SWITCH_FALSE;
				} else {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
									  "%sDialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n", space,
									  switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
				}
			} else if (time_match == -1) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
								  "%sDialplan: %s Absolute Condition [%s]\n", space,
								  switch_channel_get_name(channel), exten_name);
				anti_action = SWITCH_FALSE;
				proceed = 1;
			}

		}

		if (save_re) {
			re = save_re;
			save_re = NULL;
			
			expression = expression_expanded = save_expression;
			save_expression = NULL;
			field_data = field_expanded = save_field_data;
			field = (char *) field_data;
			save_field_data = NULL;
			proceed = save_proceed;
		}


		if (anti_action) {
			for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) {
				const char *application = switch_xml_attr_soft(xaction, "application");
				const char *loop = switch_xml_attr(xaction, "loop");
				const char *data;
				const char *inline_ = switch_xml_attr_soft(xaction, "inline");
				int xinline = switch_true(inline_);
				int loop_count = 1;

				if (!zstr(xaction->txt)) {
					data = xaction->txt;
				} else {
					data = (char *) switch_xml_attr_soft(xaction, "data");
				}

				if (!*extension) {
					if ((*extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number)) == 0) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
						proceed = 0;
						goto done;
					}
				}

				if (loop) {
					loop_count = atoi(loop);
				}

				for (;loop_count > 0; loop_count--) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
									  "%sDialplan: %s ANTI-Action %s(%s) %s\n", space,
									  switch_channel_get_name(channel), application, data, xinline ? "INLINE" : "");

					if (xinline) {
						exec_app(session, application, data);
					} else {
						switch_caller_extension_add_application(session, *extension, application, data);
					}
				}
				proceed = 1;
			}
		} else {
			if (field && strchr(expression, '(')) {
				switch_channel_set_variable(channel, "DP_MATCH", NULL);
				switch_capture_regex(re, proceed, field_data, ovector, "DP_MATCH", switch_regex_set_var_callback, session);
			}

			for (xaction = switch_xml_child(xcond, "action"); xaction; xaction = xaction->next) {
				char *application = (char *) switch_xml_attr_soft(xaction, "application");
				const char *loop = switch_xml_attr(xaction, "loop");
				char *data = NULL;
				char *substituted = NULL;
				uint32_t len = 0;
				char *app_data = NULL;
				const char *inline_ = switch_xml_attr_soft(xaction, "inline");
				int xinline = switch_true(inline_);
				int loop_count = 1;

				if (!zstr(xaction->txt)) {
					data = xaction->txt;
				} else {
					data = (char *) switch_xml_attr_soft(xaction, "data");
				}

				if (field && strchr(expression, '(')) {
					len = (uint32_t) (strlen(data) + strlen(field_data) + 10) * proceed;
					if (!(substituted = malloc(len))) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
						proceed = 0;
						goto done;
					}
					memset(substituted, 0, len);
					switch_perform_substitution(re, proceed, data, field_data, substituted, len, ovector);
					app_data = substituted;
				} else {
					app_data = data;
				}

				if (!*extension) {
					if ((*extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number)) == 0) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
						proceed = 0;
						goto done;
					}
				}

				if (loop) {
					loop_count = atoi(loop);
				}
				for (;loop_count > 0; loop_count--) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
									  "%sDialplan: %s Action %s(%s) %s\n", space,
									  switch_channel_get_name(channel), application, app_data, xinline ? "INLINE" : "");

					if (xinline) {
						exec_app(session, application, app_data);
					} else {
						switch_caller_extension_add_application(session, *extension, application, app_data);
					}
				}
				switch_safe_free(substituted);
			}
		}
		switch_regex_safe_free(re);

		if (((anti_action == SWITCH_FALSE && do_break_i == BREAK_ON_TRUE) ||
			 (anti_action == SWITCH_TRUE && do_break_i == BREAK_ON_FALSE)) || do_break_i == BREAK_ALWAYS) {
			break;
		}
	}

  done:
	switch_regex_safe_free(re);
	switch_safe_free(field_expanded);
	switch_safe_free(expression_expanded);

	if (!req_nest) proceed = 1;

	return proceed;
}
コード例 #4
0
ファイル: dbus-run-session.c プロジェクト: smcv/dbus
static int
run_session (const char *dbus_daemon,
             const char *config_file,
             char       *bus_address,
             char      **argv,
             int         prog_arg)
{
  pid_t bus_pid;
  pid_t app_pid;
  int bus_address_pipe[2] = { 0, 0 };

  if (pipe (bus_address_pipe) < 0)
    {
      fprintf (stderr, "%s: failed to create pipe: %s\n", me, strerror (errno));
      return 127;
    }

  /* Make sure our output buffers aren't redundantly printed by both the
   * parent and the child */
  fflush (stdout);
  fflush (stderr);

  bus_pid = fork ();

  if (bus_pid < 0)
    {
      fprintf (stderr, "%s: failed to fork: %s\n", me, strerror (errno));
      return 127;
    }

  if (bus_pid == 0)
    {
      /* child */
      exec_dbus_daemon (dbus_daemon, bus_address_pipe, config_file);
      /* not reached */
      return 127;
    }

  close (bus_address_pipe[PIPE_WRITE_END]);

  switch (read_line (bus_address_pipe[PIPE_READ_END], bus_address, MAX_ADDR_LEN))
    {
    case READ_STATUS_OK:
      break;

    case READ_STATUS_EOF:
      fprintf (stderr, "%s: EOF reading address from bus daemon\n", me);
      return 127;
      break;

    case READ_STATUS_ERROR:
      fprintf (stderr, "%s: error reading address from bus daemon: %s\n",
               me, strerror (errno));
      return 127;
      break;

    default:
      _dbus_assert_not_reached ("invalid read result");
    }

  close (bus_address_pipe[PIPE_READ_END]);

  if (!dbus_setenv ("DBUS_SESSION_BUS_ADDRESS", bus_address) ||
      !dbus_setenv ("DBUS_SESSION_BUS_PID", NULL) ||
      !dbus_setenv ("DBUS_SESSION_BUS_WINDOWID", NULL) ||
      !dbus_setenv ("DBUS_STARTER_ADDRESS", NULL) ||
      !dbus_setenv ("DBUS_STARTER_BUS_TYPE", NULL))
    oom ();

  fflush (stdout);
  fflush (stderr);

  app_pid = fork ();

  if (app_pid < 0)
    {
      fprintf (stderr, "%s: failed to fork: %s\n", me, strerror (errno));
      return 127;
    }

  if (app_pid == 0)
    {
      /* child */
      exec_app (prog_arg, argv);
      /* not reached */
      return 127;
    }

  while (1)
    {
      int child_status;
      pid_t child_pid = waitpid (-1, &child_status, 0);

      if (child_pid == (pid_t) -1)
        {
          int errsv = errno;

          if (errsv == EINTR)
            continue;

          /* shouldn't happen: the only other documented errors are ECHILD,
           * which shouldn't happen because we terminate when all our children
           * have died, and EINVAL, which would indicate programming error */
          fprintf (stderr, "%s: waitpid() failed: %s\n", me, strerror (errsv));
          return 127;
        }
      else if (child_pid == bus_pid)
        {
          /* no need to kill it, now */
          bus_pid = 0;

          if (WIFEXITED (child_status))
            fprintf (stderr, "%s: dbus-daemon exited with code %d\n",
                me, WEXITSTATUS (child_status));
          else if (WIFSIGNALED (child_status))
            fprintf (stderr, "%s: dbus-daemon terminated by signal %d\n",
                me, WTERMSIG (child_status));
          else
            fprintf (stderr, "%s: dbus-daemon died or something\n", me);
        }
      else if (child_pid == app_pid)
        {
          if (bus_pid != 0)
            kill (bus_pid, SIGTERM);

          if (WIFEXITED (child_status))
            return WEXITSTATUS (child_status);

          /* if it died from a signal, behave like sh(1) */
          if (WIFSIGNALED (child_status))
            return 128 + WTERMSIG (child_status);

          /* I give up (this should never be reached) */
          fprintf (stderr, "%s: child process died or something\n", me);
          return 127;
        }
      else
        {
          fprintf (stderr, "%s: ignoring unknown child process %ld\n", me,
              (long) child_pid);
        }
    }

  return 0;
}
コード例 #5
0
SWITCH_DECLARE(switch_status_t) switch_ivr_menu_execute(switch_core_session_t *session, switch_ivr_menu_t *stack, char *name, void *obj)
{
	int reps = 0, errs = 0, timeouts = 0, match = 0, running = 1;
	char *greeting_sound = NULL, *aptr = NULL;
	char arg[512];
	switch_ivr_action_t todo = SWITCH_IVR_ACTION_DIE;
	switch_ivr_menu_action_t *ap;
	switch_ivr_menu_t *menu;
	switch_channel_t *channel;
	switch_status_t status = SWITCH_STATUS_SUCCESS;

	if (++stack->stack_count > 12) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Too many levels of recursion.\n");
		switch_goto_status(SWITCH_STATUS_FALSE, end);
	}

	if (!session || !stack || zstr(name)) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid menu context\n");
		switch_goto_status(SWITCH_STATUS_FALSE, end);
	}

	channel = switch_core_session_get_channel(session);

	if (!(menu = switch_ivr_menu_find(stack, name))) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Menu!\n");
		switch_goto_status(SWITCH_STATUS_FALSE, end);
	}

	if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) {
		switch_channel_set_variable(channel, "tts_engine", menu->tts_engine);
		switch_channel_set_variable(channel, "tts_voice", menu->tts_voice);
	}

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Executing IVR menu %s\n", menu->name);
	switch_channel_set_variable(channel, "ivr_menu_status", "success");

	if (!zstr(menu->pin)) {
		char digit_buffer[128] = "";
		char *digits_regex = switch_core_session_sprintf(session, "^%s$", menu->pin);

		if (switch_play_and_get_digits(session, strlen(menu->pin), strlen(menu->pin), 3, 3000, "#",
									   menu->prompt_pin_file, menu->bad_pin_file, NULL, digit_buffer, sizeof(digit_buffer), 
									   digits_regex, 10000, NULL) != SWITCH_STATUS_SUCCESS) {
			switch_goto_status(SWITCH_STATUS_FALSE, end);
		}
	}


	for (reps = 0; running && status == SWITCH_STATUS_SUCCESS; reps++) {
		if (!switch_channel_ready(channel)) {
			break;
		}
		if (errs == menu->max_failures) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum failures\n");
			switch_channel_set_variable(channel, "ivr_menu_status", "failure");
			if (!zstr(menu->exec_on_max_fail)) {
				exec_app(session, menu->exec_on_max_fail);
			}
			break;
		}
		if (timeouts == menu->max_timeouts) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum timeouts\n");
			switch_channel_set_variable(channel, "ivr_menu_status", "timeout");
			if (!zstr(menu->exec_on_max_timeout)) {
				exec_app(session, menu->exec_on_max_timeout);
			}
			break;
		}

		if (reps > 0 && menu->short_greeting_sound) {
			greeting_sound = menu->short_greeting_sound;
		} else {
			greeting_sound = menu->greeting_sound;
		}

		match = 0;
		aptr = NULL;

		memset(arg, 0, sizeof(arg));

		memset(menu->buf, 0, menu->inlen + 1);

		if (play_and_collect(session, menu, greeting_sound, menu->inlen) == SWITCH_STATUS_TIMEOUT && *menu->buf == '\0') {
			timeouts++;
			continue;
		}

		if (*menu->buf != '\0') {

			for (ap = menu->actions; ap; ap = ap->next) {
				int ok = 0;
				char substituted[1024];
				char *use_arg = ap->arg;

				if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) {
					switch_channel_set_variable(channel, "tts_engine", menu->tts_engine);
					switch_channel_set_variable(channel, "tts_voice", menu->tts_voice);
				}

				if (ap->re) {
					switch_regex_t *re = NULL;
					int ovector[30];

					if ((ok = switch_regex_perform(menu->buf, ap->bind, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
						switch_perform_substitution(re, ok, ap->arg, menu->buf, substituted, sizeof(substituted), ovector);
						use_arg = substituted;
					}
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "action regex [%s] [%s] [%d]\n", menu->buf, ap->bind, ok);

					switch_regex_safe_free(re);
				} else {
					ok = !strcmp(menu->buf, ap->bind);
				}

				if (ok) {
					match++;
					errs = 0;
					if (ap->function) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
										  "IVR function on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, use_arg);
						todo = ap->function(menu, use_arg, arg, sizeof(arg), obj);
						aptr = arg;
					} else {
						todo = ap->ivr_action;
						aptr = use_arg;
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
										  "IVR action on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, aptr);
					}

					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "switch_ivr_menu_execute todo=[%d]\n", todo);

					switch (todo) {
					case SWITCH_IVR_ACTION_DIE:
						status = SWITCH_STATUS_FALSE;
						break;
					case SWITCH_IVR_ACTION_PLAYSOUND:
						status = switch_ivr_play_file(session, NULL, aptr, NULL);
						break;
					case SWITCH_IVR_ACTION_EXECMENU:
						if (!strcmp(aptr, menu->name)) {
							status = SWITCH_STATUS_SUCCESS;
						} else {
							reps = -1;
							status = switch_ivr_menu_execute(session, stack, aptr, obj);
						}
						break;
					case SWITCH_IVR_ACTION_EXECAPP:
						{
							switch_application_interface_t *application_interface;
							char *app_name;
							char *app_arg = NULL;

							status = SWITCH_STATUS_FALSE;

							if (!zstr(aptr)) {
								app_name = switch_core_session_strdup(session, aptr);
								if ((app_arg = strchr(app_name, ' '))) {
									*app_arg++ = '\0';
								}

								if ((application_interface = switch_loadable_module_get_application_interface(app_name))) {
									if (!zstr(menu->transfer_sound) && !strcmp(app_name, "transfer")) {
										status = play_and_collect(session, menu, menu->transfer_sound, 0);
									}

									switch_core_session_exec(session, application_interface, app_arg);
									UNPROTECT_INTERFACE(application_interface);
									status = SWITCH_STATUS_SUCCESS;
								}
							}
						}
						break;
					case SWITCH_IVR_ACTION_BACK:
						running = 0;
						status = SWITCH_STATUS_SUCCESS;
						break;
					case SWITCH_IVR_ACTION_TOMAIN:
						switch_set_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN);
						status = SWITCH_STATUS_BREAK;
						break;
					case SWITCH_IVR_ACTION_NOOP:
						status = SWITCH_STATUS_SUCCESS;
						break;
					default:
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid TODO!\n");
						break;
					}
				}
			}

			if (switch_test_flag(menu, SWITCH_IVR_MENU_FLAG_STACK)) {	/* top level */
				if (switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN)) {	/* catch the fallback and recover */
					switch_clear_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN);
					status = SWITCH_STATUS_SUCCESS;
					running = 1;
					continue;
				}
			}
		}
		if (!match) {
			if (*menu->buf) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' caught invalid input '%s'\n", menu->name,
								  menu->buf);
				if (menu->invalid_sound) {
					play_and_collect(session, menu, menu->invalid_sound, 0);
				}
			} else {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' no input detected\n", menu->name);
			}
			errs++;

			/* breaks are ok too */
			if (SWITCH_STATUS_IS_BREAK(status)) {
				status = SWITCH_STATUS_SUCCESS;
			}
		}
	}

	if (stack->stack_count == 1) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "exit-sound '%s'\n", menu->exit_sound);
		if (!zstr(menu->exit_sound)) {
			status = play_and_collect(session, menu, menu->exit_sound, 0);
		}
	}

  end:

	stack->stack_count--;

	return status;
}
コード例 #6
0
static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *caller_profile, switch_xml_t xexten, switch_caller_extension_t **extension)
{
	switch_xml_t xcond, xaction, xexpression;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	char *exten_name = (char *) switch_xml_attr(xexten, "name");
	int proceed = 0;
	char *expression_expanded = NULL, *field_expanded = NULL;
	switch_regex_t *re = NULL;

	if (!exten_name) {
		exten_name = "_anon_";
	}

	for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) {
		char *field = NULL;
		char *do_break_a = NULL;
		char *expression = NULL;
		const char *field_data = NULL;
		int ovector[30];
		switch_bool_t anti_action = SWITCH_TRUE;
		break_t do_break_i = BREAK_ON_FALSE;

		int time_match = switch_xml_std_datetime_check(xcond);

		switch_safe_free(field_expanded);
		switch_safe_free(expression_expanded);

		if (switch_xml_child(xcond, "condition")) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Nested conditions are not allowed!\n");
			proceed = 1;
			goto done;
		}

		field = (char *) switch_xml_attr(xcond, "field");

		if ((xexpression = switch_xml_child(xcond, "expression"))) {
			expression = switch_str_nil(xexpression->txt);
		} else {
			expression = (char *) switch_xml_attr_soft(xcond, "expression");
		}

		if ((expression_expanded = switch_channel_expand_variables(channel, expression)) == expression) {
			expression_expanded = NULL;
		} else {
			expression = expression_expanded;
		}

		if ((do_break_a = (char *) switch_xml_attr(xcond, "break"))) {
			if (!strcasecmp(do_break_a, "on-true")) {
				do_break_i = BREAK_ON_TRUE;
			} else if (!strcasecmp(do_break_a, "on-false")) {
				do_break_i = BREAK_ON_FALSE;
			} else if (!strcasecmp(do_break_a, "always")) {
				do_break_i = BREAK_ALWAYS;
			} else if (!strcasecmp(do_break_a, "never")) {
				do_break_i = BREAK_NEVER;
			} else {
				do_break_a = NULL;
			}
		}

		if (time_match == 1) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
							  "Dialplan: %s Date/Time Match (PASS) [%s] break=%s\n",
							  switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false");
			anti_action = SWITCH_FALSE;
		} else if (time_match == 0) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
							  "Dialplan: %s Date/Time Match (FAIL) [%s] break=%s\n",
							  switch_channel_get_name(channel), exten_name, do_break_a ? do_break_a : "on-false");
		}

		if (field) {
			if (strchr(field, '$')) {
				if ((field_expanded = switch_channel_expand_variables(channel, field)) == field) {
					field_expanded = NULL;
					field_data = field;
				} else {
					field_data = field_expanded;
				}
			} else {
				field_data = switch_caller_get_field_by_name(caller_profile, field);
			}
			if (!field_data) {
				field_data = "";
			}

			if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
								  "Dialplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n",
								  switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
				anti_action = SWITCH_FALSE;
			} else {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
								  "Dialplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n",
								  switch_channel_get_name(channel), exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false");
			}
		} else if (time_match == -1) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
							  "Dialplan: %s Absolute Condition [%s]\n", switch_channel_get_name(channel), exten_name);
			anti_action = SWITCH_FALSE;
		}

		if (anti_action) {
			for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) {
				const char *application = switch_xml_attr_soft(xaction, "application");
				const char *loop = switch_xml_attr(xaction, "loop");
				const char *data;
				const char *inline_ = switch_xml_attr_soft(xaction, "inline");
				int xinline = switch_true(inline_);
				int loop_count = 1;

				if (!zstr(xaction->txt)) {
					data = xaction->txt;
				} else {
					data = (char *) switch_xml_attr_soft(xaction, "data");
				}

				if (!*extension) {
					if ((*extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number)) == 0) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
						proceed = 0;
						goto done;
					}
				}

				if (loop) {
					loop_count = atoi(loop);
				}

				for (;loop_count > 0; loop_count--) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
							"Dialplan: %s ANTI-Action %s(%s) %s\n", switch_channel_get_name(channel), application, data, xinline ? "INLINE" : "");

					if (xinline) {
						exec_app(session, application, data);
					} else {
						switch_caller_extension_add_application(session, *extension, application, data);
					}
				}
				proceed = 1;
			}
		} else {
			for (xaction = switch_xml_child(xcond, "action"); xaction; xaction = xaction->next) {
				char *application = (char *) switch_xml_attr_soft(xaction, "application");
				const char *loop = switch_xml_attr(xaction, "loop");
				char *data = NULL;
				char *substituted = NULL;
				uint32_t len = 0;
				char *app_data = NULL;
				const char *inline_ = switch_xml_attr_soft(xaction, "inline");
				int xinline = switch_true(inline_);
				int loop_count = 1;

				if (!zstr(xaction->txt)) {
					data = xaction->txt;
				} else {
					data = (char *) switch_xml_attr_soft(xaction, "data");
				}

				if (field && strchr(expression, '(')) {
					len = (uint32_t) (strlen(data) + strlen(field_data) + 10) * proceed;
					if (!(substituted = malloc(len))) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
						proceed = 0;
						goto done;
					}
					memset(substituted, 0, len);
					switch_perform_substitution(re, proceed, data, field_data, substituted, len, ovector);
					app_data = substituted;
				} else {
					app_data = data;
				}

				if (!*extension) {
					if ((*extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number)) == 0) {
						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
						proceed = 0;
						goto done;
					}
				}

				if (loop) {
					loop_count = atoi(loop);
				}
				for (;loop_count > 0; loop_count--) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG,
							"Dialplan: %s Action %s(%s) %s\n", switch_channel_get_name(channel), application, app_data, xinline ? "INLINE" : "");

					if (xinline) {
						exec_app(session, application, app_data);
					} else {
						switch_caller_extension_add_application(session, *extension, application, app_data);
					}
				}
				switch_safe_free(substituted);
			}
		}
		switch_regex_safe_free(re);

		if (((anti_action == SWITCH_FALSE && do_break_i == BREAK_ON_TRUE) ||
			 (anti_action == SWITCH_TRUE && do_break_i == BREAK_ON_FALSE)) || do_break_i == BREAK_ALWAYS) {
			break;
		}
	}

  done:
	switch_regex_safe_free(re);
	switch_safe_free(field_expanded);
	switch_safe_free(expression_expanded);
	return proceed;
}