Example #1
0
SWITCH_DECLARE(switch_status_t) switch_limit_release(const char *backend, switch_core_session_t *session, const char *realm, const char *resource) {
	switch_limit_interface_t *limit = NULL;
	int status = SWITCH_STATUS_SUCCESS;
	
	/* locate impl, call appropriate func */
	if (!(limit = get_backend(backend))) {
		switch_limit_log(session, SWITCH_LOG_ERROR, "Limit subsystem %s not found!\n", backend);
		switch_goto_status(SWITCH_STATUS_GENERR, end);
	}
	
	status = limit->release(session, realm, resource);
	
end:
	release_backend(limit);
	return status;
}
Example #2
0
SWITCH_DECLARE(switch_status_t) switch_limit_incr(const char *backend, switch_core_session_t *session, const char *realm, const char *resource, const int max, const int interval) {
	switch_limit_interface_t *limit = NULL;
	switch_channel_t *channel = NULL;
	int status = SWITCH_STATUS_SUCCESS;
	
	if (session) {
		channel = switch_core_session_get_channel(session);
	}

	/* locate impl, call appropriate func */
	if (!(limit = get_backend(backend))) {
		switch_limit_log(session, SWITCH_LOG_ERROR, "Limit subsystem %s not found!\n", backend);
		switch_goto_status(SWITCH_STATUS_GENERR, end);
	}

	switch_limit_log(session, SWITCH_LOG_INFO, "incr called: %s_%s max:%d, interval:%d\n",
					  realm, resource, max, interval);
	
	if ((status = limit->incr(session, realm, resource, max, interval)) == SWITCH_STATUS_SUCCESS) {
		if (session) {
			/* race condition? what if another leg is doing the same thing? */
			const char *existing = switch_channel_get_variable(channel, LIMIT_BACKEND_VARIABLE);
			if (existing) {
				if (!strstr(existing, backend)) {
					switch_channel_set_variable_printf(channel, LIMIT_BACKEND_VARIABLE, "%s,%s", existing, backend);
				}
			} else {
				switch_channel_set_variable(channel, LIMIT_BACKEND_VARIABLE, backend);
				switch_core_event_hook_add_state_change(session, limit_state_handler);
			}
		}
	}
	
	release_backend(limit);
	
end:
	return status;
}
Example #3
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");

	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");
			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");
			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))) {
									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;
}
Example #4
0
static switch_status_t do_write_video(switch_file_handle_t *handle, switch_frame_t *frame)
{
	uint32_t datalen = frame->datalen;
	switch_status_t status = SWITCH_STATUS_SUCCESS;
	int is_iframe = 0;
	uint32_t size;
	uint8_t *hdr = NULL;
	uint8_t fragment_type;
	uint8_t nal_type;
	uint8_t start_bit;
	mp4_file_context_t *context = handle->private_info;

	hdr = (uint8_t *)frame->data;
	fragment_type = hdr[0] & 0x1f;
	nal_type = hdr[1] & 0x1f;
	start_bit = hdr[1] & 0x80;
	is_iframe = (((fragment_type == 28 || fragment_type == 29) && nal_type == 5 && start_bit == 128) || fragment_type == 5 || fragment_type ==7 || fragment_type ==8) ? 1 : 0;

	// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%02x %02x %02x | len:%d m:%d st:%d i:%d\n", hdr[0], hdr[1], hdr[2], datalen, frame->m, start_bit, is_iframe);

	size = htonl(datalen);
	switch_buffer_write(context->buf, &size, 4);
	switch_buffer_write(context->buf, hdr, datalen);

	switch_mutex_lock(context->mutex);

	if (fragment_type == 7 && !context->sps_set) { //sps
		context->sps_set = 1;

		init_video_track(context->fd, &context->video, frame);
		if (context->video == MP4_INVALID_TRACK_ID) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error add video track!\n");
			switch_goto_status(SWITCH_STATUS_FALSE, end);
		}
	} else if (fragment_type == 8 && context->sps_set && !context->pps_set) { //pps
		MP4AddH264PictureParameterSet(context->fd, context->video, hdr, datalen);
		context->pps_set = 1;
	}

	if (nal_type == 7 || nal_type == 8 || frame->m == 0) {
	} else if (context->sps_set && context->pps_set) {
		uint32_t used = switch_buffer_inuse(context->buf);
		const void *data;
		int duration = 0;

		if (!context->timer.interval) {
			switch_core_timer_init(&context->timer, "soft", 1, 1, context->pool);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "init timer\n");
		} else {
			switch_core_timer_sync(&context->timer);
		}

		duration = context->timer.samplecount - context->last_pts;

		// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "samplecount: %u, duration: %u\n", context->timer.samplecount, duration);
		switch_buffer_peek_zerocopy(context->buf, &data);

		if (context->last_pts == 0) { // first img, write at the very beginning so we don't see blank screen
			duration /= 2;
			MP4WriteSample(context->fd, context->video, data, used, duration, 0, is_iframe);

			if (duration > context->offset) {
				duration -= context->offset;
			} else {
				duration = 0;
			}
		}

		context->last_pts = context->timer.samplecount;

		// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "samplecount: %u, duration: %u\n", context->timer.samplecount, duration);

		if (duration) {
			MP4WriteSample(context->fd, context->video, data, used, duration, 0, is_iframe);
		}
		switch_buffer_zero(context->buf);
	}

end:
	switch_mutex_unlock(context->mutex);

	return status;
}
SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, const char *func, int line,
															  switch_file_handle_t *fh,
															  const char *file_path,
															  uint32_t channels, uint32_t rate, unsigned int flags, switch_memory_pool_t *pool)
{
	char *ext;
	switch_status_t status = SWITCH_STATUS_FALSE;
	char stream_name[128] = "";
	char *rhs = NULL;
	const char *spool_path = NULL;
	int is_stream = 0;
	char *fp = NULL;
	int to = 0;

	if (switch_test_flag(fh, SWITCH_FILE_OPEN)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Handle already open\n");
		return SWITCH_STATUS_FALSE;
	}

	fh->samples_in = 0;

	if (!fh->samplerate) {
		if (!(fh->samplerate = rate)) {
			fh->samplerate = 8000;
		}
	}

	if (zstr(file_path)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Filename\n");
		return SWITCH_STATUS_FALSE;
	}

	fh->flags = flags;

	if (pool) {
		fh->memory_pool = pool;
	} else {
		if ((status = switch_core_new_memory_pool(&fh->memory_pool)) != SWITCH_STATUS_SUCCESS) {
			UNPROTECT_INTERFACE(fh->file_interface);
			return status;
		}
		switch_set_flag(fh, SWITCH_FILE_FLAG_FREE_POOL);
	}

	if (*file_path == '{') {
		char *timeout;
		char *new_fp;
		fp = switch_core_strdup(fh->memory_pool, file_path);

		if (switch_event_create_brackets(fp, '{', '}', ',', &fh->params, &new_fp, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
			if ((timeout = switch_event_get_header(fh->params, "timeout"))) {
				if ((to = atoi(timeout)) < 1) {
					to = 0;
				}
			}
		} else {
			new_fp = fp;
		}

		file_path = new_fp;
	}

	if (switch_directory_exists(file_path, fh->memory_pool) == SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File [%s] is a directory not a file.\n", file_path);
		status = SWITCH_STATUS_GENERR;
		goto fail;
	}

	if ((rhs = strstr(file_path, SWITCH_URL_SEPARATOR))) {
		switch_copy_string(stream_name, file_path, (rhs + 1) - file_path);
		ext = stream_name;
		file_path = rhs + 3;
		fh->file_path = switch_core_strdup(fh->memory_pool, file_path);
		is_stream = 1;
	} else {
		if ((flags & SWITCH_FILE_FLAG_WRITE)) {

			char *p, *e;

			fh->file_path = switch_core_strdup(fh->memory_pool, file_path);
			p = fh->file_path;

			if (*p == '[' && *(p + 1) == *SWITCH_PATH_SEPARATOR) {
				e = switch_find_end_paren(p, '[', ']');

				if (e) {
					*e = '\0';
					spool_path = p + 1;
					fh->file_path = e + 1;
				}
			}

			if (!spool_path) {
				spool_path = switch_core_get_variable_pdup(SWITCH_AUDIO_SPOOL_PATH_VARIABLE, fh->memory_pool);
			}

			file_path = fh->file_path;
		}

		if ((ext = strrchr(file_path, '.')) == 0) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown file Format [%s]\n", file_path);
			switch_goto_status(SWITCH_STATUS_FALSE, fail);
		}
		ext++;
		fh->file_path = switch_core_strdup(fh->memory_pool, file_path);
	}



	if ((fh->file_interface = switch_loadable_module_get_file_interface(ext)) == 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid file format [%s] for [%s]!\n", ext, file_path);
		switch_goto_status(SWITCH_STATUS_GENERR, fail);
	}

	fh->file = file;
	fh->func = func;
	fh->line = line;


	if (spool_path) {
		char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
		switch_uuid_t uuid;
		switch_uuid_get(&uuid);
		switch_uuid_format(uuid_str, &uuid);

		fh->spool_path = switch_core_sprintf(fh->memory_pool, "%s%s%s.%s", spool_path, SWITCH_PATH_SEPARATOR, uuid_str, ext);
	} else {
		fh->spool_path = NULL;
	}

	if (rhs) {
		fh->handler = switch_core_strdup(fh->memory_pool, rhs);
	} else {
		fh->handler = NULL;
	}

	if (channels) {
		fh->channels = channels;
	} else {
		fh->channels = 1;
	}

	file_path = fh->spool_path ? fh->spool_path : fh->file_path;

	if ((status = fh->file_interface->file_open(fh, file_path)) != SWITCH_STATUS_SUCCESS) {
		if (fh->spool_path) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Spool dir is set.  Make sure [%s] is also a valid path\n", fh->spool_path);
		}
		UNPROTECT_INTERFACE(fh->file_interface);
		switch_goto_status(status, fail);
	}

	fh->real_channels = fh->channels;

	if (channels) {
		fh->channels = channels;
	}

	if ((flags & SWITCH_FILE_FLAG_WRITE) && !is_stream && (status = switch_file_exists(file_path, fh->memory_pool)) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File [%s] not created!\n", file_path);
		fh->file_interface->file_close(fh);
		UNPROTECT_INTERFACE(fh->file_interface);
		switch_goto_status(status, fail);
	}

	if (to) {
		fh->max_samples = (fh->samplerate / 1000) * to;
	}


	if ((flags & SWITCH_FILE_FLAG_READ)) {
		fh->native_rate = fh->samplerate;
	} else {
		fh->native_rate = rate;
	}

	if (fh->samplerate && rate && fh->samplerate != rate) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "File %s sample rate %d doesn't match requested rate %d\n", file_path, fh->samplerate, rate);
		if ((flags & SWITCH_FILE_FLAG_READ)) {
			fh->samplerate = rate;
		}
	}

	if (fh->pre_buffer_datalen) {
		//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Prebuffering %d bytes\n", (int)fh->pre_buffer_datalen);
		switch_buffer_create_dynamic(&fh->pre_buffer, fh->pre_buffer_datalen * fh->channels, fh->pre_buffer_datalen * fh->channels, 0);
		fh->pre_buffer_data = switch_core_alloc(fh->memory_pool, fh->pre_buffer_datalen * fh->channels);
	}


	if (fh->real_channels != fh->channels && (flags & SWITCH_FILE_FLAG_READ) && !(fh->flags & SWITCH_FILE_NOMUX)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "File has %d channels, muxing to %d channel%s will occur.\n", fh->real_channels, fh->channels, fh->channels == 1 ? "" : "s");
	}

	switch_set_flag(fh, SWITCH_FILE_OPEN);
	return status;

  fail:

	switch_clear_flag(fh, SWITCH_FILE_OPEN);

	if (fh->params) {
		switch_event_destroy(&fh->params);
	}

	fh->samples_in = 0;
	fh->max_samples = 0;
	
	if (switch_test_flag(fh, SWITCH_FILE_FLAG_FREE_POOL)) {
		switch_core_destroy_memory_pool(&fh->memory_pool);
	}

	return status;
}
Example #6
0
static switch_status_t nibblebill_load_config(void)
{
	char *cf = "nibblebill.conf";
	switch_cache_db_handle_t *dbh = NULL;
	switch_xml_t cfg, xml = NULL, param, settings;
	switch_status_t status = SWITCH_STATUS_SUCCESS;

	if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
		status = SWITCH_STATUS_SUCCESS;	/* We don't fail because we can still write to a text file or buffer */
		goto setdefaults;
	}

	if ((settings = switch_xml_child(cfg, "settings"))) {
		for (param = switch_xml_child(settings, "param"); param; param = param->next) {
			char *var = (char *) switch_xml_attr_soft(param, "name");
			char *val = (char *) switch_xml_attr_soft(param, "value");
			
			if (!strcasecmp(var, "odbc-dsn") && !zstr(val)) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "odbc_dsn is %s\n", val);
				switch_safe_free(globals.odbc_dsn);
				globals.odbc_dsn = strdup(val);
			} else if (!strcasecmp(var, "db_dsn") && !zstr(val)) {
				/* For backwards-compatibility */
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "this nibblebill param(db_dsn) is deprecated and will be removed in 1.4 - odbc_dsn is %s\n", val);
				switch_safe_free(globals.odbc_dsn);
				globals.odbc_dsn = strdup(val);
			} else if (!strcasecmp(var, "db_table")) {
				set_global_db_table(val);
			} else if (!strcasecmp(var, "db_column_cash")) {
				set_global_db_column_cash(val);
			} else if (!strcasecmp(var, "db_column_account")) {
				set_global_db_column_account(val);
			} else if (!strcasecmp(var, "custom_sql_save")) {
				set_global_custom_sql_save(val);
			} else if (!strcasecmp(var, "custom_sql_lookup")) {
				set_global_custom_sql_lookup(val);
			} else if (!strcasecmp(var, "percall_action")) {
				set_global_percall_action(val);
			} else if (!strcasecmp(var, "percall_max_amt")) {
				globals.percall_max_amt = atof(val);
			} else if (!strcasecmp(var, "lowbal_action")) {
				set_global_lowbal_action(val);
			} else if (!strcasecmp(var, "lowbal_amt")) {
				globals.lowbal_amt = atof(val);
			} else if (!strcasecmp(var, "nobal_action")) {
				set_global_nobal_action(val);
			} else if (!strcasecmp(var, "nobal_amt")) {
				globals.nobal_amt = atof(val);
			} else if (!strcasecmp(var, "global_heartbeat")) {
				globals.global_heartbeat = atoi(val);
			}
		}
	}
	

/* Set defaults for any variables still not set */
  setdefaults:
	if (zstr(globals.percall_action)) {
		set_global_percall_action("hangup");
	}
	if (zstr(globals.lowbal_action)) {
		set_global_lowbal_action("play ding");
	}
	if (zstr(globals.nobal_action)) {
		set_global_nobal_action("hangup");
	}

	if (globals.odbc_dsn) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG
						  , "dsn is \"%s\"\n"
						  , globals.odbc_dsn
						  );
		if (!(dbh = nibblebill_get_db_handle())) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open ODBC Database!\n");
			switch_goto_status(SWITCH_STATUS_FALSE, done);
		}
	}

  done:
	if (xml) {
		switch_xml_free(xml);
	}
	return status;
}
static switch_status_t switch_vpx_decode(switch_codec_t *codec, switch_frame_t *frame)
{
	vpx_context_t *context = (vpx_context_t *)codec->private_info;
	switch_size_t len;
	vpx_codec_ctx_t *decoder = NULL;
	switch_status_t status = SWITCH_STATUS_SUCCESS;
	int is_start = 0, is_keyframe = 0, get_refresh = 0;

	if (context->is_vp9) {
		is_start = is_keyframe = IS_VP9_KEY_FRAME(*(unsigned char *)frame->data);
	} else { // vp8
		is_start = (*(unsigned char *)frame->data & 0x10);
		is_keyframe = IS_VP8_KEY_FRAME((uint8_t *)frame->data);
	}

	// if (is_keyframe) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "got key %d\n", is_keyframe);

	if (context->need_decoder_reset != 0) {
		vpx_codec_destroy(&context->decoder);
		context->decoder_init = 0;
		init_decoder(codec);
		context->need_decoder_reset = 0;
	}
	
	if (!context->decoder_init) {
		init_decoder(codec);
	}

	if (!context->decoder_init) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "VPX decoder is not initialized!\n");
		return SWITCH_STATUS_FALSE;
	}

	decoder = &context->decoder;
	
	// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "len: %d ts: %u mark:%d\n", frame->datalen, frame->timestamp, frame->m);

	// context->last_received_timestamp = frame->timestamp;
	context->last_received_complete_picture = frame->m ? SWITCH_TRUE : SWITCH_FALSE;

	if (is_start) {
		context->got_start_frame = 1;
	}
	
	if (is_keyframe) {
		if (context->got_key_frame <= 0) {
			context->got_key_frame = 1;
			if (!is_keyframe) {
				get_refresh = 1;
			}
		} else {
			context->got_key_frame++;
		}
	} else if (context->got_key_frame <= 0) {
		if ((--context->got_key_frame % 200) == 0) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Waiting for key frame %d\n", context->got_key_frame);
		}
		if (!context->got_start_frame) {
			switch_goto_status(SWITCH_STATUS_MORE_DATA, end);
		}
	}


	status = context->is_vp9 ? buffer_vp9_packets(context, frame) : buffer_vp8_packets(context, frame);


	if (context->dec_iter && (frame->img = (switch_image_t *) vpx_codec_get_frame(decoder, &context->dec_iter))) {
		switch_goto_status(SWITCH_STATUS_SUCCESS, end);
	}

	//printf("READ buf:%ld got_key:%d st:%d m:%d\n", switch_buffer_inuse(context->vpx_packet_buffer), context->got_key_frame, status, frame->m);

	len = switch_buffer_inuse(context->vpx_packet_buffer);

	//if (frame->m && (status != SWITCH_STATUS_SUCCESS || !len)) {
		//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WTF????? %d %ld\n", status, len);
	//}


	if (status == SWITCH_STATUS_SUCCESS && frame->m && len) {
		uint8_t *data;
		int corrupted = 0;
		int err;

		switch_buffer_peek_zerocopy(context->vpx_packet_buffer, (void *)&data);

		context->dec_iter = NULL;
		err = vpx_codec_decode(decoder, data, (unsigned int)len, NULL, 0);

		if (err != VPX_CODEC_OK) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Error decoding %" SWITCH_SIZE_T_FMT " bytes, [%d:%s:%s]\n",
							  len, err, vpx_codec_error(decoder), vpx_codec_error_detail(decoder));
			switch_goto_status(SWITCH_STATUS_RESTART, end);
		}

		if (vpx_codec_control(decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted) != VPX_CODEC_OK) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "VPX control error!\n");
			switch_goto_status(SWITCH_STATUS_RESTART, end);
		}
		
		if (corrupted) {
			frame->img = NULL;
		} else {
			frame->img = (switch_image_t *) vpx_codec_get_frame(decoder, &context->dec_iter);
		}
		
		switch_buffer_zero(context->vpx_packet_buffer);
		
		if (!frame->img) {
			//context->need_decoder_reset = 1;
			context->got_key_frame = 0;
			context->got_start_frame = 0;
			status = SWITCH_STATUS_RESTART;
		}
	}

end:

	if (status == SWITCH_STATUS_RESTART) {
		switch_buffer_zero(context->vpx_packet_buffer);
		//context->need_decoder_reset = 1;
		context->got_key_frame = 0;
		context->got_start_frame = 0;
		//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "RESET VPX\n");
	}

	if (!frame->img || status == SWITCH_STATUS_RESTART) {
		status = SWITCH_STATUS_MORE_DATA;
	}

	if (context->got_key_frame <= 0 || get_refresh) {
		switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
	}

	return status;
}