mod_callcenter: Generate per member uuid different from the member session uuid. Might fix transfer between queue. More changes are commings

This commit is contained in:
Marc Olivier Chouinard 2011-03-31 05:17:04 -04:00
parent b986e13a58
commit b63a72f8b3
1 changed files with 135 additions and 73 deletions

View File

@ -177,6 +177,7 @@ static char members_sql[] =
" queue VARCHAR(255),\n"
" system VARCHAR(255),\n"
" uuid VARCHAR(255) NOT NULL DEFAULT '',\n"
" session_uuid VARCHAR(255) NOT NULL DEFAULT '',\n"
" caller_number VARCHAR(255),\n"
" caller_name VARCHAR(255),\n"
" system_epoch INTEGER NOT NULL DEFAULT 0,\n"
@ -704,7 +705,7 @@ static cc_queue_t *load_queue(const char *queue_name)
goto end;
}
switch_cache_db_test_reactive(dbh, "select count(rejoined_epoch) from members", "drop table members", members_sql);
switch_cache_db_test_reactive(dbh, "select count(session_uuid) from members", "drop table members", members_sql);
switch_cache_db_test_reactive(dbh, "select count(ready_time) from agents", NULL, "alter table agents add ready_time integer not null default 0;"
"alter table agents add reject_delay_time integer not null default 0;"
"alter table agents add busy_delay_time integer not null default 0;");
@ -718,7 +719,7 @@ static cc_queue_t *load_queue(const char *queue_name)
/* Reset a unclean shutdown */
sql = switch_mprintf("UPDATE agents SET state = 'Waiting', uuid = '' WHERE system = 'single_box';"
"UPDATE tiers SET state = 'Ready' WHERE agent IN (SELECT name FROM agents WHERE system = 'single_box');"
"UPDATE members SET state = '%q', uuid = '' WHERE system = 'single_box';",
"UPDATE members SET state = '%q', session_uuid = '' WHERE system = 'single_box';",
cc_member_state2str(CC_MEMBER_STATE_ABANDONED));
cc_execute_sql(NULL, sql, NULL);
@ -756,6 +757,7 @@ static cc_queue_t *get_queue(const char *queue_name)
struct call_helper {
const char *member_uuid;
const char *member_session_uuid;
const char *queue_name;
const char *queue_strategy;
const char *member_joined_epoch;
@ -1356,7 +1358,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
char *sql = NULL;
char *dialstr = NULL;
cc_tier_state_t tiers_state = CC_TIER_STATE_READY;
switch_core_session_t *member_session = switch_core_session_locate(h->member_uuid);
switch_core_session_t *member_session = switch_core_session_locate(h->member_session_uuid);
switch_event_t *ovars;
switch_time_t t_agent_called = 0;
switch_time_t t_agent_answered = 0;
@ -1369,7 +1371,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
/* member is gone before we could process it */
if (!member_session) {
sql = switch_mprintf("UPDATE members SET state = '%q', uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q' AND state != '%q'",
sql = switch_mprintf("UPDATE members SET state = '%q', session_uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q' AND state != '%q'",
cc_member_state2str(CC_MEMBER_STATE_ABANDONED), (long) switch_epoch_time_now(NULL), h->member_uuid, cc_member_state2str(CC_MEMBER_STATE_ABANDONED));
cc_execute_sql(NULL, sql, NULL);
@ -1384,7 +1386,8 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Type", h->agent_type);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_session_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
switch_event_fire(&event);
@ -1395,9 +1398,11 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_queue", "%s", h->queue_name);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_uuid", "%s", h->member_uuid);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_session_uuid", "%s", h->member_session_uuid);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_pre_answer_uuid", "%s", h->member_uuid);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent", "%s", h->agent_name);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent_type", "%s", h->agent_type);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_side", "%s", "agent");
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "ignore_early_media", "true");
t_agent_called = switch_epoch_time_now(NULL);
@ -1414,10 +1419,12 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_t *event;
const char *cc_warning_tone = switch_channel_get_variable(agent_channel, "cc_warning_tone");
switch_channel_set_variable(agent_channel, "cc_side", "agent");
switch_channel_set_variable(agent_channel, "cc_queue", h->queue_name);
switch_channel_set_variable(agent_channel, "cc_agent", h->agent_name);
switch_channel_set_variable(agent_channel, "cc_agent_type", h->agent_type);
switch_channel_set_variable(agent_channel, "cc_member_uuid", h->member_uuid);
switch_channel_set_variable(agent_channel, "cc_member_session_uuid", h->member_session_uuid);
/* Playback this to the agent */
if (cc_warning_tone && switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
@ -1469,6 +1476,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_channel_set_variable(agent_channel, "cc_agent", h->agent_name);
switch_channel_set_variable(agent_channel, "cc_agent_type", h->agent_type);
switch_channel_set_variable(agent_channel, "cc_member_uuid", h->member_uuid);
switch_channel_set_variable(agent_channel, "cc_member_session_uuid", h->member_session_uuid);
}
switch_core_session_rwunlock(other_loopback_session);
}
@ -1511,7 +1519,8 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Called-Time", "%ld", (long) t_agent_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_session_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
switch_event_fire(&event);
@ -1544,7 +1553,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s answered \"%s\" <%s> from queue %s%s\n",
h->agent_name, h->member_caller_name, h->member_caller_number, h->queue_name, (h->record_template?" (Recorded)":""));
switch_ivr_uuid_bridge(h->member_uuid, switch_core_session_get_uuid(agent_session));
switch_ivr_uuid_bridge(h->member_session_uuid, switch_core_session_get_uuid(agent_session));
/* This is used for the waiting caller to quit waiting for a agent */
switch_channel_set_variable(member_channel, "cc_agent_uuid", agent_uuid);
@ -1567,7 +1576,8 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Bridge-Terminated-Time", "%ld", (long) switch_epoch_time_now(NULL));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_session_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
switch_event_fire(&event);
@ -1601,7 +1611,8 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answered-Time", "%ld", (long) t_agent_answered);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Leaving-Time", "%ld", (long) switch_epoch_time_now(NULL));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_session_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
switch_event_fire(&event);
@ -1669,7 +1680,8 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Hangup-Cause", switch_channel_cause2str(cause));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", h->agent_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-System", h->agent_system);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", h->member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", h->member_session_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", h->member_caller_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", h->member_caller_number);
switch_event_fire(&event);
@ -1713,10 +1725,12 @@ done:
struct agent_callback {
const char *queue_name;
const char *system;
const char *uuid;
const char *caller_number;
const char *caller_name;
const char *joined_epoch;
const char *member_uuid;
const char *member_session_uuid;
const char *member_caller_number;
const char *member_caller_name;
const char *member_joined_epoch;
const char *member_score;
const char *strategy;
const char *record_template;
switch_bool_t tier_rules_apply;
@ -1735,15 +1749,23 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
agent_callback_t *cbt = (agent_callback_t *) pArg;
char *sql = NULL;
char res[256];
char *agent_status = argv[2];
char *agent_tier_state = argv[9];
char *agent_last_bridge_end = argv[10];
char *agent_wrap_up_time = argv[11];
char *agent_state = argv[12];
char *agent_ready_time = argv[13];
char *agent_tier_level = argv[14];
char *agent_type = argv[15];
char *agent_uuid = argv[16];
const char *agent_system = argv[0];
const char *agent_name = argv[1];
const char *agent_status = argv[2];
const char *agent_originate_string = argv[3];
const char *agent_no_answer_count = argv[4];
const char *agent_max_no_answer = argv[5];
const char *agent_reject_delay_time = argv[6];
const char *agent_busy_delay_time = argv[7];
const char *agent_no_answer_delay_time = argv[8];
const char *agent_tier_state = argv[9];
const char *agent_last_bridge_end = argv[10];
const char *agent_wrap_up_time = argv[11];
const char *agent_state = argv[12];
const char *agent_ready_time = argv[13];
const char *agent_tier_level = argv[14];
const char *agent_type = argv[15];
const char *agent_uuid = argv[16];
switch_bool_t contact_agent = SWITCH_TRUE;
@ -1756,11 +1778,11 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
if (cbt->tier_rule_no_agent_no_wait == SWITCH_TRUE && cbt->tier_agent_available == 0) {
cbt->tier = atoi(agent_tier_level);
/* Multiple the tier level by the tier wait time */
} else if (cbt->tier_rule_wait_multiply_level == SWITCH_TRUE && (long) switch_epoch_time_now(NULL) - atol(cbt->joined_epoch) >= atoi(agent_tier_level) * cbt->tier_rule_wait_second) {
} else if (cbt->tier_rule_wait_multiply_level == SWITCH_TRUE && (long) switch_epoch_time_now(NULL) - atol(cbt->member_joined_epoch) >= atoi(agent_tier_level) * cbt->tier_rule_wait_second) {
cbt->tier = atoi(agent_tier_level);
cbt->tier_agent_available = 0;
/* Just check if joined is bigger than next tier wait time */
} else if (cbt->tier_rule_wait_multiply_level == SWITCH_FALSE && (long) switch_epoch_time_now(NULL) - atol(cbt->joined_epoch) >= cbt->tier_rule_wait_second) {
} else if (cbt->tier_rule_wait_multiply_level == SWITCH_FALSE && (long) switch_epoch_time_now(NULL) - atol(cbt->member_joined_epoch) >= cbt->tier_rule_wait_second) {
cbt->tier = atoi(agent_tier_level);
cbt->tier_agent_available = 0;
} else {
@ -1792,7 +1814,7 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
}
/* If agent isn't on this box */
if (strcasecmp(argv[0],"single_box" /* SELF */)) {
if (strcasecmp(agent_system,"single_box" /* SELF */)) {
if (!strcasecmp(cbt->strategy, "ring-all")) {
return 1; /* Abort finding agent for member if we found a match but for a different Server */
} else {
@ -1802,7 +1824,7 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
if (!strcasecmp(cbt->strategy,"ring-all")) {
/* Check if member is a ring-all mode */
sql = switch_mprintf("SELECT count(*) FROM members WHERE serving_agent = 'ring-all' AND uuid = '%q' AND system = 'single_box'", cbt->uuid);
sql = switch_mprintf("SELECT count(*) FROM members WHERE serving_agent = 'ring-all' AND uuid = '%q' AND system = 'single_box'", cbt->member_uuid);
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
switch_safe_free(sql);
@ -1810,14 +1832,14 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
/* Map the Agent to the member */
sql = switch_mprintf("UPDATE members SET serving_agent = '%q', serving_system = 'single_box', state = '%q'"
" WHERE state = '%q' AND uuid = '%q' AND system = 'single_box'",
argv[1], cc_member_state2str(CC_MEMBER_STATE_TRYING),
cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt->uuid);
agent_name, cc_member_state2str(CC_MEMBER_STATE_TRYING),
cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt->member_uuid);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
/* Check if we won the race to get the member to our selected agent (Used for Multi system purposes) */
sql = switch_mprintf("SELECT count(*) FROM members WHERE serving_agent = '%q' AND serving_system = 'single_box' AND uuid = '%q' AND system = 'single_box'",
argv[1], cbt->uuid);
agent_name, cbt->member_uuid);
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
switch_safe_free(sql);
}
@ -1836,24 +1858,25 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
switch_core_new_memory_pool(&pool);
h = switch_core_alloc(pool, sizeof(*h));
h->pool = pool;
h->member_uuid = switch_core_strdup(h->pool, cbt->uuid);
h->member_uuid = switch_core_strdup(h->pool, cbt->member_uuid);
h->member_session_uuid = switch_core_strdup(h->pool, cbt->member_session_uuid);
h->queue_strategy = switch_core_strdup(h->pool, cbt->strategy);
h->originate_string = switch_core_strdup(h->pool, argv[3]);
h->agent_name = switch_core_strdup(h->pool, argv[1]);
h->originate_string = switch_core_strdup(h->pool, agent_originate_string);
h->agent_name = switch_core_strdup(h->pool, agent_name);
h->agent_system = switch_core_strdup(h->pool, "single_box");
h->agent_status = switch_core_strdup(h->pool, argv[2]);
h->agent_status = switch_core_strdup(h->pool, agent_status);
h->agent_type = switch_core_strdup(h->pool, agent_type);
h->agent_uuid = switch_core_strdup(h->pool, agent_uuid);
h->member_joined_epoch = switch_core_strdup(h->pool, cbt->joined_epoch);
h->member_caller_name = switch_core_strdup(h->pool, cbt->caller_name);
h->member_caller_number = switch_core_strdup(h->pool, cbt->caller_number);
h->member_joined_epoch = switch_core_strdup(h->pool, cbt->member_joined_epoch);
h->member_caller_name = switch_core_strdup(h->pool, cbt->member_caller_name);
h->member_caller_number = switch_core_strdup(h->pool, cbt->member_caller_number);
h->queue_name = switch_core_strdup(h->pool, cbt->queue_name);
h->record_template = switch_core_strdup(h->pool, cbt->record_template);
h->no_answer_count = atoi(argv[4]);
h->max_no_answer = atoi(argv[5]);
h->reject_delay_time = atoi(argv[6]);
h->busy_delay_time = atoi(argv[7]);
h->no_answer_delay_time = atoi(argv[8]);
h->no_answer_count = atoi(agent_no_answer_count);
h->max_no_answer = atoi(agent_max_no_answer);
h->reject_delay_time = atoi(agent_reject_delay_time);
h->busy_delay_time = atoi(agent_busy_delay_time);
h->no_answer_delay_time = atoi(agent_no_answer_delay_time);
cc_agent_update("state", cc_agent_state2str(CC_AGENT_STATE_RECEIVING), h->agent_name);
@ -1897,9 +1920,22 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
uint32_t discard_abandoned_after;
switch_bool_t abandoned_resume_allowed;
agent_callback_t cbt;
const char *member_state = NULL;
const char *member_abandoned_epoch = NULL;
memset(&cbt, 0, sizeof(cbt));
if (!argv[0] || !(queue = get_queue(argv[0]))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", argv[0]);
cbt.queue_name = argv[0];
cbt.member_uuid = argv[1];
cbt.member_session_uuid = argv[2];
cbt.member_caller_number = argv[3];
cbt.member_caller_name = argv[4];
cbt.member_joined_epoch = argv[5];
cbt.member_score = argv[6];
member_state = argv[7];
member_abandoned_epoch = argv[8];
if (!cbt.queue_name || !(queue = get_queue(cbt.queue_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", cbt.queue_name);
goto end;
} else {
queue_name = strdup(queue->name);
@ -1917,21 +1953,27 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
queue_rwunlock(queue);
}
if (!strcasecmp(argv[6], cc_member_state2str(CC_MEMBER_STATE_ABANDONED))) {
long abandoned_epoch = atol(argv[7]);
/* Checking for cleanup Abandonded calls from the db */
if (!strcasecmp(member_state, cc_member_state2str(CC_MEMBER_STATE_ABANDONED))) {
long abandoned_epoch = atol(member_abandoned_epoch);
if (abandoned_epoch == 0) {
abandoned_epoch = atol(argv[4]);
abandoned_epoch = atol(cbt.member_joined_epoch);
}
/* Once we pass a certain point, we want to get rid of the abandoned call */
if (abandoned_epoch + discard_abandoned_after < (long) switch_epoch_time_now(NULL)) {
sql = switch_mprintf("DELETE FROM members WHERE system = 'single_box' AND uuid = '%q' AND (abandoned_epoch = '%ld' OR joined_epoch = '%q')", argv[1], abandoned_epoch, argv[4]);
sql = switch_mprintf("DELETE FROM members WHERE system = 'single_box' AND uuid = '%q' AND (abandoned_epoch = '%ld' OR joined_epoch = '%q')", cbt.member_uuid, abandoned_epoch, cbt.member_joined_epoch);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
}
/* Skip this member */
goto end;
}
memset(&cbt, 0, sizeof(cbt));
/* Check if member is in the queue waiting */
if (zstr(cbt.member_session_uuid)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Member %s <%s> in Queue %s have no session uuid, skip this member\n", cbt.member_caller_name, cbt.member_caller_number, cbt.queue_name);
}
cbt.tier = 0;
cbt.tier_agent_available = 0;
@ -1940,11 +1982,6 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
cbt.tier_rule_wait_multiply_level = tier_rule_wait_multiply_level;
cbt.tier_rule_no_agent_no_wait = tier_rule_no_agent_no_wait;
cbt.uuid = argv[1];
cbt.caller_number = argv[2];
cbt.caller_name = argv[3];
cbt.joined_epoch = argv[4];
cbt.queue_name = argv[0];
cbt.strategy = queue_strategy;
cbt.record_template = queue_record_template;
cbt.agent_found = SWITCH_FALSE;
@ -1957,7 +1994,7 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
sql_order_by = switch_mprintf("level, agents.calls_answered, position");
} else if (!strcasecmp(queue_strategy, "ring-all")) {
sql = switch_mprintf("UPDATE members SET state = '%q' WHERE state = '%q' AND uuid = '%q' AND system = 'single_box'",
cc_member_state2str(CC_MEMBER_STATE_TRYING), cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt.uuid);
cc_member_state2str(CC_MEMBER_STATE_TRYING), cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt.member_uuid);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
sql_order_by = switch_mprintf("level, position");
@ -1982,8 +2019,8 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
switch_safe_free(sql_order_by);
/* We update a field in the queue struct so we can kick caller out if waiting for too long with no agent */
if (!argv[0] || !(queue = get_queue(argv[0]))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", argv[0]);
if (!cbt.queue_name || !(queue = get_queue(cbt.queue_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", cbt.queue_name);
goto end;
} else {
queue->last_agent_exist_check = switch_epoch_time_now(NULL);
@ -2025,7 +2062,7 @@ void *SWITCH_THREAD_FUNC cc_agent_dispatch_thread_run(switch_thread_t *thread, v
while (globals.running == 1) {
char *sql = NULL;
sql = switch_mprintf("SELECT queue,uuid,caller_number,caller_name,joined_epoch,(%ld-joined_epoch)+base_score+skill_score AS score, state, abandoned_epoch FROM members"
sql = switch_mprintf("SELECT queue,uuid,session_uuid,caller_number,caller_name,joined_epoch,(%ld-joined_epoch)+base_score+skill_score AS score, state, abandoned_epoch FROM members"
" WHERE state = '%q' OR state = '%q' OR (serving_agent = 'ring-all' AND state = '%q') ORDER BY score DESC",
(long) switch_epoch_time_now(NULL),
cc_member_state2str(CC_MEMBER_STATE_WAITING), cc_member_state2str(CC_MEMBER_STATE_ABANDONED), cc_member_state2str(CC_MEMBER_STATE_TRYING));
@ -2073,8 +2110,9 @@ void cc_agent_dispatch_thread_start(void)
}
struct member_thread_helper {
const char *member_uuid;
const char *queue_name;
const char *member_uuid;
const char *member_session_uuid;
switch_time_t t_member_called;
cc_member_cancel_reason_t member_cancel_reason;
@ -2085,7 +2123,7 @@ struct member_thread_helper {
void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj)
{
struct member_thread_helper *m = (struct member_thread_helper *) obj;
switch_core_session_t *member_session = switch_core_session_locate(m->member_uuid);
switch_core_session_t *member_session = switch_core_session_locate(m->member_session_uuid);
switch_channel_t *member_channel = NULL;
switch_mutex_lock(globals.mutex);
@ -2150,8 +2188,8 @@ void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj
}
struct moh_dtmf_helper {
const char *queue_name;
char dtmf;
const char *queue_name;
char dtmf;
};
static switch_status_t moh_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen) {
@ -2188,7 +2226,7 @@ SWITCH_STANDARD_APP(callcenter_function)
switch_core_session_t *member_session = session;
switch_channel_t *member_channel = switch_core_session_get_channel(member_session);
char *sql = NULL;
char *member_uuid = switch_core_session_get_uuid(member_session);
char *member_session_uuid = switch_core_session_get_uuid(member_session);
struct member_thread_helper *h = NULL;
switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL;
@ -2203,6 +2241,8 @@ SWITCH_STANDARD_APP(callcenter_function)
switch_time_t t_member_called = switch_epoch_time_now(NULL);
long abandoned_epoch = 0;
const char *agent_uuid = NULL;
switch_uuid_t smember_uuid;
char member_uuid[SWITCH_UUID_FORMATTED_LENGTH + 1] = "";
if (!zstr(data)) {
mydata = switch_core_session_strdup(member_session, data);
@ -2233,13 +2273,29 @@ SWITCH_STANDARD_APP(callcenter_function)
char res[256];
/* Check to see if agent already exist */
sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE queue = '%q' AND caller_number = '%q' AND state = '%q' ORDER BY abandoned_epoch DESC",
sql = switch_mprintf("SELECT uuid FROM members WHERE queue = '%q' AND caller_number = '%q' AND state = '%q' ORDER BY abandoned_epoch DESC",
queue_name, switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")), cc_member_state2str(CC_MEMBER_STATE_ABANDONED));
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
switch_safe_free(sql);
abandoned_epoch = atol(res);
strncpy(member_uuid, res, sizeof(member_uuid));
if (!zstr(member_uuid)) {
sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE uuid = '%q'", member_uuid);
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
switch_safe_free(sql);
abandoned_epoch = atol(res);
}
}
/* If no existing uuid is restored, let create a new one */
if (abandoned_epoch == 0) {
switch_uuid_get(&smember_uuid);
switch_uuid_format(member_uuid, &smember_uuid);
}
switch_channel_set_variable(member_channel, "cc_side", "member");
switch_channel_set_variable(member_channel, "cc_member_uuid", member_uuid);
/* Add manually imported score */
if (cc_base_score) {
cc_base_score_int += atoi(cc_base_score);
@ -2254,7 +2310,8 @@ SWITCH_STANDARD_APP(callcenter_function)
switch_channel_event_set_data(member_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-%s", (abandoned_epoch==0?"start":"resume"));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_session_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
switch_event_fire(&event);
@ -2266,10 +2323,11 @@ SWITCH_STANDARD_APP(callcenter_function)
if (abandoned_epoch == 0) {
/* Add the caller to the member queue */
sql = switch_mprintf("INSERT INTO members"
" (queue,system,uuid,system_epoch,joined_epoch,base_score,skill_score,caller_number,caller_name,serving_agent,serving_system,state)"
" VALUES('%q','single_box','%q','%q','%ld','%d','%d','%q','%q','%q','','%q')",
" (queue,system,uuid,session_uuid,system_epoch,joined_epoch,base_score,skill_score,caller_number,caller_name,serving_agent,serving_system,state)"
" VALUES('%q','single_box','%q','%q','%q','%ld','%d','%d','%q','%q','%q','','%q')",
queue_name,
member_uuid,
member_session_uuid,
start_epoch,
(long) switch_epoch_time_now(NULL),
cc_base_score_int,
@ -2283,18 +2341,20 @@ SWITCH_STANDARD_APP(callcenter_function)
} else {
char res[256];
/* Update abandoned member */
sql = switch_mprintf("UPDATE members SET uuid = '%q', state = '%q', rejoined_epoch = '%ld' WHERE caller_number = '%q' AND abandoned_epoch = '%ld' AND state = '%q' AND queue = '%q'",
member_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), (long) switch_epoch_time_now(NULL), switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")), abandoned_epoch, cc_member_state2str(CC_MEMBER_STATE_ABANDONED), queue_name);
sql = switch_mprintf("UPDATE members SET session_uuid = '%q', state = '%q', rejoined_epoch = '%ld' WHERE uuid = '%q' AND state = '%q'",
member_session_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), (long) switch_epoch_time_now(NULL), member_uuid, cc_member_state2str(CC_MEMBER_STATE_ABANDONED));
cc_execute_sql(queue, sql, NULL);
switch_safe_free(sql);
/* Confirm we took that member in */
sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE uuid = '%q' AND state = '%q' AND queue = '%q'", member_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), queue_name);
sql = switch_mprintf("SELECT abandoned_epoch FROM members WHERE uuid = '%q' AND session_uuid = '%q' AND state = '%q' AND queue = '%q'", member_session, member_session_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), queue_name);
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
switch_safe_free(sql);
if (atol(res) == 0) {
/* Failed to get the member !!! */
/* TODO Loop back to just create a uuid and add the member as a new member */
/* TODO ERROR MSG */
queue_rwunlock(queue);
goto end;
}
@ -2310,6 +2370,7 @@ SWITCH_STANDARD_APP(callcenter_function)
h->pool = pool;
h->member_uuid = switch_core_strdup(h->pool, member_uuid);
h->member_session_uuid = switch_core_strdup(h->pool, member_session_uuid);
h->queue_name = switch_core_strdup(h->pool, queue_name);
h->t_member_called = t_member_called;
h->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NONE;
@ -2376,7 +2437,7 @@ SWITCH_STANDARD_APP(callcenter_function)
/* Canceled for some reason */
if (!switch_channel_up(member_channel) || h->member_cancel_reason != CC_MEMBER_CANCEL_REASON_NONE) {
/* Update member state */
sql = switch_mprintf("UPDATE members SET state = '%q', uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
sql = switch_mprintf("UPDATE members SET state = '%q', session_uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
cc_member_state2str(CC_MEMBER_STATE_ABANDONED), (long) switch_epoch_time_now(NULL), member_uuid);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
@ -2393,7 +2454,8 @@ SWITCH_STANDARD_APP(callcenter_function)
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Caller-Joined-Time", "%ld", (long) t_member_called);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", "Cancel");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cancel-Reason", cc_member_cancel_reason2str(h->member_cancel_reason));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Member-UUID", member_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_session_uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Name", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-CID-Number", switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")));
switch_event_fire(&event);