Esempio n. 1
0
static void do_rotate_all()
{
	switch_hash_index_t *hi;
	void *val;
	cdr_fd_t *fd;

	if (globals.shutdown) {
		return;
	}

	for (hi = switch_hash_first(NULL, globals.fd_hash); hi; hi = switch_hash_next(hi)) {
		switch_hash_this(hi, NULL, NULL, &val);
		fd = (cdr_fd_t *) val;
		switch_mutex_lock(fd->mutex);
		do_rotate(fd);
		switch_mutex_unlock(fd->mutex);
	}
}
Esempio n. 2
0
static void event_handler(switch_event_t *event)
{
	switch_hash_index_t *hi;
	void *val;

	const char *sig = switch_event_get_header(event, "Trapped-Signal");

	if (sig && !strcmp(sig, "HUP")) {
		for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
			cdr_profile_t *profile;
			switch_hash_this(hi, NULL, NULL, &val);
			profile = (cdr_profile_t *) val;

			if (profile->rotate) {
				set_format_cdr_log_dirs(profile);
			}
		}
	}
}
static void event_handler(switch_event_t *event)
{
	const char *sig = switch_event_get_header(event, "Trapped-Signal");
	switch_hash_index_t *hi;
	void *val;
	cdr_fd_t *fd;

	if (globals.shutdown) {
		return;
	}

	if (sig && !strcmp(sig, "HUP")) {
		for (hi = switch_hash_first(NULL, globals.fd_hash); hi; hi = switch_hash_next(hi)) {
			switch_hash_this(hi, NULL, NULL, &val);
			fd = (cdr_fd_t *) val;
			switch_mutex_lock(fd->mutex);
			do_rotate(fd);
			switch_mutex_unlock(fd->mutex);
		}
	}
}
Esempio n. 4
0
/**
 * Search for best voice based on attributes
 * @param cur_node the desired voice attributes
 * @param map the map to search
 * @param type "say" or "tts"
 * @param lang_required if true, language must match
 * @return the voice or NULL
 */
static struct voice *find_voice(struct ssml_node *cur_node, switch_hash_t *map, char *type, int lang_required)
{
	switch_hash_index_t *hi = NULL;
	struct voice *voice = (struct voice *)switch_core_hash_find(map, cur_node->name);
	char *lang_name_gender = NULL;
	int best_score = 0;

	/* check cache */
	lang_name_gender = switch_mprintf("%s-%s-%s-%s", type, cur_node->language, cur_node->name, cur_node->gender);
	voice = (struct voice *)switch_core_hash_find(globals.voice_cache, lang_name_gender);
	if (voice) {
		/* that was easy! */
		goto done;
	}

	/* find best language, name, gender match */
	for (hi = switch_hash_first(NULL, map); hi; hi = switch_hash_next(hi)) {
		const void *key;
		void *val;
		struct voice *candidate;
		int candidate_score = 0;
		switch_hash_this(hi, &key, NULL, &val);
		candidate = (struct voice *)val;
		candidate_score = score_voice(candidate, cur_node, lang_required);
		if (candidate_score > 0 && candidate_score > best_score) {
			voice = candidate;
			best_score = candidate_score;
		}
	}

	/* remember for next time */
	if (voice) {
		switch_core_hash_insert(globals.voice_cache, lang_name_gender, voice);
	}

done:
	switch_safe_free(lang_name_gender);

	return voice;
}
Esempio n. 5
0
static switch_status_t process_node(const switch_log_node_t *node, switch_log_level_t level)
{
	switch_hash_index_t *hi;
	void *val;
	const void *var;
	logfile_profile_t *profile;

	for (hi = switch_hash_first(NULL, profile_hash); hi; hi = switch_hash_next(hi)) {
		size_t mask = 0;
		size_t ok = 0;

		switch_hash_this(hi, &var, NULL, &val);
		profile = val;

		ok = switch_log_check_mask(profile->all_level, level);

		if (!ok) {
			mask = (size_t) switch_core_hash_find(profile->log_hash, node->file);
			ok = switch_log_check_mask(mask, level);
		}

		if (!ok) {
			mask = (size_t) switch_core_hash_find(profile->log_hash, node->func);
			ok = switch_log_check_mask(mask, level);
		}

		if (ok) {
			if (profile->log_uuid && !zstr(node->userdata)) {
				char buf[2048];
				switch_snprintf(buf, sizeof(buf), "%s %s", node->userdata, node->data);
				mod_logfile_raw_write(profile, buf);
			} else {
				mod_logfile_raw_write(profile, node->data);
			}
		}

	}

	return SWITCH_STATUS_SUCCESS;
}
Esempio n. 6
0
static int valet_lot_count(valet_lot_t *lot) 
{
	switch_hash_index_t *i_hi;
	const void *i_var;
	void *i_val;
	valet_token_t *token;
	int count = 0;
	time_t now;

	now = switch_epoch_time_now(NULL);

	switch_mutex_lock(lot->mutex);
	for (i_hi = switch_hash_first(NULL, lot->hash); i_hi; i_hi = switch_hash_next(i_hi)) {
		switch_hash_this(i_hi, &i_var, NULL, &i_val);
		token = (valet_token_t *) i_val;
		if (token->timeout > 0 && (token->timeout < now || token->timeout == 1)) {
			continue;
		}
		count++;
	}	
	switch_mutex_unlock(lot->mutex);

	return count;
}
Esempio n. 7
0
static void pres_event_handler(switch_event_t *event)
{
	char *to = switch_event_get_header(event, "to");
	char *dup_to = NULL, *lot_name, *dup_lot_name = NULL, *domain_name;
	valet_lot_t *lot;
	int found = 0;
	
	if (!to || strncasecmp(to, "park+", 5) || !strchr(to, '@')) {
		return;
	}

	if (!(dup_to = strdup(to))) {
		return;
	}

	lot_name = dup_to + 5;

	if ((domain_name = strchr(lot_name, '@'))) {
		*domain_name++ = '\0';
	}

	dup_lot_name = switch_mprintf("%q@%q", lot_name, domain_name);

	if ((lot = valet_find_lot(lot_name, SWITCH_FALSE)) || (dup_lot_name && (lot = valet_find_lot(dup_lot_name, SWITCH_FALSE)))) {
		int count = valet_lot_count(lot);

		if (count) {
			if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
				if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO);
					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", lot_name);
					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", lot_name, domain_name);

					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "force-status", "Active (%d caller%s)", count, count == 1 ? "" : "s");
					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "active");
					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", lot_name);
					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING");
					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "confirmed");
					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound");
					switch_event_fire(&event);
				}
				found++;
			}
		} else {
			if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO);
				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", lot_name, domain_name);

				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", "Empty");
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", lot_name);
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP");
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "terminated");
				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound");
				switch_event_fire(&event);
			}		
		}
	} else {
		switch_console_callback_match_t *matches = NULL;
		switch_console_callback_match_node_t *m;
		switch_hash_index_t *hi;
		const void *var;
		void *val;
		const char *nvar;

		switch_mutex_lock(globals.mutex);
		for (hi = switch_hash_first(NULL, globals.hash); hi; hi = switch_hash_next(hi)) {
			switch_hash_this(hi, &var, NULL, &val);
			nvar = (const char *) var;

			if (!strchr(nvar, '@') || switch_stristr(domain_name, nvar)) {
				switch_console_push_match(&matches, nvar);
			}
		}
		switch_mutex_unlock(globals.mutex);		
		
		if (matches) {
			valet_token_t *token;
			
			for (m = matches->head; !found && m; m = m->next) {
				lot = valet_find_lot(m->val, SWITCH_FALSE);
				switch_mutex_lock(lot->mutex);

				if ((token = (valet_token_t *) switch_core_hash_find(lot->hash, lot_name)) && !token->timeout) {
					found++;
					
					if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
						switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO);
						switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", lot_name);
						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", lot_name, domain_name);

						switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", token->bridged == 0 ? "Holding" : "Active");
						switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
						switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
						switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
						switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", lot_name);
						switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING");
						switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", token->bridged == 0 ? "early" : "confirmed");
						switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", token->bridged == 0 ? "outbound" : "inbound");
						switch_event_fire(&event);
					}
				}

				switch_mutex_unlock(lot->mutex);
			}
		}
	}


	if (!found && switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", VALET_PROTO);
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", lot_name);
		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", lot_name, domain_name);

		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "force-status", "Empty");
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "event_count", "%d", EC++);
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", lot_name);
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP");
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "terminated");
		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-direction", "inbound");
		switch_event_fire(&event);
	}

	switch_safe_free(dup_to);
	switch_safe_free(dup_lot_name);
}
Esempio n. 8
0
static switch_status_t handle_ref_tuple(listener_t *listener, erlang_msg * msg, ei_x_buff * buf, ei_x_buff * rbuf)
{
	erlang_ref ref;
	erlang_pid *pid;
	char hash[100];
	int arity;
	const void *key;
	void *val;
	session_elem_t *se;
	switch_hash_index_t *iter;

	ei_decode_tuple_header(buf->buff, &buf->index, &arity);

	if (ei_decode_ref(buf->buff, &buf->index, &ref)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid reference\n");
		return SWITCH_STATUS_FALSE;
	}

	if (!(pid = malloc(sizeof(erlang_pid)))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error\n");
		ei_x_encode_tuple_header(rbuf, 2);
		ei_x_encode_atom(rbuf, "error");
		ei_x_encode_atom(rbuf, "badmem");
		return SWITCH_STATUS_SUCCESS;
	}

	if (ei_decode_pid(buf->buff, &buf->index, pid)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid pid in a reference/pid tuple\n");
		return SWITCH_STATUS_FALSE;
	}

	ei_hash_ref(&ref, hash);

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Hashed ref to %s\n", hash);

	switch_thread_rwlock_rdlock(listener->session_rwlock);
	for (iter = switch_hash_first(NULL, listener->sessions); iter; iter = switch_hash_next(iter)) {
		switch_hash_this(iter, &key, NULL, &val);
		se = (session_elem_t*)val;
		if (se->spawn_reply && !strncmp(se->spawn_reply->hash, hash, 100)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "found matching session for %s : %s\n", hash, se->uuid_str);
			switch_mutex_lock(se->spawn_reply->mutex);
			if (se->spawn_reply->state == reply_not_ready) {
				switch_thread_cond_wait(se->spawn_reply->ready_or_found, se->spawn_reply->mutex);
			}

			if (se->spawn_reply->state == reply_waiting) {
				se->spawn_reply->pid = pid;
				switch_thread_cond_broadcast(se->spawn_reply->ready_or_found);
				ei_x_encode_atom(rbuf, "ok");
				switch_thread_rwlock_unlock(listener->session_rwlock);
				switch_mutex_unlock(se->spawn_reply->mutex);
				return SWITCH_STATUS_SUCCESS;
			}
			switch_mutex_unlock(se->spawn_reply->mutex);
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "get_pid came in too late for %s; %s\n", hash, se->uuid_str);
			break;
		}
	}
	switch_thread_rwlock_unlock(listener->session_rwlock);

	ei_x_encode_tuple_header(rbuf, 2);
	ei_x_encode_atom(rbuf, "error");
	ei_x_encode_atom(rbuf, "notfound");

	switch_safe_free(pid);		/* don't need it */

	return SWITCH_STATUS_SUCCESS;
}
static void event_handler(switch_event_t *event)
{
	uint8_t send = 0;

	if (globals.running != 1) {
		return;
	}

	if (event->subclass_name && (!strcmp(event->subclass_name, MULTICAST_EVENT) ||
								 !strcmp(event->subclass_name, MULTICAST_PEERUP) || !strcmp(event->subclass_name, MULTICAST_PEERDOWN))) {
		char *event_name, *sender;
		if ((event_name = switch_event_get_header(event, "orig-event-name")) &&
			!strcasecmp(event_name, "HEARTBEAT") && (sender = switch_event_get_header(event, "orig-multicast-sender"))) {
			struct peer_status *p;
			time_t now = switch_epoch_time_now(NULL);

			if (!(p = switch_core_hash_find(globals.peer_hash, sender))) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Host %s not already in hash\n", sender);
				p = switch_core_alloc(module_pool, sizeof(struct peer_status));
				p->active = SWITCH_FALSE;
				p->lastseen = 0;
				/*} else { */
				/*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Host %s last seen %d seconds ago\n", sender, now - p->lastseen); */
			}

			if (!p->active) {
				switch_event_t *local_event;
				if (switch_event_create_subclass(&local_event, SWITCH_EVENT_CUSTOM, MULTICAST_PEERUP) == SWITCH_STATUS_SUCCESS) {
					char lastseen[21];
					switch_event_add_header_string(local_event, SWITCH_STACK_BOTTOM, "Peer", sender);
					if (p->lastseen) {
						switch_snprintf(lastseen, sizeof(lastseen), "%d", (int) p->lastseen);
					} else {
						switch_snprintf(lastseen, sizeof(lastseen), "%s", "Never");
					}
					switch_event_add_header_string(local_event, SWITCH_STACK_BOTTOM, "Lastseen", lastseen);
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Peer %s has come up; last seen: %s\n", sender, lastseen);

					switch_event_fire(&local_event);
				}
			}
			p->active = SWITCH_TRUE;
			p->lastseen = now;

			switch_core_hash_insert(globals.peer_hash, sender, p);
		}

		/* ignore our own events to avoid ping pong */
		return;
	}

	if (event->event_id == SWITCH_EVENT_RELOADXML) {
		switch_mutex_lock(globals.mutex);
		switch_core_hash_destroy(&globals.event_hash);
		globals.event_hash = NULL;
		if (globals.psk) {
			switch_safe_free(globals.psk);
			globals.psk = NULL;
		}
		switch_core_hash_init(&globals.event_hash, module_pool);
		memset(globals.event_list, 0, SWITCH_EVENT_ALL + 1);
		if (load_config() != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to reload config file\n");
		} else {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Event Multicast Reloaded\n");
		}
		switch_mutex_unlock(globals.mutex);
	}

	if (event->event_id == SWITCH_EVENT_HEARTBEAT) {
		switch_hash_index_t *cur;
		switch_ssize_t keylen;
		const void *key;
		void *value;
		time_t now = switch_epoch_time_now(NULL);
		struct peer_status *last;
		char *host;

		for (cur = switch_hash_first(NULL, globals.peer_hash); cur; cur = switch_hash_next(cur)) {
			switch_hash_this(cur, &key, &keylen, &value);
			host = (char *) key;
			last = (struct peer_status *) value;
			if (last->active && (now - (last->lastseen)) > 60) {
				switch_event_t *local_event;

				last->active = SWITCH_FALSE;
				if (switch_event_create_subclass(&local_event, SWITCH_EVENT_CUSTOM, MULTICAST_PEERDOWN) == SWITCH_STATUS_SUCCESS) {
					char lastseen[21];
					switch_event_add_header_string(local_event, SWITCH_STACK_BOTTOM, "Peer", host);
					switch_snprintf(lastseen, sizeof(lastseen), "%d", (int) last->lastseen);
					switch_event_add_header_string(local_event, SWITCH_STACK_BOTTOM, "Lastseen", lastseen);
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Peer %s has gone down; last seen: %s\n", host, lastseen);

					switch_event_fire(&local_event);
				}
			}
		}
	}

	switch_mutex_lock(globals.mutex);
	if (globals.event_list[(uint8_t) SWITCH_EVENT_ALL]) {
		send = 1;
	} else if ((globals.event_list[(uint8_t) event->event_id])) {
		if (event->event_id != SWITCH_EVENT_CUSTOM || (event->subclass_name && switch_core_hash_find(globals.event_hash, event->subclass_name))) {
			send = 1;
		}
	}
	switch_mutex_unlock(globals.mutex);

	if (send) {
		char *packet;

		switch (event->event_id) {
		case SWITCH_EVENT_LOG:
			return;
		default:
			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Multicast-Sender", switch_core_get_switchname());
			if (switch_event_serialize(event, &packet, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
				size_t len;
				char *buf;
#ifdef HAVE_OPENSSL
				int outlen, tmplen;
				EVP_CIPHER_CTX ctx;
				char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
				switch_uuid_t uuid;

				switch_uuid_get(&uuid);
				switch_uuid_format(uuid_str, &uuid);
				len = strlen(packet) + SWITCH_UUID_FORMATTED_LENGTH + EVP_MAX_IV_LENGTH + strlen((char *) MAGIC);
#else
				len = strlen(packet) + strlen((char *) MAGIC);
#endif
				buf = malloc(len + 1);
				memset(buf, 0, len + 1);
				switch_assert(buf);

#ifdef HAVE_OPENSSL
				if (globals.psk) {
					switch_copy_string(buf, uuid_str, SWITCH_UUID_FORMATTED_LENGTH);

					EVP_CIPHER_CTX_init(&ctx);
					EVP_EncryptInit(&ctx, EVP_bf_cbc(), NULL, NULL);
					EVP_CIPHER_CTX_set_key_length(&ctx, strlen(globals.psk));
					EVP_EncryptInit(&ctx, NULL, (unsigned char *) globals.psk, (unsigned char *) uuid_str);
					EVP_EncryptUpdate(&ctx, (unsigned char *) buf + SWITCH_UUID_FORMATTED_LENGTH,
									  &outlen, (unsigned char *) packet, (int) strlen(packet));
					EVP_EncryptUpdate(&ctx, (unsigned char *) buf + SWITCH_UUID_FORMATTED_LENGTH + outlen,
									  &tmplen, (unsigned char *) MAGIC, (int) strlen((char *) MAGIC));
					outlen += tmplen;
					EVP_EncryptFinal(&ctx, (unsigned char *) buf + SWITCH_UUID_FORMATTED_LENGTH + outlen, &tmplen);
					outlen += tmplen;
					len = (size_t) outlen + SWITCH_UUID_FORMATTED_LENGTH;
					*(buf + SWITCH_UUID_FORMATTED_LENGTH + outlen) = '\0';
				} else {
#endif
					switch_copy_string(buf, packet, len);
					switch_copy_string(buf + strlen(packet), (char *) MAGIC, strlen((char *) MAGIC) + 1);
#ifdef HAVE_OPENSSL
				}
#endif

				switch_socket_sendto(globals.udp_socket, globals.addr, 0, buf, &len);
				switch_safe_free(packet);
				switch_safe_free(buf);
			}
			break;
		}
	}
	return;
}
Esempio n. 10
0
static switch_status_t my_on_reporting_cb(switch_core_session_t *session, cdr_profile_t *profile)
{
	switch_xml_t xml_cdr = NULL;
	cJSON *json_cdr = NULL;
	char *cdr_text = NULL;
	char *dpath = NULL;
	char *path = NULL;
	char *curl_cdr_text = NULL;
	const char *logdir = NULL;
	char *cdr_text_escaped = NULL;
	int fd = -1;
	uint32_t cur_try;
	long httpRes;
	switch_CURL *curl_handle = NULL;
	switch_curl_slist_t *headers = NULL;
	switch_curl_slist_t *slist = NULL;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	switch_status_t status = SWITCH_STATUS_FALSE;
	int is_b;
	const char *a_prefix = "";

	if (globals.shutdown) {
		return SWITCH_STATUS_SUCCESS;
	}

	is_b = channel && switch_channel_get_originator_caller_profile(channel);
	if (!profile->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 && profile->prefix_a)
		a_prefix = "a_";

	if ( ! strcasecmp(profile->format, "json") ) {
		if (switch_ivr_generate_json_cdr(session, &json_cdr, profile->encode_values == ENCODING_DEFAULT) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Generating JSON Data!\n");
			return SWITCH_STATUS_FALSE;
		}

		/* build the JSON */
		cdr_text = cJSON_PrintUnformatted(json_cdr);

		if (!cdr_text) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error generating JSON!\n");
			goto error;
		}
	} else if ( ! strcasecmp(profile->format, "xml") ) {
		if (switch_ivr_generate_xml_cdr(session, &xml_cdr) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Generating XML Data!\n");
			return SWITCH_STATUS_FALSE;
		}

		/* build the XML */
		cdr_text = switch_xml_toxml(xml_cdr, SWITCH_TRUE);
		if (!cdr_text) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error generating XML!\n");
			goto error;
		}
	} else {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unhandled format for mod_format_cdr!\n");
		goto error;
	}

	switch_thread_rwlock_rdlock(profile->log_path_lock);

	if (!(logdir = switch_channel_get_variable(channel, "format_cdr_base"))) {
		logdir = profile->log_dir;
	}

	if (!zstr(logdir) && (profile->log_http_and_disk || !profile->url_count)) {
		dpath = switch_mprintf("%s%s%s", logdir, SWITCH_PATH_SEPARATOR, a_prefix);
		path = switch_mprintf("%s%s%s%s.cdr.%s", logdir, SWITCH_PATH_SEPARATOR, a_prefix, switch_core_session_get_uuid(session),
			profile->format);
		switch_thread_rwlock_unlock(profile->log_path_lock);
		if (path) {
			if (switch_directory_exists(dpath, profile->pool) != SWITCH_STATUS_SUCCESS) {
				switch_dir_make_recursive(dpath, SWITCH_FPROT_OS_DEFAULT, profile->pool);
			}
#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, cdr_text, (unsigned) strlen(cdr_text));
				wrote++;
				close(fd);
				fd = -1;
			} else {
				char ebuf[512] = { 0 };
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s][%s]\n",
						path, switch_strerror_r(errno, ebuf, sizeof(ebuf)));
			}
			switch_safe_free(path);
			switch_safe_free(dpath);
		}
	} else {
		switch_thread_rwlock_unlock(profile->log_path_lock);
	}

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

		if (profile->encode == ENCODING_TEXTXML) {
			headers = switch_curl_slist_append(headers, "Content-Type: text/xml");
		} else if (profile->encode == ENCODING_APPLJSON) {
			headers = switch_curl_slist_append(headers, "Content-Type: application/json");
		} else if (profile->encode) {
			switch_size_t need_bytes = strlen(cdr_text) * 3 + 1;

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

		if (profile->encode == ENCODING_TEXTXML) {
			curl_cdr_text = cdr_text;
		} else if (profile->encode == ENCODING_APPLJSON) {
			curl_cdr_text = cdr_text;
		} else if (!(curl_cdr_text = switch_mprintf("cdr=%s", cdr_text))) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
			goto error;
		}

		if (!zstr(profile->cred)) {
			switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, profile->auth_scheme);
			switch_curl_easy_setopt(curl_handle, CURLOPT_USERPWD, profile->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_cdr_text);
		switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-format-cdr/1.0");
		switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, httpCallBack);

		if (profile->disable100continue) {
			slist = switch_curl_slist_append(slist, "Expect:");
			switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, slist);
		}

		if (profile->ssl_cert_file) {
			switch_curl_easy_setopt(curl_handle, CURLOPT_SSLCERT, profile->ssl_cert_file);
		}

		if (profile->ssl_key_file) {
			switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEY, profile->ssl_key_file);
		}

		if (profile->ssl_key_password) {
			switch_curl_easy_setopt(curl_handle, CURLOPT_SSLKEYPASSWD, profile->ssl_key_password);
		}

		if (profile->ssl_version) {
			if (!strcasecmp(profile->ssl_version, "SSLv3")) {
				switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_SSLv3);
			} else if (!strcasecmp(profile->ssl_version, "TLSv1")) {
				switch_curl_easy_setopt(curl_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
			}
		}

		if (profile->ssl_cacert_file) {
			switch_curl_easy_setopt(curl_handle, CURLOPT_CAINFO, profile->ssl_cacert_file);
		}
		
		switch_curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, profile->timeout);

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

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

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

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

			if (profile->enable_cacert_check) {
				switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, TRUE);
			}

			if (profile->enable_ssl_verifyhost) {
				switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
			}

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

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

		switch_thread_rwlock_rdlock(profile->log_path_lock);
		dpath = switch_mprintf("%s%s%s", profile->err_log_dir, SWITCH_PATH_SEPARATOR, a_prefix);
		path = switch_mprintf("%s%s%s%s.cdr.%s", profile->err_log_dir, SWITCH_PATH_SEPARATOR, a_prefix, switch_core_session_get_uuid(session),
			profile->format);
		switch_thread_rwlock_unlock(profile->log_path_lock);
		if (path) {
			if (switch_directory_exists(dpath, profile->pool) != SWITCH_STATUS_SUCCESS) {
				switch_dir_make_recursive(dpath, SWITCH_FPROT_OS_DEFAULT, profile->pool);
			}
#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, cdr_text, (unsigned) strlen(cdr_text));
				wrote++;
				close(fd);
				fd = -1;
			} else {
				char ebuf[512] = { 0 };
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error![%s]\n",
						switch_strerror_r(errno, ebuf, sizeof(ebuf)));
			}
			switch_safe_free(path);
			switch_safe_free(dpath);
		}
	}

  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_cdr_text != cdr_text) {
		switch_safe_free(curl_cdr_text);
	}
	switch_safe_free(cdr_text);
	switch_safe_free(path);
	switch_safe_free(dpath);
	if ( xml_cdr )
	{
		switch_xml_free(xml_cdr);
	}
	
	if ( json_cdr )
	{
		cJSON_Delete(json_cdr);
	}

	return status;
}

static switch_status_t my_on_reporting(switch_core_session_t *session)
{
	switch_hash_index_t *hi;
	void *val;
	switch_status_t status, tmpstatus;

	status = SWITCH_STATUS_SUCCESS;

	for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
		cdr_profile_t *profile;
		switch_hash_this(hi, NULL, NULL, &val);
		profile = (cdr_profile_t *) val;

		tmpstatus = my_on_reporting_cb(session, profile);
		if ( tmpstatus != SWITCH_STATUS_SUCCESS ) {
			status = tmpstatus;
		}
	}

	return status;
}
Esempio n. 11
0
static switch_status_t handle_ref_tuple(listener_t *listener, erlang_msg * msg, ei_x_buff * buf, ei_x_buff * rbuf)
{
	erlang_ref ref;
	erlang_pid pid;
	char hash[100];
	int arity;
	const void *key;
	void *val;
	session_elem_t *se;
	switch_hash_index_t *iter;
	int found = 0;

	ei_decode_tuple_header(buf->buff, &buf->index, &arity);

	if (ei_decode_ref(buf->buff, &buf->index, &ref)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid reference\n");
		return SWITCH_STATUS_FALSE;
	}

	if (ei_decode_pid(buf->buff, &buf->index, &pid)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid pid in a reference/pid tuple\n");
		return SWITCH_STATUS_FALSE;
	}

	ei_hash_ref(&ref, hash);

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Hashed ref to %s\n", hash);

	switch_thread_rwlock_rdlock(listener->session_rwlock);
	for (iter = switch_hash_first(NULL, listener->sessions); iter; iter = switch_hash_next(iter)) {
		switch_hash_this(iter, &key, NULL, &val);
		se = (session_elem_t*)val;
		if (se->spawn_reply && !strncmp(se->spawn_reply->hash, hash, 100)) {
			
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "found matching session for %s : %s\n", hash, se->uuid_str);

			switch_mutex_lock(se->spawn_reply->mutex);

			se->spawn_reply->pid = switch_core_alloc(se->pool, sizeof(erlang_pid));
			switch_assert(se->spawn_reply->pid != NULL);
			memcpy(se->spawn_reply->pid, &pid, sizeof(erlang_pid));

			switch_thread_cond_signal(se->spawn_reply->ready_or_found);

			switch_mutex_unlock(se->spawn_reply->mutex);

			found++;

			break;
		}
	}
	switch_thread_rwlock_unlock(listener->session_rwlock);

	if (found) {
		ei_x_encode_atom(rbuf, "ok");
	} else {
		ei_x_encode_tuple_header(rbuf, 2);
		ei_x_encode_atom(rbuf, "error");
		ei_x_encode_atom(rbuf, "notfound");
	}

	return SWITCH_STATUS_SUCCESS;
}