示例#1
0
static switch_status_t spy_on_hangup(switch_core_session_t *session)
{
	switch_channel_t *channel = switch_core_session_get_channel(session);
	const char *data = switch_channel_get_private(channel, "_userspy_");
	const char *uuid = switch_core_session_get_uuid(session);
	spy_t *spy = NULL, *p = NULL, *prev = NULL;

	switch_thread_rwlock_wrlock(globals.spy_hash_lock);

	spy = switch_core_hash_find(globals.spy_hash, data);
	for (p = spy; p; p = p->next) {
		if (p->uuid == uuid) {
			if (prev) {
				prev->next = p->next;
			} else {
				spy = p->next;
			}
			globals.spy_count--;
			break;
		}
		prev = p;
	}

	switch_core_hash_insert(globals.spy_hash, data, spy);

	switch_thread_rwlock_unlock(globals.spy_hash_lock);
	
	return SWITCH_STATUS_SUCCESS;
}
示例#2
0
SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession(char *nuuid, CoreSession *a_leg)
{
	switch_channel_t *other_channel = NULL;

	init_vars();

	if (a_leg && a_leg->session) {
		other_channel = switch_core_session_get_channel(a_leg->session);
	}

	if (!strchr(nuuid, '/') && (session = switch_core_session_force_locate(nuuid))) {
		uuid = strdup(nuuid);
		channel = switch_core_session_get_channel(session);
		allocated = 1;
    } else {
		cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
		if (switch_ivr_originate(a_leg ? a_leg->session : NULL, &session, &cause, nuuid, 60, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL) 
			== SWITCH_STATUS_SUCCESS) {
			channel = switch_core_session_get_channel(session);
			allocated = 1;
			switch_set_flag(this, S_HUP);
			uuid = strdup(switch_core_session_get_uuid(session));
			switch_channel_set_state(switch_core_session_get_channel(session), CS_SOFT_EXECUTE);
			switch_channel_wait_for_state(channel, other_channel, CS_SOFT_EXECUTE);
		}
	}
}
WSChannel* WSClientParser::CreateChannel(switch_core_session_t *session) {
	WSChannel *wsChannel = NULL;

	// 创建channel
//	switch_memory_pool_t *pool = switch_core_session_get_pool(session);
	wsChannel = (WSChannel *)switch_core_alloc(mpPool, sizeof(WSChannel));
	wsChannel->session = session;
	wsChannel->parser = this;
	wsChannel->uuid_str = switch_core_strdup(mpPool, switch_core_session_get_uuid(session));

	switch_log_printf(
			SWITCH_CHANNEL_UUID_LOG(this->GetUUID()),
			SWITCH_LOG_INFO,
			"WSClientParser::CreateChannel( "
			"this : %p, "
			"wsChannel : %p "
			") \n",
			this,
			wsChannel
			);

	if( InitChannel(wsChannel) ) {
		mpChannel = wsChannel;
	} else {
		DestroyChannel(wsChannel);
	}

	return wsChannel;
}
void conference_event_adv_la(conference_obj_t *conference, conference_member_t *member, switch_bool_t join)
{

	//if (switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY) {
	switch_channel_set_flag(member->channel, CF_VIDEO_REFRESH_REQ);
	switch_core_media_gen_key_frame(member->session);
	//}

	if (conference && conference->la && member->session &&
		!switch_channel_test_flag(member->channel, CF_VIDEO_ONLY)) {
		cJSON *msg, *data;
		const char *uuid = switch_core_session_get_uuid(member->session);
		const char *cookie = switch_channel_get_variable(member->channel, "event_channel_cookie");
		const char *event_channel = cookie ? cookie : uuid;
		switch_event_t *variables;
		switch_event_header_t *hp;

		msg = cJSON_CreateObject();
		data = json_add_child_obj(msg, "pvtData", NULL);

		cJSON_AddItemToObject(msg, "eventChannel", cJSON_CreateString(event_channel));
		cJSON_AddItemToObject(msg, "eventType", cJSON_CreateString("channelPvtData"));

		cJSON_AddItemToObject(data, "action", cJSON_CreateString(join ? "conference-liveArray-join" : "conference-liveArray-part"));
		cJSON_AddItemToObject(data, "laChannel", cJSON_CreateString(conference->la_event_channel));
		cJSON_AddItemToObject(data, "laName", cJSON_CreateString(conference->la_name));
		cJSON_AddItemToObject(data, "role", cJSON_CreateString(conference_utils_member_test_flag(member, MFLAG_MOD) ? "moderator" : "participant"));
		cJSON_AddItemToObject(data, "chatID", cJSON_CreateString(conference->chat_id));
		cJSON_AddItemToObject(data, "canvasCount", cJSON_CreateNumber(conference->canvas_count));

		if (conference_utils_member_test_flag(member, MFLAG_SECOND_SCREEN)) {
			cJSON_AddItemToObject(data, "secondScreen", cJSON_CreateTrue());
		}

		if (conference_utils_member_test_flag(member, MFLAG_MOD)) {
			cJSON_AddItemToObject(data, "modChannel", cJSON_CreateString(conference->mod_event_channel));
		}

		cJSON_AddItemToObject(data, "chatChannel", cJSON_CreateString(conference->chat_event_channel));

		switch_core_get_variables(&variables);
		for (hp = variables->headers; hp; hp = hp->next) {
			if (!strncasecmp(hp->name, "conference_verto_", 17)) {
				char *var = hp->name + 17;
				if (var) {
					cJSON_AddItemToObject(data, var, cJSON_CreateString(hp->value));
				}
			}
		}
		switch_event_destroy(&variables);

		switch_event_channel_broadcast(event_channel, &msg, "mod_conference", conference_globals.event_channel_id);

		if (cookie) {
			switch_event_channel_permission_modify(cookie, conference->la_event_channel, join);
			switch_event_channel_permission_modify(cookie, conference->mod_event_channel, join);
			switch_event_channel_permission_modify(cookie, conference->chat_event_channel, join);
		}
	}
}
/**
 * Start execution of call output component
 * @param component to start
 * @param session the session to output to
 * @param output the output request
 * @param iq the original request
 */
static iks *start_call_output(struct rayo_component *component, switch_core_session_t *session, iks *output, iks *iq)
{
	switch_stream_handle_t stream = { 0 };

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

	/* build playback command */
	SWITCH_STANDARD_STREAM(stream);
	stream.write_function(&stream, "{id=%s,session=%s,pause=%s",
		RAYO_JID(component), switch_core_session_get_uuid(session),
		OUTPUT_COMPONENT(component)->start_paused ? "true" : "false");
	if (OUTPUT_COMPONENT(component)->max_time > 0) {
		stream.write_function(&stream, ",timeout=%i", OUTPUT_COMPONENT(component)->max_time * 1000);
	}
	stream.write_function(&stream, "}fileman://rayo://%s", RAYO_JID(component));

	if (switch_ivr_displace_session(session, stream.data, 0, "m") == SWITCH_STATUS_SUCCESS) {
		RAYO_UNLOCK(component);
	} else {
		if (OUTPUT_COMPONENT(component)->document) {
			iks_delete(OUTPUT_COMPONENT(component)->document);
		}
		if (switch_channel_get_state(switch_core_session_get_channel(session)) >= CS_HANGUP) {
			rayo_component_send_complete(component, COMPONENT_COMPLETE_HANGUP);
			component = NULL;
		} else {
			rayo_component_send_complete(component, COMPONENT_COMPLETE_ERROR);
			component = NULL;
		}
	}
	switch_safe_free(stream.data);
	return NULL;
}
示例#6
0
static valet_token_t *next_id(switch_core_session_t *session, valet_lot_t *lot, int min, int max, int in)
{
	int i, r = 0;
	char buf[256] = "";
	valet_token_t *token;

	if (!min) {
		min = 1;
	}

	switch_mutex_lock(globals.mutex);

	if (!in) {
		int longest = find_longest(lot, min, max);
		if (longest > 0) {
			switch_snprintf(buf, sizeof(buf), "%d", longest);
			switch_mutex_lock(lot->mutex);
			token = (valet_token_t *) switch_core_hash_find(lot->hash, buf);
			switch_mutex_unlock(lot->mutex);
			if (token) {
				goto end;
			}
		}
	}

	for (i = min; (i < max || max == 0); i++) {
		switch_snprintf(buf, sizeof(buf), "%d", i);
		switch_mutex_lock(lot->mutex);
		token = (valet_token_t *) switch_core_hash_find(lot->hash, buf);
		switch_mutex_unlock(lot->mutex);

		if ((!in && token && !token->timeout)) {
			goto end;
		}

		if (in && !token) {
			r = i;
			break;
		}
	}

	token = NULL;

	if (r) {
		switch_snprintf(buf, sizeof(buf), "%d", r);
		switch_zmalloc(token, sizeof(*token));
		switch_set_string(token->uuid, switch_core_session_get_uuid(session));
		switch_set_string(token->ext, buf);
		token->start_time = switch_epoch_time_now(NULL);
		switch_mutex_lock(lot->mutex);
		switch_core_hash_insert(lot->hash, buf, token);
		switch_mutex_unlock(lot->mutex);
	}

 end:

	switch_mutex_unlock(globals.mutex);

	return token;
}
static void tech_attach(private_t *tech_pvt, modem_t *modem)
{
	tech_pvt->modem = modem;
	switch_set_string(modem->uuid_str, switch_core_session_get_uuid(tech_pvt->session));
	switch_channel_set_variable_printf(tech_pvt->channel, "modem_slot", "%d", modem->slot);
	switch_channel_set_variable(tech_pvt->channel, "modem_devlink", modem->devlink);
	switch_channel_set_variable(tech_pvt->channel, "modem_digits", modem->digits);
	switch_channel_export_variable(tech_pvt->channel, "rtp_autoflush_during_bridge", "false", SWITCH_EXPORT_VARS_VARIABLE);
}
/**
 * Process a buffer of audio data for call progress tones
 *
 * @param bug the session's media bug 
 * @param user_data the detector
 * @param type the type of data available from the bug
 * @return SWITCH_TRUE
 */
static switch_bool_t callprogress_detector_process_buffer(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
	uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE];
	switch_frame_t frame = { 0 };
	tone_detector_t *detector = (tone_detector_t *)user_data;
	switch_core_session_t *session = switch_core_media_bug_get_session(bug);
	switch_channel_t *channel = switch_core_session_get_channel(session);

	frame.data = data;
	frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;

	switch(type) {
	case SWITCH_ABC_TYPE_INIT:
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) initializing tone detector\n", switch_channel_get_name(channel));
		tone_detector_init(detector);
		break;
	case SWITCH_ABC_TYPE_READ:
	{
		const char *detected_tone = NULL;
		if (!detector->spandsp_detector) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) detector is destroyed\n", switch_channel_get_name(channel));
			return SWITCH_FALSE;
		}
		if (switch_core_media_bug_read(bug, &frame, SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) error reading frame\n", switch_channel_get_name(channel));
			return SWITCH_FALSE;
		}
		tone_detector_process_buffer(detector, frame.data, frame.samples, &detected_tone);
		if (detected_tone) {
			switch_event_t *event = NULL;
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) DETECTED TONE: %s\n", switch_channel_get_name(channel), detected_tone);
			if (switch_event_create(&event, SWITCH_EVENT_DETECTED_TONE) == SWITCH_STATUS_SUCCESS) {
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detected-Tone", detected_tone);
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(session));
				switch_event_fire(&event);
			}
		}
		break;
	}
	case SWITCH_ABC_TYPE_WRITE:
		break;
	case SWITCH_ABC_TYPE_WRITE_REPLACE:
		break;
	case SWITCH_ABC_TYPE_READ_REPLACE:
		break;
	case SWITCH_ABC_TYPE_READ_PING:
		break;
	case SWITCH_ABC_TYPE_CLOSE:
		if (detector->spandsp_detector) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "(%s) destroying tone detector\n", switch_channel_get_name(channel));
			tone_detector_destroy(detector);
		}
		break;
	}
	return SWITCH_TRUE;
}
static void switch_core_standard_on_reset(switch_core_session_t *session)
{
	switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session));

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard RESET\n", switch_channel_get_name(session->channel));

	if (switch_channel_test_flag(session->channel, CF_RECOVERING_BRIDGE)) {
		switch_core_session_t *other_session = NULL;
		const char *uuid = switch_core_session_get_uuid(session);

		if (switch_channel_test_flag(session->channel, CF_BRIDGE_ORIGINATOR)) {
			const char *other_uuid = switch_channel_get_partner_uuid(session->channel);
			int x = 0;

			if (other_uuid) {
				for (x = 0; other_session == NULL && x < 20; x++) {
					if (!switch_channel_up(session->channel)) {
						break;
					}
					other_session = switch_core_session_locate(other_uuid);
					switch_yield(100000);
				}
			}

			if (other_session) {
				switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
				switch_channel_clear_flag(session->channel, CF_BRIDGE_ORIGINATOR);
				switch_channel_wait_for_state_timeout(other_channel, CS_RESET, 5000);
				switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 2000, NULL);

				if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) && switch_channel_test_flag(other_channel, CF_PROXY_MODE)) {
					switch_ivr_signal_bridge(session, other_session);
				} else {
					switch_ivr_uuid_bridge(uuid, other_uuid);
				}
				switch_core_session_rwunlock(other_session);
			}
		}

		switch_channel_clear_flag(session->channel, CF_RECOVERING_BRIDGE);
	}

}
示例#10
0
SWITCH_DECLARE_CONSTRUCTOR CoreSession::CoreSession(switch_core_session_t *new_session)
{
	init_vars();

	if (new_session) {
		session = new_session;
		channel = switch_core_session_get_channel(session);
		allocated = 1;
		switch_core_session_read_lock_hangup(session);
		uuid = strdup(switch_core_session_get_uuid(session));
	}
}
示例#11
0
void eventpipe_events_handler(switch_event_t *event)
{
	struct eventpipe_call *current = NULL;
	const char *uuid1 = "";
	const char *uuid2 = "";

        switch_assert(event != NULL);

	if ((event->event_id != SWITCH_EVENT_CUSTOM) && (event->event_id != SWITCH_EVENT_DTMF)) {
		return;
	}

	uuid1 = switch_event_get_header(event, "unique-id");
	if (zstr(uuid1)) {
		return;
	}
	switch_mutex_lock(globals.eventpipe_call_list_mutex);

	if (!head) {
		goto eventpipe_events_handler_done;
	}
	if (!head->session) {
		goto eventpipe_events_handler_done;
	}
	current = head;
	while (current) {
		if (current->session) {
			uuid2 = "";
			uuid2 = switch_core_session_get_uuid(current->session);	

			/* check if event unique-id is matching a call uuid in eventpipe */
			if ((uuid2) && (!zstr(uuid2) && (!strcmp(uuid1, uuid2)))) {
				/* conference event case */
				if (event->event_id == SWITCH_EVENT_CUSTOM) {
					const char *event_subclass = switch_str_nil(switch_event_get_header(event, "event-subclass"));
					if (!strcmp(event_subclass, PLIVO_EVENT_CONFERENCE)) {
						eventpipe_events_on_conference(current->session, event);
					}
				/* dtmf event case */
				} else if (event->event_id == SWITCH_EVENT_DTMF) {
					eventpipe_events_on_dtmf(current->session, event);
				}
				goto eventpipe_events_handler_done;
			}
		}
		current = current->next;
	}
eventpipe_events_handler_done:
	switch_mutex_unlock(globals.eventpipe_call_list_mutex);
}
示例#12
0
SWITCH_DECLARE(int) CoreSession::originate(CoreSession *a_leg_session, char *dest, int timeout, switch_state_handler_table_t *handlers)
{

	switch_core_session_t *aleg_core_session = NULL;

	this_check(0);

	cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;

	if (a_leg_session != NULL) {
		aleg_core_session = a_leg_session->session;
	}

	// this session has no valid switch_core_session_t at this point, and therefore
	// no valid channel.  since the threadstate is stored in the channel, and there 
	// is none, if we try to call begin_alllow_threads it will fail miserably.
	// use the 'a leg session' to do the thread swapping stuff.
    if (a_leg_session) a_leg_session->begin_allow_threads();

	if (switch_ivr_originate(aleg_core_session, 
							 &session, 
							 &cause, 
							 dest, 
							 timeout,
							 handlers, 
							 NULL, 
							 NULL, 
							 NULL,
							 NULL,
							 SOF_NONE,
							 NULL) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error Creating Outgoing Channel! [%s]\n", dest);
		goto failed;

	}

    if (a_leg_session) a_leg_session->end_allow_threads();
	channel = switch_core_session_get_channel(session);
	allocated = 1;
	switch_safe_free(uuid);
	uuid = strdup(switch_core_session_get_uuid(session));
	switch_channel_set_state(switch_core_session_get_channel(session), CS_SOFT_EXECUTE);

	return SWITCH_STATUS_SUCCESS;

 failed:
    if (a_leg_session) a_leg_session->end_allow_threads();
	return SWITCH_STATUS_FALSE;
}
示例#13
0
static void perl_function(switch_core_session_t *session, char *data)
{
	char *uuid = switch_core_session_get_uuid(session);
	PerlInterpreter *my_perl = clone_perl();
	char code[1024] = "";

	perl_parse(my_perl, xs_init, 3, embedding, NULL);

	switch_snprintf(code, sizeof(code),
					"use lib '%s/perl';\n"
					"use freeswitch;\n"
					"$SWITCH_ENV{UUID} = \"%s\";\n" "$session = new freeswitch::Session(\"%s\")", SWITCH_GLOBAL_dirs.base_dir, uuid, uuid);

	perl_parse_and_execute(my_perl, data, code);
	destroy_perl(&my_perl);
}
示例#14
0
/**
 * Process a buffer of audio data for call progress tones
 *
 * @param bug the session's media bug 
 * @param user_data the detector
 * @param type the type of data available from the bug
 * @return SWITCH_TRUE
 */
static switch_bool_t callprogress_detector_process_buffer(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
	tone_detector_t *detector = (tone_detector_t *)user_data;
	switch_core_session_t *session = detector->session;

	switch(type) {
	case SWITCH_ABC_TYPE_INIT:
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "initializing tone detector\n");
		tone_detector_init(detector);
		break;
	case SWITCH_ABC_TYPE_READ_REPLACE:
	{
		switch_frame_t *frame;
		const char *detected_tone = NULL;
		if (!detector->spandsp_detector) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "detector is destroyed\n");
			return SWITCH_FALSE;
		}
		if (!(frame = switch_core_media_bug_get_read_replace_frame(bug))) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "error reading frame\n");
			return SWITCH_FALSE;
		}
		tone_detector_process_buffer(detector, frame->data, frame->samples, &detected_tone);
		if (detected_tone) {
			switch_event_t *event = NULL;
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "DETECTED TONE: %s\n", detected_tone);
			if (switch_event_create(&event, SWITCH_EVENT_DETECTED_TONE) == SWITCH_STATUS_SUCCESS) {
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detected-Tone", detected_tone);
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(session));
				switch_event_fire(&event);
			}
		}
		break;
	}
	case SWITCH_ABC_TYPE_CLOSE:
		if (detector->spandsp_detector) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "destroying tone detector\n");
			tone_detector_destroy(detector);
		}
		break;
	default:
		break;
	}
	return SWITCH_TRUE;
}
示例#15
0
void eventpipe_events_on_conference(switch_core_session_t *session, switch_event_t *event) {
	char args[8192];
	char record_args[8192];
	const char *action = switch_str_nil(switch_event_get_header(event, "action"));
	const char *member_id = switch_str_nil(switch_event_get_header(event, "member-id"));
	const char *conf_room = switch_str_nil(switch_event_get_header(event, "conference-name"));
	const char *calluuid = switch_core_session_get_uuid(session);
	switch_channel_t *channel = switch_core_session_get_channel(session);
	if (!channel) {
		return;
	}

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 
				"Event-Name: %s, Event-Subclass: %s, Conference-Name: %s, Action: %s, Member-ID: %s, Unique-ID: %s\n", 
				switch_str_nil(switch_event_get_header(event, "event-name")), 
				switch_str_nil(switch_event_get_header(event, "event-subclass")), 
				conf_room, action, member_id, calluuid);

	if (!strcmp(action, "add-member")) {
		const char *enter_sound = switch_str_nil(switch_channel_get_variable(channel, "eventpipe_conference_enter_sound"));
		const char *record_file = switch_str_nil(switch_channel_get_variable(channel, "eventpipe_conference_record_file"));
		switch_channel_set_variable(channel, "eventpipe_conference_member_id", member_id);
		switch_channel_set_variable(channel, "eventpipe_conference_room", conf_room);
		if (!zstr(enter_sound)) {
			switch_snprintf(args, sizeof(args), "%s play %s async",
					conf_room, enter_sound);
			eventpipe_execute_api(session, "conference", args);
		}
		if (!zstr(record_file)) {
			switch_snprintf(record_args, sizeof(record_args), "%s record %s",
					conf_room, record_file);
			eventpipe_execute_api(session, "conference", record_args);
		}
	} else if (!strcmp(action, "del-member")) {
		const char *exit_sound = switch_str_nil(switch_channel_get_variable(channel, "eventpipe_conference_exit_sound"));
		switch_channel_set_variable(channel, "eventpipe_conference_member_id", "");
		switch_channel_set_variable(channel, "eventpipe_conference_room", "");
		switch_channel_set_variable(channel, "eventpipe_conference_record_file", "");
		if (!zstr(exit_sound)) {
			switch_snprintf(args, sizeof(args), "conference %s play %s async",
					conf_room, exit_sound);
			eventpipe_execute_api(session, "conference", args);
		}
	}
}
示例#16
0
char *sofia_media_get_multipart(switch_core_session_t *session, const char *prefix, const char *sdp, char **mp_type)
{
	char *extra_headers = NULL;
	switch_stream_handle_t stream = { 0 };
	switch_event_header_t *hi = NULL;
	int x = 0;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	const char *boundary = switch_core_session_get_uuid(session);

	SWITCH_STANDARD_STREAM(stream);
	if ((hi = switch_channel_variable_first(channel))) {
		for (; hi; hi = hi->next) {
			const char *name = (char *) hi->name;
			char *value = (char *) hi->value;

			if (!strncasecmp(name, prefix, strlen(prefix))) {
				const char *hname = name + strlen(prefix);
				if (*value == '~') {
					stream.write_function(&stream, "--%s\nContent-Type: %s\nContent-Length: %d\n%s\n", boundary, hname, strlen(value), value + 1);
				} else {
					stream.write_function(&stream, "--%s\nContent-Type: %s\nContent-Length: %d\n\n%s\n", boundary, hname, strlen(value) + 1, value);
				}
				x++;
			}
		}
		switch_channel_variable_last(channel);
	}

	if (x) {
		*mp_type = switch_core_session_sprintf(session, "multipart/mixed; boundary=%s", boundary);
		if (sdp) {
			stream.write_function(&stream, "--%s\nContent-Type: application/sdp\nContent-Length: %d\n\n%s\n", boundary, strlen(sdp) + 1, sdp);
		}
		stream.write_function(&stream, "--%s--\n", boundary);
	}

	if (!zstr((char *) stream.data)) {
		extra_headers = stream.data;
	} else {
		switch_safe_free(stream.data);
	}

	return extra_headers;
}
示例#17
0
SWITCH_DECLARE(switch_status_t) switch_core_session_perform_kill_channel(switch_core_session_t *session,
																		 const char *file, const char *func, int line, switch_signal_t sig)
{
	switch_io_event_hook_kill_channel_t *ptr;
	switch_status_t status = SWITCH_STATUS_FALSE;

	switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_core_session_get_uuid(session), SWITCH_LOG_DEBUG, "Send signal %s [%s]\n",
					  switch_channel_get_name(session->channel), SIG_NAMES[sig]);

	if (session->endpoint_interface->io_routines->kill_channel) {
		if ((status = session->endpoint_interface->io_routines->kill_channel(session, sig)) == SWITCH_STATUS_SUCCESS) {
			for (ptr = session->event_hooks.kill_channel; ptr; ptr = ptr->next) {
				if ((status = ptr->kill_channel(session, sig)) != SWITCH_STATUS_SUCCESS) {
					break;
				}
			}
		}
	}
	return status;
}
示例#18
0
static void put_text_msg(void *user_data, const uint8_t *msg, int len)
{
	switch_tdd_t *pvt = (switch_tdd_t *) user_data;
	switch_event_t *event, *clone;
	switch_channel_t *channel = switch_core_session_get_channel(pvt->session);
	switch_core_session_t *other_session;


	switch_channel_add_variable_var_check(channel, "tdd_messages", (char *)msg, SWITCH_FALSE, SWITCH_STACK_PUSH);


	if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TDD_RECV_MESSAGE) == SWITCH_STATUS_SUCCESS) {

		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", "mod_spandsp");
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "tdd");
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "TDD MESSAGE");
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "TDD-Data", (char *)msg);
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(pvt->session));
		switch_event_add_body(event, "%s\n\n", (char *)msg);

		if (switch_core_session_get_partner(pvt->session, &other_session) == SWITCH_STATUS_SUCCESS) {

			if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
				switch_core_session_receive_event(other_session, &clone);
			}

			if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
				switch_core_session_queue_event(other_session, &clone);
			}

			switch_core_session_rwunlock(other_session);
		}

		switch_event_fire(&event);


	}

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s got TDD Message [%s]\n", switch_channel_get_name(channel), (char *)msg);

}
示例#19
0
static void transfer_call(switch_core_session_t *session, char *destination)
{
	char *argv[4] = { 0 };
	const char *uuid;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	char *mydup;

	if (!destination) {
		return;
	}

	mydup = strdup(destination);
	switch_assert(mydup);
	switch_separate_string(mydup, ' ', argv, (sizeof(argv) / sizeof(argv[0])));

	/* Find the uuid of our B leg. If it exists, transfer it first */
	if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
		switch_core_session_t *b_session;

		/* Get info on the B leg */
		if ((b_session = switch_core_session_locate(uuid))) {
			/* Make sure we are in the media path on B leg */
			switch_ivr_media(uuid, SMF_REBRIDGE);

			/* Transfer the B leg */
			switch_ivr_session_transfer(b_session, argv[0], argv[1], argv[2]);
			switch_core_session_rwunlock(b_session);
		}
	}

	/* Make sure we are in the media path on A leg */
	uuid = switch_core_session_get_uuid(session);
	switch_ivr_media(uuid, SMF_REBRIDGE);

	/* Transfer the A leg */
	switch_ivr_session_transfer(session, argv[0], argv[1], argv[2]);
	free(mydup);
}
示例#20
0
static void switch_core_standard_on_execute(switch_core_session_t *session)
{
	switch_caller_extension_t *extension;
	const char *uuid;

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard EXECUTE\n", switch_channel_get_name(session->channel));

	switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session));

	if (switch_channel_get_variable(session->channel, "recovered") && !switch_channel_test_flag(session->channel, CF_RECOVERED)) {
		switch_channel_set_flag(session->channel, CF_RECOVERED);
	}

  top:
	switch_channel_clear_flag(session->channel, CF_RESET);
	
	if ((extension = switch_channel_get_caller_extension(session->channel)) == 0) {
		switch_channel_hangup(session->channel, SWITCH_CAUSE_NORMAL_CLEARING);
		return;
	}

	while (switch_channel_get_state(session->channel) == CS_EXECUTE && extension->current_application) {
		switch_caller_application_t *current_application = extension->current_application;

		extension->current_application = extension->current_application->next;

		if (switch_core_session_execute_application(session,
													current_application->application_name,
													current_application->application_data) != SWITCH_STATUS_SUCCESS) {
			return;
		}

		if (switch_channel_test_flag(session->channel, CF_RESET)) {
			goto top;
		}

	}

	if (switch_channel_ready(session->channel) && switch_channel_get_state(session->channel) == CS_EXECUTE && 
		switch_channel_test_flag(session->channel, CF_CONFIRM_BLIND_TRANSFER) && 
		(uuid = switch_channel_get_variable(session->channel, "blind_transfer_uuid"))) {
		switch_core_session_t *other_session;

		if ((other_session = switch_core_session_locate(uuid))) {
			switch_core_session_message_t msg = { 0 };			
			msg.message_id = SWITCH_MESSAGE_INDICATE_BLIND_TRANSFER_RESPONSE;
			msg.from = __FILE__;
			msg.numeric_arg = 0;
			switch_core_session_receive_message(other_session, &msg);
			switch_core_session_rwunlock(other_session);

			switch_channel_set_variable(session->channel, "park_timeout", "10:blind_transfer");
			switch_channel_set_state(session->channel, CS_PARK);
			switch_channel_clear_flag(session->channel, CF_CONFIRM_BLIND_TRANSFER);
		}
	}
	
	if (switch_channel_ready(session->channel) && switch_channel_get_state(session->channel) == CS_EXECUTE) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s has executed the last dialplan instruction, hanging up.\n",
						  switch_channel_get_name(session->channel));
		switch_channel_hangup(session->channel, SWITCH_CAUSE_NORMAL_CLEARING);
	}
}
示例#21
0
static void switch_core_standard_on_routing(switch_core_session_t *session)
{
	switch_dialplan_interface_t *dialplan_interface = NULL;
	switch_caller_profile_t *caller_profile;
	switch_caller_extension_t *extension = NULL;
	char *expanded = NULL;
	char *dpstr = NULL;

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard ROUTING\n", switch_channel_get_name(session->channel));

	switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session));
		
	if ((switch_channel_test_flag(session->channel, CF_ANSWERED) ||
		 switch_channel_test_flag(session->channel, CF_EARLY_MEDIA) ||
		 switch_channel_test_flag(session->channel, CF_SIGNAL_BRIDGE_TTL)) && switch_channel_test_flag(session->channel, CF_PROXY_MODE)) {
		switch_ivr_media(session->uuid_str, SMF_NONE);
	}

	if ((caller_profile = switch_channel_get_caller_profile(session->channel)) == 0) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't get profile!\n");
		switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
		return;
	} else {
		char *dp[25];
		int argc, x, count = 0;

		if ((extension = switch_channel_get_queued_extension(session->channel))) {
			switch_channel_set_caller_extension(session->channel, extension);
			switch_channel_set_state(session->channel, CS_EXECUTE);
			goto end;
		}

		if (!zstr(caller_profile->dialplan)) {
			if ((dpstr = switch_core_session_strdup(session, caller_profile->dialplan))) {
				expanded = switch_channel_expand_variables(session->channel, dpstr);
				argc = switch_separate_string(expanded, ',', dp, (sizeof(dp) / sizeof(dp[0])));
				for (x = 0; x < argc; x++) {
					char *dpname = dp[x];
					char *dparg = NULL;

					if (dpname) {
						if ((dparg = strchr(dpname, ':'))) {
							*dparg++ = '\0';
						}
					} else {
						continue;
					}
					if (!(dialplan_interface = switch_loadable_module_get_dialplan_interface(dpname))) {
						continue;
					}

					count++;

					extension = dialplan_interface->hunt_function(session, dparg, NULL);
					UNPROTECT_INTERFACE(dialplan_interface);

					if (extension) {
						switch_channel_set_caller_extension(session->channel, extension);
						switch_channel_set_state(session->channel, CS_EXECUTE);
						goto end;
					}
				}
			}
		}

		if (!count) {
			if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
				if (switch_channel_test_flag(session->channel, CF_ANSWERED)) {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
									  "No Dialplan on answered channel, changing state to HANGUP\n");
					switch_channel_hangup(session->channel, SWITCH_CAUSE_NO_ROUTE_DESTINATION);
				} else {
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No Dialplan, changing state to CONSUME_MEDIA\n");
					switch_channel_set_state(session->channel, CS_CONSUME_MEDIA);
				}
				goto end;
			}
		}
	}

	if (!extension) {

		if (switch_ivr_blind_transfer_ack(session, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "No Route, Aborting\n");
			switch_channel_hangup(session->channel, SWITCH_CAUSE_NO_ROUTE_DESTINATION);
		}
	}

  end:

	if (expanded && dpstr && expanded != dpstr) {
		free(expanded);
	}
}
示例#22
0
static void switch_core_standard_on_reset(switch_core_session_t *session)
{
	switch_channel_set_variable(session->channel, "call_uuid", switch_core_session_get_uuid(session));

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard RESET\n", switch_channel_get_name(session->channel));
}
switch_status_t navigate_entrys(switch_core_session_t *session, dir_profile_t *profile, search_params_t *params)
{
	switch_status_t status = SWITCH_STATUS_SUCCESS;
	char *sql = NULL, *sql_where = NULL;
	char entry_count[80] = "";
	callback_t cbt = { 0 };
	int result_count;
	char macro[256] = "";
	listing_callback_t listing_cbt;
	int cur_entry = 0;
	cbt.buf = entry_count;
	cbt.len = sizeof(entry_count);

	if (params->search_by == SEARCH_BY_FIRST_AND_LAST_NAME) {
		sql_where = switch_mprintf("hostname = '%q' and uuid = '%q' and name_visible = 1 and (%s like '%q%%' or %s like '%q%%')",
				globals.hostname, switch_core_session_get_uuid(session), "last_name_digit", params->digits, "first_name_digit", params->digits);
	} else if (params->search_by == SEARCH_BY_FULL_NAME) {
		sql_where = switch_mprintf("hostname = '%q' and uuid = '%q' and name_visible = 1 and full_name_digit like '%%%q%%'",
				globals.hostname, switch_core_session_get_uuid(session), "last_name_digit", params->digits, "first_name_digit", params->digits);
	} else {
		sql_where = switch_mprintf("hostname = '%q' and uuid = '%q' and name_visible = 1 and %s like '%q%%'",
				globals.hostname, switch_core_session_get_uuid(session), (params->search_by == SEARCH_BY_LAST_NAME ? "last_name_digit" : "first_name_digit"), params->digits);
	}

	sql = switch_mprintf("select count(*) from directory_search where %s", sql_where);

	directory_execute_sql_callback(globals.mutex, sql, sql2str_callback, &cbt);
	switch_safe_free(sql);

	result_count = atoi(entry_count);

	if (result_count == 0) {
		switch_snprintf(macro, sizeof(macro), "%d", result_count);
		switch_ivr_phrase_macro(session, DIR_RESULT_COUNT, macro, NULL, NULL);
		params->try_again = 1;
		status = SWITCH_STATUS_BREAK;
		goto end;
	} else if (profile->max_result != 0 && result_count > profile->max_result) {
		switch_ivr_phrase_macro(session, DIR_RESULT_COUNT_TOO_LARGE, NULL, NULL, NULL);
		params->try_again = 1;
		status = SWITCH_STATUS_BREAK;
		goto end;

	} else {
		switch_snprintf(macro, sizeof(macro), "%d", result_count);
		switch_ivr_phrase_macro(session, DIR_RESULT_COUNT, macro, NULL, NULL);
	}

	memset(&listing_cbt, 0, sizeof(listing_cbt));
	listing_cbt.params = params;

	sql = switch_mprintf("select extension, full_name, last_name, first_name, name_visible, exten_visible from directory_search where %s order by last_name, first_name", sql_where);

	for (cur_entry = 0; cur_entry < result_count; cur_entry++) {
		listing_cbt.index = 0;
		listing_cbt.want = cur_entry;
		listing_cbt.move = ENTRY_MOVE_NEXT;
		directory_execute_sql_callback(globals.mutex, sql, listing_callback, &listing_cbt);
		status = listen_entry(session, profile, &listing_cbt);
		if (!zstr(listing_cbt.transfer_to)) {
			switch_copy_string(params->transfer_to, listing_cbt.transfer_to, 255);
			break;
		}
		if (listing_cbt.new_search) {
			params->try_again = 1;
			goto end;

		}
		if (listing_cbt.move == ENTRY_MOVE_NEXT) {
			if (cur_entry == result_count - 1) {
				switch_snprintf(macro, sizeof(macro), "%d", result_count);
				switch_ivr_phrase_macro(session, DIR_RESULT_LAST, macro, NULL, NULL);
				cur_entry -= 1;
			}
		}
		if (listing_cbt.move == ENTRY_MOVE_PREV) {
			if (cur_entry <= 0) {
				cur_entry = -1;
			} else {
				cur_entry -= 2;
			}
		}
		if (status == SWITCH_STATUS_TIMEOUT) {
			goto end;
		}
		if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
			goto end;
		}
	}

  end:
	switch_safe_free(sql);
	switch_safe_free(sql_where);
	return status;

}
示例#24
0
SWITCH_DECLARE(void) switch_log_vprintf(switch_text_channel_t channel, const char *file, const char *func, int line,
										const char *userdata, switch_log_level_t level, const char *fmt, va_list ap)
{
	char *data = NULL;
	char *new_fmt = NULL;
	int ret = 0;
	FILE *handle;
	const char *filep = (file ? switch_cut_path(file) : "");
	const char *funcp = (func ? func : "");
	char *content = NULL;
	switch_time_t now = switch_micro_time_now();
	uint32_t len;
#ifdef SWITCH_FUNC_IN_LOG
	const char *extra_fmt = "%s [%s] %s:%d %s()%c%s";
#else
	const char *extra_fmt = "%s [%s] %s:%d%c%s";
#endif
	switch_log_level_t limit_level = runtime.hard_log_level;

	if (channel == SWITCH_CHANNEL_ID_SESSION && userdata) {
		switch_core_session_t *session = (switch_core_session_t *) userdata;
		if (limit_level < session->loglevel) {
			limit_level = session->loglevel;
		}
	}

	if (level > 100) {
		if ((uint32_t) (level - 100) > runtime.debug_level) {
			return;
		}

		level = 7;
	}

	if (level > limit_level) {
		return;
	}

	switch_assert(level < SWITCH_LOG_INVALID);

	handle = switch_core_data_channel(channel);

	if (channel != SWITCH_CHANNEL_ID_LOG_CLEAN) {
		char date[80] = "";
		//switch_size_t retsize;
		switch_time_exp_t tm;

		switch_time_exp_lt(&tm, now);
		switch_snprintf(date, sizeof(date), "%0.4d-%0.2d-%0.2d %0.2d:%0.2d:%0.2d.%0.6d",
						tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec);

		//switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);

#ifdef SWITCH_FUNC_IN_LOG
		len = (uint32_t) (strlen(extra_fmt) + strlen(date) + strlen(filep) + 32 + strlen(funcp) + strlen(fmt));
#else
		len = (uint32_t) (strlen(extra_fmt) + strlen(date) + strlen(filep) + 32 + strlen(fmt));
#endif
		new_fmt = malloc(len + 1);
		switch_assert(new_fmt);
#ifdef SWITCH_FUNC_IN_LOG
		switch_snprintf(new_fmt, len, extra_fmt, date, switch_log_level2str(level), filep, line, funcp, 128, fmt);
#else
		switch_snprintf(new_fmt, len, extra_fmt, date, switch_log_level2str(level), filep, line, 128, fmt);
#endif

		fmt = new_fmt;
	}

	ret = switch_vasprintf(&data, fmt, ap);

	if (ret == -1) {
		fprintf(stderr, "Memory Error\n");
		goto end;
	}

	if (channel == SWITCH_CHANNEL_ID_LOG_CLEAN) {
		content = data;
	} else {
		if ((content = strchr(data, 128))) {
			*content = ' ';
		}
	}

	if (channel == SWITCH_CHANNEL_ID_EVENT) {
		switch_event_t *event;
		if (switch_event_running() == SWITCH_STATUS_SUCCESS && switch_event_create(&event, SWITCH_EVENT_LOG) == SWITCH_STATUS_SUCCESS) {
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Log-Data", data);
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Log-File", filep);
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Log-Function", funcp);
			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Log-Line", "%d", line);
			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Log-Level", "%d", (int) level);
			if (!zstr(userdata)) {
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "User-Data", userdata);
			}
			switch_event_fire(&event);
			data = NULL;
		}

		goto end;
	}

	if (console_mods_loaded == 0 || !do_mods) {
		if (handle) {
			int aok = 1;
#ifndef WIN32

			fd_set can_write;
			int fd;
			struct timeval to;

			fd = fileno(handle);
			memset(&to, 0, sizeof(to));
			FD_ZERO(&can_write);
			FD_SET(fd, &can_write);
			to.tv_sec = 0;
			to.tv_usec = 100000;
			if (select(fd + 1, NULL, &can_write, NULL, &to) > 0) {
				aok = FD_ISSET(fd, &can_write);
			} else {
				aok = 0;
			}
#endif
			if (aok) {
				if (COLORIZE) {

#ifdef WIN32
					SetConsoleTextAttribute(hStdout, COLORS[level]);
					WriteFile(hStdout, data, (DWORD) strlen(data), NULL, NULL);
					SetConsoleTextAttribute(hStdout, wOldColorAttrs);
#else
					fprintf(handle, "%s%s%s", COLORS[level], data, SWITCH_SEQ_DEFAULT_COLOR);
#endif
				} else {
					fprintf(handle, "%s", data);
				}
			}
		}
	}

	if (do_mods && level <= MAX_LEVEL) {
		switch_log_node_t *node = switch_log_node_alloc();

		node->data = data;
		data = NULL;
		switch_set_string(node->file, filep);
		switch_set_string(node->func, funcp);
		node->line = line;
		node->level = level;
		node->content = content;
		node->timestamp = now;
		node->channel = channel;
		if (channel == SWITCH_CHANNEL_ID_SESSION) {
			node->userdata = userdata ? strdup(switch_core_session_get_uuid((switch_core_session_t *) userdata)) : NULL;
		} else {
			node->userdata = !zstr(userdata) ? strdup(userdata) : NULL;
		}

		if (switch_queue_trypush(LOG_QUEUE, node) != SWITCH_STATUS_SUCCESS) {
			switch_log_node_free(&node);
		}
	}

  end:

	switch_safe_free(data);
	switch_safe_free(new_fmt);

}
示例#25
0
static switch_status_t my_on_reporting(switch_core_session_t *session)
{
	cJSON *json_cdr = NULL;
	char *json_text = NULL;
	char *path = NULL;
	char *curl_json_text = NULL;
	const char *logdir = NULL;
	char *json_text_escaped = NULL;
	int fd = -1, err_dir_index;
	uint32_t cur_try;
	long httpRes;
	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_json_cdr(session, &json_cdr, globals.encode_values == ENCODING_DEFAULT) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Generating Data!\n");
		return SWITCH_STATUS_FALSE;
	}
	
	json_text = cJSON_PrintUnformatted(json_cdr);

	if (!json_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, "json_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.json", 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, json_text, (unsigned) strlen(json_text));
				close(fd);
				fd = -1;
				if(wrote < 0) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s]\n",path);
				}
			} 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) {
			switch_size_t need_bytes = strlen(json_text) * 3;

			json_text_escaped = malloc(need_bytes);
			switch_assert(json_text_escaped);
			memset(json_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(json_text, json_text_escaped, need_bytes);
			} else {
				headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-base64-encoded");
				switch_b64_encode((unsigned char *) json_text, need_bytes / 3, (unsigned char *) json_text_escaped, need_bytes);
			}

			switch_safe_free(json_text);
			json_text = json_text_escaped;

			if (!(curl_json_text = switch_mprintf("cdr=%s", json_text))) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
				goto error;
			}

		} else {
			headers = switch_curl_slist_append(headers, "Content-Type: application/json");
			curl_json_text = (char *)json_text;
		}


		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_json_text);
		switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-json/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);
		}

		/* these were used for testing, optionally they may be enabled if someone desires
		   switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 120); // tcp timeout
		   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", globals.urls[globals.url_index], 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 < 300) {
				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");

		for (err_dir_index = 0; err_dir_index < globals.err_dir_count; err_dir_index++) {
			switch_thread_rwlock_rdlock(globals.log_path_lock);
			path = switch_mprintf("%s%s%s%s.cdr.json", globals.err_log_dir[err_dir_index], 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, json_text, (unsigned) strlen(json_text));
					close(fd);
					fd = -1;
					if(wrote < 0) {
						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s]\n",path);
					}
					break;
				} else {
					char ebuf[512] = { 0 };
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open %s! [%s]\n",
							path, switch_strerror_r(errno, ebuf, sizeof(ebuf)));

				}

				switch_safe_free(path);
			}
		}	
	}
  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_json_text != json_text) {
		switch_safe_free(curl_json_text);
	}
	
	cJSON_Delete(json_cdr);
	switch_safe_free(json_text);

	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_json_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_json_cdr_load)
{
	char *cf = "json_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;
	globals.encode_values = ENCODING_DEFAULT;

	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_TERM;
	}

	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, "delay") && !zstr(val)) {
				globals.delay = (uint32_t) atoi(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 {
					globals.encode = switch_true(val) ? ENCODING_DEFAULT : ENCODING_NONE;
				}
			} else if (!strcasecmp(var, "retries") && !zstr(val)) {
				globals.retries = (uint32_t) atoi(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%sjson_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 (globals.err_dir_count >= MAX_ERR_DIRS) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "maximum error directories configured!\n");
				} else {

					if (zstr(val)) {
						globals.base_err_log_dir[globals.err_dir_count++] = switch_core_sprintf(globals.pool, "%s%sjson_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
					} else {
						if (switch_is_file_path(val)) {
							globals.base_err_log_dir[globals.err_dir_count++] = switch_core_strdup(globals.pool, val);
						} else {
							globals.base_err_log_dir[globals.err_dir_count++] = 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;
				}
			} else if (!strcasecmp(var, "encode-values") && !zstr(val)) {
				globals.encode_values = switch_true(val) ? ENCODING_DEFAULT : ENCODING_NONE;
			}

		}

		if (!globals.err_dir_count) {
			if (!zstr(globals.base_log_dir)) {
				globals.base_err_log_dir[globals.err_dir_count++] = switch_core_strdup(globals.pool, globals.base_log_dir);
			} else {
				globals.base_err_log_dir[globals.err_dir_count++] = switch_core_sprintf(globals.pool, "%s%sjson_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
			}
		}
	}

	if (globals.retries && !globals.delay) {
		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_json_cdr_log_dirs();

	switch_xml_free(xml);
	return status;
}

SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_json_cdr_shutdown)
{
	int err_dir_index = 0;

	globals.shutdown = 1;

	switch_safe_free(globals.log_dir);
	
	for (;err_dir_index < globals.err_dir_count; err_dir_index++) {
		switch_safe_free(globals.err_log_dir[err_dir_index]);
	}

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

	switch_thread_rwlock_destroy(globals.log_path_lock);

	return SWITCH_STATUS_SUCCESS;
}
示例#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;

	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;
}
示例#27
0
/* This is where we actually charge the guy 
  This can be called anytime a call is in progress or at the end of a call before the session is destroyed */
static switch_status_t do_billing(switch_core_session_t *session)
{
	/* FS vars we will use */
	switch_channel_t *channel;
	switch_caller_profile_t *profile;

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

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

	uuid = switch_core_session_get_uuid(session);

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

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

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

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

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

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

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

			transfer_call(session, globals.nobal_action);
		}

		return SWITCH_STATUS_SUCCESS;
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

	return SWITCH_STATUS_SUCCESS;
}
示例#28
0
/**
 * Start execution of call receivefax component
 * @param call the call to receive fax from
 * @param msg the original request
 * @param session_data the call's session
 */
static iks *start_receivefax_component(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;
	struct receivefax_component *receivefax_component = NULL;
	iks *receivefax = iks_find(iq, "receivefax");
	iks *response = NULL;
	switch_event_t *execute_event = NULL;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	switch_memory_pool_t *pool;
	int file_no;

	/* validate attributes */
	if (!VALIDATE_RAYO_RECEIVEFAX(receivefax)) {
		return iks_new_error(iq, STANZA_ERROR_BAD_REQUEST);
	}

	/* fax is only allowed if the call is not currently joined */
	if (rayo_call_is_joined(RAYO_CALL(call))) {
		return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "can't receive fax on a joined call");
	}

	if (rayo_call_is_faxing(RAYO_CALL(call))) {
		return iks_new_error_detailed(iq, STANZA_ERROR_UNEXPECTED_REQUEST, "fax already in progress");
	}

	/* create receivefax component */
	switch_core_new_memory_pool(&pool);
	receivefax_component = switch_core_alloc(pool, sizeof(*receivefax_component));
	rayo_component_init((struct rayo_component *)receivefax_component, pool, RAT_CALL_COMPONENT, "receivefax", NULL, call, iks_find_attrib(iq, "from"));
	file_no = rayo_actor_seq_next(call);
	receivefax_component->filename = switch_core_sprintf(pool, "%s%s%s-%d.tif",
		globals.file_prefix, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session), file_no);
	if (!strncmp(receivefax_component->filename, "http://", 7) || !strncmp(receivefax_component->filename, "https://", 8)) {
		/* This is an HTTP URL, need to PUT after fax is received */
		receivefax_component->local_filename = switch_core_sprintf(pool, "%s%s%s-%d",
			SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, switch_core_session_get_uuid(session), file_no);
		receivefax_component->http_put_after_receive = 1;
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s save fax to HTTP URL\n", RAYO_JID(receivefax_component));
	} else {
		/* assume file.. */
		receivefax_component->local_filename = receivefax_component->filename;
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s save fax to local file\n", RAYO_JID(receivefax_component));
	}

	/* add channel variable so that fax component can be located from fax events */
	switch_channel_set_variable(channel, "rayo_fax_jid", RAYO_JID(receivefax_component));

	/* clear fax result variables */
	switch_channel_set_variable(channel, "fax_success", NULL);
	switch_channel_set_variable(channel, "fax_result_code", NULL);
	switch_channel_set_variable(channel, "fax_result_text", NULL);
	switch_channel_set_variable(channel, "fax_document_transferred_pages", NULL);
	switch_channel_set_variable(channel, "fax_document_total_pages", NULL);
	switch_channel_set_variable(channel, "fax_image_resolution", NULL);
	switch_channel_set_variable(channel, "fax_image_size", NULL);
	switch_channel_set_variable(channel, "fax_bad_rows", NULL);
	switch_channel_set_variable(channel, "fax_transfer_rate", NULL);
	switch_channel_set_variable(channel, "fax_ecm_used", NULL);
	switch_channel_set_variable(channel, "fax_local_station_id", NULL);
	switch_channel_set_variable(channel, "fax_remote_station_id", NULL);

	/* clear fax interrupt variable */
	switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_read_frame_interrupt", NULL);

	rayo_call_set_faxing(RAYO_CALL(call), 1);

	/* execute rxfax APP */
	if (switch_event_create(&execute_event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
		switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "call-command", "execute");
		switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-name", "rxfax");
		switch_event_add_header_string(execute_event, SWITCH_STACK_BOTTOM, "execute-app-arg", receivefax_component->local_filename);
		if (!switch_channel_test_flag(channel, CF_PROXY_MODE)) {
			switch_channel_set_flag(channel, CF_BLOCK_BROADCAST_UNTIL_MEDIA);
		}

		if (switch_core_session_queue_private_event(session, &execute_event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) {
			response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to rxfax (queue event failed)");
			if (execute_event) {
				switch_event_destroy(&execute_event);
			}
			rayo_call_set_faxing(RAYO_CALL(call), 0);
			RAYO_UNLOCK(receivefax_component);
		} else {
			/* component starting... */
			rayo_component_send_start(RAYO_COMPONENT(receivefax_component), iq);
		}
	} else {
		response = iks_new_error_detailed(iq, STANZA_ERROR_INTERNAL_SERVER_ERROR, "failed to create rxfax event");
		rayo_call_set_faxing(RAYO_CALL(call), 0);
		RAYO_UNLOCK(receivefax_component);
	}

	return response;
}
static switch_status_t populate_database(switch_core_session_t *session, dir_profile_t *profile, const char *domain_name)
{
	switch_status_t status = SWITCH_STATUS_SUCCESS;

	char *sql = NULL;
	char *sqlvalues = NULL;
	char *sqltmp = NULL;
	int count = 0;

	switch_xml_t xml_root = NULL, x_domain;
	switch_xml_t ut;

	switch_event_t *xml_params = NULL;
	switch_xml_t group = NULL, groups = NULL, users = NULL, x_params = NULL, x_param = NULL, x_vars = NULL, x_var = NULL;
	switch_event_create(&xml_params, SWITCH_EVENT_REQUEST_PARAMS);
	switch_assert(xml_params);

	if (switch_xml_locate_domain(domain_name, xml_params, &xml_root, &x_domain) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate domain %s\n", domain_name);
		status = SWITCH_STATUS_FALSE;
		goto end;
	}

	if ((groups = switch_xml_child(x_domain, "groups"))) {
		for (group = switch_xml_child(groups, "group"); group; group = group->next) {
			if ((users = switch_xml_child(group, "users"))) {
				for (ut = switch_xml_child(users, "user"); ut; ut = ut->next) {
					int name_visible = 1;
					int exten_visible = 1;
					const char *type = switch_xml_attr_soft(ut, "type");
					const char *id = switch_xml_attr_soft(ut, "id");
					char *fullName = NULL;
					char *caller_name = NULL;
					char *caller_name_override = NULL;
					char *firstName = NULL;
					char *lastName = NULL;
					char *fullNameDigit = NULL;
					char *firstNameDigit = NULL;
					char *lastNameDigit = NULL;

					if (!strcasecmp(type, "pointer")) {
						continue;
					}
					/* Check all the user params */
					if ((x_params = switch_xml_child(ut, "params"))) {
						for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
							const char *var = switch_xml_attr_soft(x_param, "name");
							const char *val = switch_xml_attr_soft(x_param, "value");
							if (!strcasecmp(var, "directory-visible")) {
								name_visible = switch_true(val);
							}
							if (!strcasecmp(var, "directory-exten-visible")) {
								exten_visible = switch_true(val);
							}

						}
					}
					/* Check all the user variables */
					if ((x_vars = switch_xml_child(ut, "variables"))) {
						for (x_var = switch_xml_child(x_vars, "variable"); x_var; x_var = x_var->next) {
							const char *var = switch_xml_attr_soft(x_var, "name");
							const char *val = switch_xml_attr_soft(x_var, "value");
							if (!strcasecmp(var, "effective_caller_id_name")) {
								caller_name = switch_core_session_strdup(session, val);
							}
							if (!strcasecmp(var, "directory_full_name")) {
								caller_name_override = switch_core_session_strdup(session, val);
							}
						}
					}
					if (caller_name_override) {
						fullName = caller_name_override;
					} else {
						fullName = caller_name;
					}
					if (zstr(fullName)) {
						continue;
					}
					firstName = switch_core_session_strdup(session, fullName);

					if ((lastName = strrchr(firstName, ' '))) {
						*lastName++ = '\0';
					} else {
						lastName = switch_core_session_strdup(session, firstName);
					}

					/* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "FullName %s firstName [%s] lastName [%s]\n", fullName, firstName, lastName); */

					/* Generate Digits key mapping */
					fullNameDigit = string_to_keypad_digit(fullName);
					lastNameDigit = string_to_keypad_digit(lastName);
					firstNameDigit = string_to_keypad_digit(firstName);

					/* add user into DB */
					sql = switch_mprintf("insert into directory_search values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%d','%d')",
										 globals.hostname, switch_core_session_get_uuid(session), id, fullName, fullNameDigit, firstName, firstNameDigit,
										 lastName, lastNameDigit, name_visible, exten_visible);

					if (sqlvalues) {
						sqltmp = sqlvalues;
						sqlvalues = switch_mprintf("%s;%s", sqlvalues, sql);
						switch_safe_free(sqltmp);
					} else {
						sqlvalues = sql;
						sql = NULL;
					}
					switch_safe_free(sql);
					switch_safe_free(fullNameDigit);
					switch_safe_free(lastNameDigit);
					switch_safe_free(firstNameDigit);
					
					if (++count >= 100) {
						count = 0;
						sql = switch_mprintf("BEGIN;%s;COMMIT;", sqlvalues);
						directory_execute_sql(sql, globals.mutex);
						switch_safe_free(sql);
						switch_safe_free(sqlvalues);
					}
				}
			}
		}
	}
	if (sqlvalues) {
		sql = switch_mprintf("BEGIN;%s;COMMIT;", sqlvalues);
		directory_execute_sql(sql, globals.mutex);
	}
  end:
	switch_safe_free(sql);
	switch_safe_free(sqlvalues);
	switch_event_destroy(&xml_params);
	switch_xml_free(xml_root);

	return status;
}
示例#30
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;
}