diff --git a/build/next-release.txt b/build/next-release.txt index ba177fe9fd..63973ec2d4 100644 --- a/build/next-release.txt +++ b/build/next-release.txt @@ -1 +1 @@ -1.10.0-release +1.10.1-release diff --git a/configure.ac b/configure.ac index d2ae91b75c..95f4d16d42 100644 --- a/configure.ac +++ b/configure.ac @@ -3,10 +3,10 @@ # Must change all of the below together # For a release, set revision for that tagged release as well and uncomment -AC_INIT([freeswitch], [1.10.0-release], bugs@freeswitch.org) +AC_INIT([freeswitch], [1.10.1-release], bugs@freeswitch.org) AC_SUBST(SWITCH_VERSION_MAJOR, [1]) AC_SUBST(SWITCH_VERSION_MINOR, [10]) -AC_SUBST(SWITCH_VERSION_MICRO, [0-release]) +AC_SUBST(SWITCH_VERSION_MICRO, [1-release]) AC_SUBST(SWITCH_VERSION_REVISION, []) AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, []) diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 7aefc860d6..8fcd3faae4 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Wed Jul 17 14:35:37 EDT 2019 +Mon Aug 19 16:25:57 CDT 2019 diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sip_basic.c b/libs/sofia-sip/libsofia-sip-ua/sip/sip_basic.c index d2e1c0875e..0dc57fd680 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sip_basic.c +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sip_basic.c @@ -2797,3 +2797,118 @@ char const *sip_via_port(sip_via_t const *v, int *using_rport) else return SIP_DEFAULT_SERV; /* 5060 */ } + +/**@SIP_HEADER sip_identity Identity Header + * + * The Identity header field specifies the "logical" recipient of the + * request. It is defined in @RFC8224 with semantics shown below, + * though for now it's parsed to a single 'value' field. + * + * @code + * Identity = "Identity" HCOLON signed-identity-digest SEMI + * ident-info *( SEMI ident-info-params ) + * signed-identity-digest = 1*(base64-char / ".") + * ident-info = "info" EQUAL ident-info-uri + * ident-info-uri = LAQUOT absoluteURI RAQUOT + * ident-info-params = ident-info-alg / ident-type / + * ident-info-extension + * ident-info-alg = "alg" EQUAL token + * ident-type = "ppt" EQUAL token + * ident-info-extension = generic-param + * + * base64-char = ALPHA / DIGIT / "/" / "+" + * @endcode + * + * The parsed Identity header is stored in #sip_identity_t structure. + */ + +/**@ingroup sip_identity + * @typedef typedef struct sip_identity_s sip_identity_t; + * + * The structure #sip_identity_t contains representation of @Identity header. + * + * The #sip_identity_t is defined as follows: + * @code + * typedef struct { + * sip_common_t id_common[1]; // Common fragment info + * sip_error_t *id_next; // Link to next (dummy) + * char const *id_value; // Identity + * char const *id_info; // Info param containing URL of the cert, with no '<','>' + * } sip_identity_t; + * @endcode + * + */ + +static msg_xtra_f sip_identity_dup_xtra; +static msg_dup_f sip_identity_dup_one; +static msg_update_f sip_identity_update; + +msg_hclass_t sip_identity_class[] = +SIP_HEADER_CLASS(identity, "Identity", "", id_common, single, identity); + +issize_t sip_identity_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) +{ + sip_identity_t *id = (sip_identity_t *)h; + char const *p = NULL, *pp = NULL, *ppp = NULL, *ie = NULL; + char *result = NULL; + size_t len = 0; + + id->id_value = strdup(s); + id->id_info = NULL; + + p = strstr(s, "info="); + if (p) { + + ie = strchr(p, ';'); + pp = strchr(p, '<'); + ppp = strchr(p, '>'); + + // allow for a spaces between "info=" and opening '<' + // extract URI from inside "<>" but allow empty - let the higher level app decide what to do about it + if (ie && pp && ppp && (pp < ppp) && (ppp < ie)) { + + len = ppp - pp; + if ((result = malloc(len))) { + memcpy(result, pp + 1, len - 1); + result[len - 1] = '\0'; + id->id_info = result; + } + } + } + + return 0; +} + +issize_t sip_identity_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) +{ + sip_identity_t const *id = (sip_identity_t *)h; + + return snprintf(b, bsiz, "%s", id->id_value); +} + +isize_t sip_identity_dup_xtra(sip_header_t const *h, isize_t offset) +{ + sip_identity_t const *id = (sip_identity_t *)h; + return offset + MSG_STRING_SIZE(id->id_value); +} + +char *sip_identity_dup_one(sip_header_t *dst, sip_header_t const *src, + char *b, isize_t xtra) +{ + sip_identity_t *id = (sip_identity_t *)dst; + sip_identity_t const *o = (sip_identity_t *)src; + + MSG_STRING_DUP(b, id->id_value, o->id_value); + + return b; +} + +static int sip_identity_update(msg_common_t *h, + char const *name, isize_t namelen, + char const *value) +{ + sip_identity_t *id = (sip_identity_t *)h; + + id->id_value = strdup(value); + return 0; +} diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sip_parser.c b/libs/sofia-sip/libsofia-sip-ua/sip/sip_parser.c index 4d75e705c6..8f1b0d4110 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sip_parser.c +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sip_parser.c @@ -64,6 +64,7 @@ char const sip_version_2_0[] = "SIP/2.0"; extern msg_mclass_t sip_mclass[]; static msg_mclass_t const *_default = sip_mclass; +static msg_mclass_t *_default_parser_cloned = NULL; /** Return a built-in SIP parser object. */ msg_mclass_t const *sip_default_mclass(void) @@ -71,6 +72,15 @@ msg_mclass_t const *sip_default_mclass(void) return _default; } +/** Release SIP parser object if it was cloned. */ +void sip_cloned_parser_destroy(void) +{ + if (_default_parser_cloned) { + free(_default_parser_cloned); + _default_parser_cloned = NULL; + } +} + /** Update the default SIP parser. * * Use the extended SIP parser as default one. @@ -128,10 +138,12 @@ msg_mclass_t *sip_extend_mclass(msg_mclass_t *input) { msg_mclass_t *mclass; - if (input == NULL || input == _default) - mclass = msg_mclass_clone(_default, 0, 0); - else + if (input == NULL || input == _default) { + _default_parser_cloned = msg_mclass_clone(_default, 0, 0); + mclass = _default_parser_cloned; + } else { mclass = input; + } if (mclass) { extern msg_hclass_t * const sip_extensions[]; @@ -143,8 +155,10 @@ msg_mclass_t *sip_extend_mclass(msg_mclass_t *input) continue; if (msg_mclass_insert_header(mclass, hclass, 0) < 0) { - if (input != mclass) + if (input != mclass) { free(mclass); + _default_parser_cloned = NULL; + } return mclass = NULL; } } diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip.h b/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip.h index 37ae836598..aef7baae0f 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip.h +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip.h @@ -215,6 +215,9 @@ typedef msg_list_t sip_allow_events_t; /* RFC 3323 - @Privacy */ typedef struct sip_privacy_s sip_privacy_t; +/* SIP Identity Header, e.g. STIR-Shaken SIP Identity Header, RFC 8224 */ +typedef struct sip_identity_s sip_identity_t; + /* RFC 3327 - @Path */ typedef struct sip_route_s sip_path_t; @@ -259,6 +262,7 @@ struct sip_s { sip_to_t *sip_to; /**< To (t) */ sip_call_id_t *sip_call_id; /**< Call-ID (i) */ sip_cseq_t *sip_cseq; /**< CSeq */ + sip_identity_t *sip_identity; /**< Identity */ sip_contact_t *sip_contact; /**< Contact (m) */ sip_rseq_t *sip_rseq; /**< RSeq */ sip_rack_t *sip_rack; /**< RAck */ @@ -474,6 +478,17 @@ struct sip_cseq_s char const *cs_method_name; /**< Method name */ }; +/**@ingroup sip_identity + * @brief Structure for @Identity SIP header. + */ +struct sip_identity_s +{ + sip_common_t id_common[1]; /**< Common fragment info */ + sip_error_t *id_next; /**< Link to next (dummy) */ + char const *id_value; /**< Identity text as shown in SIP Header */ + char const *id_info; /**< Info param containing URL of the cert */ +}; + /**@ingroup sip_contact * @brief Structure for @Contact header field. */ @@ -920,6 +935,7 @@ union sip_header_u sip_separator_t sh_separator[1]; sip_payload_t sh_payload[1]; + sip_identity_t sh_identity[1]; }; SOFIA_END_DECLS diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_header.h b/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_header.h index 8e212b11f3..9271878459 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_header.h +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_header.h @@ -60,6 +60,9 @@ SOFIA_BEGIN_DECLS /** Return a built-in SIP parser object. */ SOFIAPUBFUN msg_mclass_t const *sip_default_mclass(void); +/** Release SIP parser object if it was cloned. */ +SOFIAPUBFUN void sip_cloned_parser_destroy(void); + SOFIAPUBFUN int sip_update_default_mclass(msg_mclass_t const *mclass); SOFIAPUBFUN msg_mclass_t *sip_extend_mclass(msg_mclass_t *input); @@ -224,6 +227,10 @@ SOFIAPUBFUN sip_call_id_t *sip_call_id_create(su_home_t *home, SOFIAPUBFUN sip_cseq_t *sip_cseq_create(su_home_t *, uint32_t seq, unsigned method, char const *name); +/** Create a @Identity header object. */ +SOFIAPUBFUN sip_identity_t *sip_identity_create(su_home_t *, uint32_t seq, + unsigned method, char const *name); + /** Create a @Contact header object. */ SOFIAPUBFUN sip_contact_t * sip_contact_create(su_home_t *, url_string_t const *url, diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index 81fd68cf72..f8b75fa459 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -26,6 +26,7 @@ * Marc Olivier Chouinard * Emmanuel Schmidbauer * Ítalo Rossi + * Fernando Santos * * mod_callcenter.c -- Call Center Module * @@ -185,7 +186,7 @@ typedef enum { static char members_sql[] = "CREATE TABLE members (\n" " queue VARCHAR(255),\n" -" system VARCHAR(255),\n" +" instance_id VARCHAR(255),\n" " uuid VARCHAR(255) NOT NULL DEFAULT '',\n" " session_uuid VARCHAR(255) NOT NULL DEFAULT '',\n" " cid_number VARCHAR(255),\n" @@ -208,7 +209,7 @@ static char members_sql[] = static char agents_sql[] = "CREATE TABLE agents (\n" " name VARCHAR(255),\n" -" system VARCHAR(255),\n" +" instance_id VARCHAR(255),\n" " uuid VARCHAR(255),\n" " type VARCHAR(255),\n" /* Callback , Dial in...*/ " contact VARCHAR(1024),\n" @@ -906,7 +907,7 @@ cc_status_t cc_agent_add(const char *agent, const char *type) /* Add Agent */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding Agent %s with type %s with default status %s\n", agent, type, cc_agent_status2str(CC_AGENT_STATUS_LOGGED_OUT)); - sql = switch_mprintf("INSERT INTO agents (name, system, type, status, state) VALUES('%q', 'single_box', '%q', '%q', '%q');", + sql = switch_mprintf("INSERT INTO agents (name, instance_id, type, status, state) VALUES('%q', 'single_box', '%q', '%q', '%q');", agent, type, cc_agent_status2str(CC_AGENT_STATUS_LOGGED_OUT), cc_agent_state2str(CC_AGENT_STATE_WAITING)); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); @@ -1075,13 +1076,13 @@ cc_status_t cc_agent_update(const char *key, const char *value, const char *agen goto done; } } else if (!strcasecmp(key, "uuid")) { - sql = switch_mprintf("UPDATE agents SET uuid = '%q', system = 'single_box' WHERE name = '%q'", value, agent); + sql = switch_mprintf("UPDATE agents SET uuid = '%q', instance_id = 'single_box' WHERE name = '%q'", value, agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; } else if (!strcasecmp(key, "contact")) { - sql = switch_mprintf("UPDATE agents SET contact = '%q', system = 'single_box' WHERE name = '%q'", value, agent); + sql = switch_mprintf("UPDATE agents SET contact = '%q', instance_id = 'single_box' WHERE name = '%q'", value, agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); @@ -1094,25 +1095,25 @@ cc_status_t cc_agent_update(const char *key, const char *value, const char *agen switch_event_fire(&event); } } else if (!strcasecmp(key, "ready_time")) { - sql = switch_mprintf("UPDATE agents SET ready_time = '%ld', system = 'single_box' WHERE name = '%q'", atol(value), agent); + sql = switch_mprintf("UPDATE agents SET ready_time = '%ld', instance_id = 'single_box' WHERE name = '%q'", atol(value), agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; } else if (!strcasecmp(key, "busy_delay_time")) { - sql = switch_mprintf("UPDATE agents SET busy_delay_time = '%ld', system = 'single_box' WHERE name = '%q'", atol(value), agent); + sql = switch_mprintf("UPDATE agents SET busy_delay_time = '%ld', instance_id = 'single_box' WHERE name = '%q'", atol(value), agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; } else if (!strcasecmp(key, "reject_delay_time")) { - sql = switch_mprintf("UPDATE agents SET reject_delay_time = '%ld', system = 'single_box' WHERE name = '%q'", atol(value), agent); + sql = switch_mprintf("UPDATE agents SET reject_delay_time = '%ld', instance_id = 'single_box' WHERE name = '%q'", atol(value), agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; } else if (!strcasecmp(key, "no_answer_delay_time")) { - sql = switch_mprintf("UPDATE agents SET no_answer_delay_time = '%ld', system = 'single_box' WHERE name = '%q'", atol(value), agent); + sql = switch_mprintf("UPDATE agents SET no_answer_delay_time = '%ld', instance_id = 'single_box' WHERE name = '%q'", atol(value), agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); @@ -1130,14 +1131,14 @@ cc_status_t cc_agent_update(const char *key, const char *value, const char *agen result = CC_STATUS_SUCCESS; } else if (!strcasecmp(key, "max_no_answer")) { - sql = switch_mprintf("UPDATE agents SET max_no_answer = '%d', system = 'single_box' WHERE name = '%q'", atoi(value), agent); + sql = switch_mprintf("UPDATE agents SET max_no_answer = '%d', instance_id = 'single_box' WHERE name = '%q'", atoi(value), agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); result = CC_STATUS_SUCCESS; } else if (!strcasecmp(key, "wrap_up_time")) { - sql = switch_mprintf("UPDATE agents SET wrap_up_time = '%d', system = 'single_box' WHERE name = '%q'", atoi(value), agent); + sql = switch_mprintf("UPDATE agents SET wrap_up_time = '%d', instance_id = 'single_box' WHERE name = '%q'", atoi(value), agent); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); @@ -1460,6 +1461,46 @@ end: return result; } +struct sqlite_column_rename_callback_data { + const char *table; + switch_cache_db_handle_t *dbh; +}; +typedef struct sqlite_column_rename_callback_data sqlite_column_rename_callback_data_t; + +static int sqlite_column_rename_callback(void *pArg, const char *errmsg) +{ + sqlite_column_rename_callback_data_t *callback_data = (sqlite_column_rename_callback_data_t *)pArg; + char tmptable[4096]; + char *sql = NULL; + + if (!strcasecmp("agents", callback_data->table)) { + if (NULL != (sql = strstr(agents_sql, "TABLE agents ("))) { + sql += 14; + sprintf(tmptable, "CREATE TABLE agents_tmp (%s", sql); + switch_cache_db_execute_sql_callback(callback_data->dbh, tmptable, NULL, NULL, NULL); + switch_cache_db_execute_sql_callback(callback_data->dbh, "INSERT INTO agents_tmp SELECT * FROM agents;", NULL, NULL, NULL); + switch_cache_db_execute_sql_callback(callback_data->dbh, "drop table agents", NULL, NULL, NULL); + switch_cache_db_execute_sql_callback(callback_data->dbh, agents_sql, NULL, NULL, NULL); + switch_cache_db_execute_sql_callback(callback_data->dbh, "INSERT INTO agents SELECT * FROM agents_tmp;", NULL, NULL, NULL); + switch_cache_db_execute_sql_callback(callback_data->dbh, "drop table agents_tmp", NULL, NULL, NULL); + } + } + else if (!strcasecmp("members", callback_data->table)) { + if (NULL != (sql = strstr(members_sql, "TABLE members ("))) { + sql += 15; + sprintf(tmptable, "CREATE TABLE members_tmp (%s", sql); + switch_cache_db_execute_sql_callback(callback_data->dbh, tmptable, NULL, NULL, NULL); + switch_cache_db_execute_sql_callback(callback_data->dbh, "INSERT INTO members_tmp SELECT * FROM members;", NULL, NULL, NULL); + switch_cache_db_execute_sql_callback(callback_data->dbh, "drop table members", NULL, NULL, NULL); + switch_cache_db_execute_sql_callback(callback_data->dbh, members_sql, NULL, NULL, NULL); + switch_cache_db_execute_sql_callback(callback_data->dbh, "INSERT INTO members SELECT * FROM members_tmp;", NULL, NULL, NULL); + switch_cache_db_execute_sql_callback(callback_data->dbh, "drop table members_tmp", NULL, NULL, NULL); + } + } + + return 0; +} + static switch_status_t load_config(void) { switch_status_t status = SWITCH_STATUS_SUCCESS; @@ -1531,16 +1572,34 @@ static switch_status_t load_config(void) "alter table agents add busy_delay_time integer not null default 0;"); switch_cache_db_test_reactive(dbh, "select count(no_answer_delay_time) from agents", NULL, "alter table agents add no_answer_delay_time integer not null default 0;"); switch_cache_db_test_reactive(dbh, "select count(ready_time) from agents", "drop table agents", agents_sql); - switch_cache_db_test_reactive(dbh, "select external_calls_count from agents", NULL, "alter table agents add external_calls_count integer not null default 0;"); + switch_cache_db_test_reactive(dbh, "select count(external_calls_count) from agents", NULL, "alter table agents add external_calls_count integer not null default 0;"); switch_cache_db_test_reactive(dbh, "select count(queue) from tiers", "drop table tiers" , tiers_sql); + /* This will rename column system for SQLite */ + if (switch_cache_db_get_type(dbh) == SCDB_TYPE_CORE_DB) { + char *errmsg = NULL; + sqlite_column_rename_callback_data_t callback_data; + /* SQLite < 3.27.0 ( https://www.sqlite.org/changes.html ) has issues with renaming columns and tables */ + callback_data.dbh = dbh; + callback_data.table = "agents"; + switch_cache_db_execute_sql_callback_err(dbh, "select count(instance_id) from agents", NULL, sqlite_column_rename_callback, &callback_data, &errmsg); + callback_data.table = "members"; + switch_cache_db_execute_sql_callback_err(dbh, "select count(instance_id) from members", NULL, sqlite_column_rename_callback, &callback_data, &errmsg); + } else { + /* This will rename column system for MySQL */ + switch_cache_db_test_reactive(dbh, "select count(instance_id) from agents", NULL, "alter table agents rename column `system` TO instance_id;"); + switch_cache_db_test_reactive(dbh, "select count(instance_id) from members", NULL, "alter table members rename column `system` TO instance_id;"); + /* This will rename column system for PGSql */ + switch_cache_db_test_reactive(dbh, "select count(instance_id) from agents", NULL, "alter table agents rename system TO instance_id;"); + switch_cache_db_test_reactive(dbh, "select count(instance_id) from members", NULL, "alter table members rename system TO instance_id;"); + } switch_cache_db_release_db_handle(&dbh); /* 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', session_uuid = '' where system = '%q';" - "update agents set external_calls_count = 0 where system = 'single_box';", + sql = switch_mprintf("update agents set state = 'Waiting', uuid = '' where instance_id = 'single_box';" + "update tiers set state = 'Ready' where agent IN (select name from agents where instance_id = 'single_box');" + "update members set state = '%q', session_uuid = '' where instance_id = '%q';" + "update agents set external_calls_count = 0 where instance_id = 'single_box';", cc_member_state2str(CC_MEMBER_STATE_ABANDONED), globals.cc_instance_id); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); @@ -1646,7 +1705,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Member %s <%s> with uuid %s in queue %s is gone just before we assigned an agent\n", h->member_cid_name, h->member_cid_number, h->member_session_uuid, h->queue_name); bridged = 0; - sql = switch_mprintf("UPDATE members SET state = '%q', session_uuid = '', abandoned_epoch = '%" SWITCH_TIME_T_FMT "' WHERE uuid = '%q' AND system = '%q' AND state != '%q'", + sql = switch_mprintf("UPDATE members SET state = '%q', session_uuid = '', abandoned_epoch = '%" SWITCH_TIME_T_FMT "' WHERE uuid = '%q' AND instance_id = '%q' AND state != '%q'", cc_member_state2str(CC_MEMBER_STATE_ABANDONED), local_epoch_time_now(NULL), h->member_uuid, globals.cc_instance_id, cc_member_state2str(CC_MEMBER_STATE_ABANDONED)); cc_execute_sql(NULL, sql, NULL); @@ -1848,7 +1907,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa char res[256]; /* 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 = '%q' AND serving_agent = '%q'", + " WHERE state = '%q' AND uuid = '%q' AND instance_id = '%q' AND serving_agent = '%q'", h->agent_name, cc_member_state2str(CC_MEMBER_STATE_TRYING), cc_member_state2str(CC_MEMBER_STATE_TRYING), h->member_uuid, globals.cc_instance_id, h->queue_strategy); cc_execute_sql(NULL, sql, NULL); @@ -1857,7 +1916,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa /* 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 = '%q'", + " WHERE serving_agent = '%q' AND serving_system = 'single_box' AND uuid = '%q' AND instance_id = '%q'", h->agent_name, h->member_uuid, globals.cc_instance_id); cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res)); switch_safe_free(sql); @@ -1942,7 +2001,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa } else if (!bridged && !switch_channel_up(agent_channel)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Failed to bridge, agent %s has no session\n", h->agent_name); /* Put back member on Waiting state, previous Trying */ - sql = switch_mprintf("UPDATE members SET state = 'Waiting' WHERE uuid = '%q' AND system = '%q'", h->member_uuid, globals.cc_instance_id); + sql = switch_mprintf("UPDATE members SET state = 'Waiting' WHERE uuid = '%q' AND instance_id = '%q'", h->member_uuid, globals.cc_instance_id); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); } else { @@ -1960,7 +2019,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_channel_set_variable_printf(member_channel, "cc_queue_answered_epoch", "%" SWITCH_TIME_T_FMT, local_epoch_time_now(NULL)); /* Set UUID of the Agent channel */ sql = switch_mprintf("UPDATE agents SET uuid = '%q', last_bridge_start = '%" SWITCH_TIME_T_FMT "', calls_answered = calls_answered + 1, no_answer_count = 0" - " WHERE name = '%q' AND system = '%q'", + " WHERE name = '%q' AND instance_id = '%q'", agent_uuid, local_epoch_time_now(NULL), h->agent_name, h->agent_system); cc_execute_sql(NULL, sql, NULL); @@ -2012,13 +2071,13 @@ 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 %s last_bridge_end = %" SWITCH_TIME_T_FMT ", talk_time = talk_time + (%" SWITCH_TIME_T_FMT "-last_bridge_start) WHERE name = '%q' AND system = '%q';" + sql = switch_mprintf("UPDATE agents SET %s last_bridge_end = %" SWITCH_TIME_T_FMT ", talk_time = talk_time + (%" SWITCH_TIME_T_FMT "-last_bridge_start) WHERE name = '%q' AND instance_id = '%q';" , (strcasecmp(h->agent_type, CC_AGENT_TYPE_UUID_STANDBY)?"uuid = '',":""), local_epoch_time_now(NULL), local_epoch_time_now(NULL), h->agent_name, h->agent_system); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); /* Remove the member entry from the db (Could become optional to support latter processing) */ - sql = switch_mprintf("DELETE FROM members WHERE uuid = '%q' AND system = '%q'", h->member_uuid, globals.cc_instance_id); + sql = switch_mprintf("DELETE FROM members WHERE uuid = '%q' AND instance_id = '%q'", h->member_uuid, globals.cc_instance_id); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); @@ -2057,7 +2116,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_channel_t *member_channel = switch_core_session_get_channel(member_session); switch_channel_clear_app_flag_key(CC_APP_KEY, member_channel, CC_APP_AGENT_CONNECTING); sql = switch_mprintf("UPDATE members SET state = case state when '%q' then '%q' else state end, serving_agent = '', serving_system = ''" - " WHERE serving_agent = '%q' AND serving_system = '%q' AND uuid = '%q' AND system = '%q'", + " WHERE serving_agent = '%q' AND serving_system = '%q' AND uuid = '%q' AND instance_id = '%q'", cc_member_state2str(CC_MEMBER_STATE_TRYING), /* Only switch to Waiting from Trying (state may be set to Abandoned in callcenter_function()) */ cc_member_state2str(CC_MEMBER_STATE_WAITING), h->agent_name, h->agent_system, h->member_uuid, globals.cc_instance_id); @@ -2091,7 +2150,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa tiers_state = CC_TIER_STATE_NO_ANSWER; /* Update Agent NO Answer count */ - sql = switch_mprintf("UPDATE agents SET no_answer_count = no_answer_count + 1 WHERE name = '%q' AND system = '%q';", + sql = switch_mprintf("UPDATE agents SET no_answer_count = no_answer_count + 1 WHERE name = '%q' AND instance_id = '%q';", h->agent_name, h->agent_system); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); @@ -2297,21 +2356,21 @@ static int agents_callback(void *pArg, int argc, char **argv, char **columnNames if (!strcasecmp(cbt->strategy,"ring-all") || !strcasecmp(cbt->strategy,"ring-progressively")) { /* Check if member is a ring-all mode */ - sql = switch_mprintf("SELECT count(*) FROM members WHERE serving_agent = '%q' AND uuid = '%q' AND system = '%q'", cbt->strategy, cbt->member_uuid, globals.cc_instance_id); + sql = switch_mprintf("SELECT count(*) FROM members WHERE serving_agent = '%q' AND uuid = '%q' AND instance_id = '%q'", cbt->strategy, cbt->member_uuid, globals.cc_instance_id); cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res)); switch_safe_free(sql); } else { /* Map the Agent to the member */ sql = switch_mprintf("UPDATE members SET serving_agent = '%q', serving_system = '%q', state = '%q'" - " WHERE state = '%q' AND uuid = '%q' AND system = '%q'", + " WHERE state = '%q' AND uuid = '%q' AND instance_id = '%q'", agent_name, agent_system, cc_member_state2str(CC_MEMBER_STATE_TRYING), cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt->member_uuid, globals.cc_instance_id); 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 = '%q' AND uuid = '%q' AND system = '%q'", + sql = switch_mprintf("SELECT count(*) FROM members WHERE serving_agent = '%q' AND serving_system = '%q' AND uuid = '%q' AND instance_id = '%q'", agent_name, agent_system, cbt->member_uuid, globals.cc_instance_id); cc_execute_sql2str(NULL, NULL, sql, res, sizeof(res)); switch_safe_free(sql); @@ -2431,7 +2490,7 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName if (!cbt.queue_name || !(queue = get_queue(cbt.queue_name))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, delete this member\n", cbt.queue_name); - sql = switch_mprintf("DELETE FROM members WHERE uuid = '%q' AND system = '%q'", cbt.member_uuid, cbt.member_system); + sql = switch_mprintf("DELETE FROM members WHERE uuid = '%q' AND instance_id = '%q'", cbt.member_uuid, cbt.member_system); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); goto end; @@ -2465,7 +2524,7 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName } /* Once we pass a certain point, we want to get rid of the abandoned call */ if (abandoned_epoch + discard_abandoned_after < local_epoch_time_now(NULL)) { - sql = switch_mprintf("DELETE FROM members WHERE uuid = '%q' AND system = '%q' AND (abandoned_epoch = '%" SWITCH_TIME_T_FMT "' OR joined_epoch = '%q')", cbt.member_uuid, cbt.member_system, abandoned_epoch, cbt.member_joined_epoch); + sql = switch_mprintf("DELETE FROM members WHERE uuid = '%q' AND instance_id = '%q' AND (abandoned_epoch = '%" SWITCH_TIME_T_FMT "' OR joined_epoch = '%q')", cbt.member_uuid, cbt.member_system, abandoned_epoch, cbt.member_joined_epoch); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); } @@ -2557,13 +2616,13 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName switch_core_session_rwunlock(member_session); } - sql = switch_mprintf("SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position as tiers_position, tiers.level as tiers_level, agents.type, agents.uuid, external_calls_count, agents.last_offered_call as agents_last_offered_call, 1 as dyn_order FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)" + sql = switch_mprintf("SELECT instance_id, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position as tiers_position, tiers.level as tiers_level, agents.type, agents.uuid, external_calls_count, agents.last_offered_call as agents_last_offered_call, 1 as dyn_order FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)" " WHERE tiers.queue = '%q'" " AND (agents.status = '%q' OR agents.status = '%q' OR agents.status = '%q')" " AND tiers.position > %d" " AND tiers.level = %d" " UNION " - "SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position as tiers_position, tiers.level as tiers_level, agents.type, agents.uuid, external_calls_count, agents.last_offered_call as agents_last_offered_call, 2 as dyn_order FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)" + "SELECT instance_id, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position as tiers_position, tiers.level as tiers_level, agents.type, agents.uuid, external_calls_count, agents.last_offered_call as agents_last_offered_call, 2 as dyn_order FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)" " WHERE tiers.queue = '%q'" " AND (agents.status = '%q' OR agents.status = '%q' OR agents.status = '%q')" " AND tiers.level > %d" @@ -2577,13 +2636,13 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName level ); } else if (!strcasecmp(queue->strategy, "round-robin")) { - sql = switch_mprintf("SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position as tiers_position, tiers.level as tiers_level, agents.type, agents.uuid, external_calls_count, agents.last_offered_call as agents_last_offered_call, 1 as dyn_order FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)" + sql = switch_mprintf("SELECT instance_id, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position as tiers_position, tiers.level as tiers_level, agents.type, agents.uuid, external_calls_count, agents.last_offered_call as agents_last_offered_call, 1 as dyn_order FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)" " WHERE tiers.queue = '%q'" " AND (agents.status = '%q' OR agents.status = '%q' OR agents.status = '%q')" " AND tiers.position > (SELECT tiers.position FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent) WHERE tiers.queue = '%q' AND agents.last_offered_call > 0 ORDER BY agents.last_offered_call DESC LIMIT 1)" " AND tiers.level = (SELECT tiers.level FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent) WHERE tiers.queue = '%q' AND agents.last_offered_call > 0 ORDER BY agents.last_offered_call DESC LIMIT 1)" " UNION " - "SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position as tiers_position, tiers.level as tiers_level, agents.type, agents.uuid, external_calls_count, agents.last_offered_call as agents_last_offered_call, 2 as dyn_order FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)" + "SELECT instance_id, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position as tiers_position, tiers.level as tiers_level, agents.type, agents.uuid, external_calls_count, agents.last_offered_call as agents_last_offered_call, 2 as dyn_order FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)" " WHERE tiers.queue = '%q'" " AND (agents.status = '%q' OR agents.status = '%q' OR agents.status = '%q')" " ORDER BY dyn_order asc, tiers_level, tiers_position, agents_last_offered_call", @@ -2604,7 +2663,7 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName } else if (!strcasecmp(queue_strategy, "agent-with-fewest-calls")) { sql_order_by = switch_mprintf("level, agents.calls_answered, position"); } else if (!strcasecmp(queue_strategy, "ring-all") || !strcasecmp(queue_strategy, "ring-progressively")) { - sql = switch_mprintf("UPDATE members SET state = '%q' WHERE state = '%q' AND uuid = '%q' AND system = '%q'", + sql = switch_mprintf("UPDATE members SET state = '%q' WHERE state = '%q' AND uuid = '%q' AND instance_id = '%q'", cc_member_state2str(CC_MEMBER_STATE_TRYING), cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt.member_uuid, cbt.member_system); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); @@ -2618,7 +2677,7 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName sql_order_by = switch_mprintf("level, position, agents.last_offered_call"); } - sql = switch_mprintf("SELECT system, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position, tiers.level, agents.type, agents.uuid, external_calls_count FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)" + sql = switch_mprintf("SELECT instance_id, name, status, contact, no_answer_count, max_no_answer, reject_delay_time, busy_delay_time, no_answer_delay_time, tiers.state, agents.last_bridge_end, agents.wrap_up_time, agents.state, agents.ready_time, tiers.position, tiers.level, agents.type, agents.uuid, external_calls_count FROM agents LEFT JOIN tiers ON (agents.name = tiers.agent)" " WHERE tiers.queue = '%q'" " AND (agents.status = '%q' OR agents.status = '%q' OR agents.status = '%q')" " ORDER BY %q", @@ -2706,8 +2765,8 @@ 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,session_uuid,cid_number,cid_name,joined_epoch,(%" SWITCH_TIME_T_FMT "-joined_epoch)+base_score+skill_score AS score, state, abandoned_epoch, serving_agent, system FROM members" - " WHERE (state = '%q' OR state = '%q' OR (serving_agent = 'ring-all' AND state = '%q') OR (serving_agent = 'ring-progressively' AND state = '%q')) AND system = '%q' ORDER BY score DESC", + sql = switch_mprintf("SELECT queue,uuid,session_uuid,cid_number,cid_name,joined_epoch,(%" SWITCH_TIME_T_FMT "-joined_epoch)+base_score+skill_score AS score, state, abandoned_epoch, serving_agent, instance_id FROM members" + " WHERE (state = '%q' OR state = '%q' OR (serving_agent = 'ring-all' AND state = '%q') OR (serving_agent = 'ring-progressively' AND state = '%q')) AND instance_id = '%q' ORDER BY score DESC", local_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), cc_member_state2str(CC_MEMBER_STATE_TRYING), globals.cc_instance_id); @@ -3013,7 +3072,7 @@ SWITCH_STANDARD_APP(callcenter_function) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member %s <%s> restoring it previous position in queue %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); /* Update abandoned member */ - sql = switch_mprintf("UPDATE members SET session_uuid = '%q', state = '%q', rejoined_epoch = '%" SWITCH_TIME_T_FMT "', system = '%q' WHERE uuid = '%q' AND state = '%q'", + sql = switch_mprintf("UPDATE members SET session_uuid = '%q', state = '%q', rejoined_epoch = '%" SWITCH_TIME_T_FMT "', instance_id = '%q' WHERE uuid = '%q' AND state = '%q'", member_session_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING), local_epoch_time_now(NULL), globals.cc_instance_id, member_uuid, cc_member_state2str(CC_MEMBER_STATE_ABANDONED)); cc_execute_sql(queue, sql, NULL); switch_safe_free(sql); @@ -3059,7 +3118,7 @@ SWITCH_STANDARD_APP(callcenter_function) strategy_str = ""; } sql = switch_mprintf("INSERT INTO members" - " (queue,system,uuid,session_uuid,system_epoch,joined_epoch,base_score,skill_score,cid_number,cid_name,serving_agent,serving_system,state)" + " (queue,instance_id,uuid,session_uuid,system_epoch,joined_epoch,base_score,skill_score,cid_number,cid_name,serving_agent,serving_system,state)" " VALUES('%q','%q','%q','%q','%q','%" SWITCH_TIME_T_FMT "','%d','%d','%q','%q','%q','','%q')", queue_name, globals.cc_instance_id, @@ -3182,7 +3241,7 @@ SWITCH_STANDARD_APP(callcenter_function) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member %s <%s> abandoned waiting in queue %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); /* Update member state */ - sql = switch_mprintf("UPDATE members SET state = '%q', session_uuid = '', abandoned_epoch = '%" SWITCH_TIME_T_FMT "' WHERE uuid = '%q' AND system = '%q'", + sql = switch_mprintf("UPDATE members SET state = '%q', session_uuid = '', abandoned_epoch = '%" SWITCH_TIME_T_FMT "' WHERE uuid = '%q' AND instance_id = '%q'", cc_member_state2str(CC_MEMBER_STATE_ABANDONED), local_epoch_time_now(NULL), member_uuid, globals.cc_instance_id); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); @@ -3224,7 +3283,7 @@ SWITCH_STANDARD_APP(callcenter_function) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Member %s <%s> is answered by an agent in queue %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); /* Update member state */ - sql = switch_mprintf("UPDATE members SET state = '%q', bridge_epoch = '%" SWITCH_TIME_T_FMT "' WHERE uuid = '%q' AND system = '%q'", + sql = switch_mprintf("UPDATE members SET state = '%q', bridge_epoch = '%" SWITCH_TIME_T_FMT "' WHERE uuid = '%q' AND instance_id = '%q'", cc_member_state2str(CC_MEMBER_STATE_ANSWERED), local_epoch_time_now(NULL), member_uuid, globals.cc_instance_id); cc_execute_sql(NULL, sql, NULL); switch_safe_free(sql); diff --git a/src/mod/applications/mod_enum/mod_enum.c b/src/mod/applications/mod_enum/mod_enum.c index 3e458dd129..f6ca99abce 100644 --- a/src/mod/applications/mod_enum/mod_enum.c +++ b/src/mod/applications/mod_enum/mod_enum.c @@ -75,6 +75,9 @@ static struct { int retries; int random; char *nameserver[ENUM_MAXNAMESERVERS]; +#ifdef _MSC_VER + char *nameserver_buf; +#endif } globals; SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_root, globals.root); @@ -164,7 +167,6 @@ static switch_status_t load_config(void) if (!globals.nameserver[0]) { HKEY hKey; DWORD data_sz; - char* buf; RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0, KEY_QUERY_VALUE, &hKey); @@ -172,15 +174,15 @@ static switch_status_t load_config(void) if (hKey) { RegQueryValueEx(hKey, "DhcpNameServer", NULL, NULL, NULL, &data_sz); if (data_sz) { - buf = (char*)malloc(data_sz + 1); + globals.nameserver_buf = (char*)malloc(data_sz + 1); - RegQueryValueEx(hKey, "DhcpNameServer", NULL, NULL, (LPBYTE)buf, &data_sz); + RegQueryValueEx(hKey, "DhcpNameServer", NULL, NULL, (LPBYTE)globals.nameserver_buf, &data_sz); - if(buf[data_sz - 1] != 0) { - buf[data_sz] = 0; + if(globals.nameserver_buf[data_sz - 1] != 0) { + globals.nameserver_buf[data_sz] = 0; } - switch_replace_char(buf, ' ', 0, SWITCH_FALSE); /* only use the first entry ex "192.168.1.1 192.168.1.2" */ - globals.nameserver[0] = buf; + switch_replace_char(globals.nameserver_buf, ' ', 0, SWITCH_FALSE); /* only use the first entry ex "192.168.1.1 192.168.1.2" */ + globals.nameserver[0] = globals.nameserver_buf; } RegCloseKey(hKey); @@ -924,6 +926,9 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_enum_shutdown) switch_safe_free(globals.root); switch_safe_free(globals.isn_root); +#ifdef _MSC_VER + switch_safe_free(globals.nameserver_buf); +#endif return SWITCH_STATUS_UNLOAD; } diff --git a/src/mod/applications/mod_valet_parking/mod_valet_parking.c b/src/mod/applications/mod_valet_parking/mod_valet_parking.c index b938a2953d..0c95c16265 100644 --- a/src/mod/applications/mod_valet_parking/mod_valet_parking.c +++ b/src/mod/applications/mod_valet_parking/mod_valet_parking.c @@ -933,6 +933,7 @@ static void pres_event_handler(switch_event_t *event) SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_valet_parking_shutdown) { + switch_event_unbind_callback(pres_event_handler); switch_core_hash_destroy(&globals.hash); return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index cd6b1c8f88..848f1e6924 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -6473,6 +6473,12 @@ void mod_sofia_shutdown_cleanup() { su_deinit(); + /* + Release the clone of the default SIP parser + created by `sip_update_default_mclass(sip_extend_mclass(NULL))` call with NULL argument + */ + sip_cloned_parser_destroy(); + switch_mutex_lock(mod_sofia_globals.hash_mutex); switch_core_hash_destroy(&mod_sofia_globals.profile_hash); switch_core_hash_destroy(&mod_sofia_globals.gateway_hash); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 1574798fc1..0b0b1b82a0 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4290,6 +4290,7 @@ switch_status_t sofia_init(void) su_init(); if (sip_update_default_mclass(sip_extend_mclass(NULL)) < 0) { su_deinit(); + sip_cloned_parser_destroy(); return SWITCH_STATUS_GENERR; } diff --git a/src/switch_core_codec.c b/src/switch_core_codec.c index ac21fa4567..69883f8122 100644 --- a/src/switch_core_codec.c +++ b/src/switch_core_codec.c @@ -614,14 +614,18 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_reset(switch_codec_t *codec) SWITCH_DECLARE(switch_status_t) switch_core_codec_copy(switch_codec_t *codec, switch_codec_t *new_codec, const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool) { + uint32_t codec_rate; switch_assert(codec != NULL); switch_assert(new_codec != NULL); + codec_rate = !strcasecmp(codec->implementation->iananame, "g722") + ? codec->implementation->samples_per_second : codec->implementation->actual_samples_per_second; + return switch_core_codec_init(new_codec, codec->implementation->iananame, codec->implementation->modname, codec->fmtp_in, - codec->implementation->actual_samples_per_second, + codec_rate, codec->implementation->microseconds_per_packet / 1000, codec->implementation->number_of_channels, codec->flags, diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index c642ab3aa2..3752a06b23 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -818,6 +818,7 @@ SWITCH_DECLARE(int) switch_cache_db_affected_rows(switch_cache_db_handle_t *dbh) switch_database_interface_t *database_interface = dbh->native_handle.database_interface_dbh->connection_options.database_interface; int affected_rows = 0; database_interface->affected_rows(dbh->native_handle.database_interface_dbh, &affected_rows); + return affected_rows; } break; } @@ -1188,11 +1189,10 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_event_callback(switc case SCDB_TYPE_DATABASE_INTERFACE: { switch_database_interface_t *database_interface = dbh->native_handle.database_interface_dbh->connection_options.database_interface; - switch_status_t result; - if ((result = database_interface_handle_callback_exec(database_interface, dbh->native_handle.database_interface_dbh, sql, helper_callback, &h, err)) != SWITCH_STATUS_SUCCESS) { + if ((status = database_interface_handle_callback_exec(database_interface, dbh->native_handle.database_interface_dbh, sql, helper_callback, &h, err)) != SWITCH_STATUS_SUCCESS) { char tmp[100]; - switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to execute_sql_event_callback", result); + switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to execute_sql_event_callback", status); } } break; @@ -1249,15 +1249,14 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_event_callback_err(s case SCDB_TYPE_DATABASE_INTERFACE: { switch_database_interface_t *database_interface = dbh->native_handle.database_interface_dbh->connection_options.database_interface; - switch_status_t result; - if ((result = database_interface_handle_callback_exec(database_interface, dbh->native_handle.database_interface_dbh, sql, helper_callback, &h, err)) != SWITCH_STATUS_SUCCESS) { + if ((status = database_interface_handle_callback_exec(database_interface, dbh->native_handle.database_interface_dbh, sql, helper_callback, &h, err)) != SWITCH_STATUS_SUCCESS) { char tmp[100]; - switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to execute_sql_event_callback_err", result); - } else { - if (err && *err) { - (*err_callback)(pdata, (const char*)*err); - } + switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to execute_sql_event_callback_err", status); + } + + if (err && *err) { + (*err_callback)(pdata, (const char*)*err); } } break; @@ -1316,11 +1315,10 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_callback(switch_cach case SCDB_TYPE_DATABASE_INTERFACE: { switch_database_interface_t *database_interface = dbh->native_handle.database_interface_dbh->connection_options.database_interface; - switch_status_t result; - if ((result = database_interface_handle_callback_exec(database_interface, dbh->native_handle.database_interface_dbh, sql, callback, pdata, err)) != SWITCH_STATUS_SUCCESS) { + if ((status = database_interface_handle_callback_exec(database_interface, dbh->native_handle.database_interface_dbh, sql, callback, pdata, err)) != SWITCH_STATUS_SUCCESS) { char tmp[100]; - switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to execute_sql_callback", result); + switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to execute_sql_callback", status); } } break; @@ -1372,15 +1370,14 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql_callback_err(switch_ case SCDB_TYPE_DATABASE_INTERFACE: { switch_database_interface_t *database_interface = dbh->native_handle.database_interface_dbh->connection_options.database_interface; - switch_status_t result; - if ((result = database_interface_handle_callback_exec(database_interface, dbh->native_handle.database_interface_dbh, sql, callback, pdata, err)) != SWITCH_STATUS_SUCCESS) { + if ((status = database_interface_handle_callback_exec(database_interface, dbh->native_handle.database_interface_dbh, sql, callback, pdata, err)) != SWITCH_STATUS_SUCCESS) { char tmp[100]; - switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to execute_sql_callback_err", result); - } else { - if (err && *err) { - (*err_callback)(pdata, (const char*)*err); - } + switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to execute_sql_callback_err", status); + } + + if (err && *err) { + (*err_callback)(pdata, (const char*)*err); } } break; @@ -1491,20 +1488,20 @@ SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive_ex(switch_cache_db_h char tmp[100]; switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to test_reactive with drop_sql", result); } + } - if ((result = database_interface_handle_exec(database_interface, dbh->native_handle.database_interface_dbh, reactive_sql, NULL)) != SWITCH_STATUS_SUCCESS) { - char tmp[100]; - switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to test_reactive with reactive_sql", result); + if ((result = database_interface_handle_exec(database_interface, dbh->native_handle.database_interface_dbh, reactive_sql, NULL)) != SWITCH_STATUS_SUCCESS) { + char tmp[100]; + switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to test_reactive with reactive_sql", result); - if (row_size_limited_reactive_sql && switch_test_flag(database_interface, SWITCH_DATABASE_FLAG_ROW_SIZE_LIMIT)) { - if ((result = database_interface_handle_exec(database_interface, dbh->native_handle.database_interface_dbh, row_size_limited_reactive_sql, NULL)) != SWITCH_STATUS_SUCCESS) { - switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to test_reactive with row_size_limited_reactive_sql", result); - } + if (row_size_limited_reactive_sql && switch_test_flag(database_interface, SWITCH_DATABASE_FLAG_ROW_SIZE_LIMIT)) { + if ((result = database_interface_handle_exec(database_interface, dbh->native_handle.database_interface_dbh, row_size_limited_reactive_sql, NULL)) != SWITCH_STATUS_SUCCESS) { + switch_snprintfv(tmp, sizeof(tmp), "%q-%i", "Unable to test_reactive with row_size_limited_reactive_sql", result); } } - - r = (result == SWITCH_STATUS_SUCCESS); } + + r = (result == SWITCH_STATUS_SUCCESS); } } break; diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index f0aadae139..2f6c1dca69 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -1360,7 +1360,7 @@ static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t if (switch_event_create(&event, SWITCH_EVENT_MODULE_UNLOAD) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "api"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "json_api"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "name", ptr->interface_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "description", switch_str_nil(ptr->desc)); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "syntax", switch_str_nil(ptr->syntax)); @@ -2515,6 +2515,7 @@ SWITCH_DECLARE(void) switch_loadable_module_shutdown(void) switch_core_hash_destroy(&loadable_modules.limit_hash); switch_core_hash_destroy(&loadable_modules.database_hash); switch_core_hash_destroy(&loadable_modules.dialplan_hash); + switch_core_hash_destroy(&loadable_modules.secondary_recover_hash); switch_core_destroy_memory_pool(&loadable_modules.pool); } diff --git a/src/switch_time.c b/src/switch_time.c index 46a3a08712..cbb47f9ef7 100644 --- a/src/switch_time.c +++ b/src/switch_time.c @@ -479,6 +479,10 @@ static switch_status_t _timerfd_next(switch_timer_t *timer) interval_timer_t *it = timer->private_info; uint64_t u64 = 0; + if (!it) { + return SWITCH_STATUS_GENERR; + } + if (read(it->fd, &u64, sizeof(u64)) < 0) { return SWITCH_STATUS_GENERR; } else { @@ -495,6 +499,10 @@ static switch_status_t _timerfd_check(switch_timer_t *timer, switch_bool_t step) struct itimerspec val; int diff; + if (!it) { + return SWITCH_STATUS_GENERR; + } + timerfd_gettime(it->fd, &val); diff = val.it_interval.tv_nsec / 1000; @@ -515,9 +523,12 @@ static switch_status_t _timerfd_check(switch_timer_t *timer, switch_bool_t step) static switch_status_t _timerfd_destroy(switch_timer_t *timer) { interval_timer_t *it = timer->private_info; - int rc; + int rc = SWITCH_STATUS_GENERR; + + if (it) { + rc = timerfd_stop_interval(it); + } - rc = timerfd_stop_interval(it); return rc; } diff --git a/tests/unit/conf/freeswitch.xml b/tests/unit/conf/freeswitch.xml index fe2fe1b17c..abdbcd4ae5 100644 --- a/tests/unit/conf/freeswitch.xml +++ b/tests/unit/conf/freeswitch.xml @@ -8,6 +8,9 @@ + + + diff --git a/tests/unit/switch_core_codec.c b/tests/unit/switch_core_codec.c index 4926de6b84..b01d5220c5 100644 --- a/tests/unit/switch_core_codec.c +++ b/tests/unit/switch_core_codec.c @@ -51,6 +51,7 @@ FST_CORE_BEGIN("./conf") FST_SETUP_BEGIN() { fst_requires_module("mod_opus"); + fst_requires_module("mod_spandsp"); } FST_SETUP_END() @@ -101,6 +102,20 @@ FST_CORE_BEGIN("./conf") switch_core_codec_copy(&orig_codec, &new_codec, NULL, NULL); fst_check(orig_codec.implementation->samples_per_second == new_codec.implementation->samples_per_second); fst_check(orig_codec.implementation->actual_samples_per_second == new_codec.implementation->actual_samples_per_second); + + status = switch_core_codec_init(&orig_codec, + "G722", + "mod_spandsp", + NULL, + 8000, + 20, + 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, + &codec_settings, fst_pool); + fst_check(status == SWITCH_STATUS_SUCCESS); + + switch_core_codec_copy(&orig_codec, &new_codec, NULL, NULL); + fst_check(orig_codec.implementation->samples_per_second == new_codec.implementation->samples_per_second); + fst_check(orig_codec.implementation->actual_samples_per_second == new_codec.implementation->actual_samples_per_second); } FST_TEST_END()