static switch_status_t sched_billing(switch_core_session_t *session)
{
	switch_channel_t *channel = NULL;
	
	const char *billrate = NULL;
	const char *billaccount = NULL;
	
	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");
	billaccount = switch_channel_get_variable(channel, "nibble_account");
	
	/* Return if there's no billing information on this session */
	if (!billrate || !billaccount) {
		return SWITCH_STATUS_SUCCESS;
	}

	if (globals.global_heartbeat > 0) {
		switch_core_session_enable_heartbeat(session, globals.global_heartbeat);
	}

	/* TODO: Check account balance here */

	return SWITCH_STATUS_SUCCESS;
}
Beispiel #2
0
static switch_status_t limit_state_handler(switch_core_session_t *session)
{
	switch_channel_t *channel = switch_core_session_get_channel(session);
	switch_channel_state_t state = switch_channel_get_state(channel);
	const char *vval = switch_channel_get_variable(channel, LIMIT_IGNORE_TRANSFER_VARIABLE);
	const char *backendlist = switch_channel_get_variable(channel, LIMIT_BACKEND_VARIABLE);
	
	if (zstr(backendlist)) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Unset limit backendlist!\n");
		return SWITCH_STATUS_SUCCESS;
	}

	if (state >= CS_HANGUP || (state == CS_ROUTING && !switch_true(vval))) {
		int argc = 0;
		char *argv[6] = { 0 };
		char *mydata = strdup(backendlist);
		int x;
		
		argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0])));
		for (x = 0; x < argc; x++) {
			switch_limit_release(argv[x], session, NULL, NULL);
		}
		switch_core_event_hook_remove_state_change(session, limit_state_handler);
		/* Remove limit_backend variable so we register another hook if limit is called again */
		switch_channel_set_variable(channel, LIMIT_BACKEND_VARIABLE, NULL);
		
		free(mydata);
	}
	
	return SWITCH_STATUS_SUCCESS;
}
/* send a message to every member of the conference */
void conference_event_chat_message_broadcast(conference_obj_t *conference, switch_event_t *event)
{
	conference_member_t *member = NULL;
	switch_event_t *processed;

	switch_assert(conference != NULL);
	switch_event_create(&processed, SWITCH_EVENT_CHANNEL_DATA);

	switch_mutex_lock(conference->member_mutex);
	for (member = conference->members; member; member = member->next) {
		if (member->session && !conference_utils_member_test_flag(member, MFLAG_NOCHANNEL)) {
			const char *presence_id = switch_channel_get_variable(member->channel, "presence_id");
			const char *chat_proto = switch_channel_get_variable(member->channel, "chat_proto");
			switch_event_t *reply = NULL;

			if (presence_id && chat_proto) {
				if (switch_event_get_header(processed, presence_id)) {
					continue;
				}
				switch_event_dup(&reply, event);
				switch_event_add_header_string(reply, SWITCH_STACK_BOTTOM, "to", presence_id);
				switch_event_add_header_string(reply, SWITCH_STACK_BOTTOM, "conference_name", conference->name);
				switch_event_add_header_string(reply, SWITCH_STACK_BOTTOM, "conference_domain", conference->domain);

				switch_event_set_body(reply, switch_event_get_body(event));

				switch_core_chat_deliver(chat_proto, &reply);
				switch_event_add_header_string(processed, SWITCH_STACK_BOTTOM, presence_id, "true");
			}
		}
	}
	switch_event_destroy(&processed);
	switch_mutex_unlock(conference->member_mutex);
}
Beispiel #4
0
switch_status_t mod_xml_radius_check_conditions(switch_channel_t *channel, switch_xml_t conditions) {
	switch_xml_t condition, param;
	char *channel_var = NULL;
	const char *channel_val = NULL;
	char *regex = NULL;
	char *anti = NULL;
	int all_matched = 1;
	int result = 0;
	
	if ( (condition = switch_xml_child(conditions, "condition")) == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to locate a condition under the conditions section\n");
		return SWITCH_STATUS_FALSE;
	}
	
	for (; condition; condition = condition->next) {
		
		if ( (param = switch_xml_child(condition, "param")) == NULL) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to locate a param under this condition\n");
			return SWITCH_STATUS_FALSE;
		}
		
		all_matched = 1;
		for (; param && all_matched; param = param->next) {
			channel_var = (char *) switch_xml_attr(param, "var");
			regex = (char *) switch_xml_attr(param, "regex");
			anti = (char *) switch_xml_attr(param, "anti");
			
			if ( channel_var == NULL || regex == NULL ) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Improperly constructed mod_radius condition: %s %s\n", channel_var, regex);
				continue;
			}
			
			if ( ( channel_val = switch_channel_get_variable(channel, channel_var) ) == NULL ) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, 
								  "Improperly constructed mod_radius condition, no such channel variable: %s %s\n", channel_var, regex);
				continue;
			}

			result = ( switch_regex_match( channel_val, regex) != SWITCH_STATUS_SUCCESS);
			if (( anti == NULL && result ) || ( anti != NULL && !result ) ){
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Didn't match: %s == %s \n", switch_channel_get_variable(channel, channel_var), regex);
				all_matched = 0;
			} else {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Result of %s match: %s == %s \n", 
								  anti, switch_channel_get_variable(channel, channel_var), regex);
			}
		}

		if ( all_matched ) {
			return SWITCH_STATUS_SUCCESS;
		}
	}
	
	return SWITCH_STATUS_FALSE;
}
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);
		}
	}
}
int eventpipe_check_count(switch_core_session_t *session) {
	const char *check_str = NULL;
	int check_count = 0;
	char vbuf[10] = "";

	switch_channel_t *channel = switch_core_session_get_channel(session);
	check_str = switch_channel_get_variable(channel, "eventpipe_run_count");

	if (!zstr(check_str)) {
		/* check if reach max count */
		check_count = atoi(check_str);
		if (check_count >= PLIVO_MAX_RUN) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), 
				SWITCH_LOG_ERROR, "Abort, Max eventpipe applications reached for a call (%d)!\n", PLIVO_MAX_RUN);
			return 0;
		/* increment redirect count */
		} else {
			check_count++;
			switch_snprintf(vbuf, sizeof(vbuf), "%d", check_count);
			switch_channel_set_variable(channel, "eventpipe_run_count", vbuf);
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "eventpipe_run_count %d\n", check_count);
			return 1;
		}
	}
	/* Hu ?! must never be here */
	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Hu ?! must never be here !\n");
	return 0;
}
static switch_call_cause_t sip_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)
{
	const char *profile;
	char *dup_profile = NULL;

	if (session) {
		profile = switch_channel_get_variable(switch_core_session_get_channel(session), "sip_profile");
	} else {
		dup_profile = switch_core_get_variable_dup("sip_profile");
		profile = dup_profile;
	}
	if (zstr(profile)) {
		profile = "default";
	}

	outbound_profile->destination_number = switch_core_sprintf(outbound_profile->pool, "%s/%s", profile, outbound_profile->destination_number);

	UNPROTECT_INTERFACE(sip_endpoint_interface);

	switch_safe_free(dup_profile);

	return switch_core_session_outgoing_channel(session, var_event, "sofia", outbound_profile, new_session, pool, SOF_NONE, cancel_cause);
}
Beispiel #8
0
static void nibblebill_adjust(switch_core_session_t *session, double amount)
{
	switch_channel_t *channel = switch_core_session_get_channel(session);
	const char *billaccount;

	if (!channel) {
		return;
	}

	/* Variables kept in FS but relevant only to this module */

	billaccount = switch_channel_get_variable(channel, "nibble_account");

	/* Return if there's no billing information on this session */
	if (!billaccount) {
		return;
	}

	/* Add or remove amount from adjusted billing here. Note, we bill the OPPOSITE */
	if (bill_event(-amount, billaccount, channel) == SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Recorded adjustment to %s for $%f\n", billaccount, amount);
	} else {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to record adjustment to %s for $%f\n", billaccount, amount);
	}
}
Beispiel #9
0
int fs_switch_ivr_originate(switch_core_session_t *session, switch_core_session_t **bleg, char *bridgeto, uint32_t timelimit_sec)
/*const switch_state_handler_table_t *table,
  char *  	cid_name_override,
  char *  	cid_num_override,
  switch_caller_profile_t *caller_profile_override)  */
{

	switch_channel_t *caller_channel;
	switch_core_session_t *peer_session;
	unsigned int timelimit = 60;
	char *var;
	switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;

	caller_channel = switch_core_session_get_channel(session);
	assert(caller_channel != NULL);

	if ((var = switch_channel_get_variable(caller_channel, "call_timeout"))) {
		timelimit = atoi(var);
	}

	if (switch_ivr_originate(session, &peer_session, &cause, bridgeto, timelimit, NULL, NULL, NULL, NULL, SOF_NONE) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Cannot Create Outgoing Channel!\n");
		switch_channel_hangup(caller_channel, SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL);
		return;
	} else {
		switch_ivr_multi_threaded_bridge(session, peer_session, NULL, NULL, NULL);
		switch_core_session_rwunlock(peer_session);
	}
}
Beispiel #10
0
SWITCH_DECLARE(int) CoreSession::streamFile(char *file, int starting_sample_count) {

    switch_status_t status;
    //switch_file_handle_t fh = { 0 };
	const char *prebuf;
	switch_file_handle_t local_fh;

	this_check(-1);
    sanity_check(-1);
	
	memset(&local_fh, 0, sizeof(local_fh));
	fhp = &local_fh;
    local_fh.samples = starting_sample_count;


	if ((prebuf = switch_channel_get_variable(this->channel, "stream_prebuffer"))) {
        int maybe = atoi(prebuf);
        if (maybe > 0) {
            local_fh.prebuf = maybe;
        }
	}

    begin_allow_threads();
    status = switch_ivr_play_file(session, fhp, file, ap);
    end_allow_threads();

	fhp = NULL;
	
    return status == SWITCH_STATUS_SUCCESS ? 1 : 0;

}
static int get_v18_mode(switch_core_session_t *session)
{
	switch_channel_t *channel = switch_core_session_get_channel(session);
	const char *var;
	int r = V18_MODE_5BIT_45;

	if ((var = switch_channel_get_variable(channel, "v18_mode"))) {
		if (!strcasecmp(var, "5BIT_45") || !strcasecmp(var, "baudot")) {
			r = V18_MODE_5BIT_45;
		} else if (!strcasecmp(var, "5BIT_50")) {
			r = V18_MODE_5BIT_50;
		} else if (!strcasecmp(var, "DTMF")) {
			r = V18_MODE_DTMF;
		} else if (!strcasecmp(var, "EDT")) {
			r = V18_MODE_EDT;
		} else if (!strcasecmp(var, "BELL103") || !strcasecmp(var, "ascii")) {
			r = V18_MODE_BELL103;
		} else if (!strcasecmp(var, "V23VIDEOTEX")) {
			r = V18_MODE_V23VIDEOTEX;
		} else if (!strcasecmp(var, "V21TEXTPHONE")) {
			r = V18_MODE_V21TEXTPHONE;
		} else if (!strcasecmp(var, "V18TEXTPHONE")) {
			r = V18_MODE_V18TEXTPHONE;
		}
	}

	return r;
}
SWITCH_DECLARE(switch_status_t) switch_core_media_bug_transfer_recordings(switch_core_session_t *orig_session, switch_core_session_t *new_session)
{
	switch_media_bug_t *bp;
	char *list[100] = { 0 };
	int stop_times[100] = { 0 };
	int i = 0, x = 0;

	if (orig_session->bugs) {
		switch_channel_t *new_channel = switch_core_session_get_channel(new_session);
		switch_channel_t *orig_channel = switch_core_session_get_channel(orig_session);
		const char *save_append = switch_channel_get_variable(new_channel, "record_append");
		const char *save_stereo = switch_channel_get_variable(new_channel, "record_stereo");
		const char *orig_stereo = switch_channel_get_variable(orig_channel, "record_stereo");
		const char *new_stereo = orig_stereo;
		
		switch_thread_rwlock_wrlock(orig_session->bug_rwlock);
		switch_channel_set_variable(new_channel, "RECORD_MIN_SEC", "0");
		switch_channel_set_variable(new_channel, "record_append", "true");
		switch_channel_set_variable(new_channel, "record_stereo", new_stereo);

		for (bp = orig_session->bugs; bp; bp = bp->next) {
			if (!strcmp(bp->function, "session_record")) {
				list[x] = switch_core_session_strdup(new_session, bp->target);
				if (bp->stop_time > 0) {
					stop_times[x] = (int)(bp->stop_time - switch_epoch_time_now(NULL));
				}
				x++;
			}
		}

		switch_thread_rwlock_unlock(orig_session->bug_rwlock);

		for(i = 0; i < x; i++) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(orig_session), SWITCH_LOG_DEBUG, "Transfering %s from %s to %s\n", list[i],
							  switch_core_session_get_name(orig_session), switch_core_session_get_name(new_session));
			switch_ivr_stop_record_session(orig_session, list[i]);
			switch_ivr_record_session(new_session, list[i], stop_times[i], NULL);
		}

		switch_channel_set_variable(new_channel, "record_append", save_append);
		switch_channel_set_variable(new_channel, "record_stereo", save_stereo);

	}

	return x ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
}
Beispiel #13
0
void eventpipe_events_on_dtmf(switch_core_session_t *session, switch_event_t *event) {
	char args[8192];
	const char *dtmf_digit = switch_str_nil(switch_event_get_header(event, "dtmf-digit"));
	switch_channel_t *channel = switch_core_session_get_channel(session);
	const char *hangup_on_star = switch_str_nil(switch_channel_get_variable(channel, "eventpipe_conference_hangup_on_star"));
	const char *conf_room = switch_str_nil(switch_channel_get_variable(channel, "eventpipe_conference_room"));
	const char *conf_member_id = switch_str_nil(switch_channel_get_variable(channel, "eventpipe_conference_member_id"));

	/* handle conference kick if channel is in conference and digit '*' was pressed */
	if ((!strcmp(hangup_on_star, "true")) && (!strcmp(dtmf_digit, "*")) && (!zstr(conf_room)) && (!zstr(conf_member_id))) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, 
				"Conference, dtmf '*' pressed, kick member %s from room %s\n",
				conf_member_id, conf_room);
		switch_snprintf(args, sizeof(args), "%s kick %s", conf_room, conf_member_id);
		eventpipe_execute_api(session, "conference", args);
	}
}
Beispiel #14
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);
		}
	}
}
Beispiel #15
0
switch_status_t mod_xml_radius_accounting_end(switch_core_session_t *session){
	VALUE_PAIR *send = NULL;
	uint32_t service = PW_STATUS_STOP;
	rc_handle *new_handle = NULL;
	switch_xml_t fields = NULL, conditions = NULL;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	
	if (GLOBAL_DEBUG ) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: starting accounting stop\n");
		switch_core_session_execute_application(session, "info", NULL);
	}
	
	/* If there are conditions defined, and none of them pass, then skip this accounting */
	if ((conditions = switch_xml_child(globals.acct_start_configs, "conditions")) != NULL &&
		mod_xml_radius_check_conditions(channel, conditions) != SWITCH_STATUS_SUCCESS ) {
		goto end;
	}
	
	if ( mod_xml_radius_new_handle(&new_handle, globals.acct_end_configs) != SWITCH_STATUS_SUCCESS || new_handle == NULL ) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to create new accounting_end handle for call: %s\n",
						  switch_channel_get_variable(channel, "uuid"));
		goto end;		
	}

	if ((fields = switch_xml_child(globals.acct_end_configs, "fields")) == NULL ) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find 'fields' section in config file.\n");		
		goto end;
	}
	
	if ( mod_xml_radius_add_params(session, NULL, new_handle, &send, fields) != SWITCH_STATUS_SUCCESS ) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to add params to rc_handle\n");		
		goto end;
	}
	
	if (rc_avpair_add(new_handle, &send, PW_ACCT_STATUS_TYPE, &service, -1, 0) == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius: failed to add option to handle\n");
		goto end;
	}	

	if (rc_acct(new_handle, 0, send) == OK_RC) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "mod_xml_radius:  Accounting Stop success\n");
	} else {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mod_xml_radius:  Accounting Stop failed\n");
	}

 end:
	if ( send ) {
		rc_avpair_free(send);
		send = NULL;
	}
	if ( new_handle) {
		rc_destroy(new_handle);
		new_handle = NULL;
	}
	
	return SWITCH_STATUS_SUCCESS;
}
Beispiel #16
0
static switch_status_t channel_on_routing(switch_core_session_t *session)
{
	switch_channel_t *channel = NULL;
	private_t *tech_pvt = NULL;
	const char *app, *arg;

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

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

	do_reset(tech_pvt);

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
	
	if (switch_test_flag(tech_pvt, TFLAG_RUNNING_APP)) {
		switch_clear_flag(tech_pvt, TFLAG_RUNNING_APP);
	}

	if (switch_test_flag(tech_pvt, TFLAG_APP) && !switch_test_flag(tech_pvt, TFLAG_OUTBOUND) && 
		(app = switch_channel_get_variable(channel, "loopback_app"))) {
		switch_caller_extension_t *extension = NULL;

		switch_clear_flag(tech_pvt, TFLAG_APP);
		switch_set_flag(tech_pvt, TFLAG_RUNNING_APP);

		arg = switch_channel_get_variable(channel, "loopback_app_arg");
		extension = switch_caller_extension_new(session, app, app);
		switch_caller_extension_add_application(session, extension, "pre_answer", NULL);
		switch_caller_extension_add_application(session, extension, app, arg);

		switch_channel_set_caller_extension(channel, extension);
		switch_channel_set_state(channel, CS_EXECUTE);
		return SWITCH_STATUS_FALSE;
	}



	return SWITCH_STATUS_SUCCESS;
}
Beispiel #17
0
static switch_status_t spy_on_exchange_media(switch_core_session_t *session)
{
	switch_channel_t *channel = switch_core_session_get_channel(session);
	const char *spy_uuid = switch_channel_get_variable(channel, "spy_uuid");

	if (spy_uuid) {
		if (switch_ivr_eavesdrop_session(session, spy_uuid, NULL, ED_DTMF) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't eavesdrop on uuid %s\n", spy_uuid);
		}
	}

	switch_channel_set_state(channel, CS_PARK);
	return SWITCH_STATUS_FALSE;
}
static switch_status_t loopback_bowout_on_execute_state_handler(switch_core_session_t *session)
{
	switch_channel_t *channel = switch_core_session_get_channel(session);
	switch_channel_state_t state = switch_channel_get_state(channel);
	private_t *tech_pvt = NULL;


	if (state == CS_EXECUTE) {
		const char *uuid;
		switch_core_session_t *other_session = NULL;
		switch_channel_t *b_channel = NULL;

		tech_pvt = switch_core_session_get_private(session);

		switch_core_session_read_lock(tech_pvt->other_session);
		b_channel = switch_core_session_get_channel(tech_pvt->other_session);

		uuid = switch_channel_get_variable(b_channel, SWITCH_SIGNAL_BOND_VARIABLE);

		if (uuid && (other_session = switch_core_session_locate(uuid))) {
			switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
			switch_caller_profile_t *cp, *clone;
			
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->other_session), SWITCH_LOG_INFO, "Replacing loopback channel: %s with real channel: %s\n",
							  switch_channel_get_name(b_channel), switch_channel_get_name(other_channel));
			
			if ((cp = switch_channel_get_caller_profile(channel))) {
				clone = switch_caller_profile_clone(other_session, cp);
				clone->originator_caller_profile = NULL;
				clone->originatee_caller_profile = NULL;
				switch_channel_set_caller_profile(other_channel, clone);
			}

			switch_channel_caller_extension_masquerade(channel, other_channel, 0);
			switch_channel_set_state(other_channel, CS_RESET);
			switch_channel_wait_for_state(other_channel, NULL, CS_RESET);
			switch_channel_set_variable(channel, "process_cdr", "false");
			switch_channel_set_variable(b_channel, "process_cdr", "false");
			switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
			switch_channel_set_state(other_channel, CS_EXECUTE);
			switch_core_session_rwunlock(other_session);
		}

		switch_core_session_rwunlock(tech_pvt->other_session);

		switch_core_event_hook_remove_state_change(session, loopback_bowout_on_execute_state_handler);
		
	}
	return SWITCH_STATUS_SUCCESS;
}
Beispiel #19
0
static switch_status_t spy_on_park(switch_core_session_t *session)
{
	switch_channel_t *channel = switch_core_session_get_channel(session);
	const char *moh = switch_channel_get_variable(channel, "hold_music");

	while (switch_channel_ready(channel) && switch_channel_get_state(channel) == CS_PARK) {
		if (moh) {
			switch_status_t status = switch_ivr_play_file(session, NULL, moh, NULL);
			if (!SWITCH_READ_ACCEPTABLE(status)) {
				break;
			}
		}
	}
	return SWITCH_STATUS_FALSE;
}
Beispiel #20
0
void vmivr_menu_authenticate(switch_core_session_t *session, vmivr_profile_t *profile) {
	switch_channel_t *channel = switch_core_session_get_channel(session);
	vmivr_menu_t menu = { "std_authenticate" };
	int retry;
	const char *auth_var = NULL;
	/* Initialize Menu Configs */
	menu_init(profile, &menu);

	if (profile->id && (auth_var = switch_channel_get_variable(channel, "voicemail_authorized")) && switch_true(auth_var)) {
		profile->authorized = SWITCH_TRUE;
	}

	for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0 && profile->authorized == SWITCH_FALSE; retry--) {
		const char *id = profile->id, *password = NULL;
		char *cmd = NULL;
		const char *password_mask = switch_event_get_header(menu.event_settings, "Password-Mask");
		const char *user_mask = switch_event_get_header(menu.event_settings, "User-Mask");
		if (!id) {
			vmivr_menu_t sub_menu = { "std_authenticate_ask_user" };
			/* Initialize Menu Configs */
			menu_init(profile, &sub_menu);

			switch_event_add_header(sub_menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry);

			id = vmivr_menu_get_input_set(session, profile, &sub_menu, user_mask);
			menu_free(&sub_menu);
		}
		if (!password) {
			vmivr_menu_t sub_menu = { "std_authenticate_ask_password" };
			/* Initialize Menu Configs */
			menu_init(profile, &sub_menu);

			switch_event_add_header(sub_menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry);

			password = vmivr_menu_get_input_set(session, profile, &sub_menu, password_mask);
			menu_free(&sub_menu);
		}
		cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, id, password);

		if (vmivr_api_execute(session, profile->api_auth_login, cmd) == SWITCH_STATUS_SUCCESS) {
			profile->id = id;
			profile->authorized = SWITCH_TRUE;
		} else {
			ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "fail_auth"), NULL, NULL, NULL, 0);
		}
	}
	menu_free(&menu);
}
Beispiel #21
0
static void nibblebill_resume(switch_core_session_t *session)
{
	switch_channel_t *channel = switch_core_session_get_channel(session);
	switch_time_t ts = switch_micro_time_now();
	nibble_data_t *nibble_data;
	const char *billrate;

	if (!channel) {
		return;
	}

	/* 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_");

	if (!nibble_data) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
						  "Can't resume - channel is not initialized for billing (This is expected at hangup time)!\n");
		return;
	}

	if (nibble_data->pausets == 0) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
						  "Can't resume - channel is not paused! (This is expected at hangup time)\n");
		return;
	}

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

	billrate = switch_channel_get_variable(channel, "nibble_rate");

	/* Calculate how much was "lost" to billings during pause - we do this here because you never know when the billrate may change during a call */
	nibble_data->bill_adjustments += (atof(billrate) / 1000000 / 60) * ((ts - nibble_data->pausets));
	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Resumed billing! Subtracted %f from this billing cycle.\n",
					  (atof(billrate) / 1000000 / 60) * ((ts - nibble_data->pausets)));

	nibble_data->pausets = 0;

	/* Done checking - release lock */
	if (globals.mutex) {
		switch_mutex_unlock(globals.mutex);
	}
}
void mtvm_menu_authenticate(switch_core_session_t *session, vmivr_profile_t *profile) {
	switch_channel_t *channel = switch_core_session_get_channel(session);
        vmivr_menu_profile_t menu = { "std_authenticate" };
	int retry;
	const char *auth_var = NULL;
	/* Initialize Menu Configs */
	populate_profile_menu_event(profile, &menu);

	if (profile->id && (auth_var = switch_channel_get_variable(channel, "voicemail_authorized")) && switch_true(auth_var)) {
		profile->authorized = SWITCH_TRUE;
	}

	for (retry = MAX_ATTEMPT; switch_channel_ready(channel) && retry > 0 && profile->authorized == SWITCH_FALSE; retry--) {
		const char *id = profile->id, *password = NULL;
		char *cmd = NULL;

		if (!id) {
			vmivr_menu_profile_t sub_menu = { "std_authenticate_ask_user" };
			/* Initialize Menu Configs */
			populate_profile_menu_event(profile, &sub_menu);

			id = mtvm_menu_get_input_set(session, profile, sub_menu, "X." /* TODO Conf Min 3 Digit */, "#" /* TODO Conf terminate input key */);
			free_profile_menu_event(&sub_menu);
		}
		if (!password) {
			vmivr_menu_profile_t sub_menu = { "std_authenticate_ask_password" };
			/* Initialize Menu Configs */
			populate_profile_menu_event(profile, &sub_menu);

			password = mtvm_menu_get_input_set(session, profile, sub_menu, "X." /* TODO Conf Min 3 Digit */, "#" /* TODO Conf terminate input key */);
			free_profile_menu_event(&sub_menu);
		}
		cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, id, password);

		if (mt_api_execute(session, profile->api_auth_login, cmd) == SWITCH_STATUS_SUCCESS) {
			profile->id = id;
			profile->authorized = SWITCH_TRUE;
		} else {
			playbackBufferDTMF(session, switch_event_get_header(menu.event_phrases, "fail_auth"), NULL, NULL, NULL, 0);
		}
	}
	free_profile_menu_event(&menu);
}
Beispiel #23
0
static switch_status_t process_hangup(switch_core_session_t *session)
{
	const char* billaccount;
	switch_channel_t *channel = NULL;

	channel = switch_core_session_get_channel(session);
	
	/* Resume any paused billings, just in case */
	/*  nibblebill_resume(session); */

	/* Now go handle like normal billing */
	do_billing(session);

	billaccount = switch_channel_get_variable(channel, "nibble_account");
	if (billaccount) {
		switch_channel_set_variable_printf(channel, "nibble_current_balance", "%f", get_balance(billaccount, channel));
	}			
	
	return SWITCH_STATUS_SUCCESS;
}
static void switch_core_standard_on_execute(switch_core_session_t *session)
{
	switch_caller_extension_t *extension;

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

	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_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);
	}
}
Beispiel #25
0
switch_status_t mod_xml_radius_check_conditions(switch_channel_t *channel, switch_xml_t conditions) {
	switch_xml_t condition, param;
	char *channel_var = NULL;
	char *regex = NULL;
	int all_matched = 1;
	
	if ( (condition = switch_xml_child(conditions, "condition")) == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to locate a condition under the conditions section\n");
		return SWITCH_STATUS_FALSE;
	}
	
	for (; condition; condition = condition->next) {
		
		if ( (param = switch_xml_child(condition, "param")) == NULL) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to locate a param under this condition\n");
			return SWITCH_STATUS_FALSE;
		}
		
		all_matched = 1;
		for (; param && all_matched; param = param->next) {
			channel_var = (char *) switch_xml_attr(param, "var");
			regex = (char *) switch_xml_attr(param, "regex");
			
			if ( channel_var == NULL || regex == NULL ) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Improperly constructed mod_radius condition: %s %s\n", channel_var, regex);
			}
			
			if ( switch_regex_match( switch_channel_get_variable(channel, channel_var), regex) != SWITCH_STATUS_SUCCESS) {
				all_matched = 0;
			}
		}

		if ( all_matched ) {
			return SWITCH_STATUS_SUCCESS;
		}
	}
	
	return SWITCH_STATUS_FALSE;
}
Beispiel #26
0
SWITCH_DECLARE(switch_status_t) switch_limit_incr(const char *backend, switch_core_session_t *session, const char *realm, const char *resource, const int max, const int interval) {
	switch_limit_interface_t *limit = NULL;
	switch_channel_t *channel = NULL;
	int status = SWITCH_STATUS_SUCCESS;
	
	if (session) {
		channel = switch_core_session_get_channel(session);
	}

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

	switch_limit_log(session, SWITCH_LOG_INFO, "incr called: %s_%s max:%d, interval:%d\n",
					  realm, resource, max, interval);
	
	if ((status = limit->incr(session, realm, resource, max, interval)) == SWITCH_STATUS_SUCCESS) {
		if (session) {
			/* race condition? what if another leg is doing the same thing? */
			const char *existing = switch_channel_get_variable(channel, LIMIT_BACKEND_VARIABLE);
			if (existing) {
				if (!strstr(existing, backend)) {
					switch_channel_set_variable_printf(channel, LIMIT_BACKEND_VARIABLE, "%s,%s", existing, backend);
				}
			} else {
				switch_channel_set_variable(channel, LIMIT_BACKEND_VARIABLE, backend);
				switch_core_event_hook_add_state_change(session, limit_state_handler);
			}
		}
	}
	
	release_backend(limit);
	
end:
	return status;
}
Beispiel #27
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);
}
Beispiel #28
0
char* GetValue(switch_channel_t *channel, CONFIG_VSAS* VSAS, char* value)
{
	if (VSAS == NULL)
	{
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Internal Error : VSAS is null object.\n");
		return "";
	}
	
	if (VSAS->value == NULL)
	{
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Internal Error : VSAS->value is null object.\n");
		return "";
	}
	
	if (VSAS->expr == 1)
	{
		const char* v = switch_channel_get_variable(channel, VSAS->value);

		if (v != NULL)
		{
			strcpy(value, v);
			return value;
		}
		else
		{
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Undefined channel variable: %s.\n", VSAS->value);
			strcpy(value, "");
			return value;
		}
	}
	else
	{
		strcpy(value, VSAS->value);
		return value;
	}
}
static switch_status_t enum_lookup(char *root, char *in, enum_record_t **results, switch_channel_t *channel, switch_core_session_t *session)
{
	switch_status_t sstatus = SWITCH_STATUS_SUCCESS;
	char *mnum = NULL, *mroot = NULL, *p;
	char *server[ENUM_MAXNAMESERVERS];
	int inameserver = 0;  
	char *argv[ ENUM_MAXNAMESERVERS ] = { 0 };
	int argc;
	int x = 0;
	char *enum_nameserver_dup;
	const char *enum_nameserver = NULL;

	*results = NULL;

	mnum = switch_mprintf("%s%s", *in == '+' ? "" : "+", in);

	if ((p = strchr(mnum, '*'))) {
		*p++ = '\0';
		mroot = switch_mprintf("%s.%s", p, root ? root : globals.isn_root);
		root = mroot;
	}

	if (zstr(root)) {
		root = globals.root;
	}

	/* Empty the server array */
	for(inameserver=0; inameserver<ENUM_MAXNAMESERVERS; inameserver++) {
		server[inameserver] = NULL;
	}  

	inameserver = 0;

	/* check for enum_nameserver channel var */
	
	if (channel) {
		enum_nameserver = switch_channel_get_variable(channel, "enum_nameserver");
	}

	if (zstr(enum_nameserver)) {
		enum_nameserver = switch_core_get_variable("enum-server");
	}

	if (!zstr(enum_nameserver)) {
		/* Blank the server array */
		for(inameserver=0; inameserver<ENUM_MAXNAMESERVERS; inameserver++) {
			server[inameserver] = NULL;
		}

		enum_nameserver_dup = switch_core_session_strdup(session, enum_nameserver);
		argc = switch_separate_string(enum_nameserver_dup, ',', argv, (sizeof(argv) / sizeof(argv[0])));

		inameserver = 0;
		for (x = 0; x < argc; x++) {
			server[inameserver] = argv[x];
			inameserver++;
		}
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Enum nameserver override : %s\n", enum_nameserver);
	}

	if (!inameserver) {
		/* use config param "nameserver" ( can be up to ENUM_MAXNAMESERVERS ) */
		for(inameserver = 0; inameserver<ENUM_MAXNAMESERVERS; inameserver++) {
			server[inameserver] = NULL;
			if ( globals.nameserver[inameserver] != NULL ) {
				server[inameserver] = globals.nameserver[inameserver];
			}
		}
	}

	ldns_lookup(mnum, root, server, results);

	switch_safe_free(mnum);
	switch_safe_free(mroot);

	return sstatus;
}
static switch_status_t my_on_reporting(switch_core_session_t *session)
{
	switch_channel_t *channel = switch_core_session_get_channel(session);
	switch_status_t status = SWITCH_STATUS_SUCCESS;
	const char *log_dir = NULL, *accountcode = NULL, *a_template_str = NULL, *g_template_str = NULL;
	char *log_line, *path = NULL;

	if (globals.shutdown) {
		return SWITCH_STATUS_SUCCESS;
	}

	if (!((globals.legs & CDR_LEG_A) && (globals.legs & CDR_LEG_B))) {
		if ((globals.legs & CDR_LEG_A)) {
			if (switch_channel_get_originator_caller_profile(channel)) {
				return SWITCH_STATUS_SUCCESS;
			}
		} else {
			if (switch_channel_get_originatee_caller_profile(channel)) {
				return SWITCH_STATUS_SUCCESS;
			}
		}
	}

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

	if (switch_dir_make_recursive(log_dir, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating %s\n", log_dir);
		return SWITCH_STATUS_FALSE;
	}

	if (globals.debug) {
		switch_event_t *event;
		if (switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
			char *buf;
			switch_channel_event_set_data(channel, event);
			switch_event_serialize(event, &buf, SWITCH_FALSE);
			switch_assert(buf);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "CHANNEL_DATA:\n%s\n", buf);
			switch_event_destroy(&event);
			free(buf);
		}
	}

	g_template_str = (const char *) switch_core_hash_find(globals.template_hash, globals.default_template);

	if ((accountcode = switch_channel_get_variable(channel, "ACCOUNTCODE"))) {
		a_template_str = (const char *) switch_core_hash_find(globals.template_hash, accountcode);
	}

	if (!g_template_str) {
		g_template_str =
			"\"${accountcode}\",\"${caller_id_number}\",\"${destination_number}\",\"${context}\",\"${caller_id}\",\"${channel_name}\",\"${bridge_channel}\",\"${last_app}\",\"${last_arg}\",\"${start_stamp}\",\"${answer_stamp}\",\"${end_stamp}\",\"${duration}\",\"${billsec}\",\"${hangup_cause}\",\"${amaflags}\",\"${uuid}\",\"${userfield}\";";
	}

	if (!a_template_str) {
		a_template_str = g_template_str;
	}

	log_line = switch_channel_expand_variables(channel, a_template_str);

	if ((accountcode) && (!globals.masterfileonly)) {
		path = switch_mprintf("%s%s%s.csv", log_dir, SWITCH_PATH_SEPARATOR, accountcode);
		assert(path);
		write_cdr(path, log_line);
		free(path);
	}

	if (g_template_str != a_template_str) {
		if (log_line != a_template_str) {
			switch_safe_free(log_line);
		}
		log_line = switch_channel_expand_variables(channel, g_template_str);
	}

	if (!log_line) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error creating cdr\n");
		return SWITCH_STATUS_FALSE;
	}

	path = switch_mprintf("%s%sMaster.csv", log_dir, SWITCH_PATH_SEPARATOR);
	assert(path);
	write_cdr(path, log_line);
	free(path);


	if (log_line != g_template_str) {
		free(log_line);
	}

	return status;
}