FS-6758 and other related behavior, also change to answer behavior to mimic what users tend to expect from cisco phones.
Updatd SKINNY on-hook action to hang up all calls on a device, except those in a short list of call states (or perform a blind transfer). Added a hook after completing the hangup operation to start ringing if there is an inbound call active on the device. Reorder received calls on skinny
This commit is contained in:
parent
3cd481820e
commit
9593796420
|
@ -303,11 +303,16 @@ char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *l
|
|||
call_id_condition = switch_mprintf("1=1");
|
||||
}
|
||||
switch_assert(call_id_condition);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
|
||||
"Attempting to find active call with criteria (%s and %s and %s)\n",
|
||||
device_condition, line_instance_condition, call_id_condition);
|
||||
|
||||
if((sql = switch_mprintf(
|
||||
"SELECT channel_uuid, line_instance "
|
||||
"FROM skinny_active_lines "
|
||||
"WHERE %s AND %s AND %s "
|
||||
"ORDER BY call_state, channel_uuid", /* off hook first */
|
||||
"ORDER BY call_state, line_instance, channel_uuid", /* off hook first */
|
||||
device_condition, line_instance_condition, call_id_condition
|
||||
))) {
|
||||
skinny_execute_sql_callback(profile, profile->sql_mutex, sql,
|
||||
|
@ -917,6 +922,79 @@ switch_status_t channel_on_destroy(switch_core_session_t *session)
|
|||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
struct skinny_ring_active_calls_helper {
|
||||
private_t *tech_pvt;
|
||||
listener_t *listener;
|
||||
};
|
||||
|
||||
int skinny_ring_active_calls_callback(void *pArg, int argc, char **argv, char **columnNames)
|
||||
{
|
||||
struct skinny_ring_active_calls_helper *helper = pArg;
|
||||
switch_core_session_t *session;
|
||||
|
||||
/* char *device_name = argv[0]; */
|
||||
/* uint32_t device_instance = atoi(argv[1]); */
|
||||
/* uint32_t position = atoi(argv[2]); */
|
||||
uint32_t line_instance = atoi(argv[3]);
|
||||
/* char *label = argv[4]; */
|
||||
/* char *value = argv[5]; */
|
||||
/* char *caller_name = argv[6]; */
|
||||
uint32_t ring_on_idle = atoi(argv[7]);
|
||||
/* uint32_t ring_on_active = atoi(argv[8]); */
|
||||
/* uint32_t busy_trigger = atoi(argv[9]); */
|
||||
/* char *forward_all = argv[10]; */
|
||||
/* char *forward_busy = argv[11]; */
|
||||
/* char *forward_noanswer = argv[12]; */
|
||||
/* uint32_t noanswer_duration = atoi(argv[13]); */
|
||||
/* char *channel_uuid = argv[14]; */
|
||||
uint32_t call_id = atoi(argv[15]);
|
||||
/* uint32_t call_state = atoi(argv[16]); */
|
||||
|
||||
session = skinny_profile_find_session(helper->listener->profile, helper->listener, &line_instance, call_id);
|
||||
|
||||
if(session) {
|
||||
/* After going on-hook, start ringing if there is an active call in the SKINNY_RING_IN state */
|
||||
skinny_log_l(helper->listener, SWITCH_LOG_DEBUG, "Start Ringer for active Call ID (%d), Line Instance (%d), Line State (%d).\n", call_id, line_instance, skinny_line_get_state(helper->listener,line_instance, call_id));
|
||||
|
||||
send_set_lamp(helper->listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_BLINK);
|
||||
|
||||
if ( ring_on_idle ) {
|
||||
send_set_ringer(helper->listener, SKINNY_RING_INSIDE, SKINNY_RING_FOREVER, line_instance, call_id);
|
||||
} else {
|
||||
send_set_ringer(helper->listener, SKINNY_RING_FLASHONLY, SKINNY_RING_FOREVER, line_instance, call_id);
|
||||
}
|
||||
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch_status_t skinny_ring_active_calls(listener_t *listener)
|
||||
/* Look for all SKINNY active calls in the SKINNY_RING_IN state and tell them to start ringing */
|
||||
{
|
||||
struct skinny_ring_active_calls_helper helper = {0};
|
||||
char *sql;
|
||||
|
||||
helper.listener = listener;
|
||||
|
||||
if ((sql = switch_mprintf(
|
||||
"SELECT skinny_lines.*, channel_uuid, call_id, call_state "
|
||||
"FROM skinny_active_lines "
|
||||
"INNER JOIN skinny_lines "
|
||||
"ON skinny_active_lines.device_name = skinny_lines.device_name "
|
||||
"AND skinny_active_lines.device_instance = skinny_lines.device_instance "
|
||||
"AND skinny_active_lines.line_instance = skinny_lines.line_instance "
|
||||
"WHERE skinny_lines.device_name='%s' AND skinny_lines.device_instance=%d "
|
||||
"AND (call_state=%d)",
|
||||
listener->device_name, listener->device_instance, SKINNY_RING_IN))) {
|
||||
skinny_execute_sql_callback(listener->profile, listener->profile->sql_mutex, sql, skinny_ring_active_calls_callback, &helper);
|
||||
switch_safe_free(sql);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
struct channel_on_hangup_helper {
|
||||
private_t *tech_pvt;
|
||||
switch_call_cause_t cause;
|
||||
|
@ -1002,6 +1080,9 @@ int channel_on_hangup_callback(void *pArg, int argc, char **argv, char **columnN
|
|||
send_set_speaker_mode(listener, SKINNY_SPEAKER_OFF);
|
||||
}
|
||||
send_set_ringer(listener, SKINNY_RING_OFF, SKINNY_RING_FOREVER, line_instance, call_id);
|
||||
|
||||
/* After hanging up this call, activate the ringer for any other active incoming calls */
|
||||
skinny_ring_active_calls(listener);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -112,6 +112,8 @@ switch_status_t skinny_create_incoming_session(listener_t *listener, uint32_t *l
|
|||
|
||||
skinny_line_get(listener, *line_instance_p, &button);
|
||||
|
||||
skinny_log_l(listener, SWITCH_LOG_INFO, "Attempting to create incoming session on Line %d\n", *line_instance_p);
|
||||
|
||||
if (!button || !button->shortname[0]) {
|
||||
skinny_log_l(listener, SWITCH_LOG_CRIT, "Line %d not found on device\n", *line_instance_p);
|
||||
goto error;
|
||||
|
@ -1075,6 +1077,58 @@ switch_status_t skinny_hold_active_calls(listener_t *listener)
|
|||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
struct skinny_hangup_active_calls_helper {
|
||||
listener_t *listener;
|
||||
};
|
||||
|
||||
int skinny_hangup_active_calls_callback(void *pArg, int argc, char **argv, char **columnNames)
|
||||
{
|
||||
struct skinny_hangup_active_calls_helper *helper = pArg;
|
||||
switch_core_session_t *session;
|
||||
|
||||
/* char *device_name = argv[0]; */
|
||||
/* uint32_t device_instance = atoi(argv[1]); */
|
||||
/* uint32_t position = atoi(argv[2]); */
|
||||
uint32_t line_instance = atoi(argv[3]);
|
||||
/* char *label = argv[4]; */
|
||||
/* char *value = argv[5]; */
|
||||
/* char *caller_name = argv[6]; */
|
||||
/* uint32_t ring_on_idle = atoi(argv[7]); */
|
||||
/* uint32_t ring_on_active = atoi(argv[8]); */
|
||||
/* uint32_t busy_trigger = atoi(argv[9]); */
|
||||
/* char *forward_all = argv[10]; */
|
||||
/* char *forward_busy = argv[11]; */
|
||||
/* char *forward_noanswer = argv[12]; */
|
||||
/* uint32_t noanswer_duration = atoi(argv[13]); */
|
||||
/* char *channel_uuid = argv[14]; */
|
||||
uint32_t call_id = atoi(argv[15]);
|
||||
uint32_t call_state = atoi(argv[16]);
|
||||
|
||||
session = skinny_profile_find_session(helper->listener->profile, helper->listener, &line_instance, call_id);
|
||||
|
||||
if(session) {
|
||||
switch_channel_t *channel = NULL;
|
||||
private_t *tech_pvt = NULL;
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
tech_pvt = switch_core_session_get_private(session);
|
||||
|
||||
if (tech_pvt->transfer_from_call_id) { /* Perform a blind transfer, instead of hanging up */
|
||||
skinny_session_transfer(session, helper->listener, line_instance);
|
||||
} else {
|
||||
/* Hangup on an active call that is not in one of the states listed */
|
||||
if ((call_state != SKINNY_ON_HOOK)&&(call_state != SKINNY_HOLD)&&(call_state != SKINNY_CALL_WAITING)&&(call_state != SKINNY_CALL_PARK)&&(call_state != SKINNY_IN_USE_REMOTELY)&&(call_state != SKINNY_RING_IN)) {
|
||||
skinny_log_l(helper->listener, SWITCH_LOG_DEBUG, "Hangup Line Instance (%d), Call ID (%d), Line State (%d)\n", line_instance, tech_pvt->call_id, skinny_line_get_state(helper->listener,line_instance, call_id));
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
|
||||
}
|
||||
}
|
||||
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* SKINNY MESSAGE HANDLERS */
|
||||
/*****************************************************************************/
|
||||
|
@ -1537,18 +1591,13 @@ switch_status_t skinny_handle_stimulus_message(listener_t *listener, skinny_mess
|
|||
|
||||
switch_status_t skinny_handle_off_hook_message(listener_t *listener, skinny_message_t *request)
|
||||
{
|
||||
uint32_t line_instance = 1;
|
||||
uint32_t line_instance = 0;
|
||||
uint32_t call_id = 0;
|
||||
switch_core_session_t *session = NULL;
|
||||
private_t *tech_pvt = NULL;
|
||||
uint32_t line_state;
|
||||
|
||||
if(skinny_check_data_length_soft(request, sizeof(request->data.off_hook))) {
|
||||
if (request->data.off_hook.line_instance > 0) {
|
||||
line_instance = request->data.off_hook.line_instance;
|
||||
}
|
||||
call_id = request->data.off_hook.call_id;
|
||||
}
|
||||
skinny_log_l(listener, SWITCH_LOG_INFO, "Attempting to handle off hook message for call_id %d and line_instance %d.\n", call_id, line_instance);
|
||||
|
||||
session = skinny_profile_find_session(listener->profile, listener, &line_instance, call_id);
|
||||
|
||||
|
@ -1557,6 +1606,18 @@ switch_status_t skinny_handle_off_hook_message(listener_t *listener, skinny_mess
|
|||
if(session && line_state == SKINNY_RING_IN ) { /*answering a call */
|
||||
skinny_session_answer(session, listener, line_instance);
|
||||
} else { /* start a new call */
|
||||
|
||||
/* If we went off hook to make a call, establish the call with the appropriate line instance
|
||||
I'm not sure this actually makes any sense - plain off-hook with speaker or handset would
|
||||
always use the first line on device */
|
||||
|
||||
if(skinny_check_data_length_soft(request, sizeof(request->data.off_hook))) {
|
||||
if (request->data.off_hook.line_instance > 0) {
|
||||
line_instance = request->data.off_hook.line_instance;
|
||||
}
|
||||
call_id = request->data.off_hook.call_id;
|
||||
}
|
||||
|
||||
skinny_create_incoming_session(listener, &line_instance, &session);
|
||||
if ( ! session ) {
|
||||
skinny_log_l_msg(listener, SWITCH_LOG_CRIT, "Unable to handle off hook message, could not create session.\n");
|
||||
|
@ -1580,34 +1641,31 @@ switch_status_t skinny_handle_on_hook_message(listener_t *listener, skinny_messa
|
|||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
uint32_t line_instance = 0;
|
||||
uint32_t call_id = 0;
|
||||
switch_core_session_t *session = NULL;
|
||||
struct skinny_hangup_active_calls_helper helper = {0};
|
||||
char *sql;
|
||||
|
||||
if(skinny_check_data_length_soft(request, sizeof(request->data.on_hook))) {
|
||||
line_instance = request->data.on_hook.line_instance;
|
||||
call_id = request->data.on_hook.call_id;
|
||||
}
|
||||
skinny_log_l(listener, SWITCH_LOG_INFO, "Attempting to handle on hook message for Call ID (%d), Line Instance (%d).\n", call_id, line_instance);
|
||||
|
||||
session = skinny_profile_find_session(listener->profile, listener, &line_instance, call_id);
|
||||
/* Walk through all active calls for this device. The callback should hangup any active calls that should be terminated when the device goes on-hook */
|
||||
|
||||
if(session) {
|
||||
switch_channel_t *channel = NULL;
|
||||
private_t *tech_pvt = NULL;
|
||||
helper.listener = listener;
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
tech_pvt = switch_core_session_get_private(session);
|
||||
|
||||
if (tech_pvt->transfer_from_call_id) { /* blind transfer */
|
||||
status = skinny_session_transfer(session, listener, line_instance);
|
||||
} else {
|
||||
if (skinny_line_get_state(listener, line_instance, call_id) != SKINNY_IN_USE_REMOTELY) {
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(session) {
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
if ((sql = switch_mprintf(
|
||||
"SELECT skinny_lines.*, channel_uuid, call_id, call_state "
|
||||
"FROM skinny_active_lines "
|
||||
"INNER JOIN skinny_lines "
|
||||
"ON skinny_active_lines.device_name = skinny_lines.device_name "
|
||||
"AND skinny_active_lines.device_instance = skinny_lines.device_instance "
|
||||
"AND skinny_active_lines.line_instance = skinny_lines.line_instance "
|
||||
"WHERE skinny_lines.device_name='%s' AND skinny_lines.device_instance=%d",
|
||||
listener->device_name, listener->device_instance))) {
|
||||
skinny_execute_sql_callback(listener->profile, listener->profile->sql_mutex, sql, skinny_hangup_active_calls_callback, &helper);
|
||||
switch_safe_free(sql);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -2137,6 +2195,10 @@ switch_status_t skinny_handle_soft_key_event_message(listener_t *listener, skinn
|
|||
}
|
||||
break;
|
||||
case SOFTKEY_ANSWER:
|
||||
/* find first ringing line - ccm behavior */
|
||||
line_instance = 0;
|
||||
call_id = 0;
|
||||
|
||||
session = skinny_profile_find_session(listener->profile, listener, &line_instance, call_id);
|
||||
if(session) {
|
||||
status = skinny_session_answer(session, listener, line_instance);
|
||||
|
|
Loading…
Reference in New Issue