Merge branch 'master' into smgmaster

This commit is contained in:
Moises Silva committed 2010-09-08 12:26:20 -04:00
commit 92e1a8186e
57 files changed
+2134 -801

No files matched your search

@@ -37,6 +37,7 @@
#define CC_AGENT_TYPE_UUID_STANDBY "uuid-standby"
#define CC_SQLITE_DB_NAME "callcenter"
#define CC_MAX_TIME_DIFF_CHECK 5
/* TODO
drop caller if no agent login
dont allow new caller
@@ -53,6 +54,16 @@ SWITCH_MODULE_DEFINITION(mod_callcenter, mod_callcenter_load, mod_callcenter_shu
static const char *global_cf = "callcenter.conf";
struct cc_status_table {
const char *name;
int status;
};
struct cc_state_table {
const char *name;
int state;
};
typedef enum {
CC_STATUS_SUCCESS,
CC_STATUS_FALSE,
@@ -77,12 +88,7 @@ typedef enum {
CC_TIER_STATE_STANDBY = 5
} cc_tier_state_t;
struct cc_tier_state_table {
const char *name;
cc_tier_state_t state;
};
static struct cc_tier_state_table STATE_CHART[] = {
static struct cc_state_table STATE_CHART[] = {
{"Unknown", CC_TIER_STATE_UNKNOWN},
{"No Answer", CC_TIER_STATE_NO_ANSWER},
{"Ready", CC_TIER_STATE_READY},
@@ -101,12 +107,7 @@ typedef enum {
CC_AGENT_STATUS_ON_BREAK = 4
} cc_agent_status_t;
struct cc_agent_status_table {
const char *name;
cc_agent_status_t status;
};
static struct cc_agent_status_table AGENT_STATUS_CHART[] = {
static struct cc_status_table AGENT_STATUS_CHART[] = {
{"Unknown", CC_AGENT_STATUS_UNKNOWN},
{"Logged Out", CC_AGENT_STATUS_LOGGED_OUT},
{"Available", CC_AGENT_STATUS_AVAILABLE},
@@ -124,12 +125,7 @@ typedef enum {
CC_AGENT_STATE_IDLE = 4
} cc_agent_state_t;
struct cc_agent_state_table {
const char *name;
cc_agent_state_t state;
};
static struct cc_agent_state_table AGENT_STATE_CHART[] = {
static struct cc_state_table AGENT_STATE_CHART[] = {
{"Unknown", CC_AGENT_STATE_UNKNOWN},
{"Waiting", CC_AGENT_STATE_WAITING},
{"Receiving", CC_AGENT_STATE_RECEIVING},
@@ -147,12 +143,7 @@ typedef enum {
CC_MEMBER_STATE_ABANDONED = 4
} cc_member_state_t;
struct cc_member_state_table {
const char *name;
cc_member_state_t state;
};
static struct cc_member_state_table MEMBER_STATE_CHART[] = {
static struct cc_state_table MEMBER_STATE_CHART[] = {
{"Unknown", CC_MEMBER_STATE_UNKNOWN},
{"Waiting", CC_MEMBER_STATE_WAITING},
{"Trying", CC_MEMBER_STATE_TRYING},
@@ -162,10 +153,24 @@ static struct cc_member_state_table MEMBER_STATE_CHART[] = {
};
/*static char queues_sql[] =
"CREATE TABLE queues (\n"
" name VARCHAR(255)\n" ");\n";
*/
struct cc_member_cancel_reason_table {
const char *name;
int reason;
};
typedef enum {
CC_MEMBER_CANCEL_REASON_NONE,
CC_MEMBER_CANCEL_REASON_TIMEOUT,
CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT
} cc_member_cancel_reason_t;
static struct cc_member_cancel_reason_table MEMBER_CANCEL_REASON_CHART[] = {
{"NONE", CC_MEMBER_CANCEL_REASON_NONE},
{"TIMEOUT", CC_MEMBER_CANCEL_REASON_TIMEOUT},
{"NO_AGENT_TIMEOUT", CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT},
{NULL, 0}
};
static char members_sql[] =
"CREATE TABLE members (\n"
" queue VARCHAR(255),\n"
@@ -222,7 +227,6 @@ static char agents_sql[] =
" ready_time INTEGER NOT NULL DEFAULT 0\n"
");\n";
static char tiers_sql[] =
"CREATE TABLE tiers (\n"
" queue VARCHAR(255),\n"
@@ -247,7 +251,7 @@ const char * cc_tier_state2str(cc_tier_state_t state)
uint8_t x;
const char *str = "Unknown";
for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct cc_tier_state_table)) - 1; x++) {
for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct cc_state_table)) - 1; x++) {
if (STATE_CHART[x].state == state) {
str = STATE_CHART[x].name;
break;
@@ -262,7 +266,7 @@ cc_tier_state_t cc_tier_str2state(const char *str)
uint8_t x;
cc_tier_state_t state = CC_TIER_STATE_UNKNOWN;
for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct cc_tier_state_table)) - 1 && STATE_CHART[x].name; x++) {
for (x = 0; x < (sizeof(STATE_CHART) / sizeof(struct cc_state_table)) - 1 && STATE_CHART[x].name; x++) {
if (!strcasecmp(STATE_CHART[x].name, str)) {
state = STATE_CHART[x].state;
break;
@@ -271,12 +275,41 @@ cc_tier_state_t cc_tier_str2state(const char *str)
return state;
}
const char * cc_member_cancel_reason2str(cc_member_cancel_reason_t reason)
{
uint8_t x;
const char *str = "NONE";
for (x = 0; x < (sizeof(MEMBER_CANCEL_REASON_CHART) / sizeof(struct cc_member_cancel_reason_table)) - 1; x++) {
if (MEMBER_CANCEL_REASON_CHART[x].reason == reason) {
str = MEMBER_CANCEL_REASON_CHART[x].name;
break;
}
}
return str;
}
cc_member_cancel_reason_t cc_member_cancel_str2reason(const char *str)
{
uint8_t x;
cc_member_cancel_reason_t reason = CC_MEMBER_CANCEL_REASON_NONE;
for (x = 0; x < (sizeof(MEMBER_CANCEL_REASON_CHART) / sizeof(struct cc_member_cancel_reason_table)) - 1 && MEMBER_CANCEL_REASON_CHART[x].name; x++) {
if (!strcasecmp(MEMBER_CANCEL_REASON_CHART[x].name, str)) {
reason = MEMBER_CANCEL_REASON_CHART[x].reason;
break;
}
}
return reason;
}
const char * cc_agent_status2str(cc_agent_status_t status)
{
uint8_t x;
const char *str = "Unknown";
for (x = 0; x < (sizeof(AGENT_STATUS_CHART) / sizeof(struct cc_agent_status_table)) - 1; x++) {
for (x = 0; x < (sizeof(AGENT_STATUS_CHART) / sizeof(struct cc_status_table)) - 1; x++) {
if (AGENT_STATUS_CHART[x].status == status) {
str = AGENT_STATUS_CHART[x].name;
break;
@@ -291,7 +324,7 @@ cc_agent_status_t cc_agent_str2status(const char *str)
uint8_t x;
cc_agent_status_t status = CC_AGENT_STATUS_UNKNOWN;
for (x = 0; x < (sizeof(AGENT_STATUS_CHART) / sizeof(struct cc_agent_status_table)) - 1 && AGENT_STATUS_CHART[x].name; x++) {
for (x = 0; x < (sizeof(AGENT_STATUS_CHART) / sizeof(struct cc_status_table)) - 1 && AGENT_STATUS_CHART[x].name; x++) {
if (!strcasecmp(AGENT_STATUS_CHART[x].name, str)) {
status = AGENT_STATUS_CHART[x].status;
break;
@@ -305,7 +338,7 @@ const char * cc_agent_state2str(cc_agent_state_t state)
uint8_t x;
const char *str = "Unknown";
for (x = 0; x < (sizeof(AGENT_STATE_CHART) / sizeof(struct cc_agent_state_table)) - 1; x++) {
for (x = 0; x < (sizeof(AGENT_STATE_CHART) / sizeof(struct cc_state_table)) - 1; x++) {
if (AGENT_STATE_CHART[x].state == state) {
str = AGENT_STATE_CHART[x].name;
break;
@@ -320,7 +353,7 @@ cc_agent_state_t cc_agent_str2state(const char *str)
uint8_t x;
cc_agent_state_t state = CC_AGENT_STATE_UNKNOWN;
for (x = 0; x < (sizeof(AGENT_STATE_CHART) / sizeof(struct cc_agent_state_table)) - 1 && AGENT_STATE_CHART[x].name; x++) {
for (x = 0; x < (sizeof(AGENT_STATE_CHART) / sizeof(struct cc_state_table)) - 1 && AGENT_STATE_CHART[x].name; x++) {
if (!strcasecmp(AGENT_STATE_CHART[x].name, str)) {
state = AGENT_STATE_CHART[x].state;
break;
@@ -334,7 +367,7 @@ const char * cc_member_state2str(cc_member_state_t state)
uint8_t x;
const char *str = "Unknown";
for (x = 0; x < (sizeof(MEMBER_STATE_CHART) / sizeof(struct cc_member_state_table)) - 1; x++) {
for (x = 0; x < (sizeof(MEMBER_STATE_CHART) / sizeof(struct cc_state_table)) - 1; x++) {
if (MEMBER_STATE_CHART[x].state == state) {
str = MEMBER_STATE_CHART[x].name;
break;
@@ -349,7 +382,7 @@ cc_member_state_t cc_member_str2state(const char *str)
uint8_t x;
cc_member_state_t state = CC_MEMBER_STATE_UNKNOWN;
for (x = 0; x < (sizeof(MEMBER_STATE_CHART) / sizeof(struct cc_member_state_table)) - 1 && MEMBER_STATE_CHART[x].name; x++) {
for (x = 0; x < (sizeof(MEMBER_STATE_CHART) / sizeof(struct cc_state_table)) - 1 && MEMBER_STATE_CHART[x].name; x++) {
if (!strcasecmp(MEMBER_STATE_CHART[x].name, str)) {
state = MEMBER_STATE_CHART[x].state;
break;
@@ -384,19 +417,27 @@ struct cc_queue {
char *moh;
char *record_template;
char *time_base_score;
switch_bool_t tier_rules_apply;
uint32_t tier_rule_wait_second;
switch_bool_t tier_rule_wait_multiply_level;
switch_bool_t tier_rule_no_agent_no_wait;
uint32_t discard_abandoned_after;
switch_bool_t abandoned_resume_allowed;
uint32_t max_wait_time;
uint32_t max_wait_time_with_no_agent;
switch_mutex_t *mutex;
switch_thread_rwlock_t *rwlock;
switch_memory_pool_t *pool;
uint32_t flags;
switch_time_t last_agent_exist;
switch_time_t last_agent_exist_check;
switch_xml_config_item_t config[CC_QUEUE_CONFIGITEM_COUNT];
switch_xml_config_string_options_t config_str_pool;
@@ -488,6 +529,7 @@ cc_queue_t *queue_set_config(cc_queue_t *queue)
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "moh-sound", SWITCH_CONFIG_STRING, 0, &queue->moh, NULL, &queue->config_str_pool, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "record-template", SWITCH_CONFIG_STRING, 0, &queue->record_template, NULL, &queue->config_str_pool, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "time-base-score", SWITCH_CONFIG_STRING, 0, &queue->time_base_score, "queue", &queue->config_str_pool, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rules-apply", SWITCH_CONFIG_BOOL, 0, &queue->tier_rules_apply, SWITCH_FALSE, NULL, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rule-wait-second", SWITCH_CONFIG_INT, 0, &queue->tier_rule_wait_second, 0, &config_int_0_86400, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "tier-rule-wait-multiply-level", SWITCH_CONFIG_BOOL, 0, &queue->tier_rule_wait_multiply_level, SWITCH_FALSE, NULL, NULL, NULL);
@@ -495,6 +537,9 @@ cc_queue_t *queue_set_config(cc_queue_t *queue)
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "discard-abandoned-after", SWITCH_CONFIG_INT, 0, &queue->discard_abandoned_after, 60, &config_int_0_86400, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "abandoned-resume-allowed", SWITCH_CONFIG_BOOL, 0, &queue->abandoned_resume_allowed, SWITCH_FALSE, NULL, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time", SWITCH_CONFIG_INT, 0, &queue->max_wait_time, 0, &config_int_0_86400, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(queue->config[i++], "max-wait-time-with-no-agent", SWITCH_CONFIG_INT, 0, &queue->max_wait_time_with_no_agent, 0, &config_int_0_86400, NULL, NULL);
switch_assert(i < CC_QUEUE_CONFIGITEM_COUNT);
return queue;
@@ -646,6 +691,9 @@ static cc_queue_t *load_queue(const char *queue_name)
switch_thread_rwlock_create(&queue->rwlock, pool);
queue->name = switch_core_strdup(pool, queue_name);
queue->last_agent_exist = 0;
queue->last_agent_exist_check = 0;
if (!(dbh = cc_get_db_handle())) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot open DB!\n");
goto end;
@@ -702,7 +750,7 @@ static cc_queue_t *get_queue(const char *queue_name)
struct call_helper {
const char *member_uuid;
const char *queue;
const char *queue_name;
const char *queue_strategy;
const char *member_joined_epoch;
const char *member_caller_name;
@@ -744,7 +792,7 @@ int cc_queue_count(const char *queue)
count = atoi(res);
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", queue);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "members-count");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Count", res);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Selection", event_name);
@@ -827,7 +875,7 @@ cc_agent_status_t cc_agent_get(const char *key, const char *agent, char *ret_res
result = CC_STATUS_SUCCESS;
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", agent);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", agent);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-status-get");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Status", res);
switch_event_fire(&event);
@@ -894,7 +942,7 @@ cc_status_t cc_agent_update(const char *key, const char *value, const char *agen
result = CC_STATUS_SUCCESS;
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", agent);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", agent);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-status-change");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-Status", value);
switch_event_fire(&event);
@@ -918,7 +966,7 @@ cc_status_t cc_agent_update(const char *key, const char *value, const char *agen
result = CC_STATUS_SUCCESS;
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", agent);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent", agent);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "agent-state-change");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Agent-State", value);
switch_event_fire(&event);
@@ -1118,13 +1166,13 @@ done:
return result;
}
cc_status_t cc_tier_del(const char *queue, const char *agent)
cc_status_t cc_tier_del(const char *queue_name, const char *agent)
{
cc_status_t result = CC_STATUS_SUCCESS;
char *sql;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleted tier Agent %s in Queue %s\n", agent, queue);
sql = switch_mprintf("DELETE FROM tiers WHERE queue = '%q' AND agent = '%q';", queue, agent);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleted tier Agent %s in Queue %s\n", agent, queue_name);
sql = switch_mprintf("DELETE FROM tiers WHERE queue = '%q' AND agent = '%q';", queue_name, agent);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
@@ -1307,8 +1355,11 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
}
if (!strcasecmp(h->agent_type, CC_AGENT_TYPE_CALLBACK)) {
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_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, "ignore_early_media", "true");
t_agent_called = switch_epoch_time_now(NULL);
@@ -1323,6 +1374,12 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_channel_t *agent_channel = switch_core_session_get_channel(agent_session);
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_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);
/* Playback this to the agent */
if (cc_warning_tone && switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute");
@@ -1375,7 +1432,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(agent_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", h->queue);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "bridge-agent-start");
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);
@@ -1398,11 +1455,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_safe_free(sql);
/* Change the agents Status in the tiers */
sql = switch_mprintf("UPDATE tiers SET state = '%q' WHERE agent = '%q' AND queue = '%q'",
cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), h->agent_name, h->queue);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
cc_tier_update("state", cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), h->queue_name, h->agent_name);
cc_agent_update("state", cc_agent_state2str(CC_AGENT_STATE_IN_A_QUEUE_CALL), h->agent_name);
/* Record session if record-template is provided */
@@ -1415,9 +1468,12 @@ 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, (h->record_template?" (Recorded)":""));
switch_ivr_uuid_bridge(switch_core_session_get_uuid(agent_session), h->member_uuid);
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));
/* This is used for the waiting caller to quit waiting for a agent */
switch_channel_set_variable(member_channel, "cc_agent_uuid", agent_uuid);
/* Wait until the member hangup or the agent hangup. This will quit also if the agent transfer the call */
while(switch_channel_up(member_channel) && switch_channel_up(agent_channel) && globals.running) {
@@ -1427,7 +1483,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(agent_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", h->queue);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "bridge-agent-end");
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);
@@ -1443,7 +1499,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
/* Update Agents Items */
/* Do not remove uuid of the agent if we are a standby agent */
sql = switch_mprintf("UPDATE agents SET %q last_bridge_end = %ld, talk_time = talk_time + (%ld-last_bridge_start) WHERE name = '%q' AND system = '%q';"
, (strcasecmp(h->agent_type, "uuid-standby")?"uuid = '',":""), (long) switch_epoch_time_now(NULL), (long) switch_epoch_time_now(NULL), h->agent_name, h->agent_system);
, (strcasecmp(h->agent_type, CC_AGENT_TYPE_UUID_STANDBY)?"uuid = '',":""), (long) switch_epoch_time_now(NULL), (long) switch_epoch_time_now(NULL), h->agent_name, h->agent_system);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
@@ -1455,7 +1511,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
/* Caller off event */
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(member_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", h->queue);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", h->queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-end");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", "Terminated");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Agent-Answer-Time", "%ld", (long) (t_agent_answered - t_agent_called));
@@ -1463,8 +1519,10 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Talk-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_agent_answered));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Total-Time", "%ld", (long) (switch_epoch_time_now(NULL) - 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-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_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);
}
@@ -1529,8 +1587,8 @@ done:
sql = switch_mprintf(
"UPDATE tiers SET state = '%q' WHERE agent = '%q' AND queue = '%q' AND (state = '%q' OR state = '%q' OR state = '%q');"
"UPDATE tiers SET state = '%q' WHERE agent = '%q' AND NOT queue = '%q' AND state = '%q'"
, cc_tier_state2str(tiers_state), h->agent_name, h->queue, cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), cc_tier_state2str(CC_TIER_STATE_STANDBY), cc_tier_state2str(CC_TIER_STATE_OFFERING),
cc_tier_state2str(CC_TIER_STATE_READY), h->agent_name, h->queue, cc_tier_state2str(CC_TIER_STATE_STANDBY));
, cc_tier_state2str(tiers_state), h->agent_name, h->queue_name, cc_tier_state2str(CC_TIER_STATE_ACTIVE_INBOUND), cc_tier_state2str(CC_TIER_STATE_STANDBY), cc_tier_state2str(CC_TIER_STATE_OFFERING),
cc_tier_state2str(CC_TIER_STATE_READY), h->agent_name, h->queue_name, cc_tier_state2str(CC_TIER_STATE_STANDBY));
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
@@ -1558,7 +1616,7 @@ done:
}
struct agent_callback {
const char *queue;
const char *queue_name;
const char *system;
const char *uuid;
const char *caller_number;
@@ -1570,6 +1628,7 @@ struct agent_callback {
uint32_t tier_rule_wait_second;
switch_bool_t tier_rule_wait_multiply_level;
switch_bool_t tier_rule_no_agent_no_wait;
switch_bool_t agent_found;
int tier;
int tier_agent_available;
@@ -1593,6 +1652,8 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
switch_bool_t contact_agent = SWITCH_TRUE;
cbt->agent_found = SWITCH_TRUE;
/* Check if we switch to a different tier, if so, check if we should continue further for that member */
if (cbt->tier_rules_apply == SWITCH_TRUE && atoi(agent_tier_level) > cbt->tier) {
@@ -1691,7 +1752,7 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
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->queue = switch_core_strdup(h->pool, cbt->queue);
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]);
@@ -1704,8 +1765,8 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames
sql = switch_mprintf(
"UPDATE tiers SET state = '%q' WHERE agent = '%q' AND queue = '%q';"
"UPDATE tiers SET state = '%q' WHERE agent = '%q' AND NOT queue = '%q' AND state = '%q';",
cc_tier_state2str(CC_TIER_STATE_OFFERING), h->agent_name, h->queue,
cc_tier_state2str(CC_TIER_STATE_STANDBY), h->agent_name, h->queue, cc_tier_state2str(CC_TIER_STATE_READY));
cc_tier_state2str(CC_TIER_STATE_OFFERING), h->agent_name, h->queue_name,
cc_tier_state2str(CC_TIER_STATE_STANDBY), h->agent_name, h->queue_name, cc_tier_state2str(CC_TIER_STATE_READY));
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
@@ -1772,7 +1833,7 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
switch_safe_free(sql);
}
/* Skip this member */
return 0;
goto end;
}
memset(&cbt, 0, sizeof(cbt));
cbt.tier = 0;
@@ -1787,9 +1848,10 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
cbt.caller_number = argv[2];
cbt.caller_name = argv[3];
cbt.joined_epoch = argv[4];
cbt.queue = argv[0];
cbt.queue_name = argv[0];
cbt.strategy = queue_strategy;
cbt.record_template = queue_record_template;
cbt.agent_found = SWITCH_FALSE;
if (!strcasecmp(queue->strategy, "longest-idle-agent")) {
sql_order_by = switch_mprintf("level, agents.last_offered_call, position");
@@ -1823,6 +1885,18 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName
switch_safe_free(sql);
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]);
goto end;
} else {
queue->last_agent_exist_check = switch_epoch_time_now(NULL);
if (cbt.agent_found) {
queue->last_agent_exist = queue->last_agent_exist_check;
}
queue_rwunlock(queue);
}
end:
switch_safe_free(queue_name);
switch_safe_free(queue_strategy);
@@ -1902,30 +1976,53 @@ void cc_agent_dispatch_thread_start(void)
switch_thread_create(&thread, thd_attr, cc_agent_dispatch_thread_run, NULL, globals.pool);
}
struct member_helper {
const char *uuid;
struct member_thread_helper {
const char *member_uuid;
const char *queue_name;
switch_time_t t_member_called;
cc_member_cancel_reason_t member_cancel_reason;
int running;
switch_memory_pool_t *pool;
};
void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj)
{
struct member_helper *m = (struct member_helper *) obj;
switch_core_session_t *member_session = switch_core_session_locate(m->uuid);
switch_channel_t *channel = NULL;
struct member_thread_helper *m = (struct member_thread_helper *) obj;
switch_core_session_t *member_session = switch_core_session_locate(m->member_uuid);
switch_channel_t *member_channel = NULL;
switch_mutex_lock(globals.mutex);
globals.threads++;
switch_mutex_unlock(globals.mutex);
if (member_session) {
channel = switch_core_session_get_channel(member_session);
member_channel = switch_core_session_get_channel(member_session);
} else {
switch_core_destroy_memory_pool(&m->pool);
return NULL;
}
while(switch_channel_ready(channel) && m->running && globals.running) {
while(switch_channel_ready(member_channel) && m->running && globals.running) {
cc_queue_t *queue = NULL;
if (!m->queue_name || !(queue = get_queue(m->queue_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found\n", m->queue_name);
break;
}
/* Make the Caller Leave if he went over his max wait time */
if (queue->max_wait_time > 0 && queue->max_wait_time <= switch_epoch_time_now(NULL) - m->t_member_called) {
m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_TIMEOUT;
switch_channel_set_flag_value(member_channel, CF_BREAK, 2);
}
/* Will drop the caller if no agent was found for more than X secondes */
if (queue->max_wait_time_with_no_agent > 0 && m->t_member_called < queue->last_agent_exist_check - CC_MAX_TIME_DIFF_CHECK &&
queue->last_agent_exist_check - queue->last_agent_exist >= queue->max_wait_time_with_no_agent) {
m->member_cancel_reason = CC_MEMBER_CANCEL_REASON_NO_AGENT_TIMEOUT;
switch_channel_set_flag_value(member_channel, CF_BREAK, 2);
}
/* TODO Go thought the list of phrases */
/* SAMPLE CODE to playback something over the MOH
@@ -1940,8 +2037,12 @@ void *SWITCH_THREAD_FUNC cc_member_thread_run(switch_thread_t *thread, void *obj
/* If Agent Logoff, we might need to recalculare score based on skill */
/* Play Announcement in order */
switch_yield(100000);
queue_rwunlock(queue);
switch_yield(500000);
}
switch_core_session_rwunlock(member_session);
switch_core_destroy_memory_pool(&m->pool);
@@ -1962,26 +2063,27 @@ SWITCH_STANDARD_APP(callcenter_function)
char *mydata = NULL;
cc_queue_t *queue = NULL;
const char *queue_name = NULL;
switch_channel_t *member_channel = switch_core_session_get_channel(session);
switch_core_session_t *member_session = session;
switch_channel_t *member_channel = switch_core_session_get_channel(member_session);
char *sql = NULL;
char *uuid = switch_core_session_get_uuid(session);
switch_input_args_t args = { 0 };
struct member_helper *h = NULL;
char *member_uuid = switch_core_session_get_uuid(member_session);
struct member_thread_helper *h = NULL;
switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL;
switch_memory_pool_t *pool;
int cc_base_score_int = 0;
switch_channel_timetable_t *times = NULL;
const char *cc_base_score = switch_channel_get_variable(member_channel, "cc_base_score");
const char *cc_moh_override = switch_channel_get_variable(member_channel, "cc_moh_override");
const char *cc_base_score = switch_channel_get_variable(member_channel, "cc_base_score");
int cc_base_score_int = 0;
const char *cur_moh = NULL;
char start_epoch[64];
switch_event_t *event;
switch_time_t t_member_called = switch_epoch_time_now(NULL);
long abandoned_epoch = 0;
const char *agent_uuid = NULL;
if (!zstr(data)) {
mydata = switch_core_session_strdup(session, data);
mydata = switch_core_session_strdup(member_session, data);
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No Queue name provided\n");
@@ -2004,7 +2106,7 @@ SWITCH_STANDARD_APP(callcenter_function)
times = switch_channel_get_timetable(member_channel);
switch_snprintf(start_epoch, sizeof(start_epoch), "%" SWITCH_TIME_T_FMT, times->answered / 1000000);
/* Check of we have a queued abandoned member we can resume from */
/* Check if we support and have a queued abandoned member we can resume from */
if (queue->abandoned_resume_allowed == SWITCH_TRUE) {
char res[256];
@@ -2028,9 +2130,9 @@ SWITCH_STANDARD_APP(callcenter_function)
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(member_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", queue_name);
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", uuid);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", member_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);
@@ -2045,7 +2147,7 @@ SWITCH_STANDARD_APP(callcenter_function)
" (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_name,
uuid,
member_uuid,
start_epoch,
(long) switch_epoch_time_now(NULL),
cc_base_score_int,
@@ -2060,12 +2162,12 @@ SWITCH_STANDARD_APP(callcenter_function)
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'",
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);
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);
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'", uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), queue_name);
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);
cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res));
switch_safe_free(sql);
@@ -2083,9 +2185,14 @@ SWITCH_STANDARD_APP(callcenter_function)
/* Start Thread that will playback different prompt to the channel */
switch_core_new_memory_pool(&pool);
h = switch_core_alloc(pool, sizeof(*h));
h->pool = pool;
h->uuid = switch_core_strdup(h->pool, uuid);
h->member_uuid = switch_core_strdup(h->pool, member_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;
h->running = 1;
switch_threadattr_create(&thd_attr, h->pool);
switch_threadattr_detach_set(thd_attr, 1);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
@@ -2095,16 +2202,37 @@ SWITCH_STANDARD_APP(callcenter_function)
/* TODO Add DTMF callback support */
/* TODO add MOH infitite loop */
if (cc_moh_override) {
cur_moh = switch_core_session_strdup(session, cc_moh_override);
cur_moh = switch_core_session_strdup(member_session, cc_moh_override);
} else {
cur_moh = switch_core_session_strdup(session, queue->moh);
cur_moh = switch_core_session_strdup(member_session, queue->moh);
}
queue_rwunlock(queue);
if (cur_moh) {
switch_ivr_play_file(session, NULL, cur_moh, &args);
} else {
switch_ivr_collect_digits_callback(session, &args, 0, 0);
while (switch_channel_ready(member_channel)) {
switch_input_args_t args = { 0 };
/* An agent was found, time to exit and let the bridge do it job */
if ((agent_uuid = switch_channel_get_variable(member_channel, "cc_agent_uuid"))) {
break;
}
/* If the member thread set a different reason, we monitor it so we can quit the wait */
if (h->member_cancel_reason != CC_MEMBER_CANCEL_REASON_NONE) {
break;
}
switch_core_session_flush_private_events(member_session);
if (cur_moh) {
switch_status_t status = switch_ivr_play_file(member_session, NULL, cur_moh, &args);
if (!SWITCH_READ_ACCEPTABLE(status)) {
break;
}
} else {
switch_ivr_collect_digits_callback(session, &args, 0, 0);
}
}
/* Stop Member Thread */
@@ -2114,33 +2242,42 @@ SWITCH_STANDARD_APP(callcenter_function)
/* Hangup any agents been callback */
if (!switch_channel_up(member_channel)) { /* If channel is still up, it mean that the member didn't hangup, so we should leave the agent alone */
switch_core_session_hupall_matching_var("cc_member_uuid", uuid, SWITCH_CAUSE_ORIGINATOR_CANCEL);
switch_core_session_hupall_matching_var("cc_member_uuid", member_uuid, SWITCH_CAUSE_ORIGINATOR_CANCEL);
sql = switch_mprintf("UPDATE members SET state = '%q', uuid = '', abandoned_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
cc_member_state2str(CC_MEMBER_STATE_ABANDONED), (long) switch_epoch_time_now(NULL), uuid);
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);
/* Generate an Event and update some channel variable */
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(member_channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "member-queue-end");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "CC-Wait-Time", "%ld", (long) (switch_epoch_time_now(NULL) - t_member_called));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", "Abort");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Caller-UUID", uuid);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Member \"%s\" <%s> exit queue %s due to %s\n",
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_name")),
switch_str_nil(switch_channel_get_variable(member_channel, "caller_id_number")),
queue_name, cc_member_cancel_reason2str(h->member_cancel_reason));
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Cause", 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-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);
}
/* for xml_cdr needs */
switch_channel_set_variable_printf(member_channel, "cc_queue_canceled_epoch", "%ld", (long) switch_epoch_time_now(NULL));
switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", cc_member_cancel_reason2str(h->member_cancel_reason));
/* Send Event with queue count */
cc_queue_count(queue_name);
} else {
switch_channel_set_variable_printf(member_channel, "cc_cause", "%s", "answered");
sql = switch_mprintf("UPDATE members SET state = '%q', bridge_epoch = '%ld' WHERE system = 'single_box' AND uuid = '%q'",
cc_member_state2str(CC_MEMBER_STATE_ANSWERED), (long) switch_epoch_time_now(NULL), uuid);
cc_member_state2str(CC_MEMBER_STATE_ANSWERED), (long) switch_epoch_time_now(NULL), member_uuid);
cc_execute_sql(NULL, sql, NULL);
switch_safe_free(sql);
@@ -2516,7 +2653,7 @@ SWITCH_STANDARD_API(cc_config_api_function)
stream->write_function(stream, "%d\n", atoi(res));
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CALLCENTER_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Name", queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Queue", queue_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Action", "members-count");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "CC-Count", res);
switch_event_fire(&event);
+46 -20
View File
@@ -1002,7 +1002,7 @@ static int do_candidates(struct private_object *tech_pvt, int force)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Send Candidate %s:%d [%s]\n", cand[0].address, cand[0].port,
cand[0].username);
if (ldl_session_gateway(tech_pvt->dlsession)) {
if (ldl_session_gateway(tech_pvt->dlsession) && switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
tech_pvt->cand_id = ldl_session_transport(tech_pvt->dlsession, cand, 1);
} else {
tech_pvt->cand_id = ldl_session_candidates(tech_pvt->dlsession, cand, 1);
@@ -1247,7 +1247,8 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session)
tech_pvt->rtp_session = NULL;
}
if (globals.auto_nat && tech_pvt->profile->local_network && !switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) {
if (globals.auto_nat && tech_pvt->profile->local_network && tech_pvt->remote_ip && tech_pvt->profile->local_network &&
!switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) {
switch_nat_del_mapping((switch_port_t) tech_pvt->local_port, SWITCH_NAT_UDP);
}
@@ -1259,6 +1260,10 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session)
switch_core_codec_destroy(&tech_pvt->write_codec);
}
if (tech_pvt->dlsession) {
ldl_session_destroy(&tech_pvt->dlsession);
}
switch_thread_rwlock_unlock(tech_pvt->profile->rwlock);
if (tech_pvt->profile->purge) {
@@ -1296,13 +1301,12 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
if ((tech_pvt->profile->user_flags & LDL_FLAG_COMPONENT) && is_special(tech_pvt->them)) {
ldl_handle_send_presence(tech_pvt->profile->handle, tech_pvt->them, tech_pvt->us, NULL, NULL, "Click To Call", tech_pvt->profile->avatar);
}
if (tech_pvt->dlsession) {
if (!switch_test_flag(tech_pvt, TFLAG_TERM)) {
ldl_session_terminate(tech_pvt->dlsession);
switch_set_flag_locked(tech_pvt, TFLAG_TERM);
}
ldl_session_destroy(&tech_pvt->dlsession);
if (!switch_test_flag(tech_pvt, TFLAG_TERM) && tech_pvt->dlsession) {
ldl_session_terminate(tech_pvt->dlsession);
switch_set_flag_locked(tech_pvt, TFLAG_TERM);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel));
@@ -1324,15 +1328,6 @@ static switch_status_t channel_kill_channel(switch_core_session_t *session, int
switch_clear_flag_locked(tech_pvt, TFLAG_VOICE);
switch_set_flag_locked(tech_pvt, TFLAG_BYE);
if (tech_pvt->dlsession) {
if (!switch_test_flag(tech_pvt, TFLAG_TERM)) {
ldl_session_terminate(tech_pvt->dlsession);
switch_set_flag_locked(tech_pvt, TFLAG_TERM);
}
ldl_session_destroy(&tech_pvt->dlsession);
}
if (switch_rtp_ready(tech_pvt->rtp_session)) {
switch_rtp_kill_socket(tech_pvt->rtp_session);
}
@@ -2980,6 +2975,8 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
tech_pvt->flags |= profile->flags;
channel = switch_core_session_get_channel(session);
switch_core_session_set_private(session, tech_pvt);
tech_pvt->dlsession = dlsession;
tech_pvt->session = session;
tech_pvt->codec_index = -1;
tech_pvt->profile = profile;
@@ -3025,6 +3022,24 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
cid_num = tech_pvt->recip;
}
if (switch_stristr("voice.google.com", from)) {
char *id = switch_core_session_strdup(session, from);
char *p;
if ((p = strchr(id, '@'))) {
*p++ = '\0';
cid_name = "Google Voice";
cid_num = id;
}
ldl_session_set_gateway(dlsession);
do_candidates(tech_pvt, 1);
}
/* context of "_auto_" means set it to the domain */
if (profile->context && !strcmp(profile->context, "_auto_")) {
context = profile->name;
@@ -3047,7 +3062,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
switch_safe_free(tmp);
}
if (!tech_pvt->caller_profile) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"Creating an identity for %s %s <%s> %s\n", ldl_session_get_id(dlsession), cid_name, cid_num, exten);
@@ -3079,7 +3094,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Creating a session for %s\n", ldl_session_get_id(dlsession));
ldl_session_set_private(dlsession, session);
tech_pvt->dlsession = dlsession;
switch_channel_set_name(channel, "DingaLing/new");
switch_channel_set_state(channel, CS_INIT);
if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
@@ -3230,6 +3245,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
}
}
}
}
break;
@@ -3259,7 +3275,15 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
if (profile->acl_count) {
for (x = 0; x < len; x++) {
uint32_t y = 0;
if (strcasecmp(candidates[x].protocol, "udp")) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "candidate %s:%d has an unsupported protocol!\n",
candidates[x].address, candidates[x].port);
continue;
}
for (y = 0; y < profile->acl_count; y++) {
if (switch_check_network_list_ip(candidates[x].address, profile->acl[y])) {
choice = x;
ok = 1;
@@ -3268,7 +3292,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
if (ok) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "candidate %s:%d PASS ACL %s\n",
candidates[x].address, candidates[x].port, profile->acl[y]);
break;
goto end_candidates;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "candidate %s:%d FAIL ACL %s\n",
candidates[x].address, candidates[x].port, profile->acl[y]);
@@ -3311,6 +3335,8 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
}
}
end_candidates:
if (ok) {
ldl_payload_t payloads[5];
+138 -44
View File
@@ -1233,7 +1233,6 @@ static void walk_listeners(skinny_listener_callback_func_t callback, void *pvt)
switch_hash_index_t *hi;
void *val;
skinny_profile_t *profile;
listener_t *l;
/* walk listeners */
switch_mutex_lock(globals.mutex);
@@ -1241,11 +1240,7 @@ static void walk_listeners(skinny_listener_callback_func_t callback, void *pvt)
switch_hash_this(hi, NULL, NULL, &val);
profile = (skinny_profile_t *) val;
switch_mutex_lock(profile->listener_mutex);
for (l = profile->listeners; l; l = l->next) {
callback(l, pvt);
}
switch_mutex_unlock(profile->listener_mutex);
profile_walk_listeners(profile, callback, pvt);
}
switch_mutex_unlock(globals.mutex);
}
@@ -1509,6 +1504,7 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void
new_socket:
while(globals.running) {
switch_clear_flag_locked(profile, PFLAG_RESPAWN);
rv = switch_sockaddr_info_get(&sa, profile->ip, SWITCH_INET, profile->port, 0, tmp_pool);
if (rv)
goto fail;
@@ -1546,8 +1542,10 @@ new_socket:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n");
goto end;
} else if (switch_test_flag(profile, PFLAG_RESPAWN)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Creating a new socket\n");
switch_clear_flag_locked(profile, PFLAG_RESPAWN);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Respawn in progress. Waiting for socket to close.\n");
while (profile->sock) {
switch_cond_next();
}
goto new_socket;
} else {
/* I wish we could use strerror_r here but its not defined everywhere =/ */
@@ -1619,6 +1617,18 @@ switch_endpoint_interface_t *skinny_get_endpoint_interface()
return skinny_endpoint_interface;
}
switch_status_t skinny_profile_respawn(skinny_profile_t *profile, int force)
{
if (force || switch_test_flag(profile, PFLAG_SHOULD_RESPAWN)) {
switch_clear_flag_locked(profile, PFLAG_SHOULD_RESPAWN);
switch_set_flag_locked(profile, PFLAG_RESPAWN);
switch_clear_flag_locked(profile, PFLAG_LISTENER_READY);
profile_walk_listeners(profile, kill_listener, NULL);
close_socket(&profile->sock, profile);
}
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, const char *val)
{
if (!var)
@@ -1633,9 +1643,15 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c
if (!strcasecmp(var, "domain")) {
profile->domain = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "ip")) {
profile->ip = switch_core_strdup(profile->pool, val);
if (!profile->ip || strcmp(val, profile->ip)) {
profile->ip = switch_core_strdup(profile->pool, val);
switch_set_flag_locked(profile, PFLAG_SHOULD_RESPAWN);
}
} else if (!strcasecmp(var, "port")) {
profile->port = atoi(val);
if (atoi(val) != profile->port) {
profile->port = atoi(val);
switch_set_flag_locked(profile, PFLAG_SHOULD_RESPAWN);
}
} else if (!strcasecmp(var, "patterns-dialplan")) {
profile->patterns_dialplan = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "patterns-context")) {
@@ -1669,15 +1685,21 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c
} else {
return SWITCH_STATUS_FALSE;
}
if (profile->sock && (!strcasecmp(var, "ip") || !strcasecmp(var, "port"))) {
switch_set_flag_locked(profile, PFLAG_RESPAWN);
switch_clear_flag_locked(profile, PFLAG_LISTENER_READY);
close_socket(&profile->sock, profile);
}
return SWITCH_STATUS_SUCCESS;
}
void profile_walk_listeners(skinny_profile_t *profile, skinny_listener_callback_func_t callback, void *pvt)
{
listener_t *l;
switch_mutex_lock(profile->listener_mutex);
for (l = profile->listeners; l; l = l->next) {
callback(l, pvt);
}
switch_mutex_unlock(profile->listener_mutex);
}
static switch_status_t load_skinny_config(void)
{
char *cf = "skinny.conf";
@@ -1692,8 +1714,7 @@ static switch_status_t load_skinny_config(void)
if ((xprofiles = switch_xml_child(xcfg, "profiles"))) {
for (xprofile = switch_xml_child(xprofiles, "profile"); xprofile; xprofile = xprofile->next) {
char *profile_name = (char *) switch_xml_attr_soft(xprofile, "name");
switch_xml_t xsettings;
switch_xml_t xdevice_types;
switch_xml_t xsettings, xdevice_types, xsoft_key_set_sets;
if (zstr(profile_name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"<profile> is missing name attribute\n");
@@ -1749,6 +1770,96 @@ static switch_status_t load_skinny_config(void)
profile->port = 2000;
}
/* Soft Key Set Sets */
switch_core_hash_init(&profile->soft_key_set_sets_hash, profile->pool);
if ((xsoft_key_set_sets = switch_xml_child(xprofile, "soft-key-set-sets"))) {
switch_xml_t xsoft_key_set_set;
for (xsoft_key_set_set = switch_xml_child(xsoft_key_set_sets, "soft-key-set-set"); xsoft_key_set_set; xsoft_key_set_set = xsoft_key_set_set->next) {
char *soft_key_set_set_name = (char *) switch_xml_attr_soft(xsoft_key_set_set, "name");
if (soft_key_set_set_name) {
switch_xml_t xsoft_key_set;
skinny_message_t *message;
message = switch_core_alloc(profile->pool, 12+sizeof(message->data.soft_key_set));
message->type = SOFT_KEY_SET_RES_MESSAGE;
message->length = 4 + sizeof(message->data.soft_key_set);
message->data.soft_key_set.soft_key_set_offset = 0;
message->data.soft_key_set.soft_key_set_count = 11;
message->data.soft_key_set.total_soft_key_set_count = 11;
for (xsoft_key_set = switch_xml_child(xsoft_key_set_set, "soft-key-set"); xsoft_key_set; xsoft_key_set = xsoft_key_set->next) {
uint32_t soft_key_set_id;
if ((soft_key_set_id = skinny_str2soft_key_set(switch_xml_attr_soft(xsoft_key_set, "name"))) != -1) {
char *val =switch_core_strdup(profile->pool, switch_xml_attr_soft(xsoft_key_set, "value"));
size_t string_len = strlen(val);
size_t string_pos, start = 0;
int field_no = 0;
if (soft_key_set_id > 15) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"soft-key-set name '%s' is greater than 15 in soft-key-set-set '%s' in profile %s.\n",
switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
continue;
}
for (string_pos = 0; string_pos <= string_len; string_pos++) {
if ((val[string_pos] == ',') || (string_pos == string_len)) {
val[string_pos] = '\0';
if (field_no > 15) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"soft-key-set name '%s' is limited to 16 buttons in soft-key-set-set '%s' in profile %s.\n",
switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
break;
}
message->data.soft_key_set.soft_key_set[soft_key_set_id].soft_key_template_index[field_no++] = skinny_str2soft_key_event(&val[start]);
start = string_pos+1;
}
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unknown soft-key-set name '%s' in soft-key-set-set '%s' in profile %s.\n",
switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
}
} /* soft-key-set */
switch_core_hash_insert(profile->soft_key_set_sets_hash, soft_key_set_set_name, message);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"<soft-key-set-set> is missing a name attribute in profile %s.\n", profile->name);
}
} /* soft-key-set-set */
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"<soft-key-set-sets> is missing in profile %s.\n", profile->name);
} /* soft-key-set-sets */
if (!switch_core_hash_find(profile->soft_key_set_sets_hash, "default")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Profile %s doesn't have a default <soft-key-set-set>. Profile ignored.\n", profile->name);
switch_core_destroy_memory_pool(&profile_pool);
continue;
}
/* Device types */
switch_core_hash_init(&profile->device_type_params_hash, profile->pool);
if ((xdevice_types = switch_xml_child(xprofile, "device-types"))) {
switch_xml_t xdevice_type;
for (xdevice_type = switch_xml_child(xdevice_types, "device-type"); xdevice_type; xdevice_type = xdevice_type->next) {
uint32_t id = skinny_str2device_type(switch_xml_attr_soft(xdevice_type, "id"));
if (id != 0) {
char *id_str = switch_mprintf("%d", id);
skinny_device_type_params_t *params = switch_core_alloc(profile->pool, sizeof(skinny_device_type_params_t));
for (param = switch_xml_child(xdevice_type, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (!strcasecmp(var, "firmware-version")) {
strncpy(params->firmware_version, val, 16);
}
} /* param */
switch_core_hash_insert(profile->device_type_params_hash, id_str, params);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unknow device type %s in profile %s.\n", switch_xml_attr_soft(xdevice_type, "id"), profile->name);
}
}
}
/* Database */
switch_snprintf(dbname, sizeof(dbname), "skinny_%s", profile->name);
profile->dbname = switch_core_strdup(profile->pool, dbname);
@@ -1787,30 +1898,7 @@ static switch_status_t load_skinny_config(void)
skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_buttons", NULL, NULL);
skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_active_lines", NULL, NULL);
/* Device types */
switch_core_hash_init(&profile->device_type_params_hash, profile->pool);
if ((xdevice_types = switch_xml_child(xprofile, "device-types"))) {
switch_xml_t xdevice_type;
for (xdevice_type = switch_xml_child(xdevice_types, "device-type"); xdevice_type; xdevice_type = xdevice_type->next) {
uint32_t id = skinny_str2device_type(switch_xml_attr_soft(xdevice_type, "id"));
if (id != 0) {
char *id_str = switch_mprintf("%d", id);
skinny_device_type_params_t *params = switch_core_alloc(profile->pool, sizeof(skinny_device_type_params_t));
for (param = switch_xml_child(xdevice_type, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (!strcasecmp(var, "firmware-version")) {
strncpy(params->firmware_version, val, 16);
}
} /* param */
switch_core_hash_insert(profile->device_type_params_hash, id_str, params);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unknow device type %s in profile %s.\n", switch_xml_attr_soft(xdevice_type, "id"), profile->name);
}
}
}
skinny_profile_respawn(profile, 0);
/* Register profile */
switch_mutex_lock(globals.mutex);
@@ -2009,6 +2097,7 @@ static void skinny_trap_event_handler(switch_event_t *event)
} else if (!strcmp(profile->ip, old_ip6)) {
skinny_profile_set(profile, "ip", new_ip6);
}
skinny_profile_respawn(profile, 0);
}
}
}
@@ -2034,9 +2123,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
load_skinny_config();
/* at least one profile */
if (!switch_hash_first(NULL, globals.profile_hash)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No profile found!\n");
return SWITCH_STATUS_TERM;
}
/* bind to events */
if ((switch_event_bind_removable(modname, SWITCH_EVENT_HEARTBEAT, NULL, skinny_heartbeat_event_handler, NULL, &globals.heartbeat_node) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our heartbeat handler!\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't bind our heartbeat handler!\n");
/* Not such severe to prevent loading */
}
if ((switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_CALL_STATE, skinny_call_state_event_handler, NULL, &globals.call_state_node) != SWITCH_STATUS_SUCCESS)) {
@@ -2044,11 +2138,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
return SWITCH_STATUS_TERM;
}
if ((switch_event_bind_removable(modname, SWITCH_EVENT_MESSAGE_WAITING, NULL, skinny_message_waiting_event_handler, NULL, &globals.message_waiting_node) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our message waiting handler!\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't bind our message waiting handler!\n");
/* Not such severe to prevent loading */
}
if ((switch_event_bind_removable(modname, SWITCH_EVENT_TRAP, NULL, skinny_trap_event_handler, NULL, &globals.trap_node) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our trap handler!\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't bind our trap handler!\n");
/* Not such severe to prevent loading */
}
+7 -2
View File
@@ -61,7 +61,8 @@ extern skinny_globals_t globals;
typedef enum {
PFLAG_LISTENER_READY = (1 << 0),
PFLAG_RESPAWN = (1 << 1),
PFLAG_SHOULD_RESPAWN = (1 << 1),
PFLAG_RESPAWN = (1 << 2),
} profile_flag_t;
struct skinny_profile {
@@ -78,6 +79,7 @@ struct skinny_profile {
char date_format[6];
int debug;
int auto_restart;
switch_hash_t *soft_key_set_sets_hash;
switch_hash_t *device_type_params_hash;
/* db */
char *dbname;
@@ -133,6 +135,7 @@ struct listener {
uint32_t device_type;
char firmware_version[16];
char *soft_key_set_set;
switch_socket_t *sock;
switch_memory_pool_t *pool;
@@ -220,6 +223,9 @@ switch_core_session_t * skinny_profile_perform_find_session(skinny_profile_t *pr
switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id);
#endif
switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream);
switch_status_t skinny_profile_respawn(skinny_profile_t *profile, int force);
switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, const char *val);
void profile_walk_listeners(skinny_profile_t *profile, skinny_listener_callback_func_t callback, void *pvt);
/*****************************************************************************/
/* SQL FUNCTIONS */
@@ -262,7 +268,6 @@ switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
/* MODULE FUNCTIONS */
/*****************************************************************************/
switch_endpoint_interface_t *skinny_get_endpoint_interface();
switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, const char *val);
#endif /* _MOD_SKINNY_H */
+9 -1
View File
@@ -275,6 +275,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_ringer_message(const c
skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
if(listener) {
send_set_ringer(listener, skinny_str2ring_type(ring_type), skinny_str2ring_mode(ring_mode), 0, 0);
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "Listener not found!\n");
}
@@ -294,6 +295,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_lamp_message(const cha
skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
if(listener) {
send_set_lamp(listener, skinny_str2button(stimulus), atoi(instance), skinny_str2lamp_mode(lamp_mode));
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "Listener not found!\n");
}
@@ -313,6 +315,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_speaker_mode_message(c
skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
if(listener) {
send_set_speaker_mode(listener, skinny_str2speaker_mode(speaker_mode));
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "Listener not found!\n");
}
@@ -332,6 +335,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_call_state_message(con
skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
if(listener) {
send_call_state(listener, skinny_str2call_state(call_state), atoi(line_instance), atoi(call_id));
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "Listener not found!\n");
}
@@ -351,6 +355,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_reset_message(const ch
skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
if(listener) {
send_reset(listener, skinny_str2device_reset_type(reset_type));
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "Listener not found!\n");
}
@@ -366,7 +371,10 @@ static switch_status_t skinny_api_cmd_profile_set(const char *profile_name, cons
skinny_profile_t *profile;
if ((profile = skinny_find_profile(profile_name))) {
if (skinny_profile_set(profile, name, value) != SWITCH_STATUS_SUCCESS) {
if (skinny_profile_set(profile, name, value) == SWITCH_STATUS_SUCCESS) {
skinny_profile_respawn(profile, 0);
stream->write_function(stream, "+OK\n");
} else {
stream->write_function(stream, "Unable to set skinny setting '%s'. Does it exists?\n", name);
}
} else {
@@ -122,6 +122,9 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
while (listener_is_ready(listener)) {
uint8_t do_sleep = 1;
if (listener->expire_time && listener->expire_time < switch_epoch_time_now(NULL)) {
return SWITCH_STATUS_TIMEOUT;
}
if(bytes < SKINNY_MESSAGE_FIELD_SIZE) {
/* We have nothing yet, get length header field */
mlen = SKINNY_MESSAGE_FIELD_SIZE - bytes;
@@ -171,9 +174,6 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
}
}
}
if (listener->expire_time && listener->expire_time < switch_epoch_time_now(NULL)) {
return SWITCH_STATUS_TIMEOUT;
}
if (do_sleep) {
switch_cond_next();
}
@@ -151,7 +151,7 @@ struct PACKED open_receive_channel_ack_message {
/* SoftKeyEventMessage */
#define SOFT_KEY_EVENT_MESSAGE 0x0026
struct PACKED soft_key_event_message {
uint32_t event;
uint32_t event; /* See enum skinny_soft_key_event */
uint32_t line_instance;
uint32_t call_id;
};
+15 -42
View File
@@ -999,6 +999,8 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r
const char *value = switch_xml_attr_soft(xparam, "value");
if (!strcasecmp(name, "skinny-firmware-version")) {
strncpy(listener->firmware_version, value, 16);
} else if (!strcasecmp(name, "skinny-soft-key-set-set")) {
listener->soft_key_set_set = switch_core_strdup(profile->pool, value);
}
}
}
@@ -1693,49 +1695,20 @@ end:
switch_status_t skinny_handle_soft_key_set_request(listener_t *listener, skinny_message_t *request)
{
skinny_message_t *message;
skinny_profile_t *profile;
skinny_message_t *message = NULL;
switch_assert(listener->profile);
switch_assert(listener->device_name);
profile = listener->profile;
message = switch_core_alloc(listener->pool, 12+sizeof(message->data.soft_key_set));
message->type = SOFT_KEY_SET_RES_MESSAGE;
message->length = 4 + sizeof(message->data.soft_key_set);
message->data.soft_key_set.soft_key_set_offset = 0;
message->data.soft_key_set.soft_key_set_count = 11;
message->data.soft_key_set.total_soft_key_set_count = 11;
/* TODO fill the set */
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[0] = SOFTKEY_NEWCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[2] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT].soft_key_template_index[0] = SOFTKEY_BACKSPACE;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT].soft_key_template_index[2] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[0] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[1] = SOFTKEY_HOLD;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[2] = SOFTKEY_NEWCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[3] = SOFTKEY_TRANSFER;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[0] = SOFTKEY_ANSWER;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[1] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[2] = SOFTKEY_NEWCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[0] = SOFTKEY_NEWCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[1] = SOFTKEY_RESUME;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[2] = SOFTKEY_ENDCALL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES].soft_key_template_index[1] = SOFTKEY_REDIAL;
message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES].soft_key_template_index[2] = SOFTKEY_ENDCALL;
skinny_send_reply(listener, message);
if (listener->soft_key_set_set) {
message = switch_core_hash_find(listener->profile->soft_key_set_sets_hash, listener->soft_key_set_set);
}
if (!message) {
message = switch_core_hash_find(listener->profile->soft_key_set_sets_hash, "default");
}
if (message) {
skinny_send_reply(listener, message);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Profile %s doesn't have a default <soft-key-set-set>.\n", listener->profile->name);
}
/* Init the states */
send_select_soft_keys(listener, 0, 0, SKINNY_KEY_SET_ON_HOOK, 0xffff);
@@ -152,6 +152,32 @@ struct skinny_table SKINNY_BUTTONS[] = {
SKINNY_DECLARE_ID2STR(skinny_button2str, SKINNY_BUTTONS, "Unknown")
SKINNY_DECLARE_STR2ID(skinny_str2button, SKINNY_BUTTONS, -1)
struct skinny_table SKINNY_SOFT_KEY_EVENTS[] = {
{"SoftkeyRedial", SOFTKEY_REDIAL},
{"SoftkeyNewcall", SOFTKEY_NEWCALL},
{"SoftkeyHold", SOFTKEY_HOLD},
{"SoftkeyTransfer", SOFTKEY_TRANSFER},
{"SoftkeyCfwdall", SOFTKEY_CFWDALL},
{"SoftkeyCfwdbusy", SOFTKEY_CFWDBUSY},
{"SoftkeyCfwdnoanswer", SOFTKEY_CFWDNOANSWER},
{"SoftkeyBackspace", SOFTKEY_BACKSPACE},
{"SoftkeyEndcall", SOFTKEY_ENDCALL},
{"SoftkeyResume", SOFTKEY_RESUME},
{"SoftkeyAnswer", SOFTKEY_ANSWER },
{"SoftkeyInfo", SOFTKEY_INFO},
{"SoftkeyConfrm", SOFTKEY_CONFRM},
{"SoftkeyPark", SOFTKEY_PARK},
{"SoftkeyJoin", SOFTKEY_JOIN},
{"SoftkeyMeetmeconfrm", SOFTKEY_MEETMECONFRM},
{"SoftkeyCallpickup", SOFTKEY_CALLPICKUP},
{"SoftkeyGrpcallpickup", SOFTKEY_GRPCALLPICKUP},
{"SoftkeyDnd", SOFTKEY_DND},
{"SoftkeyIdivert", SOFTKEY_IDIVERT},
{NULL, 0}
};
SKINNY_DECLARE_ID2STR(skinny_soft_key_event2str, SKINNY_SOFT_KEY_EVENTS, "SoftkeyUnknown")
SKINNY_DECLARE_STR2ID(skinny_str2soft_key_event, SKINNY_SOFT_KEY_EVENTS, 0)
struct skinny_table SKINNY_LAMP_MODES[] = {
{"Off", SKINNY_LAMP_OFF},
{"On", SKINNY_LAMP_ON},
@@ -194,6 +194,10 @@ enum skinny_soft_key_event {
SOFTKEY_DND = 0x13,
SOFTKEY_IDIVERT = 0x14,
};
extern struct skinny_table SKINNY_SOFT_KEY_EVENTS[21];
const char *skinny_soft_key_event2str(uint32_t id);
uint32_t skinny_str2soft_key_event(const char *str);
#define SKINNY_PUSH_SOFT_KEY_EVENTS SKINNY_DECLARE_PUSH_MATCH(SOFT_KEY_EVENTS)
enum skinny_key_set {
SKINNY_KEY_SET_ON_HOOK = 0,
+18 -3
View File
@@ -697,7 +697,11 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
char *cid = generate_pai_str(session);
char *cid = NULL;
if (sofia_test_pflag(tech_pvt->profile, PFLAG_PASS_CALLEE_ID)) {
cid = generate_pai_str(session);
}
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) && tech_pvt->early_sdp && strcmp(tech_pvt->early_sdp, tech_pvt->local_sdp_str)) {
/* The SIP RFC for SOA forbids sending a 183 with one sdp then a 200 with another but it won't do us much good unless
@@ -1761,7 +1765,14 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
nua_update(tech_pvt->nh,
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END());
}
} else if ((ua && (switch_stristr("cisco", ua)))) {
snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <sip:%s@%s>", name, number, tech_pvt->profile->sipip);
sofia_set_flag_locked(tech_pvt, TFLAG_UPDATING_DISPLAY);
nua_update(tech_pvt->nh,
TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message)),
TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END());
}
tech_pvt->last_sent_callee_id_name = switch_core_session_strdup(tech_pvt->session, name);
tech_pvt->last_sent_callee_id_number = switch_core_session_strdup(tech_pvt->session, number);
@@ -2158,7 +2169,11 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) {
char *extra_header = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX);
char *cid = generate_pai_str(session);
char *cid = NULL;
if (sofia_test_pflag(tech_pvt->profile, PFLAG_PASS_CALLEE_ID)) {
cid = generate_pai_str(session);
}
if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) &&
tech_pvt->early_sdp && strcmp(tech_pvt->early_sdp, tech_pvt->local_sdp_str)) {
+9 -9
View File
@@ -4664,22 +4664,22 @@ void sofia_glue_tech_track(sofia_profile_t *profile, switch_core_session_t *sess
return;
}
if (sofia_test_flag(tech_pvt, TFLAG_TRACKED)) {
sofia_glue_tech_untrack(profile, session, SWITCH_TRUE);
}
if (switch_ivr_generate_xml_cdr(session, &cdr) == SWITCH_STATUS_SUCCESS) {
xml_cdr_text = switch_xml_toxml(cdr, SWITCH_FALSE);
switch_xml_free(cdr);
}
if (xml_cdr_text) {
sql = switch_mprintf("insert into sip_recovery (runtime_uuid, profile_name, hostname, uuid, metadata) values ('%q','%q','%q','%q','%q')",
switch_core_get_uuid(), profile->name, mod_sofia_globals.hostname, switch_core_session_get_uuid(session), xml_cdr_text);
if (sofia_test_flag(tech_pvt, TFLAG_TRACKED)) {
sql = switch_mprintf("update sip_recovery set metadata='%q' where uuid='%q'", xml_cdr_text, switch_core_session_get_uuid(session));
} else {
sql = switch_mprintf("insert into sip_recovery (runtime_uuid, profile_name, hostname, uuid, metadata) values ('%q','%q','%q','%q','%q')",
switch_core_get_uuid(), profile->name, mod_sofia_globals.hostname, switch_core_session_get_uuid(session), xml_cdr_text);
}
if (sofia_test_pflag(profile, PFLAG_TRACK_CALLS_EVENTS)) {
switch_event_t *event = NULL;
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_RECOVERY_SEND) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "profile_name", profile->name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sql", sql);
@@ -4687,8 +4687,8 @@ void sofia_glue_tech_track(sofia_profile_t *profile, switch_core_session_t *sess
}
}
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
free(xml_cdr_text);
sofia_set_flag(tech_pvt, TFLAG_TRACKED);
+13 -13
View File
@@ -673,8 +673,8 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot)
if (now && sofia_test_pflag(profile, PFLAG_NAT_OPTIONS_PING)) {
switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,"
"expires,user_agent,server_user,server_host,profile_name"
" from sip_registrations where (status like '%%AUTO-NAT%%' "
"or status like '%%UDP-NAT%%') and hostname='%s'", mod_sofia_globals.hostname);
" from sip_registrations where (status like '%%NAT%%' "
"or contact like '%%fs_nat=true%%') and hostname='%s'", mod_sofia_globals.hostname);
sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_nat_callback, profile);
}
@@ -1178,17 +1178,6 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET);
if (profile->reg_db_domain) {
if (!sofia_glue_profile_exists(to_host)) {
if (sofia_glue_add_profile(switch_core_strdup(profile->pool, to_host), profile) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Auto-Adding Alias [%s] for profile [%s]\n", to_host, profile->name);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Alias [%s] for profile [%s] (already exists)\n",
to_host, profile->name);
}
}
}
sql = switch_mprintf("insert into sip_registrations "
"(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires,"
@@ -1430,6 +1419,17 @@ void sofia_reg_handle_sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_h
int network_port = 0;
char *is_nat = NULL;
if (sip->sip_to && sip->sip_to->a_url && sip->sip_to->a_url->url_host) {
const char *to_host = sip->sip_to->a_url->url_host;
if (profile->reg_db_domain) {
if (!sofia_glue_profile_exists(to_host)) {
if (sofia_glue_add_profile(switch_core_strdup(profile->pool, to_host), profile) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Auto-Adding Alias [%s] for profile [%s]\n", to_host, profile->name);
}
}
}
}
sofia_glue_get_addr(nua_current_request(nua), network_ip, sizeof(network_ip), &network_port);
if (!(sip->sip_contact && sip->sip_contact->m_url)) {
+18 -4
View File
@@ -18,6 +18,10 @@
%}
/* Lua function typemap */
%typemap(in,checkfn="lua_isfunction") SWIGLUA_FN
%{ $1.L=L; $1.idx=$input; %}
%ignore SwitchToMempool;
%newobject EventConsumer::pop;
@@ -25,6 +29,7 @@
%newobject CoreSession;
%newobject Event;
%newobject Stream;
%newobject Dbh;
/**
* tell swig to grok everything defined in these header files and
@@ -66,9 +71,18 @@ class Session : public CoreSession {
void setLUA(lua_State *state);
};
class Dbh {
private:
switch_cache_db_handle_t *dbh;
bool connected;
static int query_callback(void *pArg, int argc, char **argv, char **cargv);
public:
Dbh(char *dsn, char *user = NULL, char *pass = NULL);
~Dbh();
bool release();
bool query(char *sql, SWIGLUA_FN lua_fun);
};
}
@@ -308,3 +308,69 @@ switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t ityp
return SWITCH_STATUS_SUCCESS;
}
Dbh::Dbh(char *dsn, char *user, char *pass)
{
switch_cache_db_connection_options_t options = { {0} };
options.odbc_options.dsn = dsn;
options.odbc_options.user = user;
options.odbc_options.pass = pass;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) == SWITCH_STATUS_SUCCESS) {
connected = true;
} else {
connected = false;
}
}
Dbh::~Dbh()
{
release();
}
bool Dbh::release()
{
if (connected) {
switch_cache_db_release_db_handle(&dbh);
connected = false;
return true;
}
return false;
}
int Dbh::query_callback(void *pArg, int argc, char **argv, char **cargv)
{
SWIGLUA_FN *lua_fun = (SWIGLUA_FN *)pArg;
lua_pushvalue(lua_fun->L, lua_fun->idx); /* get the lua callback function onto the stack */
lua_newtable(lua_fun->L); /* push a row (table) */
for (int i = 0; i < argc; i++) {
lua_pushstring(lua_fun->L, switch_str_nil(cargv[i]));
lua_pushstring(lua_fun->L, switch_str_nil(argv[i]));
lua_settable(lua_fun->L, -3);
}
lua_call(lua_fun->L, 1, 1); /* 1 in, 1 out */
if (lua_isnumber(lua_fun->L, -1)) {
if (lua_tonumber(lua_fun->L, -1) != 0) {
return 1;
}
}
return 0; /* 0 to continue with next row */
}
bool Dbh::query(char *sql, SWIGLUA_FN lua_fun)
{
if (connected) {
if (switch_cache_db_execute_sql_callback(dbh, sql, query_callback, &lua_fun, NULL) == SWITCH_STATUS_SUCCESS) {
return true;
}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no workie workie :(\n");
return false;
}
@@ -8,6 +8,16 @@ extern "C" {
#include "mod_lua_extra.h"
}
#include <switch_cpp.h>
typedef struct{
lua_State* L;
int idx;
}SWIGLUA_FN;
#define SWIGLUA_FN_GET(fn) {lua_pushvalue(fn.L,fn.idx);}
namespace LUA {
class Session:public CoreSession {
private:
@@ -41,5 +51,17 @@ namespace LUA {
void setLUA(lua_State * state);
};
class Dbh {
protected:
switch_cache_db_handle_t *dbh;
bool connected;
static int query_callback(void *pArg, int argc, char **argv, char **cargv);
public:
Dbh(char *dsn, char *user = NULL, char *pass = NULL);
~Dbh();
bool release();
bool query(char *sql, SWIGLUA_FN lua_fun);
};
}
#endif
+14 -14
View File
@@ -1,38 +1,38 @@
--- mod_lua_wrap.cpp 2008-07-16 16:58:58.000000000 -0400
+++ old.cpp 2008-07-16 16:58:42.000000000 -0400
@@ -6731,7 +6731,7 @@
SWIG_check_num_args("LUA::Session",0,0)
--- mod_lua_wrap.cpp.orig 2010-09-05 16:39:26.000000000 +0200
+++ mod_lua_wrap.cpp 2010-09-05 16:39:44.000000000 +0200
@@ -4913,7 +4913,7 @@
result = (LUA::Session *)new LUA::Session();
SWIG_arg=0;
- SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++;
+ SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L);
return SWIG_arg;
if(0) SWIG_fail;
@@ -6759,7 +6759,7 @@
fail:
@@ -4934,7 +4934,7 @@
arg2=(CoreSession *)SWIG_MustGetPtr(L,2,SWIGTYPE_p_CoreSession,0,2,"new_Session");
result = (LUA::Session *)new LUA::Session(arg1,arg2);
SWIG_arg=0;
- SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++;
+ SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L);
return SWIG_arg;
if(0) SWIG_fail;
@@ -6780,7 +6780,7 @@
arg1 = (char *)lua_tostring(L, 1);
fail:
@@ -4952,7 +4952,7 @@
arg1 = (char*)lua_tostring(L, 1);
result = (LUA::Session *)new LUA::Session(arg1);
SWIG_arg=0;
- SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++;
+ SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L);
return SWIG_arg;
if(0) SWIG_fail;
@@ -6805,7 +6805,7 @@
fail:
@@ -4970,7 +4970,7 @@
arg1=(switch_core_session_t *)SWIG_MustGetPtr(L,1,SWIGTYPE_p_switch_core_session_t,0,1,"new_Session");
result = (LUA::Session *)new LUA::Session(arg1);
SWIG_arg=0;
- SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++;
+ SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L);
return SWIG_arg;
if(0) SWIG_fail;
fail:
+257 -23
View File
@@ -1490,29 +1490,31 @@ SWIG_Lua_dostring(lua_State *L, const char* str) {
#define SWIGTYPE_p_Event swig_types[3]
#define SWIGTYPE_p_EventConsumer swig_types[4]
#define SWIGTYPE_p_IVRMenu swig_types[5]
#define SWIGTYPE_p_LUA__Session swig_types[6]
#define SWIGTYPE_p_Stream swig_types[7]
#define SWIGTYPE_p_input_callback_state swig_types[8]
#define SWIGTYPE_p_lua_State swig_types[9]
#define SWIGTYPE_p_p_switch_event_node_t swig_types[10]
#define SWIGTYPE_p_session_flag_t swig_types[11]
#define SWIGTYPE_p_switch_call_cause_t swig_types[12]
#define SWIGTYPE_p_switch_channel_state_t swig_types[13]
#define SWIGTYPE_p_switch_channel_t swig_types[14]
#define SWIGTYPE_p_switch_core_session_t swig_types[15]
#define SWIGTYPE_p_switch_event_t swig_types[16]
#define SWIGTYPE_p_switch_event_types_t swig_types[17]
#define SWIGTYPE_p_switch_input_args_t swig_types[18]
#define SWIGTYPE_p_switch_input_type_t swig_types[19]
#define SWIGTYPE_p_switch_priority_t swig_types[20]
#define SWIGTYPE_p_switch_queue_t swig_types[21]
#define SWIGTYPE_p_switch_state_handler_table_t swig_types[22]
#define SWIGTYPE_p_switch_status_t swig_types[23]
#define SWIGTYPE_p_switch_stream_handle_t swig_types[24]
#define SWIGTYPE_p_uint32_t swig_types[25]
#define SWIGTYPE_p_void swig_types[26]
static swig_type_info *swig_types[28];
static swig_module_info swig_module = {swig_types, 27, 0, 0, 0, 0};
#define SWIGTYPE_p_LUA__Dbh swig_types[6]
#define SWIGTYPE_p_LUA__Session swig_types[7]
#define SWIGTYPE_p_SWIGLUA_FN swig_types[8]
#define SWIGTYPE_p_Stream swig_types[9]
#define SWIGTYPE_p_input_callback_state swig_types[10]
#define SWIGTYPE_p_lua_State swig_types[11]
#define SWIGTYPE_p_p_switch_event_node_t swig_types[12]
#define SWIGTYPE_p_session_flag_t swig_types[13]
#define SWIGTYPE_p_switch_call_cause_t swig_types[14]
#define SWIGTYPE_p_switch_channel_state_t swig_types[15]
#define SWIGTYPE_p_switch_channel_t swig_types[16]
#define SWIGTYPE_p_switch_core_session_t swig_types[17]
#define SWIGTYPE_p_switch_event_t swig_types[18]
#define SWIGTYPE_p_switch_event_types_t swig_types[19]
#define SWIGTYPE_p_switch_input_args_t swig_types[20]
#define SWIGTYPE_p_switch_input_type_t swig_types[21]
#define SWIGTYPE_p_switch_priority_t swig_types[22]
#define SWIGTYPE_p_switch_queue_t swig_types[23]
#define SWIGTYPE_p_switch_state_handler_table_t swig_types[24]
#define SWIGTYPE_p_switch_status_t swig_types[25]
#define SWIGTYPE_p_switch_stream_handle_t swig_types[26]
#define SWIGTYPE_p_uint32_t swig_types[27]
#define SWIGTYPE_p_void swig_types[28]
static swig_type_info *swig_types[30];
static swig_module_info swig_module = {swig_types, 29, 0, 0, 0, 0};
#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
@@ -7005,6 +7007,230 @@ static swig_lua_class *swig_LUA_Session_bases[] = {0,0};
static const char *swig_LUA_Session_base_names[] = {"CoreSession *",0};
static swig_lua_class _wrap_class_LUA_Session = { "Session", &SWIGTYPE_p_LUA__Session,_wrap_new_Session, swig_delete_Session, swig_LUA_Session_methods, swig_LUA_Session_attributes, swig_LUA_Session_bases, swig_LUA_Session_base_names };
static int _wrap_new_Dbh__SWIG_0(lua_State* L) {
int SWIG_arg = -1;
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
char *arg3 = (char *) 0 ;
LUA::Dbh *result = 0 ;
SWIG_check_num_args("LUA::Dbh",3,3)
if(!lua_isstring(L,1)) SWIG_fail_arg("LUA::Dbh",1,"char *");
if(!lua_isstring(L,2)) SWIG_fail_arg("LUA::Dbh",2,"char *");
if(!lua_isstring(L,3)) SWIG_fail_arg("LUA::Dbh",3,"char *");
arg1 = (char *)lua_tostring(L, 1);
arg2 = (char *)lua_tostring(L, 2);
arg3 = (char *)lua_tostring(L, 3);
result = (LUA::Dbh *)new LUA::Dbh(arg1,arg2,arg3);
SWIG_arg=0;
SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Dbh,1); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_new_Dbh__SWIG_1(lua_State* L) {
int SWIG_arg = -1;
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
LUA::Dbh *result = 0 ;
SWIG_check_num_args("LUA::Dbh",2,2)
if(!lua_isstring(L,1)) SWIG_fail_arg("LUA::Dbh",1,"char *");
if(!lua_isstring(L,2)) SWIG_fail_arg("LUA::Dbh",2,"char *");
arg1 = (char *)lua_tostring(L, 1);
arg2 = (char *)lua_tostring(L, 2);
result = (LUA::Dbh *)new LUA::Dbh(arg1,arg2);
SWIG_arg=0;
SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Dbh,1); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_new_Dbh__SWIG_2(lua_State* L) {
int SWIG_arg = -1;
char *arg1 = (char *) 0 ;
LUA::Dbh *result = 0 ;
SWIG_check_num_args("LUA::Dbh",1,1)
if(!lua_isstring(L,1)) SWIG_fail_arg("LUA::Dbh",1,"char *");
arg1 = (char *)lua_tostring(L, 1);
result = (LUA::Dbh *)new LUA::Dbh(arg1);
SWIG_arg=0;
SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Dbh,1); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_new_Dbh(lua_State* L) {
int argc;
int argv[4]={
1,2,3,4
};
argc = lua_gettop(L);
if (argc == 1) {
int _v;
{
_v = lua_isstring(L,argv[0]);
}
if (_v) {
return _wrap_new_Dbh__SWIG_2(L);
}
}
if (argc == 2) {
int _v;
{
_v = lua_isstring(L,argv[0]);
}
if (_v) {
{
_v = lua_isstring(L,argv[1]);
}
if (_v) {
return _wrap_new_Dbh__SWIG_1(L);
}
}
}
if (argc == 3) {
int _v;
{
_v = lua_isstring(L,argv[0]);
}
if (_v) {
{
_v = lua_isstring(L,argv[1]);
}
if (_v) {
{
_v = lua_isstring(L,argv[2]);
}
if (_v) {
return _wrap_new_Dbh__SWIG_0(L);
}
}
}
}
lua_pushstring(L,"No matching function for overloaded 'new_Dbh'");
lua_error(L);return 0;
}
static int _wrap_delete_Dbh(lua_State* L) {
int SWIG_arg = -1;
LUA::Dbh *arg1 = (LUA::Dbh *) 0 ;
SWIG_check_num_args("LUA::~Dbh",1,1)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("LUA::~Dbh",1,"LUA::Dbh *");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,SWIG_POINTER_DISOWN))){
SWIG_fail_ptr("delete_Dbh",1,SWIGTYPE_p_LUA__Dbh);
}
delete arg1;
SWIG_arg=0;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_Dbh_release(lua_State* L) {
int SWIG_arg = -1;
LUA::Dbh *arg1 = (LUA::Dbh *) 0 ;
bool result;
SWIG_check_num_args("release",1,1)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("release",1,"LUA::Dbh *");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){
SWIG_fail_ptr("Dbh_release",1,SWIGTYPE_p_LUA__Dbh);
}
result = (bool)(arg1)->release();
SWIG_arg=0;
lua_pushboolean(L,(int)(result==true)); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static int _wrap_Dbh_query(lua_State* L) {
int SWIG_arg = -1;
LUA::Dbh *arg1 = (LUA::Dbh *) 0 ;
char *arg2 = (char *) 0 ;
SWIGLUA_FN arg3 ;
bool result;
SWIG_check_num_args("query",3,3)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("query",1,"LUA::Dbh *");
if(!lua_isstring(L,2)) SWIG_fail_arg("query",2,"char *");
if(!lua_isfunction(L,3)) SWIG_fail_arg("query",3,"SWIGLUA_FN");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){
SWIG_fail_ptr("Dbh_query",1,SWIGTYPE_p_LUA__Dbh);
}
arg2 = (char *)lua_tostring(L, 2);
(&arg3)->L=L; (&arg3)->idx=3;
result = (bool)(arg1)->query(arg2,arg3);
SWIG_arg=0;
lua_pushboolean(L,(int)(result==true)); SWIG_arg++;
return SWIG_arg;
if(0) SWIG_fail;
fail:
lua_error(L);
return SWIG_arg;
}
static void swig_delete_Dbh(void *obj) {
LUA::Dbh *arg1 = (LUA::Dbh *) obj;
delete arg1;
}
static swig_lua_method swig_LUA_Dbh_methods[] = {
{"release", _wrap_Dbh_release},
{"query", _wrap_Dbh_query},
{0,0}
};
static swig_lua_attribute swig_LUA_Dbh_attributes[] = {
{0,0,0}
};
static swig_lua_class *swig_LUA_Dbh_bases[] = {0};
static const char *swig_LUA_Dbh_base_names[] = {0};
static swig_lua_class _wrap_class_LUA_Dbh = { "Dbh", &SWIGTYPE_p_LUA__Dbh,_wrap_new_Dbh, swig_delete_Dbh, swig_LUA_Dbh_methods, swig_LUA_Dbh_attributes, swig_LUA_Dbh_bases, swig_LUA_Dbh_base_names };
#ifdef __cplusplus
}
#endif
@@ -7043,7 +7269,9 @@ static swig_type_info _swigt__p_DTMF = {"_p_DTMF", "DTMF *", 0, 0, (void*)&_wrap
static swig_type_info _swigt__p_Event = {"_p_Event", "Event *", 0, 0, (void*)&_wrap_class_Event, 0};
static swig_type_info _swigt__p_EventConsumer = {"_p_EventConsumer", "EventConsumer *", 0, 0, (void*)&_wrap_class_EventConsumer, 0};
static swig_type_info _swigt__p_IVRMenu = {"_p_IVRMenu", "IVRMenu *", 0, 0, (void*)&_wrap_class_IVRMenu, 0};
static swig_type_info _swigt__p_LUA__Dbh = {"_p_LUA__Dbh", "LUA::Dbh *", 0, 0, (void*)&_wrap_class_LUA_Dbh, 0};
static swig_type_info _swigt__p_LUA__Session = {"_p_LUA__Session", "LUA::Session *", 0, 0, (void*)&_wrap_class_LUA_Session, 0};
static swig_type_info _swigt__p_SWIGLUA_FN = {"_p_SWIGLUA_FN", "SWIGLUA_FN *", 0, 0, (void*)0, 0};
static swig_type_info _swigt__p_Stream = {"_p_Stream", "Stream *", 0, 0, (void*)&_wrap_class_Stream, 0};
static swig_type_info _swigt__p_input_callback_state = {"_p_input_callback_state", "input_callback_state_t *|input_callback_state *", 0, 0, (void*)&_wrap_class_input_callback_state_t, 0};
static swig_type_info _swigt__p_lua_State = {"_p_lua_State", "lua_State *", 0, 0, (void*)0, 0};
@@ -7072,7 +7300,9 @@ static swig_type_info *swig_type_initial[] = {
&_swigt__p_Event,
&_swigt__p_EventConsumer,
&_swigt__p_IVRMenu,
&_swigt__p_LUA__Dbh,
&_swigt__p_LUA__Session,
&_swigt__p_SWIGLUA_FN,
&_swigt__p_Stream,
&_swigt__p_input_callback_state,
&_swigt__p_lua_State,
@@ -7101,7 +7331,9 @@ static swig_cast_info _swigc__p_DTMF[] = { {&_swigt__p_DTMF, 0, 0, 0},{0, 0, 0,
static swig_cast_info _swigc__p_Event[] = { {&_swigt__p_Event, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_EventConsumer[] = { {&_swigt__p_EventConsumer, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_IVRMenu[] = { {&_swigt__p_IVRMenu, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_LUA__Dbh[] = { {&_swigt__p_LUA__Dbh, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_LUA__Session[] = { {&_swigt__p_LUA__Session, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_SWIGLUA_FN[] = { {&_swigt__p_SWIGLUA_FN, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_Stream[] = { {&_swigt__p_Stream, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_input_callback_state[] = { {&_swigt__p_input_callback_state, 0, 0, 0},{0, 0, 0, 0}};
static swig_cast_info _swigc__p_lua_State[] = { {&_swigt__p_lua_State, 0, 0, 0},{0, 0, 0, 0}};
@@ -7130,7 +7362,9 @@ static swig_cast_info *swig_cast_initial[] = {
_swigc__p_Event,
_swigc__p_EventConsumer,
_swigc__p_IVRMenu,
_swigc__p_LUA__Dbh,
_swigc__p_LUA__Session,
_swigc__p_SWIGLUA_FN,
_swigc__p_Stream,
_swigc__p_input_callback_state,
_swigc__p_lua_State,
@@ -49,6 +49,19 @@ class Event {
};
class Dbh {
protected:
switch_cache_db_handle_t *dbh;
bool connected;
static int query_callback(void *pArg, int argc, char **argv, char **cargv);
public:
Dbh(char *dsn, char *user = NULL, char *pass = NULL);
~Dbh();
bool release();
bool query(char *sql, SWIGLUA_FN lua_fun);
};
class CoreSession {
protected:
switch_input_args_t args;