diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 11ce877b8e..53117de6a7 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -50,6 +50,8 @@ SWITCH_BEGIN_EXTERN_C struct switch_channel_timetable { switch_time_t transferred; switch_time_t resurrected; switch_time_t bridged; + switch_time_t last_hold; + switch_time_t hold_accum; struct switch_channel_timetable *next; }; diff --git a/src/switch_channel.c b/src/switch_channel.c index f236014887..c818496bb9 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -1495,6 +1495,9 @@ SWITCH_DECLARE(void) switch_channel_set_flag_value(switch_channel_t *channel, sw if (HELD) { switch_channel_set_callstate(channel, CCS_HELD); + switch_mutex_lock(channel->profile_mutex); + channel->caller_profile->times->last_hold = switch_time_now(); + switch_mutex_unlock(channel->profile_mutex); } if (flag == CF_OUTBOUND) { @@ -1630,6 +1633,11 @@ SWITCH_DECLARE(void) switch_channel_clear_flag(switch_channel_t *channel, switch if (ACTIVE) { switch_channel_set_callstate(channel, CCS_ACTIVE); + switch_mutex_lock(channel->profile_mutex); + if (channel->caller_profile->times->last_hold) { + channel->caller_profile->times->hold_accum += (switch_time_now() - channel->caller_profile->times->last_hold); + } + switch_mutex_unlock(channel->profile_mutex); } if (flag == CF_OUTBOUND) { @@ -3508,13 +3516,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] = "", bridge[80] = "", progress[80] = "", progress_media[80] = "", end[80] = "", tmp[80] = "", + char start[80] = "", resurrect[80] = "", answer[80] = "", hold[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, 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, waitusec = 0; - time_t tt_created = 0, tt_answered = 0, tt_resurrected = 0, tt_bridged, + time_t tt_created = 0, tt_answered = 0, tt_resurrected = 0, tt_bridged, tt_last_hold, tt_hold_accum, 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; @@ -3593,6 +3602,12 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t * switch_channel_set_variable(channel, "bridge_stamp", bridge); } + if (caller_profile->times->last_hold) { + switch_time_exp_lt(&tm, caller_profile->times->last_hold); + switch_strftime_nocheck(hold, &retsize, sizeof(hold), fmt, &tm); + switch_channel_set_variable(channel, "hold_stamp", hold); + } + if (caller_profile->times->resurrected) { switch_time_exp_lt(&tm, caller_profile->times->resurrected); switch_strftime_nocheck(resurrect, &retsize, sizeof(resurrect), fmt, &tm); @@ -3643,6 +3658,20 @@ SWITCH_DECLARE(switch_status_t) switch_channel_set_timestamps(switch_channel_t * switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->bridged); switch_channel_set_variable(channel, "bridge_uepoch", tmp); + tt_last_hold = (time_t) (caller_profile->times->last_hold / 1000000); + switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_last_hold); + switch_channel_set_variable(channel, "last_hold_epoch", tmp); + switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->last_hold); + switch_channel_set_variable(channel, "last_hold_uepoch", tmp); + + tt_hold_accum = (time_t) (caller_profile->times->hold_accum / 1000000); + switch_snprintf(tmp, sizeof(tmp), "%" TIME_T_FMT, tt_hold_accum); + switch_channel_set_variable(channel, "hold_accum_seconds", tmp); + switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hold_accum); + switch_channel_set_variable(channel, "hold_accum_usec", tmp); + switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hold_accum / 1000); + switch_channel_set_variable(channel, "hold_accum_ms", 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); diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 6c1202a4ed..2929a547dc 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -2286,6 +2286,18 @@ 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->bridged); switch_xml_set_txt_d(time_tag, tmp); + if (!(time_tag = switch_xml_add_child_d(x_times, "last_hold_time", t_off++))) { + goto error; + } + switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->last_hold); + switch_xml_set_txt_d(time_tag, tmp); + + if (!(time_tag = switch_xml_add_child_d(x_times, "hold_accum_time", t_off++))) { + goto error; + } + switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, caller_profile->times->hold_accum); + switch_xml_set_txt_d(time_tag, tmp); + if (!(time_tag = switch_xml_add_child_d(x_times, "hangup_time", t_off++))) { goto error; }