Exemple #1
0
static switch_status_t my_on_reporting(switch_core_session_t *session)
{
	switch_status_t status = SWITCH_STATUS_SUCCESS;
	switch_channel_t *channel = switch_core_session_get_channel(session);
	switch_event_header_t *hi;
	switch_caller_profile_t *caller_profile;
	switch_app_log_t *app_log;
	bson cdr;
	int is_b;
	char *tmp;

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

	bson_init(&cdr);

	/* Channel data */
	bson_append_start_object(&cdr, "channel_data");
	bson_append_string(&cdr, "state", switch_channel_state_name(switch_channel_get_state(channel)));
	bson_append_string(&cdr, "direction", switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");
	bson_append_int(&cdr, "state_number", switch_channel_get_state(channel));

	if ((tmp = switch_channel_get_flag_string(channel))) {
		bson_append_string(&cdr, "flags", tmp);
		free(tmp);
	}

	if ((tmp = switch_channel_get_cap_string(channel))) {
		bson_append_string(&cdr, "caps", tmp);
		free(tmp);
	}
	bson_append_finish_object(&cdr);				/* channel_data */


	/* Channel variables */
	bson_append_start_object(&cdr, "variables");

	if ((hi = switch_channel_variable_first(channel))) {
		for (; hi; hi = hi->next) {
			if (!zstr(hi->name) && !zstr(hi->value)) {
				bson_append_string(&cdr, hi->name, hi->value);
			}
		}
		switch_channel_variable_last(channel);
	}

	bson_append_finish_object(&cdr);				/* variables */


	/* App log */
	if ((app_log = switch_core_session_get_app_log(session))) {
		switch_app_log_t *ap;

		bson_append_start_object(&cdr, "app_log");
		for (ap = app_log; ap; ap = ap->next) {
			bson_append_start_object(&cdr, "application");
			bson_append_string(&cdr, "app_name", ap->app);
			bson_append_string(&cdr, "app_data", ap->arg);
			bson_append_long(&cdr, "app_stamp", ap->stamp);
			bson_append_finish_object(&cdr);		/* application */
		}

		bson_append_finish_object(&cdr);			/* app_log */
	}


	/* Callflow */
	caller_profile = switch_channel_get_caller_profile(channel);

	while (caller_profile) {
		bson_append_start_object(&cdr, "callflow");

		if (!zstr(caller_profile->dialplan)) {
			bson_append_string(&cdr, "dialplan", caller_profile->dialplan);
		}

		if (!zstr(caller_profile->profile_index)) {
			bson_append_string(&cdr, "profile_index", caller_profile->profile_index);
		}

		if (caller_profile->caller_extension) {
			switch_caller_application_t *ap;

			bson_append_start_object(&cdr, "extension");

			bson_append_string(&cdr, "name", caller_profile->caller_extension->extension_name);
			bson_append_string(&cdr, "number", caller_profile->caller_extension->extension_number);

			if (caller_profile->caller_extension->current_application) {
				bson_append_string(&cdr, "current_app", caller_profile->caller_extension->current_application->application_name);
			}

			for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) {
				bson_append_start_object(&cdr, "application");
				if (ap == caller_profile->caller_extension->current_application) {
					bson_append_bool(&cdr, "last_executed", 1);
				}
				bson_append_string(&cdr, "app_name", ap->application_name);
				bson_append_string(&cdr, "app_data", ap->application_data);
				bson_append_finish_object(&cdr);
			}

			if (caller_profile->caller_extension->children) {
				switch_caller_profile_t *cp = NULL;

				for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) {

					if (!cp->caller_extension) {
						continue;
					}

					bson_append_start_object(&cdr, "sub_extensions");
					bson_append_start_object(&cdr, "extension");

					bson_append_string(&cdr, "name", cp->caller_extension->extension_name);
					bson_append_string(&cdr, "number", cp->caller_extension->extension_number);
					bson_append_string(&cdr, "dialplan", cp->dialplan);
					if (cp->caller_extension->current_application) {
						bson_append_string(&cdr, "current_app", cp->caller_extension->current_application->application_name);
					}

					for (ap = cp->caller_extension->applications; ap; ap = ap->next) {
						bson_append_start_object(&cdr, "application");
						if (ap == cp->caller_extension->current_application) {
							bson_append_bool(&cdr, "last_executed", 1);
						}
						bson_append_string(&cdr, "app_name", ap->application_name);
						bson_append_string(&cdr, "app_data", ap->application_data);
						bson_append_finish_object(&cdr);
					}

					bson_append_finish_object(&cdr);	/* extension */
					bson_append_finish_object(&cdr);	/* sub_extensions */
				}
			}

			bson_append_finish_object(&cdr);			/* extension */
		}

		bson_append_start_object(&cdr, "caller_profile");
		set_bson_profile_data(&cdr, caller_profile);

		if (caller_profile->origination_caller_profile) {
			switch_caller_profile_t *cp = NULL;

			bson_append_start_object(&cdr, "origination");
			for (cp = caller_profile->origination_caller_profile; cp; cp = cp->next) {
				bson_append_start_object(&cdr, "origination_caller_profile");
				set_bson_profile_data(&cdr, cp);
				bson_append_finish_object(&cdr);
			}
			bson_append_finish_object(&cdr);			/* origination */
		}

		if (caller_profile->originator_caller_profile) {
			switch_caller_profile_t *cp = NULL;

			bson_append_start_object(&cdr, "originator");
			for (cp = caller_profile->originator_caller_profile; cp; cp = cp->next) {
				bson_append_start_object(&cdr, "originator_caller_profile");
				set_bson_profile_data(&cdr, cp);
				bson_append_finish_object(&cdr);
			}
			bson_append_finish_object(&cdr);			/* originator */
		}

		if (caller_profile->originatee_caller_profile) {
			switch_caller_profile_t *cp = NULL;

			bson_append_start_object(&cdr, "originatee");
			for (cp = caller_profile->originatee_caller_profile; cp; cp = cp->next) {
				bson_append_start_object(&cdr, "originatee_caller_profile");
				set_bson_profile_data(&cdr, cp);
				bson_append_finish_object(&cdr);
			}
			bson_append_finish_object(&cdr);			/* originatee */
		}

		bson_append_finish_object(&cdr);				/* caller_profile */

		/* Timestamps */
		if (caller_profile->times) {
			bson_append_start_object(&cdr, "times");

			/* Insert timestamps as long ints (microseconds) to preserve accuracy */
			bson_append_long(&cdr, "created_time", caller_profile->times->created);
			bson_append_long(&cdr, "profile_created_time", caller_profile->times->profile_created);
			bson_append_long(&cdr, "progress_time", caller_profile->times->progress);
			bson_append_long(&cdr, "progress_media_time", caller_profile->times->progress_media);
			bson_append_long(&cdr, "answered_time", caller_profile->times->answered);
			bson_append_long(&cdr, "bridged_time", caller_profile->times->bridged);
			bson_append_long(&cdr, "last_hold_time", caller_profile->times->last_hold);
			bson_append_long(&cdr, "hold_accum_time", caller_profile->times->hold_accum);
			bson_append_long(&cdr, "hangup_time", caller_profile->times->hungup);
			bson_append_long(&cdr, "resurrect_time", caller_profile->times->resurrected);
			bson_append_long(&cdr, "transfer_time", caller_profile->times->transferred);
			bson_append_finish_object(&cdr);			/* times */
		}

		bson_append_finish_object(&cdr);				/* callflow */
		caller_profile = caller_profile->next;
	}

	bson_finish(&cdr);

	switch_mutex_lock(globals.mongo_mutex);

	if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr) != MONGO_OK) {
		if (globals.mongo_conn->err == MONGO_IO_ERROR) {
			mongo_error_t db_status;
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "MongoDB connection failed; attempting reconnect...\n");
			db_status = mongo_reconnect(globals.mongo_conn);

			if (db_status != MONGO_OK) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MongoDB reconnect failed with error code %d\n", db_status);
				status = SWITCH_STATUS_FALSE;
			} else {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MongoDB connection re-established.\n");
				if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr) != MONGO_OK) {
					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: error code %d\n", globals.mongo_conn->err);
					status = SWITCH_STATUS_FALSE;
				}
			}

		} else {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: error code %d\n", globals.mongo_conn->err);
			status = SWITCH_STATUS_FALSE;
		}
	}

	switch_mutex_unlock(globals.mongo_mutex);
	bson_destroy(&cdr);

	return status;
}
static switch_status_t generate_json_cdr(switch_core_session_t *session, struct json_object **json_cdr)
{

	struct json_object *cdr = json_object_new_object();
	switch_channel_t *channel = switch_core_session_get_channel(session);
	switch_caller_profile_t *caller_profile;
	struct json_object *variables, *j_main_cp, *j_caller_profile, *j_caller_extension, *j_times, *time_tag,
		*j_application, *j_callflow, *j_inner_extension, *j_apps, *j_o, *j_channel_data, *j_field;
	switch_app_log_t *app_log;
	char tmp[512], *f;
	
	if (is_error(cdr)) {
		return SWITCH_STATUS_FALSE;
	}

	j_channel_data = json_object_new_object();
	if (is_error(j_channel_data)) {
		goto error;
	}
	json_object_object_add(cdr, "channel_data", j_channel_data);

	
	j_field = json_object_safe_new_string((char *) switch_channel_state_name(switch_channel_get_state(channel)));
	json_object_object_add(j_channel_data, "state", j_field);

	j_field = json_object_safe_new_string(switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound");

	json_object_object_add(j_channel_data, "direction", j_field);


	switch_snprintf(tmp, sizeof(tmp), "%d", switch_channel_get_state(channel));
	j_field = json_object_new_string((char *) tmp);
	json_object_object_add(j_channel_data, "state_number", j_field);
	

	if ((f = switch_channel_get_flag_string(channel))) {
		j_field = json_object_safe_new_string((char *) f);
		json_object_object_add(j_channel_data, "flags", j_field);
		free(f);
	}

	if ((f = switch_channel_get_cap_string(channel))) {
		j_field = json_object_safe_new_string((char *) f);
		json_object_object_add(j_channel_data, "caps", j_field);
		free(f);
	}


	variables = json_object_new_object();
	json_object_object_add(cdr, "variables", variables);

	if (is_error(variables)) {
		goto error;
	}

	set_json_chan_vars(variables, channel);


	if ((app_log = switch_core_session_get_app_log(session))) {
		switch_app_log_t *ap;

		j_apps = json_object_new_object();

		if (is_error(j_apps)) {
			goto error;
		}

		json_object_object_add(cdr, "app_log", j_apps);

		for (ap = app_log; ap; ap = ap->next) {
			j_application = json_object_new_object();

			if (is_error(j_application)) {
				goto error;
			}

			json_object_object_add(j_application, "app_name", json_object_safe_new_string(ap->app));
			json_object_object_add(j_application, "app_data", json_object_safe_new_string(ap->arg));

			json_object_object_add(j_apps, "application", j_application);
		}
	}


	caller_profile = switch_channel_get_caller_profile(channel);

	while (caller_profile) {

		j_callflow = json_object_new_object();

		if (is_error(j_callflow)) {
			goto error;
		}

		json_object_object_add(cdr, "callflow", j_callflow);

		if (!zstr(caller_profile->dialplan)) {
			json_object_object_add(j_callflow, "dialplan", json_object_safe_new_string((char *)caller_profile->dialplan));
		}

		if (!zstr(caller_profile->profile_index)) {
			json_object_object_add(j_callflow, "profile_index", json_object_safe_new_string((char *)caller_profile->profile_index));
		}

		if (caller_profile->caller_extension) {
			switch_caller_application_t *ap;

			j_caller_extension = json_object_new_object();

			if (is_error(j_caller_extension)) {
				goto error;
			}

			json_object_object_add(j_callflow, "extension", j_caller_extension);

			json_object_object_add(j_caller_extension, "name", json_object_safe_new_string(caller_profile->caller_extension->extension_name));
			json_object_object_add(j_caller_extension, "number", json_object_safe_new_string(caller_profile->caller_extension->extension_number));

			if (caller_profile->caller_extension->current_application) {
				json_object_object_add(j_caller_extension, "current_app", json_object_safe_new_string(caller_profile->caller_extension->current_application->application_name));
			}

			for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) {
				j_application = json_object_new_object();

				if (is_error(j_application)) {
					goto error;
				}


				json_object_object_add(j_caller_extension, "application", j_application);

				if (ap == caller_profile->caller_extension->current_application) {
					json_object_object_add(j_application, "last_executed", json_object_new_string("true"));
				}
				json_object_object_add(j_application, "app_name", json_object_safe_new_string(ap->application_name));
				json_object_object_add(j_application, "app_data", json_object_safe_new_string(switch_str_nil(ap->application_data)));
			}

			if (caller_profile->caller_extension->children) {
				switch_caller_profile_t *cp = NULL;
				for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) {

					if (!cp->caller_extension) {
						continue;
					}

					j_inner_extension = json_object_new_object();
					if (is_error(j_inner_extension)) {
						goto error;
					}

					json_object_object_add(j_caller_extension, "sub_extensions", j_inner_extension);


					j_caller_extension = json_object_new_object();
					if (is_error(j_caller_extension)) {
						goto error;
					}

					json_object_object_add(j_inner_extension, "extension", j_caller_extension);

					json_object_object_add(j_caller_extension, "name", json_object_safe_new_string(cp->caller_extension->extension_name));
					json_object_object_add(j_caller_extension, "number", json_object_safe_new_string(cp->caller_extension->extension_number));

					json_object_object_add(j_caller_extension, "dialplan", json_object_safe_new_string((char *)cp->dialplan));

					if (cp->caller_extension->current_application) {
						json_object_object_add(j_caller_extension, "current_app", json_object_safe_new_string(cp->caller_extension->current_application->application_name));
					}

					for (ap = cp->caller_extension->applications; ap; ap = ap->next) {
						j_application = json_object_new_object();
						
						if (is_error(j_application)) {
							goto error;
						}
						json_object_object_add(j_caller_extension, "application", j_application);

						if (ap == cp->caller_extension->current_application) {
							json_object_object_add(j_application, "last_executed", json_object_new_string("true"));
						}
						json_object_object_add(j_application, "app_name", json_object_safe_new_string(ap->application_name));
						json_object_object_add(j_application, "app_data", json_object_safe_new_string(switch_str_nil(ap->application_data)));
					}
				}
			}
		}

		j_main_cp = json_object_new_object();
		if (is_error(j_main_cp)) {
			goto error;
		}

		json_object_object_add(j_callflow, "caller_profile", j_main_cp);

		set_json_profile_data(j_main_cp, caller_profile);

		if (caller_profile->originator_caller_profile) {
			switch_caller_profile_t *cp = NULL;

			j_o = json_object_new_object();
			if (is_error(j_o)) {
				goto error;
			}
			
			json_object_object_add(j_main_cp, "originator", j_o);

			for (cp = caller_profile->originator_caller_profile; cp; cp = cp->next) {
				j_caller_profile = json_object_new_object();
				if (is_error(j_caller_profile)) {
					goto error;
				}

				json_object_object_add(j_o, "originator_caller_profile", j_caller_profile);

				set_json_profile_data(j_caller_profile, cp);
			}
		}

		if (caller_profile->originatee_caller_profile) {
			switch_caller_profile_t *cp = NULL;

			j_o = json_object_new_object();
			if (is_error(j_o)) {
				goto error;
			}

			json_object_object_add(j_main_cp, "originatee", j_o);

			for (cp = caller_profile->originatee_caller_profile; cp; cp = cp->next) {

				j_caller_profile = json_object_new_object();
				if (is_error(j_caller_profile)) {
					goto error;
				}
				
				json_object_object_add(j_o, "originatee_caller_profile", j_caller_profile);
				set_json_profile_data(j_caller_profile, cp);
			}
		}

		if (caller_profile->times) {

			j_times = json_object_new_object();
			if (is_error(j_times)) {
				goto error;
			}

			json_object_object_add(j_callflow, "times", j_times);

			switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->created);
			time_tag = json_object_new_string(tmp);
			if (is_error(time_tag)) {
				goto error;
			}
			json_object_object_add(j_times, "created_time", time_tag);

			switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->profile_created);
			time_tag = json_object_new_string(tmp);
			if (is_error(time_tag)) {
				goto error;
			}
			json_object_object_add(j_times, "profile_created_time", time_tag);

			switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress);
			time_tag = json_object_new_string(tmp);
			if (is_error(time_tag)) {
				goto error;
			}
			json_object_object_add(j_times, "progress_time", time_tag);

			switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->progress_media);
			time_tag = json_object_new_string(tmp);
			if (is_error(time_tag)) {
				goto error;
			}
			json_object_object_add(j_times, "progress_media_time", time_tag);


			switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered);
			time_tag = json_object_new_string(tmp);
			if (is_error(time_tag)) {
				goto error;
			}
			json_object_object_add(j_times, "answered_time", time_tag);

			switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hungup);
			time_tag = json_object_new_string(tmp);
			if (is_error(time_tag)) {
				goto error;
			}
			json_object_object_add(j_times, "hangup_time", time_tag);

			switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->resurrected);
			time_tag = json_object_new_string(tmp);
			if (is_error(time_tag)) {
				goto error;
			}
			json_object_object_add(j_times, "resurrect_time", time_tag);

			switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->transferred);
			time_tag = json_object_new_string(tmp);
			if (is_error(time_tag)) {
				goto error;
			}
			json_object_object_add(j_times, "transfer_time", time_tag);

		}

		caller_profile = caller_profile->next;
	}

	*json_cdr = cdr;

	return SWITCH_STATUS_SUCCESS;
	
  error:

	if (cdr) {
		json_object_put(cdr);
	}

	return SWITCH_STATUS_FALSE;
}