From 9e77e6f3923eda774eb2d46b79679e937fd9fbae Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 23 Oct 2013 20:45:29 -0500 Subject: [PATCH] device state tweaks --- src/include/switch_core.h | 22 ++++++++++ src/switch_channel.c | 89 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 106 insertions(+), 5 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 6d7d37e3bd..db3e67c5a8 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -82,18 +82,33 @@ typedef struct device_uuid_node_s { switch_channel_callstate_t callstate; switch_hold_record_t *hold_record; switch_caller_profile_t *hup_profile; + switch_call_direction_t direction; struct switch_device_record_s *parent; struct device_uuid_node_s *next; } switch_device_node_t; typedef struct switch_device_stats_s { uint32_t total; + uint32_t total_in; + uint32_t total_out; uint32_t offhook; + uint32_t offhook_in; + uint32_t offhook_out; uint32_t active; + uint32_t active_in; + uint32_t active_out; uint32_t held; + uint32_t held_in; + uint32_t held_out; uint32_t hup; + uint32_t hup_in; + uint32_t hup_out; uint32_t ringing; + uint32_t ringing_in; + uint32_t ringing_out; uint32_t early; + uint32_t early_in; + uint32_t early_out; } switch_device_stats_t; @@ -102,15 +117,22 @@ typedef struct switch_device_record_s { char *uuid; int refs; switch_device_stats_t stats; + switch_device_stats_t last_stats; switch_device_state_t state; switch_device_state_t last_state; switch_time_t active_start; switch_time_t active_stop; switch_time_t last_call_time; + switch_time_t ring_start; + switch_time_t ring_stop; + switch_time_t hold_start; + switch_time_t hold_stop; + switch_time_t call_start; struct device_uuid_node_s *uuid_list; struct device_uuid_node_s *uuid_tail; switch_mutex_t *mutex; switch_memory_pool_t *pool; + void *user_data; } switch_device_record_t; typedef void(*switch_device_state_function_t)(switch_core_session_t *session, switch_channel_callstate_t callstate, switch_device_record_t *drec); diff --git a/src/switch_channel.c b/src/switch_channel.c index be9e31b1d8..9e2cfcfdc8 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -277,7 +277,11 @@ SWITCH_DECLARE(void) switch_channel_perform_set_callstate(switch_channel_t *chan switch_channel_callstate2str(o_callstate), switch_channel_callstate2str(callstate)); switch_channel_check_device_state(channel, channel->callstate); - + + if (callstate == CCS_HANGUP) { + process_device_hup(channel); + } + if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_CALLSTATE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Original-Channel-Call-State", switch_channel_callstate2str(o_callstate)); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Call-State-Number", "%d", callstate); @@ -3102,8 +3106,6 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_chan channel->state = CS_HANGUP; switch_mutex_unlock(channel->state_mutex); - process_device_hup(channel); - channel->hangup_cause = hangup_cause; switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_channel_get_uuid(channel), SWITCH_LOG_NOTICE, "Hangup %s [%s] [%s]\n", channel->name, state_names[last_state], switch_channel_cause2str(channel->hangup_cause)); @@ -4614,28 +4616,64 @@ static void fetch_device_stats(switch_device_record_t *drec) { switch_device_node_t *np; + memset(&drec->stats, 0, sizeof(switch_device_stats_t)); switch_mutex_lock(drec->mutex); for(np = drec->uuid_list; np; np = np->next) { drec->stats.total++; + if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) { + drec->stats.total_in++; + } else { + drec->stats.total_out++; + } if (!np->hup_profile) { drec->stats.offhook++; + if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) { + drec->stats.offhook_in++; + } else { + drec->stats.offhook_out++; + } if (np->callstate == CCS_HELD) { drec->stats.held++; + if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) { + drec->stats.held_in++; + } else { + drec->stats.held_out++; + } } else { if (np->callstate == CCS_EARLY) { drec->stats.early++; + if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) { + drec->stats.early_in++; + } else { + drec->stats.early_out++; + } } else if (np->callstate == CCS_RINGING) { drec->stats.ringing++; + if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) { + drec->stats.ringing_in++; + } else { + drec->stats.ringing_out++; + } } else if (np->callstate != CCS_DOWN) { drec->stats.active++; + if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) { + drec->stats.active_in++; + } else { + drec->stats.active_out++; + } } } } else { drec->stats.hup++; + if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) { + drec->stats.hup_in++; + } else { + drec->stats.hup_out++; + } } } switch_mutex_unlock(drec->mutex); @@ -4776,7 +4814,7 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_ drec->state = SDS_HANGUP; } else { if (drec->stats.active == 0) { - if ((drec->stats.ringing + drec->stats.early) > 0) { + if ((drec->stats.ringing_out + drec->stats.early_out) > 0) { drec->state = SDS_RINGING; } else { if (drec->stats.held > 0) { @@ -4798,7 +4836,15 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_ return; } + if (!drec->call_start) { + drec->call_start = switch_micro_time_now(); + } + switch(drec->state) { + case SDS_RINGING: + drec->ring_start = switch_micro_time_now(); + drec->ring_stop = 0; + break; case SDS_ACTIVE: case SDS_ACTIVE_MULTI: if (drec->last_state != SDS_HELD && drec->active_start) { @@ -4807,6 +4853,9 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_ drec->active_start = switch_micro_time_now(); } break; + case SDS_HELD: + drec->hold_start = switch_micro_time_now(); + drec->hold_stop = 0; default: if (drec->last_state != SDS_HELD) { drec->active_stop = switch_micro_time_now(); @@ -4814,6 +4863,15 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_ break; } + if (drec->ring_start && !drec->ring_stop && drec->state != SDS_RINGING) { + drec->ring_stop = switch_micro_time_now(); + } + + if (drec->hold_start && !drec->hold_stop && drec->state != SDS_HELD) { + drec->hold_stop = switch_micro_time_now(); + } + + if (switch_event_create(&event, SWITCH_EVENT_DEVICE_STATE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Device-ID", drec->device_id); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-Device-State", switch_channel_device_state2str(drec->last_state)); @@ -4834,7 +4892,8 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_ } switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, - "%s device: %s\nState: %s Dev State: %s/%s Total:%u Offhook:%u Ringing:%u Early:%u Active:%u Held:%u Hungup:%u Dur: %u %s\n", + "%s device: %s\nState: %s Dev State: %s/%s Total:%u Offhook:%u " + "Ringing:%u Early:%u Active:%u Held:%u Hungup:%u Dur: %u Ringtime: %u Holdtime: %u %s\n", switch_channel_get_name(channel), drec->device_id, switch_channel_callstate2str(callstate), @@ -4848,12 +4907,16 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_ drec->stats.held, drec->stats.hup, drec->active_stop ? (uint32_t)(drec->active_stop - drec->active_start) / 1000 : 0, + drec->ring_stop ? (uint32_t)(drec->ring_stop - drec->ring_start) / 1000 : 0, + drec->hold_stop ? (uint32_t)(drec->hold_stop - drec->hold_start) / 1000 : 0, switch_channel_test_flag(channel, CF_FINAL_DEVICE_LEG) ? "FINAL LEG" : ""); for (ptr = globals.device_bindings; ptr; ptr = ptr->next) { ptr->function(channel->session, callstate, drec); } + drec->last_stats = drec->stats; + if (drec->active_stop) { drec->active_start = drec->active_stop = 0; if (drec->state == SDS_ACTIVE || drec->state == SDS_ACTIVE_MULTI) { @@ -4861,6 +4924,20 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_ } } + if (drec->hold_stop) { + drec->hold_start = drec->hold_stop = 0; + if (drec->state == SDS_HELD) { + drec->hold_start = switch_micro_time_now(); + } + } + + if (drec->ring_stop) { + drec->ring_start = drec->ring_stop = 0; + if (drec->state == SDS_RINGING) { + drec->ring_start = switch_micro_time_now(); + } + } + drec->last_call_time = switch_micro_time_now(); drec->last_state = drec->state; @@ -4888,6 +4965,8 @@ static void add_uuid(switch_device_record_t *drec, switch_channel_t *channel) node->uuid = switch_core_strdup(drec->pool, switch_core_session_get_uuid(channel->session)); node->parent = drec; node->callstate = channel->callstate; + node->direction = channel->direction == SWITCH_CALL_DIRECTION_INBOUND ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND; + channel->device_node = node; if (!drec->uuid_list) {