add bridged timestamp and hangup_complete_with_xml=true to add xml_cdr to the body of hangup_complete events

This commit is contained in:
Anthony Minessale 2011-04-28 13:46:39 -05:00
parent a391d82b57
commit bd471fc6a9
6 changed files with 97 additions and 26 deletions

View File

@ -49,6 +49,7 @@ SWITCH_BEGIN_EXTERN_C struct switch_channel_timetable {
switch_time_t hungup;
switch_time_t transferred;
switch_time_t resurrected;
switch_time_t bridged;
struct switch_channel_timetable *next;
};
@ -597,7 +598,7 @@ SWITCH_DECLARE(int) switch_channel_test_app_flag_key(const char *app, switch_cha
#define switch_channel_clear_app_flag(_c, _f) switch_channel_clear_app_flag_key(__FILE__, _c, _f)
#define switch_channel_test_app_flag(_c, _f) switch_channel_test_app_flag_key(__FILE__, _c, _f)
SWITCH_DECLARE(void) switch_channel_set_bridge_time(switch_channel_t *channel);
SWITCH_DECLARE(void) switch_channel_set_hangup_time(switch_channel_t *channel);
SWITCH_DECLARE(switch_call_direction_t) switch_channel_direction(switch_channel_t *channel);
SWITCH_DECLARE(switch_core_session_t *) switch_channel_get_session(switch_channel_t *channel);

View File

@ -239,20 +239,23 @@ SWITCH_DECLARE(switch_size_t) switch_fd_read_line(int fd, char *buf, switch_size
SWITCH_DECLARE(switch_status_t) switch_frame_alloc(switch_frame_t **frame, switch_size_t size);
SWITCH_DECLARE(switch_status_t) switch_frame_dup(switch_frame_t *orig, switch_frame_t **clone);
SWITCH_DECLARE(switch_status_t) switch_frame_free(switch_frame_t **frame);
SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str);
/*!
\brief Evaluate the truthfullness of a string expression
\param expr a string expression
\return true or false
*/
#define switch_true(expr)\
((expr && ( !strcasecmp(expr, "yes") ||\
!strcasecmp(expr, "on") ||\
!strcasecmp(expr, "true") ||\
!strcasecmp(expr, "enabled") ||\
!strcasecmp(expr, "active") ||\
!strcasecmp(expr, "allow") ||\
(switch_is_number(expr) && atoi(expr)))) ? SWITCH_TRUE : SWITCH_FALSE)
static inline int switch_true(const char *expr)
{
return ((expr && ( !strcasecmp(expr, "yes") ||
!strcasecmp(expr, "on") ||
!strcasecmp(expr, "true") ||
!strcasecmp(expr, "enabled") ||
!strcasecmp(expr, "active") ||
!strcasecmp(expr, "allow") ||
(switch_is_number(expr) && atoi(expr)))) ? SWITCH_TRUE : SWITCH_FALSE);
}
#define switch_true_buf(expr)\
((( !strcasecmp(expr, "yes") ||\
@ -268,14 +271,16 @@ SWITCH_DECLARE(switch_status_t) switch_frame_free(switch_frame_t **frame);
\param expr a string expression
\return true or false
*/
#define switch_false(expr)\
((expr && ( !strcasecmp(expr, "no") ||\
!strcasecmp(expr, "off") ||\
!strcasecmp(expr, "false") ||\
!strcasecmp(expr, "disabled") ||\
!strcasecmp(expr, "inactive") ||\
!strcasecmp(expr, "disallow") ||\
(switch_is_number(expr) && !atoi(expr)))) ? SWITCH_TRUE : SWITCH_FALSE)
static inline int switch_false(const char *expr)
{
return ((expr && ( !strcasecmp(expr, "no") ||
!strcasecmp(expr, "off") ||
!strcasecmp(expr, "false") ||
!strcasecmp(expr, "disabled") ||
!strcasecmp(expr, "inactive") ||
!strcasecmp(expr, "disallow") ||
(switch_is_number(expr) && !atoi(expr)))) ? SWITCH_TRUE : SWITCH_FALSE);
}
SWITCH_DECLARE(switch_status_t) switch_resolve_host(const char *host, char *buf, size_t buflen);
@ -670,7 +675,7 @@ SWITCH_DECLARE(switch_time_t) switch_str_time(const char *in);
SWITCH_DECLARE(unsigned int) switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen);
SWITCH_DECLARE(unsigned int) switch_separate_string_string(char *buf, char *delim, _Post_count_(return) char **array, unsigned int arraylen);
SWITCH_DECLARE(switch_bool_t) switch_is_number(const char *str);
SWITCH_DECLARE(char *) switch_strip_spaces(char *str, switch_bool_t dup);
SWITCH_DECLARE(char *) switch_strip_whitespace(const char *str);
SWITCH_DECLARE(char *) switch_strip_commas(char *in, char *out, switch_size_t len);

View File

@ -2513,11 +2513,21 @@ SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_caller_extension(
}
SWITCH_DECLARE(void) switch_channel_set_bridge_time(switch_channel_t *channel)
{
switch_mutex_lock(channel->profile_mutex);
if (channel->caller_profile && channel->caller_profile->times) {
channel->caller_profile->times->bridged = switch_micro_time_now();
}
switch_mutex_unlock(channel->profile_mutex);
}
SWITCH_DECLARE(void) switch_channel_set_hangup_time(switch_channel_t *channel)
{
if (channel->caller_profile && channel->caller_profile->times && !channel->caller_profile->times->hungup) {
if (channel->caller_profile && channel->caller_profile->times && !channel->caller_profile->times->bridged) {
switch_mutex_lock(channel->profile_mutex);
channel->caller_profile->times->hungup = switch_micro_time_now();
channel->caller_profile->times->bridged = switch_micro_time_now();
switch_mutex_unlock(channel->profile_mutex);
}
}
@ -3348,14 +3358,14 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
switch_caller_profile_t *caller_profile, *ocp;
switch_app_log_t *app_log, *ap;
char *last_app = NULL, *last_arg = NULL;
char start[80] = "", resurrect[80] = "", answer[80] = "", progress[80] = "", progress_media[80] = "", end[80] = "", tmp[80] = "",
char start[80] = "", resurrect[80] = "", answer[80] = "", bridge[80] = "", progress[80] = "", progress_media[80] = "", end[80] = "", tmp[80] = "",
profile_start[80] = "";
int32_t duration = 0, legbillsec = 0, billsec = 0, mduration = 0, billmsec = 0, legbillmsec = 0, progressmsec = 0, progress_mediamsec = 0;
int32_t answersec = 0, answermsec = 0;
int32_t answersec = 0, answermsec = 0, waitsec = 0, waitmsec = 0;
switch_time_t answerusec = 0;
switch_time_t uduration = 0, legbillusec = 0, billusec = 0, progresssec = 0, progressusec = 0, progress_mediasec = 0, progress_mediausec = 0;
time_t tt_created = 0, tt_answered = 0, tt_resurrected = 0,
tt_progress = 0, tt_progress_media = 0, tt_hungup = 0, mtt_created = 0, mtt_answered = 0,
switch_time_t uduration = 0, legbillusec = 0, billusec = 0, progresssec = 0, progressusec = 0, progress_mediasec = 0, progress_mediausec = 0, waitusec = 0;
time_t tt_created = 0, tt_answered = 0, tt_resurrected = 0, tt_bridged,
tt_progress = 0, tt_progress_media = 0, tt_hungup = 0, mtt_created = 0, mtt_answered = 0, mtt_bridged = 0,
mtt_hungup = 0, tt_prof_created, mtt_prof_created, mtt_progress = 0, mtt_progress_media = 0;
void *pop;
char dtstr[SWITCH_DTMF_LOG_LEN + 1] = "";
@ -3427,6 +3437,12 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
switch_channel_set_variable(channel, "answer_stamp", answer);
}
if (caller_profile->times->bridged) {
switch_time_exp_lt(&tm, caller_profile->times->bridged);
switch_strftime_nocheck(bridge, &retsize, sizeof(bridge), fmt, &tm);
switch_channel_set_variable(channel, "bridge_stamp", bridge);
}
if (caller_profile->times->resurrected) {
switch_time_exp_lt(&tm, caller_profile->times->resurrected);
switch_strftime_nocheck(resurrect, &retsize, sizeof(resurrect), fmt, &tm);
@ -3470,6 +3486,13 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered);
switch_channel_set_variable(channel, "answer_uepoch", tmp);
tt_bridged = (time_t) (caller_profile->times->bridged / 1000000);
mtt_bridged = (time_t) (caller_profile->times->bridged / 1000);
switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_bridged);
switch_channel_set_variable(channel, "bridge_epoch", tmp);
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->bridged);
switch_channel_set_variable(channel, "bridge_uepoch", tmp);
tt_resurrected = (time_t) (caller_profile->times->resurrected / 1000000);
switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_resurrected);
switch_channel_set_variable(channel, "resurrect_epoch", tmp);
@ -3501,6 +3524,16 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
mduration = (int32_t) (mtt_hungup - mtt_created);
uduration = caller_profile->times->hungup - caller_profile->times->created;
if (caller_profile->times->bridged > caller_profile->times->created) {
waitsec = (int32_t) (tt_bridged - tt_created);
waitmsec = (int32_t) (mtt_bridged - mtt_created);
waitusec = caller_profile->times->bridged - caller_profile->times->created;
} else {
waitsec = 0;
waitmsec = 0;
waitusec = 0;
}
if (caller_profile->times->answered) {
billsec = (int32_t) (tt_hungup - tt_answered);
billmsec = (int32_t) (mtt_hungup - mtt_answered);
@ -3545,6 +3578,9 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
switch_snprintf(tmp, sizeof(tmp), "%d", answersec);
switch_channel_set_variable(channel, "answersec", tmp);
switch_snprintf(tmp, sizeof(tmp), "%d", waitsec);
switch_channel_set_variable(channel, "waitsec", tmp);
switch_snprintf(tmp, sizeof(tmp), "%d", progress_mediasec);
switch_channel_set_variable(channel, "progress_mediasec", tmp);
@ -3563,6 +3599,9 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
switch_snprintf(tmp, sizeof(tmp), "%d", answermsec);
switch_channel_set_variable(channel, "answermsec", tmp);
switch_snprintf(tmp, sizeof(tmp), "%d", waitmsec);
switch_channel_set_variable(channel, "waitmsec", tmp);
switch_snprintf(tmp, sizeof(tmp), "%d", progress_mediamsec);
switch_channel_set_variable(channel, "progress_mediamsec", tmp);
@ -3581,6 +3620,9 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t *
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, answerusec);
switch_channel_set_variable(channel, "answerusec", tmp);
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, waitusec);
switch_channel_set_variable(channel, "waitusec", tmp);
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, progress_mediausec);
switch_channel_set_variable(channel, "progress_mediausec", tmp);

View File

@ -636,6 +636,18 @@ SWITCH_DECLARE(void) switch_core_session_reporting_state(switch_core_session_t *
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", switch_channel_cause2str(cause));
switch_channel_event_set_data(session->channel, event);
if (switch_true(switch_channel_get_variable(session->channel, "hangup_complete_with_xml"))) {
switch_xml_t cdr = NULL;
char *xml_cdr_text;
if (switch_ivr_generate_xml_cdr(session, &cdr) == SWITCH_STATUS_SUCCESS) {
xml_cdr_text = switch_xml_toxml(cdr, SWITCH_FALSE);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CDR-Attached", "xml");
switch_event_add_body(event, "%s", xml_cdr_text);
switch_xml_free(cdr);
switch_safe_free(xml_cdr_text);
}
}
switch_event_fire(&event);
}

View File

@ -2219,6 +2219,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_generate_xml_cdr(switch_core_session_
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->answered);
switch_xml_set_txt_d(time_tag, tmp);
if (!(time_tag = switch_xml_add_child_d(x_times, "bridged_time", t_off++))) {
goto error;
}
switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->bridged);
switch_xml_set_txt_d(time_tag, tmp);
if (!(time_tag = switch_xml_add_child_d(x_times, "hangup_time", t_off++))) {
goto error;
}

View File

@ -201,7 +201,9 @@ static void *audio_bridge_thread(switch_thread_t *thread, void *obj)
chan_a = switch_core_session_get_channel(session_a);
chan_b = switch_core_session_get_channel(session_b);
switch_channel_set_bridge_time(chan_a);
if ((exec_app = switch_channel_get_variable(chan_a, "bridge_pre_execute_app"))) {
exec_data = switch_channel_get_variable(chan_a, "bridge_pre_execute_data");
}
@ -1067,6 +1069,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_signal_bridge(switch_core_session_t *
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Application-Data", switch_core_session_get_uuid(session));
switch_event_fire(&event);
}
switch_channel_set_bridge_time(caller_channel);
switch_channel_set_bridge_time(peer_channel);
switch_channel_set_state_flag(caller_channel, CF_RESET);
switch_channel_set_state_flag(peer_channel, CF_RESET);