add conference cdrs to mod_conference

This commit is contained in:
Anthony Minessale 2011-10-14 11:30:51 -05:00
parent 0b1adc6a20
commit 127be02db2
2 changed files with 220 additions and 0 deletions

View File

@ -29,6 +29,13 @@
<profiles>
<!--If no profile is specified it will default to "default"-->
<profile name="default">
<!-- Directory to drop CDR's
'auto' means $PREFIX/logs/conference_cdr/<confernece_uuid>.cdr.xml
a non-absolute path means $PREFIX/logs/<value>/<confernece_uuid>.cdr.xml
absolute path means <value>/<confernece_uuid>.cdr.xml
-->
<!-- <param name="cdr-log-dir" value="auto"/> -->
<!-- Domain (for presence) -->
<param name="domain" value="$${domain}"/>
<!-- Sample Rate-->

View File

@ -43,6 +43,16 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_conference_shutdown);
SWITCH_MODULE_DEFINITION(mod_conference, mod_conference_load, mod_conference_shutdown, NULL);
typedef struct conference_cdr_node_s {
switch_caller_profile_t *cp;
char *record_path;
switch_time_t join_time;
switch_time_t leave_time;
struct conference_cdr_node_s *next;
} conference_cdr_node_t;
typedef enum {
CONF_SILENT_REQ = (1 << 0),
CONF_SILENT_DONE = (1 << 1)
@ -308,6 +318,10 @@ typedef struct conference_obj {
char *uuid_str;
uint32_t originating;
switch_call_cause_t cancel_cause;
conference_cdr_node_t *cdr_nodes;
switch_time_t start_time;
switch_time_t end_time;
char *log_dir;
} conference_obj_t;
/* Relationship with another member */
@ -369,6 +383,7 @@ struct conference_member {
uint32_t avg_tally;
struct conference_member *next;
switch_ivr_dmachine_t *dmachine;
conference_cdr_node_t *cdr_node;
};
/* Record Node */
@ -466,6 +481,173 @@ static switch_status_t conference_add_event_member_data(conference_member_t *mem
//#define lock_member(_member) switch_mutex_lock(_member->write_mutex)
//#define unlock_member(_member) switch_mutex_unlock(_member->write_mutex)
static void conference_cdr_del(conference_member_t *member)
{
member->cdr_node->leave_time = switch_epoch_time_now(NULL);
}
static void conference_cdr_add(conference_member_t *member)
{
conference_cdr_node_t *np;
switch_caller_profile_t *cp;
switch_channel_t *channel;
np = switch_core_alloc(member->conference->pool, sizeof(*np));
np->next = member->conference->cdr_nodes;
member->conference->cdr_nodes = member->cdr_node = np;
member->cdr_node->join_time = switch_epoch_time_now(NULL);
if (!member->session) {
member->cdr_node->record_path = switch_core_strdup(member->conference->pool, member->rec_path);
return;
}
channel = switch_core_session_get_channel(member->session);
if (!(cp = switch_channel_get_caller_profile(channel))) {
return;
}
member->cdr_node->cp = switch_caller_profile_dup(member->conference->pool, cp);
}
static void conference_cdr_render(conference_obj_t *conference)
{
switch_xml_t cdr, x_ptr, x_member, x_members, x_conference, x_cp;
conference_cdr_node_t *np;
int cdr_off = 0, conf_off = 0;
char str[512];
char *path, *xml_text;
int fd;
if (zstr(conference->log_dir)) return;
if (!conference->cdr_nodes) return;
if (!(cdr = switch_xml_new("cdr"))) {
abort();
}
if (!(x_conference = switch_xml_add_child_d(cdr, "conference", cdr_off++))) {
abort();
}
if (!(x_ptr = switch_xml_add_child_d(x_conference, "name", conf_off++))) {
abort();
}
switch_xml_set_txt_d(x_ptr, conference->name);
if (!(x_ptr = switch_xml_add_child_d(x_conference, "rate", conf_off++))) {
abort();
}
switch_snprintf(str, sizeof(str), "%d", conference->rate);
switch_xml_set_txt_d(x_ptr, str);
if (!(x_ptr = switch_xml_add_child_d(x_conference, "interval", conf_off++))) {
abort();
}
switch_snprintf(str, sizeof(str), "%d", conference->interval);
switch_xml_set_txt_d(x_ptr, str);
if (!(x_ptr = switch_xml_add_child_d(x_conference, "start_time", conf_off++))) {
abort();
}
switch_xml_set_attr_d(x_ptr, "type", "UNIX-epoch");
switch_snprintf(str, sizeof(str), "%ld", (long)conference->start_time);
switch_xml_set_txt_d(x_ptr, str);
if (!(x_ptr = switch_xml_add_child_d(x_conference, "end_time", conf_off++))) {
abort();
}
switch_xml_set_attr_d(x_ptr, "type", "UNIX-epoch");
switch_snprintf(str, sizeof(str), "%ld", (long)conference->end_time);
switch_xml_set_txt_d(x_ptr, str);
if (!(x_members = switch_xml_add_child_d(x_conference, "members", conf_off++))) {
abort();
}
for (np = conference->cdr_nodes; np; np = np->next) {
int member_off = 0;
if (!(x_member = switch_xml_add_child_d(x_members, "member", conf_off++))) {
abort();
}
switch_xml_set_attr_d(x_member, "type", np->cp ? "caller" : "recording_node");
if (!(x_ptr = switch_xml_add_child_d(x_member, "join_time", member_off++))) {
abort();
}
switch_xml_set_attr_d(x_ptr, "type", "UNIX-epoch");
switch_snprintf(str, sizeof(str), "%ld", (long) np->join_time);
switch_xml_set_txt_d(x_ptr, str);
if (!(x_ptr = switch_xml_add_child_d(x_member, "leave_time", member_off++))) {
abort();
}
switch_xml_set_attr_d(x_ptr, "type", "UNIX-epoch");
switch_snprintf(str, sizeof(str), "%ld", (long) np->leave_time);
switch_xml_set_txt_d(x_ptr, str);
if (np->cp) {
if (!(x_cp = switch_xml_add_child_d(x_member, "caller_profile", member_off++))) {
abort();
}
switch_ivr_set_xml_profile_data(x_cp, np->cp, 0);
}
if (!zstr(np->record_path)) {
if (!(x_ptr = switch_xml_add_child_d(x_member, "record_path", member_off++))) {
abort();
}
switch_xml_set_txt_d(x_ptr, np->record_path);
}
}
xml_text = switch_xml_toxml(cdr, SWITCH_TRUE);
path = switch_mprintf("%s%s%s.cdr.xml", conference->log_dir, SWITCH_PATH_SEPARATOR, conference->uuid_str);
#ifdef _MSC_VER
if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) {
#else
if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) > -1) {
#endif
int wrote;
wrote = write(fd, xml_text, (unsigned) strlen(xml_text));
wrote++;
close(fd);
fd = -1;
} else {
char ebuf[512] = { 0 };
#ifdef WIN32
strerror_s(ebuf, sizeof(ebuf), errno);
#else
strerror_r(errno, ebuf, sizeof(ebuf));
#endif
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error writing [%s][%s]\n", path, ebuf);
}
switch_safe_free(path);
switch_safe_free(xml_text);
}
static switch_status_t conference_add_event_data(conference_obj_t *conference, switch_event_t *event)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
@ -692,6 +874,7 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
conference->members = member;
switch_set_flag_locked(member, MFLAG_INTREE);
switch_mutex_unlock(conference->member_mutex);
conference_cdr_add(member);
if (!switch_test_flag(member, MFLAG_NOCHANNEL)) {
conference->count++;
@ -847,6 +1030,11 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
lock_member(member);
conference_cdr_del(member);
member_fnode = member->fnode;
member_sh = member->sh;
member->fnode = NULL;
@ -1609,6 +1797,9 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
conference->sh = NULL;
}
conference->end_time = switch_epoch_time_now(NULL);
conference_cdr_render(conference);
if (conference->pool) {
switch_memory_pool_t *pool = conference->pool;
switch_core_destroy_memory_pool(&pool);
@ -3095,6 +3286,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
switch_safe_free(data_buf);
switch_core_timer_destroy(&timer);
conference_del_member(conference, member);
switch_buffer_destroy(&member->audio_buffer);
switch_buffer_destroy(&member->mux_buffer);
switch_clear_flag_locked(member, MFLAG_RUNNING);
@ -6513,6 +6705,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
char *suppress_events = NULL;
char *verbose_events = NULL;
char *auto_record = NULL;
char *conference_log_dir = NULL;
char *terminate_on_silence = NULL;
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH+1];
switch_uuid_t uuid;
@ -6642,6 +6835,8 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
member_flags = val;
} else if (!strcasecmp(var, "conference-flags") && !zstr(val)) {
conference_flags = val;
} else if (!strcasecmp(var, "cdr-log-dir") && !zstr(val)) {
conference_log_dir = val;
} else if (!strcasecmp(var, "kicked-sound") && !zstr(val)) {
kicked_sound = val;
} else if (!strcasecmp(var, "pin") && !zstr(val)) {
@ -6755,6 +6950,8 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
goto end;
}
conference->start_time = switch_epoch_time_now(NULL);
/* initialize the conference object with settings from the specified profile */
conference->pool = pool;
conference->profile_name = switch_core_strdup(conference->pool, cfg.profile ? switch_xml_attr_soft(cfg.profile, "name") : "none");
@ -6775,6 +6972,22 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c
conference->caller_controls = switch_core_strdup(conference->pool, caller_controls);
conference->moderator_controls = switch_core_strdup(conference->pool, moderator_controls);
conference->run_time = switch_epoch_time_now(NULL);
if (!zstr(conference_log_dir)) {
char *path;
if (!strcmp(conference_log_dir, "auto")) {
path = switch_core_sprintf(conference->pool, "%s%sconference_cdr", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR);
} else if (!switch_is_file_path(conference_log_dir)) {
path = switch_core_sprintf(conference->pool, "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, conference_log_dir);
} else {
path = switch_core_strdup(conference->pool, conference_log_dir);
}
switch_dir_make_recursive(path, SWITCH_DEFAULT_DIR_PERMS, conference->pool);
conference->log_dir = path;
}
if (!zstr(perpetual_sound)) {