static switch_status_t create_session(switch_core_session_t **new_session, modem_t *modem)
{
	switch_status_t status = SWITCH_STATUS_FALSE;
	switch_core_session_t *session;
	switch_channel_t *channel;
	private_t *tech_pvt = NULL;
	char name[1024];
	switch_caller_profile_t *caller_profile;
	char *ani = NULL, *p, *digits = NULL;
	
	if (!(session = switch_core_session_request(modem_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL))) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failure.\n");
		goto end;
	}

	switch_core_session_add_stream(session, NULL);
	channel = switch_core_session_get_channel(session);
	tech_pvt = (private_t *) switch_core_session_alloc(session, sizeof(*tech_pvt));
	
	p = switch_core_session_strdup(session, modem->digits);

	if (*p == '*') {
		ani = p + 1;
		if ((digits = strchr(ani, '*'))) {
			*digits++ = '\0';
		} else {
			ani = NULL;
		}
	}
	
	if (zstr(digits)) {
		digits = p;
	}

	if (zstr(ani)) {
		ani = modem->devlink + 5;
	}

	switch_snprintf(name, sizeof(name), "modem/%d/%s", modem->slot, digits);
	switch_channel_set_name(channel, name);

	if (tech_init(tech_pvt, session) != SWITCH_STATUS_SUCCESS) {
		switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
		switch_core_session_destroy(&session);
		goto end;
	}

	caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
											   modem->devlink,
											   spandsp_globals.modem_dialplan,
											   "FSModem", 
											   ani,
											   NULL, 
											   ani,
											   NULL, 
											   NULL, 
											   "mod_spandsp", 
											   spandsp_globals.modem_context, 
											   digits);


	
	caller_profile->source = switch_core_strdup(caller_profile->pool, "mod_spandsp");
	switch_channel_set_caller_profile(channel, caller_profile);
	tech_pvt->caller_profile = caller_profile;
	switch_channel_set_state(channel, CS_INIT);

	if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error spawning thread\n");
		switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
		goto end;
	}

	status = SWITCH_STATUS_SUCCESS;
	tech_attach(tech_pvt, modem);
	*new_session = session;

 end:

	return status;
}
Beispiel #2
0
switch_status_t rtmp_tcp_init(rtmp_profile_t *profile, const char *bindaddr, rtmp_io_t **new_io, switch_memory_pool_t *pool)
{
	char *szport;
	switch_sockaddr_t *sa;
	switch_threadattr_t *thd_attr = NULL;
	rtmp_io_tcp_t *io_tcp;
		
	io_tcp = (rtmp_io_tcp_t*)switch_core_alloc(pool, sizeof(rtmp_io_tcp_t));
	io_tcp->base.pool = pool;
	io_tcp->ip = switch_core_strdup(pool, bindaddr);
	
	*new_io = (rtmp_io_t*)io_tcp;
	io_tcp->base.profile = profile;
	io_tcp->base.read = rtmp_tcp_read;
	io_tcp->base.write = rtmp_tcp_write;
	io_tcp->base.close = rtmp_tcp_close;
	io_tcp->base.name = "tcp";
	io_tcp->base.address = switch_core_strdup(pool, io_tcp->ip);
	
	if ((szport = strchr(io_tcp->ip, ':'))) {
		*szport++ = '\0';
		io_tcp->port = atoi(szport);
	} else {
		io_tcp->port = RTMP_DEFAULT_PORT;
	}
	
	if (switch_sockaddr_info_get(&sa, io_tcp->ip, SWITCH_INET, io_tcp->port, 0, pool)) {
		goto fail;
	}
	if (switch_socket_create(&io_tcp->listen_socket, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, pool)) {
		goto fail;
	}
	if (switch_socket_opt_set(io_tcp->listen_socket, SWITCH_SO_REUSEADDR, 1)) {
		goto fail;
	}
	if (switch_socket_opt_set(io_tcp->listen_socket, SWITCH_SO_TCP_NODELAY, 1)) {
		goto fail;
	}
	if (switch_socket_bind(io_tcp->listen_socket, sa)) {
		goto fail;
	}
	if (switch_socket_listen(io_tcp->listen_socket, 10)) {
		goto fail;
	}
	if (switch_socket_opt_set(io_tcp->listen_socket, SWITCH_SO_NONBLOCK, TRUE)) {
		goto fail;
	}

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Listening on %s:%u (tcp)\n", io_tcp->ip, io_tcp->port);
	
	io_tcp->base.running = 1;
	
	if (switch_pollset_create(&io_tcp->pollset, 1000 /* max poll fds */, pool, 0) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pollset_create failed\n");
		goto fail;
	}
	
	switch_socket_create_pollfd(&(io_tcp->listen_pollfd), io_tcp->listen_socket, SWITCH_POLLIN | SWITCH_POLLERR, NULL, pool);
	if (switch_pollset_add(io_tcp->pollset, io_tcp->listen_pollfd) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pollset_add failed\n");
		goto fail;
	}
	
	switch_mutex_init(&io_tcp->mutex, SWITCH_MUTEX_NESTED, pool);
	
	switch_threadattr_create(&thd_attr, pool);
	switch_threadattr_detach_set(thd_attr, 1);
	switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
	switch_thread_create(&io_tcp->thread, thd_attr, rtmp_io_tcp_thread, *new_io, pool);
	
	return SWITCH_STATUS_SUCCESS;
fail:
	if (io_tcp->listen_socket) {
		switch_socket_close(io_tcp->listen_socket);
	}
	*new_io = NULL;
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Socket error. Couldn't listen on %s:%u\n", io_tcp->ip, io_tcp->port);
	return SWITCH_STATUS_FALSE;
}
static long do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, char **response, const char *query, struct curl_httppost *post,
						  switch_curl_slist_t *headers, int timeout)
{
	switch_time_t start_time = switch_micro_time_now();
	switch_time_t time_diff = 0;
	CURL *curl_handle = NULL;
	long httpRes = 0;

	struct http_data http_data;

	memset(&http_data, 0, sizeof(http_data));

	http_data.max_bytes = 10240;
	SWITCH_STANDARD_STREAM(http_data.stream);

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "url: %s\n", query);
	curl_handle = switch_curl_easy_init();

	switch_curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 0);
	switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);

	if (!strncasecmp(query, "https", 5)) {
		switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
		switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
	}
	if (post) {
		switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST, post);
	} else {
		switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1);
	}
	if (headers) {
		switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
	}
	switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
	switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
	/*
	   TIMEOUT_MS is introduced in 7.16.2, we have 7.16.0 in tree 
	 */
#ifdef CURLOPT_TIMEOUT_MS
	if (timeout > 0) {
		switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, timeout);
	} else {
		switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT_MS, globals.curl_timeout);
	}
#else
	if (timeout > 0) {
		switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, timeout);
	} else {
		switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, globals.curl_timeout / 1000);
	}
#endif
	switch_curl_easy_setopt(curl_handle, CURLOPT_URL, query);
	switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, file_callback);
	switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &http_data);
	switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-cidlookup/1.0");

	switch_curl_easy_perform(curl_handle);
	switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
	switch_curl_easy_cleanup(curl_handle);

	if (http_data.stream.data && !zstr((char *) http_data.stream.data) && strcmp(" ", http_data.stream.data)) {

		/* don't return UNKNOWN */
		if (strcmp("UNKNOWN", http_data.stream.data) || strcmp("UNAVAILABLE", http_data.stream.data)) {
			*response = switch_core_strdup(pool, http_data.stream.data);
		}
	}

	time_diff = (switch_micro_time_now() - start_time);	/* convert to milli from micro */

	if ((time_diff / 1000) >= globals.curl_warnduration) {
		switch_core_time_duration_t duration;
		switch_core_measure_time(time_diff, &duration);
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SLOW LOOKUP ("
						  "%um, " "%us, " "%ums" "): url: %s\n", duration.min, duration.sec, duration.ms, query);
	}

	switch_safe_free(http_data.stream.data);
	return httpRes;
}
Beispiel #4
0
/* 
   State methods they get called when the state changes to the specific state 
   returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
   so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
*/
static switch_status_t channel_on_init(switch_core_session_t *session)
{
	switch_channel_t *channel, *b_channel;
	private_t *tech_pvt = NULL, *b_tech_pvt = NULL;
	switch_core_session_t *b_session;
	char name[128];
	switch_caller_profile_t *caller_profile;

	tech_pvt = switch_core_session_get_private(session);
	switch_assert(tech_pvt != NULL);

	channel = switch_core_session_get_channel(session);
	switch_assert(channel != NULL);



	if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND) && !switch_test_flag(tech_pvt, TFLAG_BLEG)) {

		if (!(b_session = switch_core_session_request(loopback_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, NULL))) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failure.\n");
			goto end;
		}

		if (switch_core_session_read_lock(b_session) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failure.\n");
			switch_core_session_destroy(&b_session);
			goto end;
		}

		switch_core_session_add_stream(b_session, NULL);
		b_channel = switch_core_session_get_channel(b_session);
		b_tech_pvt = (private_t *) switch_core_session_alloc(b_session, sizeof(*b_tech_pvt));

		switch_snprintf(name, sizeof(name), "loopback/%s-b", tech_pvt->caller_profile->destination_number);
		switch_channel_set_name(b_channel, name);
		if (tech_init(b_tech_pvt, b_session, switch_core_session_get_read_codec(session)) != SWITCH_STATUS_SUCCESS) {
			switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
			switch_core_session_destroy(&b_session);
			goto end;
		}

		caller_profile = switch_caller_profile_clone(b_session, tech_pvt->caller_profile);
		caller_profile->source = switch_core_strdup(caller_profile->pool, modname);
		switch_channel_set_caller_profile(b_channel, caller_profile);
		b_tech_pvt->caller_profile = caller_profile;
		switch_channel_set_state(b_channel, CS_INIT);

		tech_pvt->other_session = b_session;
		tech_pvt->other_tech_pvt = b_tech_pvt;
		tech_pvt->other_channel = b_channel;

		//b_tech_pvt->other_session = session;
		//b_tech_pvt->other_tech_pvt = tech_pvt;
		//b_tech_pvt->other_channel = channel;

		b_tech_pvt->other_uuid = switch_core_session_strdup(b_session, switch_core_session_get_uuid(session));

		switch_set_flag_locked(tech_pvt, TFLAG_LINKED);
		switch_set_flag_locked(b_tech_pvt, TFLAG_LINKED);
		switch_set_flag_locked(b_tech_pvt, TFLAG_BLEG);


		switch_channel_set_flag(channel, CF_ACCEPT_CNG);
		//switch_ivr_transfer_variable(session, tech_pvt->other_session, "process_cdr");
		switch_ivr_transfer_variable(session, tech_pvt->other_session, NULL);

		switch_channel_set_variable(channel, "other_loopback_leg_uuid", switch_channel_get_uuid(b_channel));
		switch_channel_set_variable(b_channel, "other_loopback_leg_uuid", switch_channel_get_uuid(channel));

		if (switch_core_session_thread_launch(b_session) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error spawning thread\n");
			switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
			goto end;
		}
	} else if ((tech_pvt->other_session = switch_core_session_locate(tech_pvt->other_uuid))) {
		tech_pvt->other_tech_pvt = switch_core_session_get_private(tech_pvt->other_session);
		tech_pvt->other_channel = switch_core_session_get_channel(tech_pvt->other_session);
	}

	if (!tech_pvt->other_session) {
		switch_clear_flag_locked(tech_pvt, TFLAG_LINKED);
		switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
		goto end;
	}

	switch_channel_set_variable(channel, "loopback_leg", switch_test_flag(tech_pvt, TFLAG_BLEG) ? "B" : "A");
	switch_channel_set_state(channel, CS_ROUTING);

  end:

	return SWITCH_STATUS_SUCCESS;
}
Beispiel #5
0
SWITCH_DECLARE(switch_status_t) switch_ivr_menu_init(switch_ivr_menu_t ** new_menu,
													 switch_ivr_menu_t *main,
													 const char *name,
													 const char *greeting_sound,
													 const char *short_greeting_sound,
													 const char *invalid_sound,
													 const char *exit_sound,
													 const char *confirm_macro,
													 const char *confirm_key,
													 const char *tts_engine,
													 const char *tts_voice,
													 int confirm_attempts,
													 int inter_timeout,
													 int digit_len, int timeout, int max_failures, int max_timeouts, switch_memory_pool_t *pool)
{
	switch_ivr_menu_t *menu;
	uint8_t newpool = 0;

	if (!pool) {
		if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
			return SWITCH_STATUS_MEMERR;
		}
		newpool = 1;
	}

	if (!(menu = switch_core_alloc(pool, sizeof(*menu)))) {
		if (newpool) {
			switch_core_destroy_memory_pool(&pool);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
			return SWITCH_STATUS_MEMERR;
		}
	}

	menu->pool = pool;

	if (!confirm_attempts) {
		confirm_attempts = 3;
	}

	if (!inter_timeout) {
		inter_timeout = timeout / 2;
	}

	if (!zstr(name)) {
		menu->name = switch_core_strdup(menu->pool, name);
	}

	if (!zstr(greeting_sound)) {
		menu->greeting_sound = switch_core_strdup(menu->pool, greeting_sound);
	}

	if (!zstr(short_greeting_sound)) {
		menu->short_greeting_sound = switch_core_strdup(menu->pool, short_greeting_sound);
	}

	if (!zstr(invalid_sound)) {
		menu->invalid_sound = switch_core_strdup(menu->pool, invalid_sound);
	}

	if (!zstr(exit_sound)) {
		menu->exit_sound = switch_core_strdup(menu->pool, exit_sound);
	}

	if (!zstr(confirm_key)) {
		menu->confirm_key = switch_core_strdup(menu->pool, confirm_key);
	}

	if (!zstr(confirm_macro)) {
		menu->confirm_macro = switch_core_strdup(menu->pool, confirm_macro);
	}

	if (!zstr(tts_engine)) {
		menu->tts_engine = switch_core_strdup(menu->pool, tts_engine);
	}

	if (!zstr(tts_voice)) {
		menu->tts_voice = switch_core_strdup(menu->pool, tts_voice);
	}

	menu->confirm_attempts = confirm_attempts;

	menu->inlen = digit_len;

	if (max_failures > 0) {
		menu->max_failures = max_failures;
	} else {
		menu->max_failures = 3;
	}

	if (max_timeouts > 0) {
		menu->max_timeouts = max_timeouts;
	} else {
		menu->max_timeouts = 3;
	}

	menu->timeout = timeout;

	menu->inter_timeout = inter_timeout;

	menu->actions = NULL;

	if (newpool) {
		switch_set_flag(menu, SWITCH_IVR_MENU_FLAG_FREEPOOL);
	}

	if (menu->timeout <= 0) {
		menu->timeout = 10000;
	}

	if (main) {
		switch_ivr_menu_stack_add(&main, menu);
	} else {
		switch_set_flag(menu, SWITCH_IVR_MENU_FLAG_STACK);
	}

	menu->buf = switch_core_alloc(menu->pool, 1024);

	*new_menu = menu;

	return SWITCH_STATUS_SUCCESS;
}
Beispiel #6
0
static char *print_json(switch_memory_pool_t *pool, http_data_t *http_data)
{
	struct json_object *top = NULL;
	struct json_object *headers = NULL;
	char *data = NULL;
	switch_curl_slist_t *header = http_data->headers;

	top = json_object_new_object();
	headers = json_object_new_array();
	json_object_object_add(top, "status_code", json_object_new_int(http_data->http_response_code));
	if (http_data->http_response) {
		json_object_object_add(top, "body", json_object_new_string(http_data->http_response));
	}

	/* parse header data */
	while (header) {
		struct json_object *obj = NULL;
		/* remove trailing \r */
		if ((data =  strrchr(header->data, '\r'))) {
			*data = '\0';
		}

		if (zstr(header->data)) {
			header = header->next;
			continue;
		}

		if ((data = strchr(header->data, ':'))) {
			*data = '\0';
			data++;
			while (*data == ' ' && *data != '\0') {
				data++;
			}
			obj = json_object_new_object();
			json_object_object_add(obj, "key", json_object_new_string(header->data));
			json_object_object_add(obj, "value", json_object_new_string(data));
			json_object_array_add(headers, obj);
		} else {
			if (!strncmp("HTTP", header->data, 4)) {
				char *argv[3] = { 0 };
				int argc;
				if ((argc = switch_separate_string(header->data, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
					if (argc > 2) {
						json_object_object_add(top, "version", json_object_new_string(argv[0]));
						json_object_object_add(top, "phrase", json_object_new_string(argv[2]));
					} else {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unparsable header: argc: %d\n", argc);
					}
				} else {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Starts with HTTP but not parsable: %s\n", header->data);
				}
			} else {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unparsable header: %s\n", header->data);
			}
		}
		header = header->next;
	}
	json_object_object_add(top, "headers", headers);
	data = switch_core_strdup(pool, json_object_to_json_string(top));
	json_object_put(top);		/* should free up all children */

	return data;
}
Beispiel #7
0
SWITCH_DECLARE(switch_status_t) switch_core_codec_init(switch_codec_t *codec, const char *codec_name, const char *fmtp,
													   uint32_t rate, int ms, int channels, uint32_t flags,
													   const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool)
{
	switch_codec_interface_t *codec_interface;
	const switch_codec_implementation_t *iptr, *implementation = NULL;

	switch_assert(codec != NULL);
	switch_assert(codec_name != NULL);

	memset(codec, 0, sizeof(*codec));

	if (channels == 2) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Stereo is currently unsupported. please downsample audio source to mono.\n");
		return SWITCH_STATUS_GENERR;
	}

	if ((codec_interface = switch_loadable_module_get_codec_interface(codec_name)) == 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid codec %s!\n", codec_name);
		return SWITCH_STATUS_GENERR;
	}

	/* If no specific codec interval is requested opt for 20ms above all else because lots of stuff assumes it */
	if (!ms) {
		for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
			if ((!rate || rate == iptr->samples_per_second) &&
				(20 == (iptr->microseconds_per_packet / 1000)) && (!channels || channels == iptr->number_of_channels)) {
				implementation = iptr;
				goto found;
			}
		}
	}

	/* Either looking for a specific interval or there was no interval specified and there wasn't one @20ms available */
	for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
		if ((!rate || rate == iptr->samples_per_second) &&
			(!ms || ms == (iptr->microseconds_per_packet / 1000)) && (!channels || channels == iptr->number_of_channels)) {
			implementation = iptr;
			break;
		}
	}

  found:

	if (implementation) {
		switch_status_t status;
		codec->codec_interface = codec_interface;
		codec->implementation = implementation;
		codec->flags = flags;

		if (pool) {
			codec->memory_pool = pool;
		} else {
			if ((status = switch_core_new_memory_pool(&codec->memory_pool)) != SWITCH_STATUS_SUCCESS) {
				return status;
			}
			switch_set_flag(codec, SWITCH_CODEC_FLAG_FREE_POOL);
		}

		if (fmtp) {
			codec->fmtp_in = switch_core_strdup(codec->memory_pool, fmtp);
		}

		implementation->init(codec, flags, codec_settings);
		switch_mutex_init(&codec->mutex, SWITCH_MUTEX_NESTED, codec->memory_pool);
		switch_set_flag(codec, SWITCH_CODEC_FLAG_READY);
		return SWITCH_STATUS_SUCCESS;
	} else {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec %s Exists but not at the desired implementation. %dhz %dms\n", codec_name, rate,
						  ms);
	}

	UNPROTECT_INTERFACE(codec_interface);

	return SWITCH_STATUS_NOTIMPL;
}
Beispiel #8
0
SWITCH_DECLARE(switch_caller_profile_t *) switch_caller_profile_new(switch_memory_pool_t *pool,
																	const char *username,
																	const char *dialplan,
																	const char *caller_id_name,
																	const char *caller_id_number,
																	const char *network_addr,
																	const char *ani,
																	const char *aniii,
																	const char *rdnis,
																	const char *source, const char *context, const char *destination_number)
{
	switch_caller_profile_t *profile = NULL;
	char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];

	profile = switch_core_alloc(pool, sizeof(*profile));
	switch_assert(profile != NULL);
	memset(profile, 0, sizeof(*profile));

	switch_uuid_str(uuid_str, sizeof(uuid_str));
	profile->uuid_str = switch_core_strdup(pool, uuid_str);
	
	if (!context) {
		context = "default";
	}

	if (zstr(caller_id_name)) {
		caller_id_name = SWITCH_DEFAULT_CLID_NAME;
	}

	if (zstr(caller_id_number)) {
		caller_id_number = SWITCH_DEFAULT_CLID_NUMBER;
	}

	/* ANI defaults to Caller ID Number when not specified */
	if (zstr(ani)) {
		ani = caller_id_number;
	}

	profile_dup_clean(username, profile->username, pool);
	profile_dup_clean(dialplan, profile->dialplan, pool);
	profile_dup_clean(caller_id_name, profile->caller_id_name, pool);
	profile_dup_clean(caller_id_number, profile->caller_id_number, pool);
	profile_dup_clean(caller_id_name, profile->orig_caller_id_name, pool);
	profile_dup_clean(caller_id_number, profile->orig_caller_id_number, pool);
	profile->caller_ton = SWITCH_TON_UNDEF;
	profile->caller_numplan = SWITCH_NUMPLAN_UNDEF;
	profile_dup_clean(network_addr, profile->network_addr, pool);
	profile_dup_clean(ani, profile->ani, pool);
	profile->ani_ton = SWITCH_TON_UNDEF;
	profile->ani_numplan = SWITCH_NUMPLAN_UNDEF;
	profile_dup_clean(aniii, profile->aniii, pool);
	profile_dup_clean(rdnis, profile->rdnis, pool);
	profile->rdnis_ton = SWITCH_TON_UNDEF;
	profile->rdnis_numplan = SWITCH_NUMPLAN_UNDEF;
	profile_dup_clean(source, profile->source, pool);
	profile_dup_clean(context, profile->context, pool);
	profile_dup_clean(destination_number, profile->destination_number, pool);
	profile->destination_number_ton = SWITCH_TON_UNDEF;
	profile->destination_number_numplan = SWITCH_NUMPLAN_UNDEF;
	profile->uuid = SWITCH_BLANK_STRING;
	profile->chan_name = SWITCH_BLANK_STRING;
	profile->callee_id_name = SWITCH_BLANK_STRING;
	profile->callee_id_number = SWITCH_BLANK_STRING;
	switch_set_flag(profile, SWITCH_CPF_SCREEN);
	profile->pool = pool;
	return profile;
}
static switch_status_t load_config(switch_memory_pool_t *pool)
{
    switch_status_t status = SWITCH_STATUS_SUCCESS;
    char *cf = "cdr_pg_csv.conf", *ptr;
    switch_xml_t cfg, xml, schema, field;
    const char *attr;
    int num_fields = 0;
    switch_size_t len = 0;
    cdr_field_t *cdr_field;

    if (globals.db_online) {
        PQfinish(globals.db_connection);
        switch_mutex_destroy(globals.db_mutex);
        globals.db_online = 0;
    }

    memset(&globals, 0, sizeof(globals));
    switch_core_hash_init(&globals.fd_hash, pool);
    switch_mutex_init(&globals.db_mutex, SWITCH_MUTEX_NESTED, pool);

    globals.pool = pool;

    if (switch_xml_config_parse_module_settings(cf, SWITCH_FALSE, config_settings) != SWITCH_STATUS_SUCCESS) {
        return SWITCH_STATUS_FALSE;
    }

    if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
        if ((schema = switch_xml_child(cfg, "schema"))) {
            /* Count fields in schema so we can calculate required buffer size */
            for (field = switch_xml_child(schema, "field"); field; field = field->next) {
                if (switch_xml_attr(field, "var")) {
                    num_fields++;
                }
            }

            globals.db_schema = switch_core_alloc(pool, (num_fields + 1) * sizeof(cdr_field_t));
            cdr_field = globals.db_schema->fields;

            for (field = switch_xml_child(schema, "field"); field; field = field->next) {
                if ((attr = switch_xml_attr(field, "var"))) {
                    cdr_field->var_name = switch_core_strdup(pool, attr);

                    /* Assume SQL column name is the same as FreeSWITCH channel var name, unless specified otherwise */
                    if ((attr = switch_xml_attr(field, "column"))) {
                        cdr_field->col_name = switch_core_strdup(pool, attr);
                    } else {
                        cdr_field->col_name = switch_core_strdup(pool, cdr_field->var_name);
                    }

                    /* Assume all fields should be quoted (treated as strings), unless specified otherwise */
                    if ((attr = switch_xml_attr(field, "quote")) && !strncmp(attr, "false", 5)) {
                        cdr_field->quote = SWITCH_FALSE;
                    } else {
                        cdr_field->quote = SWITCH_TRUE;
                    }

                    /* Assume all fields allow SQL nulls, unless specified otherwise */
                    if ((attr = switch_xml_attr(field, "not-null")) && !strncmp(attr, "true", 4)) {
                        cdr_field->not_null = SWITCH_TRUE;
                    } else {
                        cdr_field->not_null = SWITCH_FALSE;
                    }

                    len += strlen(cdr_field->col_name) + 1;
                    cdr_field++;
                }
            }
            cdr_field->var_name = 0;

            globals.db_schema->columns = switch_core_alloc(pool, len);
            ptr = globals.db_schema->columns;
            for (cdr_field = globals.db_schema->fields; cdr_field->col_name; cdr_field++) {
                len = strlen(cdr_field->col_name);
                memcpy(ptr, cdr_field->col_name, len);
                ptr += len;
                *ptr = ',';
                ptr++;
            }
            *--ptr = '\0';
        }

        switch_xml_free(xml);
    }

    return status;
}
static switch_status_t load_config(switch_memory_pool_t *pool)
{
	char *cf = "cdr_csv.conf";
	switch_xml_t cfg, xml, settings, param;
	switch_status_t status = SWITCH_STATUS_SUCCESS;

	memset(&globals, 0, sizeof(globals));
	switch_core_hash_init(&globals.fd_hash, pool);
	switch_core_hash_init(&globals.template_hash, pool);

	globals.pool = pool;

	switch_core_hash_insert(globals.template_hash, "default", default_template);
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding default template.\n");
	globals.legs = CDR_LEG_A;

	if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) {

		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, "debug")) {
					globals.debug = switch_true(val);
				} else if (!strcasecmp(var, "legs")) {
					globals.legs = 0;

					if (strchr(val, 'a')) {
						globals.legs |= CDR_LEG_A;
					}

					if (strchr(val, 'b')) {
						globals.legs |= CDR_LEG_B;
					}
				} else if (!strcasecmp(var, "log-base")) {
					globals.log_dir = switch_core_sprintf(pool, "%s%scdr-csv", val, SWITCH_PATH_SEPARATOR);
				} else if (!strcasecmp(var, "rotate-on-hup")) {
					globals.rotate = switch_true(val);
				} else if (!strcasecmp(var, "default-template")) {
					globals.default_template = switch_core_strdup(pool, val);
				} else if (!strcasecmp(var, "master-file-only")) {
					globals.masterfileonly = switch_true(val);
				}
			}
		}

		if ((settings = switch_xml_child(cfg, "templates"))) {
			for (param = switch_xml_child(settings, "template"); param; param = param->next) {
				char *var = (char *) switch_xml_attr(param, "name");
				if (var) {
					char *tpl;
					size_t len = strlen(param->txt) + 2;
					if (end_of(param->txt) != '\n') {
						tpl = switch_core_alloc(pool, len);
						switch_snprintf(tpl, len, "%s\n", param->txt);
					} else {
						tpl = switch_core_strdup(pool, param->txt);
					}

					switch_core_hash_insert(globals.template_hash, var, tpl);
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding template %s.\n", var);
				}
			}
		}
		switch_xml_free(xml);
	}


	if (zstr(globals.default_template)) {
		globals.default_template = switch_core_strdup(pool, "default");
	}

	if (!globals.log_dir) {
		globals.log_dir = switch_core_sprintf(pool, "%s%scdr-csv", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
	}

	return status;
}
Beispiel #11
0
SWITCH_DECLARE(switch_caller_profile_t *) switch_caller_profile_dup(switch_memory_pool_t *pool, switch_caller_profile_t *tocopy)
{
	switch_caller_profile_t *profile = NULL;
	char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];

	profile = switch_core_alloc(pool, sizeof(*profile));
	switch_assert(profile != NULL);

	switch_uuid_str(uuid_str, sizeof(uuid_str));
	profile->uuid_str = switch_core_strdup(pool, uuid_str);
	profile->clone_of = switch_core_strdup(pool, tocopy->uuid_str);

	profile_dup(tocopy->username, profile->username, pool);
	profile_dup(tocopy->dialplan, profile->dialplan, pool);
	profile_dup(tocopy->caller_id_name, profile->caller_id_name, pool);
	profile_dup(tocopy->caller_id_number, profile->caller_id_number, pool);
	profile_dup(tocopy->callee_id_name, profile->callee_id_name, pool);
	profile_dup(tocopy->callee_id_number, profile->callee_id_number, pool);
	profile_dup(tocopy->orig_caller_id_name, profile->orig_caller_id_name, pool);
	profile_dup(tocopy->orig_caller_id_number, profile->orig_caller_id_number, pool);
	profile_dup(tocopy->network_addr, profile->network_addr, pool);
	profile_dup(tocopy->ani, profile->ani, pool);
	profile_dup(tocopy->aniii, profile->aniii, pool);
	profile_dup(tocopy->rdnis, profile->rdnis, pool);
	profile_dup(tocopy->source, profile->source, pool);
	profile_dup(tocopy->context, profile->context, pool);
	profile_dup(tocopy->destination_number, profile->destination_number, pool);
	profile_dup(tocopy->uuid, profile->uuid, pool);
	profile_dup(tocopy->chan_name, profile->chan_name, pool);

	profile->caller_ton = tocopy->caller_ton;
	profile->caller_numplan = tocopy->caller_numplan;
	profile->ani_ton = tocopy->ani_ton;
	profile->ani_numplan = tocopy->ani_numplan;
	profile->rdnis_ton = tocopy->rdnis_ton;
	profile->rdnis_numplan = tocopy->rdnis_numplan;
	profile->destination_number_ton = tocopy->destination_number_ton;
	profile->destination_number_numplan = tocopy->destination_number_numplan;
	profile->flags = tocopy->flags;
	profile->pool = pool;
	profile->direction = tocopy->direction;

	if (tocopy->times) {
		profile->old_times = (switch_channel_timetable_t *) switch_core_alloc(profile->pool, sizeof(switch_channel_timetable_t));
		*profile->old_times = *tocopy->times;
	} else {
		tocopy->times = (switch_channel_timetable_t *) switch_core_alloc(tocopy->pool, sizeof(*tocopy->times));
	}

	if (tocopy->soft) {
		profile_node_t *pn;

		for (pn = tocopy->soft; pn; pn = pn->next) {
			profile_node_t *pp, *n = switch_core_alloc(profile->pool, sizeof(*n));

			n->var = switch_core_strdup(profile->pool, pn->var);
			n->val = switch_core_strdup(profile->pool, pn->val);

			if (!profile->soft) {
				profile->soft = n;
			} else {
				for(pp = profile->soft; pp && pp->next; pp = pp->next);
			
				if (pp) {
					pp->next = n;
				}	
			}
		}

	}

	return profile;
}
Beispiel #12
0
static switch_status_t my_on_reporting(switch_core_session_t *session)
{
	switch_xml_t cdr = NULL;
	char *xml_text = NULL;
	char *path = NULL;
	char *curl_xml_text = NULL;
	const char *logdir = NULL;
	char *xml_text_escaped = NULL;
	int fd = -1;
	uint32_t cur_try;
	long httpRes;
	switch_CURL *curl_handle = NULL;
	switch_curl_slist_t *headers = NULL;
	switch_curl_slist_t *slist = NULL;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	switch_status_t status = SWITCH_STATUS_FALSE;
	int is_b;
	const char *a_prefix = "";

	if (globals.shutdown) {
		return SWITCH_STATUS_SUCCESS;
	}

	is_b = channel && switch_channel_get_originator_caller_profile(channel);
	if (!globals.log_b && is_b) {
		const char *force_cdr = switch_channel_get_variable(channel, SWITCH_FORCE_PROCESS_CDR_VARIABLE);
		if (!switch_true(force_cdr)) {
			return SWITCH_STATUS_SUCCESS;
		}
	}
	if (!is_b && globals.prefix_a)
		a_prefix = "a_";

	if (switch_ivr_generate_xml_cdr(session, &cdr) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Generating Data!\n");
		return SWITCH_STATUS_FALSE;
	}

	/* build the XML */
	xml_text = switch_xml_toxml(cdr, SWITCH_TRUE);
	if (!xml_text) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
		goto error;
	}

	switch_thread_rwlock_rdlock(globals.log_path_lock);

	if (!(logdir = switch_channel_get_variable(channel, "xml_cdr_base"))) {
		logdir = globals.log_dir;
	}

	if (!zstr(logdir) && (globals.log_http_and_disk || !globals.url_count)) {
		path = switch_mprintf("%s%s%s%s.cdr.xml", logdir, SWITCH_PATH_SEPARATOR, a_prefix, switch_core_session_get_uuid(session));
		switch_thread_rwlock_unlock(globals.log_path_lock);
		if (path) {
#ifdef _MSC_VER
			if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) {
#else
			if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) > -1) {
#endif
				int wrote;
				wrote = write(fd, xml_text, (unsigned) strlen(xml_text));
				wrote++;
				close(fd);
				fd = -1;
			} else {
				char ebuf[512] = { 0 };
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s][%s]\n",
						path, switch_strerror_r(errno, ebuf, sizeof(ebuf)));
			}
			switch_safe_free(path);
		}
	} else {
		switch_thread_rwlock_unlock(globals.log_path_lock);
	}

	/* try to post it to the web server */
	if (globals.url_count) {
		char *destUrl = NULL;
		curl_handle = switch_curl_easy_init();

		if (globals.encode == ENCODING_TEXTXML) {
			headers = switch_curl_slist_append(headers, "Content-Type: text/xml");
		} else if (globals.encode) {
			switch_size_t need_bytes = strlen(xml_text) * 3 + 1;

			xml_text_escaped = malloc(need_bytes);
			switch_assert(xml_text_escaped);
			memset(xml_text_escaped, 0, need_bytes);
			if (globals.encode == ENCODING_DEFAULT) {
				headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
				switch_url_encode(xml_text, xml_text_escaped, need_bytes);
			} else {
				headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-base64-encoded");
				switch_b64_encode((unsigned char *) xml_text, need_bytes / 3, (unsigned char *) xml_text_escaped, need_bytes);
			}
			switch_safe_free(xml_text);
			xml_text = xml_text_escaped;
		} else {
			headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-plaintext");
		}

		if (globals.encode == ENCODING_TEXTXML) {
			curl_xml_text = xml_text;
		} else if (!(curl_xml_text = switch_mprintf("cdr=%s", xml_text))) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
			goto error;
		}

		if (!zstr(globals.cred)) {
			switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, globals.auth_scheme);
			switch_curl_easy_setopt(curl_handle, CURLOPT_USERPWD, globals.cred);
		}

		switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
		switch_curl_easy_setopt(curl_handle, CURLOPT_POST, 1);
		switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
		switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, curl_xml_text);
		switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-xml/1.0");
		switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, httpCallBack);

		if (globals.disable100continue) {
			slist = switch_curl_slist_append(slist, "Expect:");
			switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist);
		}

		if (globals.ssl_cert_file) {
			switch_curl_easy_setopt(curl_handle, CURLOPT_SSLCERT, globals.ssl_cert_file);
		}

		if (globals.ssl_key_file) {
			switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEY, globals.ssl_key_file);
		}

		if (globals.ssl_key_password) {
			switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEYPASSWD, globals.ssl_key_password);
		}

		if (globals.ssl_version) {
			if (!strcasecmp(globals.ssl_version, "SSLv3")) {
				switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);
			} else if (!strcasecmp(globals.ssl_version, "TLSv1")) {
				switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
			}
		}

		if (globals.ssl_cacert_file) {
			switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, globals.ssl_cacert_file);
		}
		
		switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, globals.timeout);

		/* these were used for testing, optionally they may be enabled if someone desires
		   switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); // 302 recursion level
		 */

		for (cur_try = 0; cur_try < globals.retries; cur_try++) {
			if (cur_try > 0) {
				switch_yield(globals.delay * 1000000);
			}

			destUrl = switch_mprintf("%s?uuid=%s%s", globals.urls[globals.url_index], a_prefix, switch_core_session_get_uuid(session));
			switch_curl_easy_setopt(curl_handle, CURLOPT_URL, destUrl);

			if (!strncasecmp(destUrl, "https", 5)) {
				switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
				switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
			}

			if (globals.enable_cacert_check) {
				switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, TRUE);
			}

			if (globals.enable_ssl_verifyhost) {
				switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
			}

			switch_curl_easy_perform(curl_handle);
			switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
			switch_safe_free(destUrl);
			if (httpRes >= 200 && httpRes <= 299) {
				goto success;
			} else {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Got error [%ld] posting to web server [%s]\n",
								  httpRes, globals.urls[globals.url_index]);
				globals.url_index++;
				switch_assert(globals.url_count <= MAX_URLS);
				if (globals.url_index >= globals.url_count) {
					globals.url_index = 0;
				}
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Retry will be with url [%s]\n", globals.urls[globals.url_index]);
			}
		}
		switch_curl_easy_cleanup(curl_handle);
		switch_curl_slist_free_all(headers);
		switch_curl_slist_free_all(slist);
		slist = NULL;
		headers = NULL;
		curl_handle = NULL;

		/* if we are here the web post failed for some reason */
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to post to web server, writing to file\n");

		switch_thread_rwlock_rdlock(globals.log_path_lock);
		path = switch_mprintf("%s%s%s%s.cdr.xml", globals.err_log_dir, SWITCH_PATH_SEPARATOR, a_prefix, switch_core_session_get_uuid(session));
		switch_thread_rwlock_unlock(globals.log_path_lock);
		if (path) {
#ifdef _MSC_VER
			if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) {
#else
			if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) > -1) {
#endif
				int wrote;
				wrote = write(fd, xml_text, (unsigned) strlen(xml_text));
				wrote++;
				close(fd);
				fd = -1;
			} else {
				char ebuf[512] = { 0 };
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error![%s]\n",
						switch_strerror_r(errno, ebuf, sizeof(ebuf)));
			}
		}
	}

  success:
	status = SWITCH_STATUS_SUCCESS;

  error:
	if (curl_handle) {
		switch_curl_easy_cleanup(curl_handle);
	}
	if (headers) {
		switch_curl_slist_free_all(headers);
	}
	if (slist) {
		switch_curl_slist_free_all(slist);
	}
	if (curl_xml_text != xml_text) {
		switch_safe_free(curl_xml_text);
	}
	switch_safe_free(xml_text);
	switch_safe_free(path);
	switch_xml_free(cdr);

	return status;
}

static void event_handler(switch_event_t *event)
{
	const char *sig = switch_event_get_header(event, "Trapped-Signal");

	if (sig && !strcmp(sig, "HUP")) {
		if (globals.rotate) {
			set_xml_cdr_log_dirs();
		}
	}
}

static switch_state_handler_table_t state_handlers = {
	/*.on_init */ NULL,
	/*.on_routing */ NULL,
	/*.on_execute */ NULL,
	/*.on_hangup */ NULL,
	/*.on_exchange_media */ NULL,
	/*.on_soft_execute */ NULL,
	/*.on_consume_media */ NULL,
	/*.on_hibernate */ NULL,
	/*.on_reset */ NULL,
	/*.on_park */ NULL,
	/*.on_reporting */ my_on_reporting
};

SWITCH_MODULE_LOAD_FUNCTION(mod_xml_cdr_load)
{
	char *cf = "xml_cdr.conf";
	switch_xml_t cfg, xml, settings, param;
	switch_status_t status = SWITCH_STATUS_SUCCESS;

	/* test global state handlers */
	switch_core_add_state_handler(&state_handlers);

	*module_interface = switch_loadable_module_create_module_interface(pool, modname);

	memset(&globals, 0, sizeof(globals));

	if (switch_event_bind_removable(modname, SWITCH_EVENT_TRAP, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL, &globals.node) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
		return SWITCH_STATUS_GENERR;
	}

	globals.log_http_and_disk = 0;
	globals.log_b = 1;
	globals.disable100continue = 0;
	globals.pool = pool;
	globals.auth_scheme = CURLAUTH_BASIC;

	switch_thread_rwlock_create(&globals.log_path_lock, pool);

	/* parse the config */
	if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
		return SWITCH_STATUS_FALSE;
	}

	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, "cred") && !zstr(val)) {
				globals.cred = switch_core_strdup(globals.pool, val);
			} else if (!strcasecmp(var, "url") && !zstr(val)) {
				if (globals.url_count >= MAX_URLS) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "maximum urls configured!\n");
				} else {
					globals.urls[globals.url_count++] = switch_core_strdup(globals.pool, val);
				}
			} else if (!strcasecmp(var, "log-http-and-disk")) {
				globals.log_http_and_disk = switch_true(val);
			} else if (!strcasecmp(var, "timeout")) {
				int tmp = atoi(val);
				if (tmp >= 0) {
					globals.timeout = tmp;
				} else {
					globals.timeout = 0;
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set a negative timeout!\n");
				}
			} else if (!strcasecmp(var, "delay") && !zstr(val)) {
				globals.delay = switch_atoui(val);
			} else if (!strcasecmp(var, "log-b-leg")) {
				globals.log_b = switch_true(val);
			} else if (!strcasecmp(var, "prefix-a-leg")) {
				globals.prefix_a = switch_true(val);
			} else if (!strcasecmp(var, "disable-100-continue") && switch_true(val)) {
				globals.disable100continue = 1;
			} else if (!strcasecmp(var, "encode") && !zstr(val)) {
				if (!strcasecmp(val, "base64")) {
					globals.encode = ENCODING_BASE64;
				} else if (!strcasecmp(val, "textxml")) {
					globals.encode = ENCODING_TEXTXML;
				} else {
					globals.encode = switch_true(val) ? ENCODING_DEFAULT : ENCODING_NONE;
				}
			} else if (!strcasecmp(var, "retries") && !zstr(val)) {
				globals.retries = switch_atoui(val);
			} else if (!strcasecmp(var, "rotate") && !zstr(val)) {
				globals.rotate = switch_true(val);
			} else if (!strcasecmp(var, "log-dir")) {
				if (zstr(val)) {
					globals.base_log_dir = switch_core_sprintf(globals.pool, "%s%sxml_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
				} else {
					if (switch_is_file_path(val)) {
						globals.base_log_dir = switch_core_strdup(globals.pool, val);
					} else {
						globals.base_log_dir = switch_core_sprintf(globals.pool, "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, val);
					}
				}
			} else if (!strcasecmp(var, "err-log-dir")) {
				if (zstr(val)) {
					globals.base_err_log_dir = switch_core_sprintf(globals.pool, "%s%sxml_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
				} else {
					if (switch_is_file_path(val)) {
						globals.base_err_log_dir = switch_core_strdup(globals.pool, val);
					} else {
						globals.base_err_log_dir = switch_core_sprintf(globals.pool, "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, val);
					}
				}
			} else if (!strcasecmp(var, "enable-cacert-check") && switch_true(val)) {
				globals.enable_cacert_check = 1;
			} else if (!strcasecmp(var, "ssl-cert-path")) {
				globals.ssl_cert_file = switch_core_strdup(globals.pool, val);
			} else if (!strcasecmp(var, "ssl-key-path")) {
				globals.ssl_key_file = switch_core_strdup(globals.pool, val);
			} else if (!strcasecmp(var, "ssl-key-password")) {
				globals.ssl_key_password = switch_core_strdup(globals.pool, val);
			} else if (!strcasecmp(var, "ssl-version")) {
				globals.ssl_version = switch_core_strdup(globals.pool, val);
			} else if (!strcasecmp(var, "ssl-cacert-file")) {
				globals.ssl_cacert_file = switch_core_strdup(globals.pool, val);
			} else if (!strcasecmp(var, "enable-ssl-verifyhost") && switch_true(val)) {
				globals.enable_ssl_verifyhost = 1;
			} else if (!strcasecmp(var, "auth-scheme")) {
				if (*val == '=') {
					globals.auth_scheme = 0;
					val++;
				}

				if (!strcasecmp(val, "basic")) {
					globals.auth_scheme |= CURLAUTH_BASIC;
				} else if (!strcasecmp(val, "digest")) {
					globals.auth_scheme |= CURLAUTH_DIGEST;
				} else if (!strcasecmp(val, "NTLM")) {
					globals.auth_scheme |= CURLAUTH_NTLM;
				} else if (!strcasecmp(val, "GSS-NEGOTIATE")) {
					globals.auth_scheme |= CURLAUTH_GSSNEGOTIATE;
				} else if (!strcasecmp(val, "any")) {
					globals.auth_scheme = CURLAUTH_ANY;
				}
			}
		}
		
		if (zstr(globals.base_err_log_dir)) {
			if (!zstr(globals.base_log_dir)) {
				globals.base_err_log_dir = switch_core_strdup(globals.pool, globals.base_log_dir);
			} else {
				globals.base_err_log_dir = switch_core_sprintf(globals.pool, "%s%sxml_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
			}
		}
		
	}

	if (globals.retries && globals.delay == 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Retries set but delay 0 setting to 5 seconds\n");
		globals.delay = 5;
	}

	globals.retries++;

	set_xml_cdr_log_dirs();

	switch_xml_free(xml);

	return status;
}

SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_cdr_shutdown)
{

	globals.shutdown = 1;

	switch_safe_free(globals.log_dir);
	switch_safe_free(globals.err_log_dir);

	switch_event_unbind(&globals.node);
	switch_core_remove_state_handler(&state_handlers);

	switch_thread_rwlock_destroy(globals.log_path_lock);

	return SWITCH_STATUS_SUCCESS;
}
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;
}
Beispiel #14
0
/**
 * Wraps file with interface that can be controlled by fileman flags
 * @param handle
 * @param path the file to play
 * @return SWITCH_STATUS_SUCCESS if opened
 */
static switch_status_t fileman_file_open(switch_file_handle_t *handle, const char *path)
{
	int start_offset_ms = 0;
	switch_status_t status = SWITCH_STATUS_FALSE;
	struct fileman_file_context *context = switch_core_alloc(handle->memory_pool, sizeof(*context));
	handle->private_info = context;

	if (handle->params) {
		const char *id = switch_event_get_header(handle->params, "id");
		const char *uuid = switch_event_get_header(handle->params, "session");
		const char *start_offset_ms_str = switch_event_get_header(handle->params, "start_offset_ms");
		if (!zstr(id)) {
			context->id = switch_core_strdup(handle->memory_pool, id);
		}
		if (!zstr(uuid)) {
			context->uuid = switch_core_strdup(handle->memory_pool, uuid);
		}
		if (!zstr(start_offset_ms_str) && switch_is_number(start_offset_ms_str)) {
			start_offset_ms = atoi(start_offset_ms_str);
			if (start_offset_ms < 0) {
				start_offset_ms = 0;
			}
		}
	}

	switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Got path %s\n", path);

	if ((status = switch_core_file_open(&context->fh, path, handle->channels, handle->samplerate, handle->flags, NULL)) != SWITCH_STATUS_SUCCESS) {
		return status;
	}

	/* set up handle for external control */
	if (!context->id) {
		/* use filename as ID */
		context->id = switch_core_strdup(handle->memory_pool, path);
	}
	switch_mutex_lock(fileman_globals.mutex);
	if (!switch_core_hash_find(fileman_globals.hash, context->id)) {
		switch_core_hash_insert(fileman_globals.hash, context->id, handle);
	} else {
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_WARNING, "Duplicate fileman ID: %s\n", context->id);
		return SWITCH_STATUS_FALSE;
	}
	switch_mutex_unlock(fileman_globals.mutex);

	context->max_frame_len = (handle->samplerate / 1000 * SWITCH_MAX_INTERVAL);
	switch_zmalloc(context->abuf, FILE_STARTBYTES * sizeof(*context->abuf));

	if (!context->fh.audio_buffer) {
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "Create audio buffer\n");
		switch_buffer_create_dynamic(&context->fh.audio_buffer, FILE_BLOCKSIZE, FILE_BUFSIZE, 0);
		switch_assert(context->fh.audio_buffer);
	}

	handle->samples = context->fh.samples;
	handle->format = context->fh.format;
	handle->sections = context->fh.sections;
	handle->seekable = context->fh.seekable;
	handle->speed = context->fh.speed;
	handle->vol = context->fh.vol;
	handle->offset_pos = context->fh.offset_pos;
	handle->interval = context->fh.interval;

	if (switch_test_flag((&context->fh), SWITCH_FILE_NATIVE)) {
		switch_set_flag(handle, SWITCH_FILE_NATIVE);
	} else {
		switch_clear_flag(handle, SWITCH_FILE_NATIVE);
	}

	if (handle->params && switch_true(switch_event_get_header(handle->params, "pause"))) {
		switch_set_flag(handle, SWITCH_FILE_PAUSE);
	}

	if (handle->seekable && start_offset_ms) {
		unsigned int pos = 0;
		int32_t target = start_offset_ms * (handle->samplerate / 1000);
		switch_log_printf(SWITCH_CHANNEL_UUID_LOG(context->uuid), SWITCH_LOG_DEBUG, "seek to position %d\n", target);
		switch_core_file_seek(&context->fh, &pos, target, SEEK_SET);
	}

	return status;
}
static void launch_thread(const char *name, const char *path, switch_xml_t directory)
{
	local_stream_source_t *source = NULL;
	switch_memory_pool_t *pool;
	switch_xml_t param;
	switch_thread_t *thread;
	switch_threadattr_t *thd_attr = NULL;

	if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
		abort();
	}
	source = switch_core_alloc(pool, sizeof(*source));
	assert(source != NULL);
	source->pool = pool;

	source->name = switch_core_strdup(source->pool, name);
	source->location = switch_core_strdup(source->pool, path);
	source->rate = 8000;
	source->interval = 20;
	source->channels = 1;
	source->timer_name = "soft";
	source->prebuf = DEFAULT_PREBUFFER_SIZE;
	source->stopped = 0;
	source->hup = 0;
	source->chime_freq = 30;
	for (param = switch_xml_child(directory, "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, "rate")) {
			int tmp = atoi(val);
			if (tmp == 8000 || tmp == 12000 || tmp == 16000 || tmp == 24000 || tmp == 32000 || tmp == 48000) {
				source->rate = tmp;
			}
		} else if (!strcasecmp(var, "shuffle")) {
			source->shuffle = switch_true(val);
		} else if (!strcasecmp(var, "prebuf")) {
			int tmp = atoi(val);
			if (tmp > 0) {
				source->prebuf = (uint32_t) tmp;
			}
		} else if (!strcasecmp(var, "channels")) {
			int tmp = atoi(val);
			if (tmp == 1 || tmp == 2) {
				source->channels = (uint8_t) tmp;
			}
		} else if (!strcasecmp(var, "chime-freq")) {
			int tmp = atoi(val);
			if (tmp > 1) {
				source->chime_freq = tmp;
			}
		} else if (!strcasecmp(var, "chime-max")) {
			int tmp = atoi(val);
			if (tmp > 1) {
				source->chime_max = tmp;
			}
		} else if (!strcasecmp(var, "chime-list")) {
			char *list_dup = switch_core_strdup(source->pool, val);
			source->chime_total =
				switch_separate_string(list_dup, ',', source->chime_list, (sizeof(source->chime_list) / sizeof(source->chime_list[0])));
		} else if (!strcasecmp(var, "interval")) {
			int tmp = atoi(val);
			if (SWITCH_ACCEPTABLE_INTERVAL(tmp)) {
				source->interval = tmp;
			} else {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
								  "Interval must be multiple of 10 and less than %d, Using default of 20\n", SWITCH_MAX_INTERVAL);
			}
		} else if (!strcasecmp(var, "timer-name")) {
			source->timer_name = switch_core_strdup(source->pool, val);
		}
	}

	if (source->chime_max) {
		source->chime_max *= source->rate;
	}

	if (source->chime_total) {
		source->chime_counter = source->rate * source->chime_freq;
	}

	source->samples = switch_samples_per_packet(source->rate, source->interval);
	switch_mutex_init(&source->mutex, SWITCH_MUTEX_NESTED, source->pool);
	switch_threadattr_create(&thd_attr, source->pool);
	switch_threadattr_detach_set(thd_attr, 1);
	switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
	switch_thread_create(&thread, thd_attr, read_stream_thread, source, source->pool);
}
static switch_status_t load_config(switch_bool_t reload)
{
    switch_status_t status = SWITCH_STATUS_SUCCESS;
    switch_xml_t cfg, xml = NULL, settings, param, x_profiles, x_profile;
    switch_cache_db_handle_t *dbh = NULL;

    if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
        return SWITCH_STATUS_TERM;
    }

    switch_mutex_lock(globals.mutex);
    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)) {
                if (switch_odbc_available()) {
                    switch_set_string(globals.odbc_dsn, val);
                    if ((globals.odbc_user = strchr(globals.odbc_dsn, ':'))) {
                        *globals.odbc_user++ = '\0';
                        if ((globals.odbc_pass = strchr(globals.odbc_user, ':'))) {
                            *globals.odbc_pass++ = '\0';
                        }
                    }
                } else {
                    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n");
                }
            } else if (!strcasecmp(var, "dbname") && !zstr(val)) {
                globals.dbname = switch_core_strdup(globals.pool, val);
            }

            if (!strcasecmp(var, "debug")) {
                globals.debug = atoi(val);
            }
        }
    }

    if ((x_profiles = switch_xml_child(cfg, "profiles"))) {
        for (x_profile = switch_xml_child(x_profiles, "profile"); x_profile; x_profile = x_profile->next) {
            load_profile(switch_xml_attr_soft(x_profile, "name"));
        }
    }

    if (zstr(globals.odbc_dsn) && zstr(globals.dbname)) {
        globals.dbname = switch_core_sprintf(globals.pool, "directory");
    }

    dbh = directory_get_db_handle();
    if (dbh) {
        if (!reload) {
            switch_cache_db_test_reactive(dbh, "delete from directory_search where uuid != '' and name_visible != '' ", "drop table directory_search", dir_sql);
        }
        switch_cache_db_release_db_handle(&dbh);
    } else {
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot open DB!2\n");
        status = SWITCH_STATUS_TERM;
        goto end;
    }
end:
    switch_mutex_unlock(globals.mutex);

    switch_xml_free(xml);
    return status;
}
Beispiel #17
0
static http_data_t *do_lookup_url(switch_memory_pool_t *pool, const char *url, const char *method, const char *data, const char *content_type, curl_options_t *options)
{
	switch_CURL *curl_handle = NULL;
	long httpRes = 0;
	http_data_t *http_data = NULL;
	switch_curl_slist_t *headers = NULL;

	http_data = switch_core_alloc(pool, sizeof(http_data_t));
	memset(http_data, 0, sizeof(http_data_t));
	http_data->pool = pool;

	http_data->max_bytes = 64000;
	SWITCH_STANDARD_STREAM(http_data->stream);

	if (!method) {
		method = "get";
	}

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "method: %s, url: %s, content-type: %s\n", method, url, content_type);
	curl_handle = switch_curl_easy_init();

	if (options) {
		if (options->connect_timeout) {
			switch_curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, options->connect_timeout);
		}

		if (options->timeout) {
			switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, options->timeout);
		}
	}

	if (!strncasecmp(url, "https", 5)) {
		switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
		switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
	}
	if (!strcasecmp(method, "head")) {
		switch_curl_easy_setopt(curl_handle, CURLOPT_NOBODY, 1);
	} else if (!strcasecmp(method, "post")) {
		switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, strlen(data));
		switch_curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, (void *) data);
		if (content_type) {
			char *ct = switch_mprintf("Content-Type: %s", content_type);
			headers = switch_curl_slist_append(headers, ct);
			switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
			switch_safe_free(ct);
		}
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Post data: %s\n", data);
	} else {
		switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1);
	}
	switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
	switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 15);
	switch_curl_easy_setopt(curl_handle, CURLOPT_URL, url);
	switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
	switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, file_callback);
	switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) http_data);
	switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_callback);
	switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, (void *) http_data);
	switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-curl/1.0");

	switch_curl_easy_perform(curl_handle);
	switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
	switch_curl_easy_cleanup(curl_handle);
	switch_curl_slist_free_all(headers);

	if (http_data->stream.data && !zstr((char *) http_data->stream.data) && strcmp(" ", http_data->stream.data)) {

		http_data->http_response = switch_core_strdup(pool, http_data->stream.data);
	}

	http_data->http_response_code = httpRes;

	switch_safe_free(http_data->stream.data);
	return http_data;
}
Beispiel #18
0
static switch_status_t do_config(void)
{
	char *cf = "xml_scgi.conf";
	switch_xml_t cfg, xml, bindings_tag, binding_tag, param;
	xml_binding_t *binding = NULL;
	int x = 0;
	int need_vars_map = 0;
	switch_hash_t *vars_map = NULL;

	if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
		return SWITCH_STATUS_TERM;
	}

	if (!(bindings_tag = switch_xml_child(cfg, "bindings"))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing <bindings> tag!\n");
		goto done;
	}

	for (binding_tag = switch_xml_child(bindings_tag, "binding"); binding_tag; binding_tag = binding_tag->next) {
		char *bname = (char *) switch_xml_attr_soft(binding_tag, "name");
		char *host = "127.0.0.1";
		char *port = "8080";
		char *bind_mask = NULL;
		int timeout = 0;
		char *server = NULL;

		hash_node_t *hash_node;
		need_vars_map = 0;
		vars_map = NULL;

		for (param = switch_xml_child(binding_tag, "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, "host")) {
				bind_mask = (char *) switch_xml_attr_soft(param, "bindings");
				if (val) {
					host = val;
				}
			} else if (!strcasecmp(var, "port")) {
				port = val;
			} else if (!strcasecmp(var, "timeout")) {
				int tmp = atoi(val);
				if (tmp >= 0) {
					timeout = tmp;
				} else {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't set a negative timeout!\n");
				}
			} else if (!strcasecmp(var, "enable-post-var")) {
				if (!vars_map && need_vars_map == 0) {
					if (switch_core_hash_init(&vars_map, globals.pool) != SWITCH_STATUS_SUCCESS) {
						need_vars_map = -1;
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't init params hash!\n");
						continue;
					}
					need_vars_map = 1;
				}

				if (vars_map && val) {
					if (switch_core_hash_insert(vars_map, val, ENABLE_PARAM_VALUE) != SWITCH_STATUS_SUCCESS) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't add %s to params hash!\n", val);
					}
				}
			} else if (!strcasecmp(var, "server")) {
				server = val;
			}
		}

		if (!host) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Binding has no host!\n");
			if (vars_map) {
				switch_core_hash_destroy(&vars_map);
			}
			continue;
		}

		if (!(binding = switch_core_alloc(globals.pool, sizeof(*binding)))) {
			if (vars_map) {
				switch_core_hash_destroy(&vars_map);
			}
			goto done;
		}
		memset(binding, 0, sizeof(*binding));

		binding->timeout = timeout;
		binding->host = switch_core_strdup(globals.pool, host);
		binding->port = atoi(port);
		binding->vars_map = vars_map;
		binding->uri = switch_mprintf("/%s", bname);
		binding->url = switch_mprintf("scgi://%s:%s/%s", host, port, bname);

		if (server) {
			binding->server = switch_core_strdup(globals.pool, server);
		}

        if (bind_mask) {
			binding->bindings = switch_core_strdup(globals.pool, bind_mask);
		}                                         

		if (vars_map) {
			switch_zmalloc(hash_node, sizeof(hash_node_t));
			hash_node->hash = vars_map;
			hash_node->next = NULL;

			if (!globals.hash_root) {
				globals.hash_root = hash_node;
				globals.hash_tail = globals.hash_root;
			}

			else {
				globals.hash_tail->next = hash_node;
				globals.hash_tail = globals.hash_tail->next;
			}

		}

		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Binding [%s] XML Fetch Function [%s] [%s]\n",
						  zstr(bname) ? "N/A" : bname, binding->url, binding->bindings ? binding->bindings : "all");
		switch_xml_bind_search_function(xml_url_fetch, switch_xml_parse_section_string(binding->bindings), binding);
		
		if (binding->server) {
			launch_monitor_thread(binding);
		}

		binding->next = globals.bindings;
		globals.bindings = binding;
		

		x++;
		binding = NULL;
	}

  done:
	switch_xml_free(xml);

	return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
}
Beispiel #19
0
// This function and do_lookup_url functions could possibly be merged together.  Or at least have do_lookup_url call this up as part of the initialization routine as it is a subset of the operations.
static void http_sendfile_initialize_curl(http_sendfile_data_t *http_data)
{
	uint8_t count;
	http_data->curl_handle = curl_easy_init();
	
	if (!strncasecmp(http_data->url, "https", 5))
	{
		curl_easy_setopt(http_data->curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
		curl_easy_setopt(http_data->curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
	}
	
	/* From the docs: 
	 * Optionally, you can provide data to POST using the CURLOPT_READFUNCTION and CURLOPT_READDATA 
	 * options but then you must make sure to not set CURLOPT_POSTFIELDS to anything but NULL
	 * curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, strlen(data));
	 * curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, (void *) data);
	 */
	
	// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Post data: %s\n", data);
	
	curl_easy_setopt(http_data->curl_handle, CURLOPT_FOLLOWLOCATION, 1);
	curl_easy_setopt(http_data->curl_handle, CURLOPT_MAXREDIRS, 15);
	curl_easy_setopt(http_data->curl_handle, CURLOPT_URL, http_data->url);
	curl_easy_setopt(http_data->curl_handle, CURLOPT_NOSIGNAL, 1);
	curl_easy_setopt(http_data->curl_handle, CURLOPT_USERAGENT, "freeswitch-curl/1.0");
	
	http_data->sendfile_response = switch_core_alloc(http_data->pool, sizeof(char) * HTTP_SENDFILE_RESPONSE_SIZE);
	memset(http_data->sendfile_response, 0, sizeof(char) * HTTP_SENDFILE_RESPONSE_SIZE);
	
	// Set the function where we will copy out the response body data to
	curl_easy_setopt(http_data->curl_handle, CURLOPT_WRITEFUNCTION, http_sendfile_response_callback);
	curl_easy_setopt(http_data->curl_handle, CURLOPT_WRITEDATA, (void *) http_data);
	
	/* Add the file to upload as a POST form field */ 
	curl_formadd(&http_data->formpost, &http_data->lastptr, CURLFORM_COPYNAME, http_data->filename_element_name, CURLFORM_FILE, http_data->filename_element, CURLFORM_END);
	
	if(!zstr(http_data->extrapost_elements))
	{
		// Now to parse out the individual post element/value pairs
		char *argv[64] = { 0 }; // Probably don't need 64 but eh does it really use that much memory?
		uint32_t argc = 0;
		char *temp_extrapost = switch_core_strdup(http_data->pool, http_data->extrapost_elements);
		
		argc = switch_separate_string(temp_extrapost, '&', argv, (sizeof(argv) / sizeof(argv[0])));
		
		for(count = 0; count < argc; count++)
		{
			char *argv2[4] = { 0 };
			uint32_t argc2 = switch_separate_string(argv[count], '=', argv2, (sizeof(argv2) / sizeof(argv2[0])));
			
			if(argc2 == 2)
				curl_formadd(&http_data->formpost, &http_data->lastptr, CURLFORM_COPYNAME, argv2[0], CURLFORM_COPYCONTENTS, argv2[1], CURLFORM_END);
		}
	}
	
	/* Fill in the submit field too, even if this isn't really needed */ 
	curl_formadd(&http_data->formpost, &http_data->lastptr, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "or_die", CURLFORM_END);
	
	/* what URL that receives this POST */ 
	curl_easy_setopt(http_data->curl_handle, CURLOPT_HTTPPOST, http_data->formpost);
	
	// This part actually fires off the curl, captures the HTTP response code, and then frees up the handle.
	curl_easy_perform(http_data->curl_handle);
	curl_easy_getinfo(http_data->curl_handle, CURLINFO_RESPONSE_CODE, &http_data->http_response_code);
	
	curl_easy_cleanup(http_data->curl_handle);
		
	// Clean up the form data from POST
	curl_formfree(http_data->formpost);
}
static switch_status_t portaudio_stream_file_open(switch_file_handle_t *handle, const char *path)
{
	portaudio_stream_context_t *context;
	portaudio_stream_source_t *source;
	switch_memory_pool_t *pool;
	switch_status_t status = SWITCH_STATUS_FALSE;
	switch_thread_t *thread;
	switch_threadattr_t *thd_attr = NULL;
	uint32_t rate = PREFERRED_RATE;
	char *npath;
	int devNumber;
	int tmp;

	handle->pre_buffer_datalen = 0;

	if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "This format does not support writing! (yet)\n");
		return status;
	}

	npath = switch_core_strdup(module_pool, path);

	tmp = handle->samplerate;
	if (tmp == 8000 || tmp == 16000 || tmp == 32000 || tmp == 48000) {
		rate = tmp;
	}

	if (*path == '#') {
		devNumber = get_dev_by_number(npath + 1, 1);
	} else {
		devNumber = get_dev_by_name(npath, 1);
	}
	npath = switch_mprintf("device-%d at %d", devNumber, rate);

	switch_mutex_lock(globals.mutex);
	source = switch_core_hash_find(globals.source_hash, npath);

	/* dev isnt there, try to start thread */
	if (!source) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, " source isnt Created, create and start thread!\n");

		if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, " :S no pool\n");
		} else {
			source = switch_core_alloc(pool, sizeof(*source));
			if (source != NULL) {
				source->pool = pool;
				source->sourcedev = devNumber;
				source->sourcename = switch_core_strdup(source->pool, npath);
				source->rate = rate;
				source->interval = 20;
				source->channels = 1;
				source->timer_name = "soft";
				source->prebuf = DEFAULT_PREBUFFER_SIZE;
				source->stopped = 0;
				source->ready = 0;
				source->samples = switch_samples_per_packet(source->rate, source->interval);

				switch_mutex_init(&source->mutex, SWITCH_MUTEX_NESTED, source->pool);

				switch_threadattr_create(&thd_attr, source->pool);
				switch_threadattr_detach_set(thd_attr, 1);

				switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
				switch_thread_create(&thread, thd_attr, read_stream_thread, source, source->pool);
			}
		}
	}
	switch_mutex_unlock(globals.mutex);
	switch_yield(1000000);
	/* dev already engaged */
	if (source) {

		/*wait for source to be ready */
		while (source->ready == 0) {
			switch_yield(100000);
		}

		if (switch_thread_rwlock_tryrdlock(source->rwlock) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, " error rwlock !\n");
			source = NULL;
		}
	}

	if (source) {
		status = SWITCH_STATUS_SUCCESS;

		if ((context = switch_core_alloc(handle->memory_pool, sizeof(*context))) == 0) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, " error allocating context!\n");
			status = SWITCH_STATUS_MEMERR;
		} else {
			/* everything goes fine at this point */
			handle->samples = 0;
			handle->samplerate = source->rate;
			handle->channels = 1;
			handle->format = 0;
			handle->sections = 0;
			handle->seekable = 0;
			handle->speed = 0;
			handle->private_info = context;
			handle->interval = source->interval;

			switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, handle->memory_pool);
			if (switch_buffer_create_dynamic(&context->audio_buffer, 512, 1024, 0) != SWITCH_STATUS_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
				status = SWITCH_STATUS_MEMERR;
			} else {
				/* context created... then continue */
				context->source = source;
				context->file = handle->file;
				context->func = handle->func;
				context->line = handle->line;
				context->handle = handle;
				switch_mutex_lock(source->mutex);
				context->next = source->context_list;
				source->context_list = context;
				source->total++;
				switch_mutex_unlock(source->mutex);
			}
		}
	} else {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown source %s\n", path);
		status = SWITCH_STATUS_FALSE;
	}

	return status;
}
bool WSClientParser::ParseFirstLine(char* line) {
	bool bFlag = false;

	// Get Param
	char* p = line;
	char* delim = " ";
	char decodeUrl[HTTP_URL_MAX_PATH] = {0};

	char *array[HTTP_URL_FIRSTLINE_PARAM_MAX_COUNT];
	if( switch_separate_string_string(p, delim, array, HTTP_URL_FIRSTLINE_PARAM_MAX_COUNT) >= HTTP_URL_FIRSTLINE_PARAM_COUNT ) {
		Arithmetic ac;
		ac.decode_url(array[1], strlen(array[1]), decodeUrl);

		switch_log_printf(
				SWITCH_CHANNEL_UUID_LOG(this->uuid),
				SWITCH_LOG_INFO,
				"WSClientParser::ParseFirstLine( "
				"this : %p, "
				"decodeUrl : '%s' "
				") \n",
				this,
				decodeUrl
				);

		if( strlen(decodeUrl) > 0 ) {
//			p = decodeUrl;
			p = switch_core_strdup(mpPool, decodeUrl);
			delim = "/";
			if( *p == *delim ) {
				p++;
			}

			char *array2[HTTP_URL_PATH_PARAM_MAX_COUNT];
			if( switch_separate_string_string(p, delim, array2, HTTP_URL_PATH_PARAM_MAX_COUNT) >= HTTP_URL_PATH_PARAM_COUNT ) {
				mpUser = switch_core_strdup(mpPool, array2[0]);
				mpDomain = switch_core_strdup(mpPool, array2[1]);
				mpDestNumber = switch_core_strdup(mpPool, array2[2]);
				// 暂时不做PHP验证
				mpSite = switch_core_strdup(mpPool, array2[3]);
				mpCustom = switch_core_strdup(mpPool, array2[4]);
//				mpSite = switch_core_strdup(mpPool, "");
//				mpCustom = switch_core_strdup(mpPool, "");

				switch_log_printf(
						SWITCH_CHANNEL_UUID_LOG(this->uuid),
						SWITCH_LOG_INFO,
						"WSClientParser::ParseFirstLine( "
						"this : %p, "
						"user : '******', "
						"domain : '%s', "
						"destnumber : '%s', "
						"site : '%s', "
						"custom : '%s' "
						") \n",
						this,
						mpUser,
						mpDomain,
						mpDestNumber,
						mpSite,
						mpCustom
						);

				bFlag = true;
			}
		}
	}

	if( !bFlag ) {
		switch_log_printf(
				SWITCH_CHANNEL_UUID_LOG(this->uuid),
				SWITCH_LOG_ERROR,
				"WSClientParser::ParseFirstLine( "
				"[Fail], "
				"this : %p, "
				"decodeUrl : '%s' "
				") \n",
				this,
				decodeUrl
				);
	}

	return bFlag;
}
Beispiel #22
0
static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *path)
{
	vlc_file_context_t *context;
	libvlc_event_manager_t *mp_event_manager, *m_event_manager;
	
	context = switch_core_alloc(handle->memory_pool, sizeof(*context));
	context->pool = handle->memory_pool;

	context->path = switch_core_strdup(context->pool, path);

	switch_buffer_create_dynamic(&(context->audio_buffer), VLC_BUFFER_SIZE, VLC_BUFFER_SIZE * 8, 0);
	switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->pool);
	switch_thread_cond_create(&(context->started), context->pool);

	if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) {
		
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC open %s for reading\n", path);
		
		/* Determine if this is a url or a path */
		/* TODO: Change this so that it tries local files first, and then if it fails try location. */
		if(! strncmp(context->path, "http", 4)){
			context->m = libvlc_media_new_location(read_inst, context->path);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is http %s\n", context->path);
		} else if (! strncmp(context->path, "mms", 3)){
			context->m = libvlc_media_new_path(read_inst, context->path);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is mms %s\n", context->path);
		} else if (! strncmp(context->path, "/", 1)){
			context->m = libvlc_media_new_path(read_inst, context->path);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is file %s\n", context->path);
		} else {
			context->m = libvlc_media_new_location(read_inst, context->path);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VLC Path is unknown type %s\n", context->path);
		}

		if ( context->m == NULL ) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VLC error opening %s for reading\n", path);
			return SWITCH_STATUS_GENERR;
		}
		
		context->playing = 0;
		context->err = 0;
		
		context->mp = libvlc_media_player_new_from_media(context->m);
		
		if (!handle->samplerate) {
			handle->samplerate = 16000;
		}

		context->samplerate = handle->samplerate;
		context->channels = handle->channels;

		libvlc_audio_set_format(context->mp, "S16N", context->samplerate, handle->channels);
		
		m_event_manager = libvlc_media_event_manager(context->m);
		libvlc_event_attach(m_event_manager, libvlc_MediaStateChanged, vlc_media_state_callback, (void *) context);

		mp_event_manager = libvlc_media_player_event_manager(context->mp);
		libvlc_event_attach(mp_event_manager, libvlc_MediaPlayerEncounteredError, vlc_mediaplayer_error_callback, (void *) context);
		
		libvlc_audio_set_callbacks(context->mp, vlc_auto_play_callback, NULL,NULL,NULL,NULL, (void *) context);

		libvlc_media_player_play(context->mp);
		
	} else if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
		const char * opts[10] = {
			vlc_args,
			switch_mprintf("--sout=%s", path)
		};
		int opts_count = 10;
		
		if ( !handle->samplerate)
			handle->samplerate = 16000;
		
		context->samplerate = handle->samplerate;

		opts[2] = switch_mprintf("--imem-get=%ld", vlc_imem_get_callback);
		opts[3] = switch_mprintf("--imem-release=%ld", vlc_imem_release_callback);
		opts[4] = switch_mprintf("--imem-cat=%d", 4);
		opts[5] = "--demux=rawaud";
		opts[6] = "--rawaud-fourcc=s16l";
		opts[7] = switch_mprintf("--rawaud-samplerate=%d", context->samplerate);
		opts[8] = switch_mprintf("--imem-data=%ld", context);
		//opts[9] = "--rawaud-channels=1";

		/* Prepare to write to an output stream. */
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "VLC open %s for writing\n", path);

		/* load the vlc engine. */
		context->inst_out = libvlc_new(opts_count, opts);
		
		/* Tell VLC the audio will come from memory, and to use the callbacks to fetch it. */
		context->m = libvlc_media_new_location(context->inst_out, "imem/rawaud://");
		context->mp = libvlc_media_player_new_from_media(context->m);
		context->samples = 0;
		context->pts = 0;
		context->playing = 1;		
		libvlc_media_player_play(context->mp);
	} else {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VLC tried to open %s for unknown reason\n", path);
		return SWITCH_STATUS_GENERR;
	}

	handle->private_info = context;
	
	return SWITCH_STATUS_SUCCESS;
}
Beispiel #23
0
static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
													switch_caller_profile_t *outbound_profile,
													switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
													switch_call_cause_t *cancel_cause)
{
	char name[128];

	if (session) {
		switch_channel_t *channel = switch_core_session_get_channel(session);
		switch_channel_clear_flag(channel, CF_PROXY_MEDIA);
		switch_channel_clear_flag(channel, CF_PROXY_MODE);
		switch_channel_pre_answer(channel);
	}

	if ((*new_session = switch_core_session_request(loopback_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, pool)) != 0) {
		private_t *tech_pvt;
		switch_channel_t *channel;
		switch_caller_profile_t *caller_profile;

		switch_core_session_add_stream(*new_session, NULL);

		if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) {
			channel = switch_core_session_get_channel(*new_session);
			switch_snprintf(name, sizeof(name), "loopback/%s-a", outbound_profile->destination_number);
			switch_channel_set_name(channel, name);
			if (tech_init(tech_pvt, *new_session, session ? switch_core_session_get_read_codec(session) : NULL) != SWITCH_STATUS_SUCCESS) {
				switch_core_session_destroy(new_session);
				return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
			}
		} else {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
			switch_core_session_destroy(new_session);
			return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
		}

		if (outbound_profile) {
			char *dialplan = NULL, *context = NULL;

			caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
			caller_profile->source = switch_core_strdup(caller_profile->pool, modname);
			if (!strncasecmp(caller_profile->destination_number, "app=", 4)) {
				char *dest = switch_core_session_strdup(*new_session, caller_profile->destination_number);
				char *app = dest + 4;
				char *arg = NULL;

				if ((arg = strchr(app, ':'))) {
					*arg++ = '\0';
				}

				switch_channel_set_variable(channel, "loopback_app", app);
				if (arg) {
					switch_channel_set_variable(channel, "loopback_app_arg", arg);
				}

				caller_profile->destination_number = switch_core_strdup(caller_profile->pool, app);
			}

			if ((context = strchr(caller_profile->destination_number, '/'))) {
				*context++ = '\0';

				if ((dialplan = strchr(context, '/'))) {
					*dialplan++ = '\0';
				}

				if (!zstr(context)) {
					caller_profile->context = switch_core_strdup(caller_profile->pool, context);
				}

				if (!zstr(dialplan)) {
					caller_profile->dialplan = switch_core_strdup(caller_profile->pool, dialplan);
				}
			}

			if (zstr(caller_profile->context)) {
				caller_profile->context = switch_core_strdup(caller_profile->pool, "default");
			}

			if (zstr(caller_profile->dialplan)) {
				caller_profile->dialplan = switch_core_strdup(caller_profile->pool, "xml");
			}

			switch_snprintf(name, sizeof(name), "loopback/%s-a", caller_profile->destination_number);
			switch_channel_set_name(channel, name);
			switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
			switch_channel_set_caller_profile(channel, caller_profile);
			tech_pvt->caller_profile = caller_profile;
		} else {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_ERROR, "Doh! no caller profile\n");
			switch_core_session_destroy(new_session);
			return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
		}

		switch_channel_set_state(channel, CS_INIT);

		return SWITCH_CAUSE_SUCCESS;
	}

	return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
}
Beispiel #24
0
static switch_status_t load_config(void)
{
	char *cf = "pocketsphinx.conf";
	switch_xml_t cfg, xml = NULL, param, settings;
	switch_status_t status = SWITCH_STATUS_SUCCESS;

	/* Set defaults */
	globals.thresh = 400;
	globals.silence_hits = 35;
	globals.listen_hits = 1;
	globals.auto_reload = 1;

	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_FALSE;
		goto done;
	}

	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, "threshold")) {
				globals.thresh = atoi(val);
			} else if (!strcasecmp(var, "silence-hits")) {
				globals.silence_hits = atoi(val);
			} else if (!strcasecmp(var, "language-weight")) {
				globals.language_weight = switch_core_strdup(globals.pool, val);
			} else if (!strcasecmp(var, "listen-hits")) {
				globals.listen_hits = atoi(val);
			} else if (!strcasecmp(var, "auto-reload")) {
				globals.auto_reload = switch_true(val);
			} else if (!strcasecmp(var, "narrowband-model")) {
				globals.model8k = switch_core_strdup(globals.pool, val);
			} else if (!strcasecmp(var, "wideband-model")) {
				globals.model16k = switch_core_strdup(globals.pool, val);
			} else if (!strcasecmp(var, "dictionary")) {
				globals.dictionary = switch_core_strdup(globals.pool, val);
			}
		}
	}

	if (!globals.model8k) {
		globals.model8k = switch_core_strdup(globals.pool, "communicator");
	}

	if (!globals.model16k) {
		globals.model16k = switch_core_strdup(globals.pool, "wsj1");
	}

	if (!globals.dictionary) {
		globals.dictionary = switch_core_strdup(globals.pool, "default.dic");
	}

	if (!globals.language_weight) {
		globals.language_weight = switch_core_strdup(globals.pool, "6.5");
	}

  done:
	if (xml) {
		switch_xml_free(xml);
	}

	return status;
}
Beispiel #25
0
void *SWITCH_THREAD_FUNC rtmp_io_tcp_thread(switch_thread_t *thread, void *obj)
{
	rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)obj;
	io->base.running = 1;
	
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s: I/O Thread starting\n", io->base.profile->name);
	
	
	while(io->base.running) {
		const switch_pollfd_t *fds;
		int32_t numfds;
		int32_t i;
		switch_status_t status;
		
		switch_mutex_lock(io->mutex);
		status = switch_pollset_poll(io->pollset, 500000, &numfds, &fds);
		switch_mutex_unlock(io->mutex);
		
		if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_TIMEOUT) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "pollset_poll failed\n");
			continue;
		} else if (status == SWITCH_STATUS_TIMEOUT) {
			switch_cond_next();
		}
		
		for (i = 0; i < numfds; i++) {
			if (!fds[i].client_data) { 
				switch_socket_t *newsocket;
				if (switch_socket_accept(&newsocket, io->listen_socket, io->base.pool) != SWITCH_STATUS_SUCCESS) {
					if (io->base.running) {
						/* Don't spam the logs if we are shutting down */
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error [%s]\n", strerror(errno));	
					} else {
						return NULL;
					}
				} else {
					rtmp_session_t *rsession;
					
					if (switch_socket_opt_set(newsocket, SWITCH_SO_NONBLOCK, TRUE)) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't set socket as non-blocking\n");
					}

					if (switch_socket_opt_set(newsocket, SWITCH_SO_TCP_NODELAY, 1)) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't disable Nagle.\n");
					}
					
					if (rtmp_session_request(io->base.profile, &rsession) != SWITCH_STATUS_SUCCESS) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTMP session request failed\n");
						switch_socket_close(newsocket);
					} else {
						switch_sockaddr_t *addr = NULL;
						char ipbuf[200];
						
						/* Create out private data and attach it to the rtmp session structure */
						rtmp_tcp_io_private_t *pvt = switch_core_alloc(rsession->pool, sizeof(*pvt));
						rsession->io_private = pvt;
						pvt->socket = newsocket;
						switch_socket_create_pollfd(&pvt->pollfd, newsocket, SWITCH_POLLIN | SWITCH_POLLERR, rsession, rsession->pool);
						switch_pollset_add(io->pollset, pvt->pollfd);
						switch_buffer_create_dynamic(&pvt->sendq, 512, 1024, 0);
						
						/* Get the remote address/port info */
						switch_socket_addr_get(&addr, SWITCH_TRUE, newsocket);
						switch_get_addr(ipbuf, sizeof(ipbuf), addr);
						rsession->remote_address = switch_core_strdup(rsession->pool, ipbuf);
						rsession->remote_port = switch_sockaddr_get_port(addr);
						switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_INFO, "Rtmp connection from %s:%i\n",
										  rsession->remote_address, rsession->remote_port);
					}
				}
			} else {
				rtmp_session_t *rsession = (rtmp_session_t*)fds[i].client_data;
				rtmp_tcp_io_private_t *io_pvt = (rtmp_tcp_io_private_t*)rsession->io_private;
				
				if (fds[i].rtnevents & SWITCH_POLLOUT && switch_buffer_inuse(io_pvt->sendq) > 0) {
					/* Send as much remaining data as possible */
					switch_size_t sendlen;
					const void *ptr;
					sendlen = switch_buffer_peek_zerocopy(io_pvt->sendq, &ptr);
					switch_socket_send_nonblock(io_pvt->socket, ptr, &sendlen);
					switch_buffer_toss(io_pvt->sendq, sendlen);
					if (switch_buffer_inuse(io_pvt->sendq) == 0) {
						/* Remove our fd from OUT polling */
						rtmp_tcp_alter_pollfd(rsession, SWITCH_FALSE);
					}
				} else 	if (fds[i].rtnevents & SWITCH_POLLIN && rtmp_handle_data(rsession) != SWITCH_STATUS_SUCCESS) {
					switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_DEBUG, "Closing socket\n");
					
					switch_mutex_lock(io->mutex);
					switch_pollset_remove(io->pollset, io_pvt->pollfd);
					switch_mutex_unlock(io->mutex);
					
					switch_socket_close(io_pvt->socket);
					io_pvt->socket = NULL;
					
					rtmp_session_destroy(&rsession);
				}
			}
		}
	}
	
	io->base.running = -1;
	switch_socket_close(io->listen_socket);
	
	return NULL;
}
Beispiel #26
0
/* 
   State methods they get called when the state changes to the specific state 
   returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
   so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
*/
static switch_status_t channel_on_init(switch_core_session_t *session)
{
	switch_channel_t *channel, *b_channel;
	private_t *tech_pvt = NULL, *b_tech_pvt = NULL;
	switch_core_session_t *b_session;
	char name[128];
	switch_caller_profile_t *caller_profile;
	switch_event_t *vars = NULL;
	const char *var;

	tech_pvt = switch_core_session_get_private(session);
	switch_assert(tech_pvt != NULL);

	channel = switch_core_session_get_channel(session);
	switch_assert(channel != NULL);



	if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND) && !switch_test_flag(tech_pvt, TFLAG_BLEG)) {

		if (!(b_session = switch_core_session_request(loopback_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL))) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failure.\n");
			goto end;
		}

		if (switch_core_session_read_lock(b_session) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failure.\n");
			switch_core_session_destroy(&b_session);
			goto end;
		}

		switch_core_session_add_stream(b_session, NULL);
		b_channel = switch_core_session_get_channel(b_session);
		b_tech_pvt = (private_t *) switch_core_session_alloc(b_session, sizeof(*b_tech_pvt));

		switch_snprintf(name, sizeof(name), "loopback/%s-b", tech_pvt->caller_profile->destination_number);
		switch_channel_set_name(b_channel, name);
		if (tech_init(b_tech_pvt, b_session, switch_core_session_get_read_codec(session)) != SWITCH_STATUS_SUCCESS) {
			switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
			switch_core_session_destroy(&b_session);
			goto end;
		}

		caller_profile = switch_caller_profile_clone(b_session, tech_pvt->caller_profile);
		caller_profile->source = switch_core_strdup(caller_profile->pool, modname);
		switch_channel_set_caller_profile(b_channel, caller_profile);
		b_tech_pvt->caller_profile = caller_profile;
		switch_channel_set_state(b_channel, CS_INIT);

		tech_pvt->other_session = b_session;
		tech_pvt->other_tech_pvt = b_tech_pvt;
		tech_pvt->other_channel = b_channel;

		//b_tech_pvt->other_session = session;
		//b_tech_pvt->other_tech_pvt = tech_pvt;
		//b_tech_pvt->other_channel = channel;

		b_tech_pvt->other_uuid = switch_core_session_strdup(b_session, switch_core_session_get_uuid(session));

		switch_set_flag_locked(tech_pvt, TFLAG_LINKED);
		switch_set_flag_locked(b_tech_pvt, TFLAG_LINKED);
		switch_set_flag_locked(b_tech_pvt, TFLAG_BLEG);


		switch_channel_set_flag(channel, CF_ACCEPT_CNG);

		if ((vars = (switch_event_t *) switch_channel_get_private(channel, "__loopback_vars__"))) {
			switch_event_header_t *h;
		
			switch_channel_set_private(channel, "__loopback_vars__", NULL);

			for (h = vars->headers; h; h = h->next) {
				switch_channel_set_variable(tech_pvt->other_channel, h->name, h->value);
			}

			switch_event_destroy(&vars);
		}

		if ((var = switch_channel_get_variable(channel, "loopback_export"))) {
			int argc = 0;
			char *argv[128] = { 0 };
			char *dup = switch_core_session_strdup(session, var);

			if ((argc = switch_split(dup, ',', argv))) {
				int i;
				for (i = 0; i < argc; i++) {
					
					if (!zstr(argv[i])) {
						const char *val = switch_channel_get_variable(channel, argv[i]);

						if(!zstr(val)) {
							switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Transfer variable [%s]=[%s] %s -> %s\n",
											  argv[i], val, switch_channel_get_name(channel), switch_channel_get_name(tech_pvt->other_channel));
											  
							switch_channel_set_variable(tech_pvt->other_channel, argv[i], val);
						}
					}
				}
			}
		}

		if (switch_test_flag(tech_pvt, TFLAG_APP)) {
			switch_set_flag(b_tech_pvt, TFLAG_APP);
			switch_clear_flag(tech_pvt, TFLAG_APP);
		}

		switch_channel_set_variable(channel, "other_loopback_leg_uuid", switch_channel_get_uuid(b_channel));
		switch_channel_set_variable(b_channel, "other_loopback_leg_uuid", switch_channel_get_uuid(channel));

		if (switch_core_session_thread_launch(b_session) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error spawning thread\n");
			switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
			goto end;
		}
	} else if ((tech_pvt->other_session = switch_core_session_locate(tech_pvt->other_uuid))) {
		tech_pvt->other_tech_pvt = switch_core_session_get_private(tech_pvt->other_session);
		tech_pvt->other_channel = switch_core_session_get_channel(tech_pvt->other_session);
	}

	if (!tech_pvt->other_session) {
		switch_clear_flag_locked(tech_pvt, TFLAG_LINKED);
		switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
		goto end;
	}

	switch_channel_set_variable(channel, "loopback_leg", switch_test_flag(tech_pvt, TFLAG_BLEG) ? "B" : "A");
	switch_channel_set_state(channel, CS_ROUTING);

  end:

	return SWITCH_STATUS_SUCCESS;
}
Beispiel #27
0
/**
 * Start CPA
 */
iks *rayo_cpa_component_start(struct rayo_actor *call, struct rayo_message *msg, void *session_data)
{
    iks *iq = msg->payload;
    switch_core_session_t *session = (switch_core_session_t *)session_data;
    iks *input = iks_find(iq, "input");
    switch_memory_pool_t *pool = NULL;
    struct cpa_component *component = NULL;
    int have_grammar = 0;
    iks *grammar = NULL;

    /* create CPA component */
    switch_core_new_memory_pool(&pool);
    component = switch_core_alloc(pool, sizeof(*component));
    component = CPA_COMPONENT(rayo_component_init((struct rayo_component *)component, pool, RAT_CALL_COMPONENT, "cpa", NULL, call, iks_find_attrib(iq, "from")));
    if (!component) {
        switch_core_destroy_memory_pool(&pool);
        return iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "Failed to create CPA entity");
    }

    switch_core_hash_init(&component->signals);

    /* start CPA detectors */
    for (grammar = iks_find(input, "grammar"); grammar; grammar = iks_next_tag(grammar)) {
        if (!strcmp("grammar", iks_name(grammar))) {
            const char *error_str = "";
            const char *url = iks_find_attrib_soft(grammar, "url");
            char *url_dup;
            char *url_params;

            if (zstr(url)) {
                stop_cpa_detectors(component);
                RAYO_UNLOCK(component);
                RAYO_DESTROY(component);
                return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "Missing grammar URL");
            }
            have_grammar = 1;

            url_dup = strdup(url);
            if ((url_params = strchr(url_dup, '?'))) {
                *url_params = '\0';
                url_params++;
            }

            if (switch_core_hash_find(component->signals, url)) {
                free(url_dup);
                stop_cpa_detectors(component);
                RAYO_UNLOCK(component);
                RAYO_DESTROY(component);
                return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "Duplicate URL");
            }

            /* start detector */
            /* TODO return better reasons... */
            if (rayo_cpa_detector_start(switch_core_session_get_uuid(session), url_dup, &error_str)) {
                struct cpa_signal *cpa_signal = switch_core_alloc(pool, sizeof(*cpa_signal));
                cpa_signal->terminate = !zstr(url_params) && strstr(url_params, "terminate=true");
                cpa_signal->name = switch_core_strdup(pool, url_dup);
                switch_core_hash_insert(component->signals, cpa_signal->name, cpa_signal);
                subscribe(switch_core_session_get_uuid(session), cpa_signal->name, RAYO_JID(component));
            } else {
                free(url_dup);
                stop_cpa_detectors(component);
                RAYO_UNLOCK(component);
                RAYO_DESTROY(component);
                return iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, error_str);
            }

            free(url_dup);
        }
    }

    if (!have_grammar) {
        stop_cpa_detectors(component);
        RAYO_UNLOCK(component);
        RAYO_DESTROY(component);
        return iks_new_error_detailed(iq, STANZA_ERROR_BAD_REQUEST, "No grammar defined");
    }

    /* acknowledge command */
    rayo_component_send_start(RAYO_COMPONENT(component), iq);

    /* TODO hangup race condition */
    subscribe(switch_core_session_get_uuid(session), "hangup", RAYO_JID(component));

    /* ready to forward detector events */
    component->ready = 1;

    return NULL;
}
static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void *obj)
{
	local_stream_source_t *source = obj;
	switch_file_handle_t fh = { 0 };
	local_stream_context_t *cp;
	char file_buf[128] = "", path_buf[512] = "";
	switch_timer_t timer = { 0 };
	int fd = -1;
	switch_buffer_t *audio_buffer;
	switch_byte_t *dist_buf;
	switch_size_t used;
	int skip = 0;
	switch_memory_pool_t *temp_pool = NULL;

	switch_mutex_lock(globals.mutex);
	THREADS++;
	switch_mutex_unlock(globals.mutex);

	if (!source->prebuf) {
		source->prebuf = DEFAULT_PREBUFFER_SIZE;
	}

	switch_buffer_create_dynamic(&audio_buffer, 1024, source->prebuf + 10, 0);
	dist_buf = switch_core_alloc(source->pool, source->prebuf + 10);

	if (source->shuffle) {
		skip = do_rand();
	}

	switch_thread_rwlock_create(&source->rwlock, source->pool);

	if (RUNNING) {
		switch_mutex_lock(globals.mutex);
		switch_core_hash_insert(globals.source_hash, source->name, source);
		switch_mutex_unlock(globals.mutex);
		source->ready = 1;
	}

	while (RUNNING && !source->stopped) {
		const char *fname;

		if (temp_pool) {
			switch_core_destroy_memory_pool(&temp_pool);
		}

		if (switch_core_new_memory_pool(&temp_pool) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error creating pool");
			goto done;
		}

		if (switch_dir_open(&source->dir_handle, source->location, temp_pool) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't open directory: %s\n", source->location);
			goto done;
		}

		switch_yield(1000000);

		while (RUNNING && !source->stopped) {
			switch_size_t olen;
			uint8_t abuf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 };

			if (fd > -1) {
				char *p;
				if (switch_fd_read_line(fd, path_buf, sizeof(path_buf))) {
					if ((p = strchr(path_buf, '\r')) || (p = strchr(path_buf, '\n'))) {
						*p = '\0';
					}
				} else {
					close(fd);
					fd = -1;
					continue;
				}
			} else {
				if (!(fname = switch_dir_next_file(source->dir_handle, file_buf, sizeof(file_buf)))) {
					break;
				}

				switch_snprintf(path_buf, sizeof(path_buf), "%s%s%s", source->location, SWITCH_PATH_SEPARATOR, fname);

				if (switch_stristr(".loc", path_buf)) {
					if ((fd = open(path_buf, O_RDONLY)) < 0) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", fname);
						switch_yield(1000000);
					}
					continue;
				}
			}

			if (skip > 0) {
				skip--;
				continue;
			}

			fname = path_buf;
			fh.prebuf = source->prebuf;
			fh.pre_buffer_datalen = source->prebuf;

			if (switch_core_file_open(&fh,
									  (char *) fname,
									  source->channels, source->rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", fname);
				switch_yield(1000000);
				continue;
			}

			if (switch_core_timer_init(&timer, source->timer_name, source->interval, (int)source->samples, temp_pool) != SWITCH_STATUS_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Can't start timer.\n");
				switch_dir_close(source->dir_handle);
				source->dir_handle = NULL;
				goto done;
			}

			while (RUNNING && !source->stopped) {
				int is_open;
				switch_file_handle_t *use_fh = &fh;

				switch_core_timer_next(&timer);
				olen = source->samples;

				if (source->chime_total) {

					if (source->chime_counter > 0) {
						source->chime_counter -= (int32_t)source->samples;
					}

					if (!switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN) && source->chime_counter <= 0) {
						char *val;

						val = source->chime_list[source->chime_cur++];

						if (source->chime_cur >= source->chime_total) {
							source->chime_cur = 0;
						}

						if (switch_core_file_open(&source->chime_fh,
												  (char *) val,
												  source->channels,
												  source->rate, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s\n", val);
						}
					}

					if (switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN)) {
						use_fh = &source->chime_fh;
					}
				}

			  retry:

				is_open = switch_test_flag(use_fh, SWITCH_FILE_OPEN);

				if (source->hup) {
					source->hup = 0;
					if (is_open) {
						is_open = 0;

						switch_core_file_close(use_fh);
						if (use_fh == &source->chime_fh) {
							source->chime_counter = source->rate * source->chime_freq;
							use_fh = &fh;
							goto retry;
							//switch_core_file_close(&fh);
						}
					}
				}



				if (is_open) {
					if (switch_core_file_read(use_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) {
						switch_core_file_close(use_fh);
						if (use_fh == &source->chime_fh) {
							source->chime_counter = source->rate * source->chime_freq;
						}
						is_open = 0;
					} else {
						if (use_fh == &source->chime_fh && source->chime_max) {
							source->chime_max_counter += (int32_t)source->samples;
							if (source->chime_max_counter >= source->chime_max) {
								source->chime_max_counter = 0;
								switch_core_file_close(use_fh);
								source->chime_counter = source->rate * source->chime_freq;
								use_fh = &fh;
								goto retry;
							}
						}

						switch_buffer_write(audio_buffer, abuf, olen * 2);
					}
				}

				used = switch_buffer_inuse(audio_buffer);

				if (!used && !is_open) {
					break;
				}

				if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2)) {
					used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2);
					if (source->total) {
						uint32_t bused = 0;
						switch_mutex_lock(source->mutex);
						for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
							if (switch_test_flag(cp->handle, SWITCH_FILE_CALLBACK)) {
								continue;
							}
							switch_mutex_lock(cp->audio_mutex);
							bused = (uint32_t)switch_buffer_inuse(cp->audio_buffer);
							if (bused > source->samples * 768) {
								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Flushing Stream Handle Buffer [%s() %s:%d] size: %u samples: %ld\n", 
												  cp->func, cp->file, cp->line, bused, (long)source->samples);
								switch_buffer_zero(cp->audio_buffer);
							} else {
								switch_buffer_write(cp->audio_buffer, dist_buf, used);
							}
							switch_mutex_unlock(cp->audio_mutex);
						}
						switch_mutex_unlock(source->mutex);
					}
				}
			}

			switch_core_timer_destroy(&timer);
			if (RUNNING && source->shuffle) {
				skip = do_rand();
			}
		}

		switch_dir_close(source->dir_handle);
		source->dir_handle = NULL;

		if (source->full_reload) {
			if (source->rwlock && switch_thread_rwlock_trywrlock(source->rwlock) != SWITCH_STATUS_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Cannot stop local_stream://%s because it is in use.\n",source->name);
				if (source->part_reload) {
					switch_xml_t cfg, xml, directory, param;
					if (!(xml = switch_xml_open_cfg(global_cf, &cfg, NULL))) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", global_cf);
					}
					if ((directory = switch_xml_find_child(cfg, "directory", "name", source->name))) {
						for (param = switch_xml_child(directory, "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, "shuffle")) {
								source->shuffle = switch_true(val);
							} else if (!strcasecmp(var, "chime-freq")) {
								int tmp = atoi(val);
								if (tmp > 1) {
									source->chime_freq = tmp;
								}
							} else if (!strcasecmp(var, "chime-max")) {
								int tmp = atoi(val);
								if (tmp > 1) {
									source->chime_max = tmp;
								}
							} else if (!strcasecmp(var, "chime-list")) {
								char *list_dup = switch_core_strdup(source->pool, val);
								source->chime_total =
									switch_separate_string(list_dup, ',', source->chime_list, (sizeof(source->chime_list) / sizeof(source->chime_list[0])));
							} else if (!strcasecmp(var, "interval")) {
								int tmp = atoi(val);
								if (SWITCH_ACCEPTABLE_INTERVAL(tmp)) {
									source->interval = tmp;
								} else {
									switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
													  "Interval must be multiple of 10 and less than %d, Using default of 20\n", SWITCH_MAX_INTERVAL);
								}
							}
							if (source->chime_max) {
								source->chime_max *= source->rate;
							}
							if (source->chime_total) {
								source->chime_counter = source->rate * source->chime_freq;
							}
						}
					}
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s partially reloaded.\n",source->name);
					source->part_reload = 0;
				}
			} else {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "local_stream://%s fully reloaded.\n",source->name);
				launch_streams(source->name);
				goto done;
			}
		}
	}

  done:

	if (switch_test_flag((&fh), SWITCH_FILE_OPEN)) {
		switch_core_file_close(&fh);
	}

	if (switch_test_flag((&source->chime_fh), SWITCH_FILE_OPEN)) {
		switch_core_file_close(&source->chime_fh);
	}

	source->ready = 0;
	switch_mutex_lock(globals.mutex);
	switch_core_hash_delete(globals.source_hash, source->name);
	switch_mutex_unlock(globals.mutex);

	switch_thread_rwlock_wrlock(source->rwlock);
	switch_thread_rwlock_unlock(source->rwlock);

	switch_buffer_destroy(&audio_buffer);

	if (fd > -1) {
		close(fd);
	}

	if (temp_pool) {
		switch_core_destroy_memory_pool(&temp_pool);
	}

	switch_core_destroy_memory_pool(&source->pool);

	switch_mutex_lock(globals.mutex);
	THREADS--;
	switch_mutex_unlock(globals.mutex);

	return NULL;
}
static cid_data_t *do_whitepages_lookup(switch_memory_pool_t *pool, switch_event_t *event, const char *num)
{
	char *xml_s = NULL;
	char *query = NULL;
	char *name = NULL;
	char *city = NULL;
	char *state = NULL;
	char *area = NULL;
	switch_xml_t xml = NULL;
	switch_xml_t node = NULL;
	cid_data_t *cid = NULL;

	/* NANPA check */
	if (strlen(num) == 11 && num[0] == '1') {
		num++;					/* skip past leading 1 */
	} else {
		goto done;
	}

	switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "whitepages-cid", num);
	switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "whitepages-api-key", globals.whitepages_apikey);

	query = switch_event_expand_headers(event, "http://api.whitepages.com/reverse_phone/1.0/?phone=${whitepages-cid};api_key=${whitepages-api-key}");
	do_lookup_url(pool, event, &xml_s, query, NULL, NULL, 0);
	
	if (zstr(xml_s)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No XML returned for number %s\n", num);
		goto done;
	}
	
	xml = switch_xml_parse_str_dup(xml_s);

	if (!xml) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to parse XML: %s\n", xml_s);
		goto done;
	}

	/* try for bizname first */
	node = switch_xml_get(xml, "wp:listings", 0, "wp:listing", 0, "wp:business", 0, "wp:businessname", -1);
	if (node) {
		name = switch_core_strdup(pool, switch_xml_txt(node));
		goto area;
	}

	node = switch_xml_get(xml, "wp:listings", 0, "wp:listing", 0, "wp:displayname", -1);
	if (node) {
		name = switch_core_strdup(pool, switch_xml_txt(node));
	}

  area:

	node = switch_xml_get(xml, "wp:listings", 0, "wp:listing", 0, "wp:address", 0, "wp:city", -1);
	if (node) {
		city = switch_xml_txt(node);
	}

	node = switch_xml_get(xml, "wp:listings", 0, "wp:listing", 0, "wp:address", 0, "wp:state", -1);
	if (node) {
		state = switch_xml_txt(node);
	}

	if (city || state) {
		area = switch_core_sprintf(pool, "%s %s", city ? city : "", state ? state : "");
	}

  done:

	if (query) {
		switch_safe_free(query);
	}
	if (xml) {
		switch_xml_free(xml);
	}
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "whitepages XML: %s\n", xml_s);
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "whitepages name: %s, area: %s\n", name ? name : "(null)", area ? area : "(null)");

	cid = switch_core_alloc(pool, sizeof(cid_data_t));
	switch_assert(cid);

	cid->name = name;
	cid->area = area;
	cid->src = "whitepages";
	return cid;
}
static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
													switch_caller_profile_t *outbound_profile,
													switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
													switch_call_cause_t *cancel_cause)
{
	char name[128];
	switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;

	if ((*new_session = switch_core_session_request(modem_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool)) != 0) {
		private_t *tech_pvt;
		switch_channel_t *channel;
		switch_caller_profile_t *caller_profile;
		char *dest = switch_core_session_strdup(*new_session, outbound_profile->destination_number);
		char *modem_id_string = NULL;
		char *number = NULL;
		int modem_id = 0;
		modem_t *modem = NULL;

		if ((modem_id_string = dest)) {
			if ((number = strchr(modem_id_string, '/'))) {
				*number++ = '\0';
			}
		}

		if (zstr(modem_id_string) || zstr(number)) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_ERROR, "Invalid dial string.\n");
			cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT; goto fail;
		}

		if (!strcasecmp(modem_id_string, "a")) {
			modem_id = -1;
		} else {
			modem_id = atoi(modem_id_string);
		}

		if (!(modem = acquire_modem(modem_id))) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_ERROR, "Cannot find a modem.\n");
			cause = SWITCH_CAUSE_USER_BUSY; goto fail;
		}
		
		switch_core_session_add_stream(*new_session, NULL);

		if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) {
			channel = switch_core_session_get_channel(*new_session);
			switch_snprintf(name, sizeof(name), "modem/%d/%s", modem->slot, number);
			switch_channel_set_name(channel, name);

			if (tech_init(tech_pvt, *new_session) != SWITCH_STATUS_SUCCESS) {
				cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; goto fail;
			}

			switch_set_string(modem->digits, number);
			tech_attach(tech_pvt, modem);
		} else {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
			switch_core_session_destroy(new_session);
			cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; goto fail;
		}

		if (outbound_profile) {
			caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
			caller_profile->source = switch_core_strdup(caller_profile->pool, "mod_spandsp");
			switch_channel_set_caller_profile(channel, caller_profile);
			tech_pvt->caller_profile = caller_profile;
		} else {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_ERROR, "Doh! no caller profile\n");
			cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; goto fail;
		}

		switch_channel_set_state(channel, CS_INIT);

		return SWITCH_CAUSE_SUCCESS;

	fail:

		if (new_session) {
			switch_core_session_destroy(new_session);
		}

		if (modem) {
			modem_set_state(modem, MODEM_STATE_ONHOOK);
		}
	}

	return cause;
}