diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 2348a4cc54..f4655a23e6 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -642,6 +642,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_api_on(switch_channel_t *channel, SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_queued_extension(switch_channel_t *channel); SWITCH_DECLARE(void) switch_channel_transfer_to_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension); SWITCH_DECLARE(const char *) switch_channel_get_partner_uuid(switch_channel_t *channel); +SWITCH_DECLARE(switch_hold_record_t *) switch_channel_get_hold_record(switch_channel_t *channel); SWITCH_END_EXTERN_C #endif diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 50ec7a965e..b340078f41 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -61,6 +61,16 @@ struct switch_app_log { struct switch_app_log *next; }; + +typedef struct switch_hold_record_s { + switch_time_t on; + switch_time_t off; + char *uuid; + struct switch_hold_record_s *next; +} switch_hold_record_t; + + + #define MESSAGE_STAMP_FFL(_m) _m->_file = __FILE__; _m->_func = __SWITCH_FUNC__; _m->_line = __LINE__ #define MESSAGE_STRING_ARG_MAX 10 diff --git a/src/switch_channel.c b/src/switch_channel.c index 38331f0be9..3f767ae21d 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -155,8 +155,13 @@ struct switch_channel { switch_event_t *app_list; switch_event_t *api_list; switch_event_t *var_list; + switch_hold_record_t *hold_record; }; +SWITCH_DECLARE(switch_hold_record_t *) switch_channel_get_hold_record(switch_channel_t *channel) +{ + return channel->hold_record; +} SWITCH_DECLARE(const char *) switch_channel_cause2str(switch_call_cause_t cause) { @@ -1611,9 +1616,24 @@ SWITCH_DECLARE(void) switch_channel_set_flag_value(switch_channel_t *channel, sw switch_mutex_unlock(channel->flag_mutex); if (HELD) { + switch_hold_record_t *hr; + const char *brto = switch_channel_get_partner_uuid(channel); + switch_channel_set_callstate(channel, CCS_HELD); switch_mutex_lock(channel->profile_mutex); channel->caller_profile->times->last_hold = switch_time_now(); + + hr = switch_core_session_alloc(channel->session, sizeof(*hr)); + hr->on = switch_time_now(); + if (brto) { + hr->uuid = switch_core_session_strdup(channel->session, brto); + } + + if (channel->hold_record) { + hr->next = channel->hold_record; + } + channel->hold_record = hr; + switch_mutex_unlock(channel->profile_mutex); } @@ -1763,6 +1783,11 @@ SWITCH_DECLARE(void) switch_channel_clear_flag(switch_channel_t *channel, switch if (channel->caller_profile->times->last_hold) { channel->caller_profile->times->hold_accum += (switch_time_now() - channel->caller_profile->times->last_hold); } + + if (channel->hold_record) { + channel->hold_record->off = switch_time_now(); + } + switch_mutex_unlock(channel->profile_mutex); } @@ -2905,6 +2930,12 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_chan switch_event_t *event; const char *var; + switch_mutex_lock(channel->profile_mutex); + if (channel->hold_record && !channel->hold_record->off) { + channel->hold_record->off = switch_time_now(); + } + switch_mutex_unlock(channel->profile_mutex); + switch_mutex_lock(channel->state_mutex); last_state = channel->state; channel->state = CS_HANGUP; diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 92f6186934..63721e66fd 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -2195,11 +2195,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_generate_xml_cdr(switch_core_session_ switch_channel_t *channel = switch_core_session_get_channel(session); switch_caller_profile_t *caller_profile; switch_xml_t variables, cdr, x_main_cp, x_caller_profile, x_caller_extension, x_times, time_tag, - x_application, x_callflow, x_inner_extension, x_apps, x_o, x_channel_data, x_field; + x_application, x_callflow, x_inner_extension, x_apps, x_o, x_channel_data, x_field, xhr, x_hold; switch_app_log_t *app_log; char tmp[512], *f; int cdr_off = 0, v_off = 0, cd_off = 0; - + switch_hold_record_t *hold_record = switch_channel_get_hold_record(channel), *hr; + if (*xml_cdr) { cdr = *xml_cdr; } else { @@ -2266,6 +2267,36 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_generate_xml_cdr(switch_core_session_ } } + if (hold_record) { + int cf_off = 0; + + if (!(xhr = switch_xml_add_child_d(cdr, "hold-record", cdr_off++))) { + goto error; + } + + for (hr = hold_record; hr; hr = hr->next) { + char *t = tmp; + if (!(x_hold = switch_xml_add_child_d(xhr, "hold", cf_off++))) { + goto error; + } + + switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, hr->on); + switch_xml_set_attr_d(x_hold, "on", t); + + switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, hr->off); + switch_xml_set_attr_d(x_hold, "off", t); + + if (hr->uuid) { + switch_xml_set_attr_d(x_hold, "bridged-to", hr->uuid); + } + + + } + + + } + + caller_profile = switch_channel_get_caller_profile(channel);