device state tweaks

This commit is contained in:
Anthony Minessale 2013-10-23 20:45:29 -05:00
parent 82c27013d7
commit 9e77e6f392
2 changed files with 106 additions and 5 deletions

View File

@ -82,18 +82,33 @@ typedef struct device_uuid_node_s {
switch_channel_callstate_t callstate; switch_channel_callstate_t callstate;
switch_hold_record_t *hold_record; switch_hold_record_t *hold_record;
switch_caller_profile_t *hup_profile; switch_caller_profile_t *hup_profile;
switch_call_direction_t direction;
struct switch_device_record_s *parent; struct switch_device_record_s *parent;
struct device_uuid_node_s *next; struct device_uuid_node_s *next;
} switch_device_node_t; } switch_device_node_t;
typedef struct switch_device_stats_s { typedef struct switch_device_stats_s {
uint32_t total; uint32_t total;
uint32_t total_in;
uint32_t total_out;
uint32_t offhook; uint32_t offhook;
uint32_t offhook_in;
uint32_t offhook_out;
uint32_t active; uint32_t active;
uint32_t active_in;
uint32_t active_out;
uint32_t held; uint32_t held;
uint32_t held_in;
uint32_t held_out;
uint32_t hup; uint32_t hup;
uint32_t hup_in;
uint32_t hup_out;
uint32_t ringing; uint32_t ringing;
uint32_t ringing_in;
uint32_t ringing_out;
uint32_t early; uint32_t early;
uint32_t early_in;
uint32_t early_out;
} switch_device_stats_t; } switch_device_stats_t;
@ -102,15 +117,22 @@ typedef struct switch_device_record_s {
char *uuid; char *uuid;
int refs; int refs;
switch_device_stats_t stats; switch_device_stats_t stats;
switch_device_stats_t last_stats;
switch_device_state_t state; switch_device_state_t state;
switch_device_state_t last_state; switch_device_state_t last_state;
switch_time_t active_start; switch_time_t active_start;
switch_time_t active_stop; switch_time_t active_stop;
switch_time_t last_call_time; 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_list;
struct device_uuid_node_s *uuid_tail; struct device_uuid_node_s *uuid_tail;
switch_mutex_t *mutex; switch_mutex_t *mutex;
switch_memory_pool_t *pool; switch_memory_pool_t *pool;
void *user_data;
} switch_device_record_t; } 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); typedef void(*switch_device_state_function_t)(switch_core_session_t *session, switch_channel_callstate_t callstate, switch_device_record_t *drec);

View File

@ -278,6 +278,10 @@ SWITCH_DECLARE(void) switch_channel_perform_set_callstate(switch_channel_t *chan
switch_channel_check_device_state(channel, channel->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) { 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_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); 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; channel->state = CS_HANGUP;
switch_mutex_unlock(channel->state_mutex); switch_mutex_unlock(channel->state_mutex);
process_device_hup(channel);
channel->hangup_cause = hangup_cause; 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", 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)); 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; switch_device_node_t *np;
memset(&drec->stats, 0, sizeof(switch_device_stats_t)); memset(&drec->stats, 0, sizeof(switch_device_stats_t));
switch_mutex_lock(drec->mutex); switch_mutex_lock(drec->mutex);
for(np = drec->uuid_list; np; np = np->next) { for(np = drec->uuid_list; np; np = np->next) {
drec->stats.total++; drec->stats.total++;
if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
drec->stats.total_in++;
} else {
drec->stats.total_out++;
}
if (!np->hup_profile) { if (!np->hup_profile) {
drec->stats.offhook++; drec->stats.offhook++;
if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
drec->stats.offhook_in++;
} else {
drec->stats.offhook_out++;
}
if (np->callstate == CCS_HELD) { if (np->callstate == CCS_HELD) {
drec->stats.held++; drec->stats.held++;
if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
drec->stats.held_in++;
} else {
drec->stats.held_out++;
}
} else { } else {
if (np->callstate == CCS_EARLY) { if (np->callstate == CCS_EARLY) {
drec->stats.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) { } else if (np->callstate == CCS_RINGING) {
drec->stats.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) { } else if (np->callstate != CCS_DOWN) {
drec->stats.active++; drec->stats.active++;
if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
drec->stats.active_in++;
} else {
drec->stats.active_out++;
}
} }
} }
} else { } else {
drec->stats.hup++; drec->stats.hup++;
if (np->direction == SWITCH_CALL_DIRECTION_INBOUND) {
drec->stats.hup_in++;
} else {
drec->stats.hup_out++;
}
} }
} }
switch_mutex_unlock(drec->mutex); 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; drec->state = SDS_HANGUP;
} else { } else {
if (drec->stats.active == 0) { 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; drec->state = SDS_RINGING;
} else { } else {
if (drec->stats.held > 0) { if (drec->stats.held > 0) {
@ -4798,7 +4836,15 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_
return; return;
} }
if (!drec->call_start) {
drec->call_start = switch_micro_time_now();
}
switch(drec->state) { switch(drec->state) {
case SDS_RINGING:
drec->ring_start = switch_micro_time_now();
drec->ring_stop = 0;
break;
case SDS_ACTIVE: case SDS_ACTIVE:
case SDS_ACTIVE_MULTI: case SDS_ACTIVE_MULTI:
if (drec->last_state != SDS_HELD && drec->active_start) { 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(); drec->active_start = switch_micro_time_now();
} }
break; break;
case SDS_HELD:
drec->hold_start = switch_micro_time_now();
drec->hold_stop = 0;
default: default:
if (drec->last_state != SDS_HELD) { if (drec->last_state != SDS_HELD) {
drec->active_stop = switch_micro_time_now(); drec->active_stop = switch_micro_time_now();
@ -4814,6 +4863,15 @@ static void switch_channel_check_device_state(switch_channel_t *channel, switch_
break; 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) { 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, "Device-ID", drec->device_id);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-Device-State", switch_channel_device_state2str(drec->last_state)); 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, 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), switch_channel_get_name(channel),
drec->device_id, drec->device_id,
switch_channel_callstate2str(callstate), 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.held,
drec->stats.hup, drec->stats.hup,
drec->active_stop ? (uint32_t)(drec->active_stop - drec->active_start) / 1000 : 0, 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" : ""); switch_channel_test_flag(channel, CF_FINAL_DEVICE_LEG) ? "FINAL LEG" : "");
for (ptr = globals.device_bindings; ptr; ptr = ptr->next) { for (ptr = globals.device_bindings; ptr; ptr = ptr->next) {
ptr->function(channel->session, callstate, drec); ptr->function(channel->session, callstate, drec);
} }
drec->last_stats = drec->stats;
if (drec->active_stop) { if (drec->active_stop) {
drec->active_start = drec->active_stop = 0; drec->active_start = drec->active_stop = 0;
if (drec->state == SDS_ACTIVE || drec->state == SDS_ACTIVE_MULTI) { 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_call_time = switch_micro_time_now();
drec->last_state = drec->state; 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->uuid = switch_core_strdup(drec->pool, switch_core_session_get_uuid(channel->session));
node->parent = drec; node->parent = drec;
node->callstate = channel->callstate; node->callstate = channel->callstate;
node->direction = channel->direction == SWITCH_CALL_DIRECTION_INBOUND ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND;
channel->device_node = node; channel->device_node = node;
if (!drec->uuid_list) { if (!drec->uuid_list) {