run indent on the whole tree and update copyright dates in prep for 1.0.5

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@16579 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale committed 2010-02-06 03:38:24 +00:00
1 parent 7b347417e5
commit 886e1ddb4d
229 files changed
+20252 -20192

No files matched your search

+134 -143
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -28,7 +28,7 @@
* mod_cidlookup.c -- API for querying cid->name services
*
*/
#include <switch.h>
#include <curl/curl.h>
@@ -50,12 +50,12 @@ static struct {
char *url;
int curl_timeout;
int curl_warnduration;
char *whitepages_apikey;
switch_bool_t cache;
int cache_expire;
char *odbc_dsn;
char *odbc_user;
char *odbc_pass;
@@ -92,22 +92,24 @@ static switch_cache_db_handle_t *cidlookup_get_db_handle(void)
{
switch_cache_db_connection_options_t options = { {0} };
switch_cache_db_handle_t *dbh = NULL;
if (!zstr(globals.odbc_dsn)) {
options.odbc_options.dsn = globals.odbc_dsn;
options.odbc_options.user = globals.odbc_user;
options.odbc_options.pass = globals.odbc_pass;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) dbh = NULL;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS)
dbh = NULL;
}
return dbh;
}
static switch_status_t config_callback_dsn(switch_xml_config_item_t *data, const char *newvalue, switch_config_callback_type_t callback_type, switch_bool_t changed)
static switch_status_t config_callback_dsn(switch_xml_config_item_t *data, const char *newvalue, switch_config_callback_type_t callback_type,
switch_bool_t changed)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_cache_db_handle_t *dbh = NULL;
if (!switch_odbc_available()) {
@@ -139,25 +141,31 @@ static switch_status_t config_callback_dsn(switch_xml_config_item_t *data, const
}
switch_goto_status(SWITCH_STATUS_SUCCESS, done);
done:
done:
switch_cache_db_release_db_handle(&dbh);
return status;
}
static switch_xml_config_string_options_t config_opt_dsn = {NULL, 0, NULL}; /* anything is ok here */
static switch_xml_config_string_options_t config_opt_dsn = { NULL, 0, NULL }; /* anything is ok here */
static switch_xml_config_item_t instructions[] = {
/* parameter name type reloadable pointer default value options structure */
SWITCH_CONFIG_ITEM_STRING_STRDUP("url", CONFIG_RELOAD, &globals.url, NULL, "http://server.example.com/app?number=${caller_id_number}", "URL for the CID lookup service"),
SWITCH_CONFIG_ITEM_STRING_STRDUP("whitepages-apikey", CONFIG_RELOAD, &globals.whitepages_apikey, NULL, "api key for whitepages.com", "api key for whitepages.com"),
SWITCH_CONFIG_ITEM_STRING_STRDUP("url", CONFIG_RELOAD, &globals.url, NULL, "http://server.example.com/app?number=${caller_id_number}",
"URL for the CID lookup service"),
SWITCH_CONFIG_ITEM_STRING_STRDUP("whitepages-apikey", CONFIG_RELOAD, &globals.whitepages_apikey, NULL, "api key for whitepages.com",
"api key for whitepages.com"),
SWITCH_CONFIG_ITEM("cache", SWITCH_CONFIG_BOOL, CONFIG_RELOAD, &globals.cache, SWITCH_FALSE, NULL, "true|false", "whether to cache via cidlookup"),
SWITCH_CONFIG_ITEM("cache-expire", SWITCH_CONFIG_INT, CONFIG_RELOAD, &globals.cache_expire, (void *)300, NULL, "expire", "seconds to preserve num->name cache"),
SWITCH_CONFIG_ITEM("curl-timeout", SWITCH_CONFIG_INT, CONFIG_RELOAD, &globals.curl_timeout, (void *)2000, NULL, "timeout for curl", "milliseconds to timeout"),
SWITCH_CONFIG_ITEM("curl-warning-duration", SWITCH_CONFIG_INT, CONFIG_RELOAD, &globals.curl_warnduration, (void *)1000, NULL, "warning when curl queries are longer than specified time", "milliseconds"),
SWITCH_CONFIG_ITEM("cache-expire", SWITCH_CONFIG_INT, CONFIG_RELOAD, &globals.cache_expire, (void *) 300, NULL, "expire",
"seconds to preserve num->name cache"),
SWITCH_CONFIG_ITEM("curl-timeout", SWITCH_CONFIG_INT, CONFIG_RELOAD, &globals.curl_timeout, (void *) 2000, NULL, "timeout for curl",
"milliseconds to timeout"),
SWITCH_CONFIG_ITEM("curl-warning-duration", SWITCH_CONFIG_INT, CONFIG_RELOAD, &globals.curl_warnduration, (void *) 1000, NULL,
"warning when curl queries are longer than specified time", "milliseconds"),
SWITCH_CONFIG_ITEM_STRING_STRDUP("sql", CONFIG_RELOAD, &globals.sql, NULL, "sql whre number=${caller_id_number}", "SQL to run if overriding CID"),
SWITCH_CONFIG_ITEM_STRING_STRDUP("citystate-sql", CONFIG_RELOAD, &globals.citystate_sql, NULL, "sql to look up city/state info", "SQL to run if overriding CID"),
SWITCH_CONFIG_ITEM_STRING_STRDUP("citystate-sql", CONFIG_RELOAD, &globals.citystate_sql, NULL, "sql to look up city/state info",
"SQL to run if overriding CID"),
SWITCH_CONFIG_ITEM_CALLBACK("odbc-dsn", SWITCH_CONFIG_STRING, CONFIG_RELOAD, &globals.odbc_dsn, "", config_callback_dsn, &config_opt_dsn,
"db:user:passwd", "Database to use."),
"db:user:passwd", "Database to use."),
SWITCH_CONFIG_ITEM_END()
};
@@ -166,7 +174,7 @@ static switch_status_t do_config(switch_bool_t reload)
if (switch_xml_config_parse_module_settings("cidlookup.conf", reload, instructions) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_GENERR;
}
return SWITCH_STATUS_SUCCESS;
}
@@ -179,10 +187,10 @@ static switch_bool_t cidlookup_execute_sql_callback(char *sql, switch_core_db_ca
{
switch_bool_t retval = SWITCH_FALSE;
switch_cache_db_handle_t *dbh = NULL;
if (globals.odbc_dsn && (dbh = cidlookup_get_db_handle())) {
if (switch_cache_db_execute_sql_callback(dbh, sql, callback, (void *)cbt, err)
== SWITCH_ODBC_FAIL) {
if (switch_cache_db_execute_sql_callback(dbh, sql, callback, (void *) cbt, err)
== SWITCH_ODBC_FAIL) {
retval = SWITCH_FALSE;
} else {
retval = SWITCH_TRUE;
@@ -190,7 +198,7 @@ static switch_bool_t cidlookup_execute_sql_callback(char *sql, switch_core_db_ca
} else {
*err = switch_core_sprintf(cbt->pool, "Unable to get ODBC handle. dsn: %s, dbh is %s\n", globals.odbc_dsn, dbh ? "not null" : "null");
}
switch_cache_db_release_db_handle(&dbh);
return retval;
}
@@ -199,33 +207,31 @@ static int cidlookup_callback(void *pArg, int argc, char **argv, char **columnNa
{
callback_t *cbt = (callback_t *) pArg;
switch_memory_pool_t *pool = cbt->pool;
if (argc < 1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Unexpected number of columns returned for SQL. Returned column count: %d. ",
argc);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected number of columns returned for SQL. Returned column count: %d. ", argc);
return SWITCH_STATUS_GENERR;
}
cbt->name = switch_core_strdup(pool, switch_str_nil(argv[0]));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Name: %s\n", cbt->name);
return SWITCH_STATUS_SUCCESS;
}
/* make a new string with digits only */
static char *string_digitsonly(switch_memory_pool_t *pool, const char *str)
static char *string_digitsonly(switch_memory_pool_t *pool, const char *str)
{
char *p, *np, *newstr;
size_t len;
p = (char *)str;
p = (char *) str;
len = strlen(str);
newstr = switch_core_alloc(pool, len+1);
newstr = switch_core_alloc(pool, len + 1);
switch_assert(newstr);
np = newstr;
while(*p) {
while (*p) {
if (switch_isdigit(*p)) {
*np = *p;
np++;
@@ -237,16 +243,17 @@ static char *string_digitsonly(switch_memory_pool_t *pool, const char *str)
return newstr;
}
static cid_data_t *check_cache(switch_memory_pool_t *pool, const char *number) {
static cid_data_t *check_cache(switch_memory_pool_t *pool, const char *number)
{
char *cmd;
char *name = NULL;
char *area = NULL;
char *src = NULL;
cid_data_t *cid = NULL;
switch_stream_handle_t stream = { 0 };
SWITCH_STANDARD_STREAM(stream);
cmd = switch_core_sprintf(pool, "get fs:cidlookup:name:%s", number);
if (switch_api_execute("memcache", cmd, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
if (strncmp("-ERR", stream.data, 4)) {
@@ -275,7 +282,7 @@ static cid_data_t *check_cache(switch_memory_pool_t *pool, const char *number) {
src = NULL;
}
}
if (name || area || src) {
cid = switch_core_alloc(pool, sizeof(cid_data_t));
switch_assert(cid);
@@ -283,24 +290,21 @@ static cid_data_t *check_cache(switch_memory_pool_t *pool, const char *number) {
cid->area = area;
cid->src = src;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "memcache: k:'%s', vn:'%s', va:'%s', vs:'%s'\n",
cmd,
(name) ? name : "(null)",
(area) ? area : "(null)",
(src) ? src : "(null)"
);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "memcache: k:'%s', vn:'%s', va:'%s', vs:'%s'\n",
cmd, (name) ? name : "(null)", (area) ? area : "(null)", (src) ? src : "(null)");
switch_safe_free(stream.data);
return cid;
}
switch_bool_t set_cache(switch_memory_pool_t *pool, char *number, cid_data_t *cid) {
switch_bool_t set_cache(switch_memory_pool_t *pool, char *number, cid_data_t *cid)
{
char *cmd;
switch_bool_t success = SWITCH_TRUE;
switch_stream_handle_t stream = { 0 };
SWITCH_STANDARD_STREAM(stream);
cmd = switch_core_sprintf(pool, "set fs:cidlookup:name:%s '%s' %d", number, cid->name, globals.cache_expire);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "memcache: %s\n", cmd);
if (switch_api_execute("memcache", cmd, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
@@ -334,7 +338,7 @@ switch_bool_t set_cache(switch_memory_pool_t *pool, char *number, cid_data_t *ci
}
}
done:
done:
switch_safe_free(stream.data);
return success;
}
@@ -347,17 +351,18 @@ static size_t file_callback(void *ptr, size_t size, size_t nmemb, void *data)
http_data->bytes += realsize;
if (http_data->bytes > http_data->max_bytes) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Oversized file detected [%d bytes]\n", (int)http_data->bytes);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Oversized file detected [%d bytes]\n", (int) http_data->bytes);
http_data->err = 1;
return 0;
}
http_data->stream.write_function(
&http_data->stream, "%.*s", realsize, ptr);
http_data->stream.write_function(&http_data->stream, "%.*s", realsize, ptr);
return realsize;
}
static long do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, char **response, const char *query, struct curl_httppost *post, struct curl_slist *headers, int timeout) {
static long do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, char **response, const char *query, struct curl_httppost *post,
struct curl_slist *headers, int timeout)
{
switch_time_t start_time = switch_micro_time_now();
switch_time_t time_diff = 0;
CURL *curl_handle = NULL;
@@ -365,20 +370,20 @@ static long do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, cha
char hostname[256] = "";
struct http_data http_data;
memset(&http_data, 0, sizeof(http_data));
http_data.max_bytes = 10240;
SWITCH_STANDARD_STREAM(http_data.stream);
gethostname(hostname, sizeof(hostname));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "url: %s\n", query);
curl_handle = curl_easy_init();
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 0);
curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
if (!strncasecmp(query, "https", 5)) {
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
@@ -394,7 +399,7 @@ static long do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, cha
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
/*
TIMEOUT_MS is introduced in 7.16.2, we have 7.16.0 in tree
TIMEOUT_MS is introduced in 7.16.2, we have 7.16.0 in tree
*/
#ifdef CURLOPT_TIMEOUT_MS
if (timeout > 0) {
@@ -406,7 +411,7 @@ static long do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, cha
if (timeout > 0) {
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, timeout);
} else {
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, globals.curl_timeout/1000);
curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, globals.curl_timeout / 1000);
}
#endif
curl_easy_setopt(curl_handle, CURLOPT_URL, query);
@@ -417,34 +422,24 @@ static long do_lookup_url(switch_memory_pool_t *pool, switch_event_t *event, cha
curl_easy_perform(curl_handle);
curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
curl_easy_cleanup(curl_handle);
if ( http_data.stream.data &&
!zstr((char *)http_data.stream.data) &&
strcmp(" ", http_data.stream.data) ) {
if (http_data.stream.data && !zstr((char *) http_data.stream.data) && strcmp(" ", http_data.stream.data)) {
/* don't return UNKNOWN */
if (strcmp("UNKNOWN", http_data.stream.data) ||
strcmp("UNAVAILABLE", http_data.stream.data)) {
if (strcmp("UNKNOWN", http_data.stream.data) || strcmp("UNAVAILABLE", http_data.stream.data)) {
*response = switch_core_strdup(pool, http_data.stream.data);
}
}
time_diff = (switch_micro_time_now() - start_time); /* convert to milli from micro */
if ((time_diff/1000) >= globals.curl_warnduration) {
time_diff = (switch_micro_time_now() - start_time); /* convert to milli from micro */
if ((time_diff / 1000) >= globals.curl_warnduration) {
switch_core_time_duration_t duration;
switch_core_measure_time(time_diff, &duration);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SLOW LOOKUP ("
"%um, "
"%us, "
"%ums"
"): url: %s\n",
duration.min,
duration.sec,
duration.ms,
query);
"%um, " "%us, " "%ums" "): url: %s\n", duration.min, duration.sec, duration.ms, query);
}
switch_safe_free(http_data.stream.data);
return httpRes;
}
@@ -463,19 +458,19 @@ static cid_data_t *do_whitepages_lookup(switch_memory_pool_t *pool, switch_event
/* NANPA check */
if (strlen(num) == 11 && num[0] == '1') {
num++; /* skip past leading 1 */
num++; /* skip past leading 1 */
} else {
goto done;
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "whitepages-cid", num);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "whitepages-api-key", globals.whitepages_apikey);
query = switch_event_expand_headers(event, "http://api.whitepages.com/reverse_phone/1.0/?phone=${whitepages-cid};api_key=${whitepages-api-key}");
do_lookup_url(pool, event, &xml_s, query, NULL, NULL, 0);
xml = switch_xml_parse_str_dup(xml_s);
if (!xml) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to parse XML: %s\n", xml_s);
goto done;
@@ -487,14 +482,14 @@ static cid_data_t *do_whitepages_lookup(switch_memory_pool_t *pool, switch_event
name = switch_core_strdup(pool, switch_xml_txt(node));
goto area;
}
node = switch_xml_get(xml, "wp:listings", 0, "wp:listing", 0, "wp:displayname", -1);
if (node) {
name = switch_core_strdup(pool, switch_xml_txt(node));
}
area:
area:
node = switch_xml_get(xml, "wp:listings", 0, "wp:listing", 0, "wp:address", 0, "wp:city", -1);
if (node) {
city = switch_xml_txt(node);
@@ -504,12 +499,12 @@ area:
if (node) {
state = switch_xml_txt(node);
}
if (city || state) {
area = switch_core_sprintf(pool, "%s %s", city ? city : "", state ? state : "");
}
done:
done:
if (query) {
switch_safe_free(query);
@@ -519,23 +514,24 @@ done:
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "whitepages XML: %s\n", xml_s);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "whitepages name: %s, area: %s\n", name ? name : "(null)", area ? area : "(null)");
cid = switch_core_alloc(pool, sizeof(cid_data_t));
switch_assert(cid);
cid->name = name;
cid->area = area;
cid->src = "whitepages";
return cid;
}
static char *do_db_lookup(switch_memory_pool_t *pool, switch_event_t *event, const char *num, const char *sql) {
static char *do_db_lookup(switch_memory_pool_t *pool, switch_event_t *event, const char *num, const char *sql)
{
char *name = NULL;
char *newsql = NULL;
char *err = NULL;
callback_t cbt = { 0 };
cbt.pool = pool;
if (globals.odbc_dsn) {
newsql = switch_event_expand_headers(event, sql);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SQL: %s\n", newsql);
@@ -551,13 +547,14 @@ static char *do_db_lookup(switch_memory_pool_t *pool, switch_event_t *event, con
return name;
}
static cid_data_t *do_lookup(switch_memory_pool_t *pool, switch_event_t *event, const char *num, switch_bool_t skipurl, switch_bool_t skipcitystate) {
static cid_data_t *do_lookup(switch_memory_pool_t *pool, switch_event_t *event, const char *num, switch_bool_t skipurl, switch_bool_t skipcitystate)
{
char *number = NULL;
char *name = NULL;
char *url_query = NULL;
cid_data_t *cid = NULL;
switch_bool_t save_cache = SWITCH_FALSE;
cid = switch_core_alloc(pool, sizeof(cid_data_t));
switch_assert(cid);
@@ -581,40 +578,37 @@ static cid_data_t *do_lookup(switch_memory_pool_t *pool, switch_event_t *event,
goto done;
}
}
if (!skipurl && globals.whitepages_apikey) {
cid = do_whitepages_lookup(pool, event, number);
if (cid && cid->name) { /* only cache if we have a name */
if (cid && cid->name) { /* only cache if we have a name */
save_cache = SWITCH_TRUE;
goto done;
}
}
if (!skipurl && globals.url) {
url_query = switch_event_expand_headers(event, globals.url);
do_lookup_url(pool, event, &name, url_query, NULL, NULL, 0);
if (name) {
cid->name = name;
cid->src = "url";
save_cache = SWITCH_TRUE;
}
if (url_query != globals.url) {
switch_safe_free(url_query);
}
}
done:
done:
if (!cid) {
cid = switch_core_alloc(pool, sizeof(cid_data_t));
switch_assert(cid);
}
/* append area if we can */
if (!cid->area &&
!skipcitystate &&
strlen(number) == 11 && number[0] == '1' &&
switch_odbc_available() && globals.odbc_dsn && globals.citystate_sql) {
if (!cid->area && !skipcitystate && strlen(number) == 11 && number[0] == '1' && switch_odbc_available() && globals.odbc_dsn && globals.citystate_sql) {
/* yes, this is really area */
name = do_db_lookup(pool, event, number, globals.citystate_sql);
if (name) {
@@ -626,7 +620,7 @@ done:
}
}
}
if (!cid->area) {
cid->area = "UNKNOWN";
}
@@ -636,11 +630,11 @@ done:
if (!cid->src) {
cid->src = "UNKNOWN";
}
if (globals.cache && save_cache) {
set_cache(pool, number, cid);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "cidlookup source: %s\n", cid->src);
return cid;
@@ -649,7 +643,7 @@ done:
SWITCH_STANDARD_APP(cidlookup_app_function)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
char *argv[4] = { 0 };
int argc;
char *mydata = NULL;
@@ -663,7 +657,7 @@ SWITCH_STANDARD_APP(cidlookup_app_function)
const char *number = NULL;
switch_bool_t skipurl = SWITCH_FALSE;
switch_bool_t skipcitystate = SWITCH_FALSE;
if (session) {
pool = switch_core_session_get_pool(session);
} else {
@@ -674,7 +668,7 @@ SWITCH_STANDARD_APP(cidlookup_app_function)
if (!(mydata = switch_core_session_strdup(session, data))) {
return;
}
if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
if (argc > 0) {
number = switch_core_session_strdup(session, argv[0]);
@@ -687,20 +681,20 @@ SWITCH_STANDARD_APP(cidlookup_app_function)
}
}
}
if (!number && profile) {
number = switch_caller_get_field_by_name(profile, "caller_id_number");
}
if (number) {
cid = do_lookup(pool, event, number, skipurl, skipcitystate);
}
if (switch_string_var_check_const(cid->name)) {
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "Invalid CID data {%s} contains a variable\n", cid->name);
switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_CRIT, "Invalid CID data {%s} contains a variable\n", cid->name);
switch_goto_status(SWITCH_STATUS_GENERR, done);
}
if (cid && channel) {
switch_channel_set_variable(channel, "original_caller_id_name", switch_core_strdup(pool, profile->caller_id_name));
if (!zstr(cid->src)) {
@@ -711,10 +705,10 @@ SWITCH_STANDARD_APP(cidlookup_app_function)
}
profile->caller_id_name = switch_core_strdup(profile->pool, cid->name);;
}
switch_goto_status(SWITCH_STATUS_SUCCESS, done);
done:
done:
if (event) {
switch_event_destroy(&event);
}
@@ -722,6 +716,7 @@ done:
switch_core_destroy_memory_pool(&pool);
}
}
SWITCH_STANDARD_API(cidlookup_function)
{
switch_status_t status;
@@ -736,7 +731,7 @@ SWITCH_STANDARD_API(cidlookup_function)
switch_bool_t skipurl = SWITCH_FALSE;
switch_bool_t skipcitystate = SWITCH_FALSE;
switch_bool_t verbose = SWITCH_FALSE;
if (zstr(cmd)) {
switch_goto_status(SWITCH_STATUS_SUCCESS, usage);
}
@@ -753,22 +748,18 @@ SWITCH_STANDARD_API(cidlookup_function)
if (argc < 1) {
switch_goto_status(SWITCH_STATUS_SUCCESS, usage);
}
if (!strcmp("status", argv[0])) {
stream->write_function(stream, "+OK\n url: %s\n cache: %s\n cache-expire: %d\n",
globals.url ? globals.url : "(null)",
(globals.cache) ? "true" : "false",
globals.cache_expire);
stream->write_function(stream, " curl-timeout: %" SWITCH_TIME_T_FMT "\n curl-warn-duration: %" SWITCH_TIME_T_FMT "\n",
globals.curl_timeout,
globals.curl_warnduration);
stream->write_function(stream, " odbc-dsn: %s\n sql: %s\n citystate-sql: %s\n",
globals.odbc_dsn ? globals.odbc_dsn : "(null)",
globals.sql ? globals.sql : "(null)",
globals.citystate_sql ? globals.citystate_sql : "(null)");
stream->write_function(stream, " ODBC Compiled: %s\n", switch_odbc_available() ? "true" : "false");
stream->write_function(stream, "+OK\n url: %s\n cache: %s\n cache-expire: %d\n",
globals.url ? globals.url : "(null)", (globals.cache) ? "true" : "false", globals.cache_expire);
stream->write_function(stream, " curl-timeout: %" SWITCH_TIME_T_FMT "\n curl-warn-duration: %" SWITCH_TIME_T_FMT "\n",
globals.curl_timeout, globals.curl_warnduration);
stream->write_function(stream, " odbc-dsn: %s\n sql: %s\n citystate-sql: %s\n",
globals.odbc_dsn ? globals.odbc_dsn : "(null)",
globals.sql ? globals.sql : "(null)", globals.citystate_sql ? globals.citystate_sql : "(null)");
stream->write_function(stream, " ODBC Compiled: %s\n", switch_odbc_available()? "true" : "false");
switch_goto_status(SWITCH_STATUS_SUCCESS, done);
}
for (i = 1; i < argc; i++) {
@@ -784,7 +775,7 @@ SWITCH_STANDARD_API(cidlookup_function)
cid = do_lookup(pool, event, argv[0], skipurl, skipcitystate);
if (cid) {
if (switch_string_var_check_const(cid->name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Invalid CID data {%s} contains a variable\n", cid->name);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Invalid CID data {%s} contains a variable\n", cid->name);
stream->write_function(stream, "-ERR Invalid CID data {%s} contains a variable\n", cid->name);
switch_goto_status(SWITCH_STATUS_SUCCESS, done);
}
@@ -798,11 +789,11 @@ SWITCH_STANDARD_API(cidlookup_function)
}
switch_goto_status(SWITCH_STATUS_SUCCESS, done);
usage:
usage:
stream->write_function(stream, "-ERR\n%s\n", SYNTAX);
switch_goto_status(status, done);
done:
done:
switch_safe_free(mydata);
if (event) {
switch_event_destroy(&event);
@@ -822,16 +813,16 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cidlookup_load)
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
memset(&globals, 0, sizeof(globals));
globals.pool = pool;
do_config(SWITCH_FALSE);
if ((switch_event_bind_removable(modname, SWITCH_EVENT_RELOADXML, NULL, event_handler, NULL, &reload_xml_event) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind event!\n");
return SWITCH_STATUS_TERM;
}
SWITCH_ADD_API(api_interface, "cidlookup", "cidlookup API", cidlookup_function, SYNTAX);
SWITCH_ADD_APP(app_interface, "cidlookup", "Perform a CID lookup", "Perform a CID lookup",
cidlookup_app_function, "[number [skipurl]]", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
+187 -158
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -52,11 +52,11 @@ int vgo(int i, switch_core_session_t *session);
SWITCH_STANDARD_APP(cluechoo_app)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_channel_answer(channel);
switch_ivr_sleep(session, 1000, SWITCH_FALSE, NULL);
while(switch_channel_ready(channel)) {
while (switch_channel_ready(channel)) {
if (vgo(0, session) < 0) {
break;
}
@@ -66,7 +66,7 @@ SWITCH_STANDARD_APP(cluechoo_app)
SWITCH_STANDARD_API(cluechoo_function)
{
//stream->write_function(stream, "+OK Reloading\n");
go(0);
return SWITCH_STATUS_SUCCESS;
}
@@ -81,7 +81,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_cluechoo_load)
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n");
SWITCH_ADD_API(api_interface, "cluechoo", "Cluechoo API", cluechoo_function, "syntax");
SWITCH_ADD_APP(app_interface, "cluechoo", "cluechoo", "cluechoo", cluechoo_app, "", SAF_NONE);
@@ -134,36 +134,45 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cluechoo_shutdown)
#include <unistd.h>
#include "sl.h"
int ACCIDENT = 0;
int LOGO = 0;
int FLY = 0;
int ACCIDENT = 0;
int LOGO = 0;
int FLY = 0;
int my_mvaddstr(int y, int x, char *str)
{
for ( ; x < 0; ++x, ++str)
if (*str == '\0') return ERR;
for ( ; *str != '\0'; ++str, ++x)
if (mvaddch(y, x, *str) == ERR) return ERR;
return OK;
for (; x < 0; ++x, ++str)
if (*str == '\0')
return ERR;
for (; *str != '\0'; ++str, ++x)
if (mvaddch(y, x, *str) == ERR)
return ERR;
return OK;
}
void option(char *str)
{
extern int ACCIDENT, FLY;
extern int ACCIDENT, FLY;
while (*str != '\0') {
while (*str != '\0') {
switch (*str++) {
case 'a': ACCIDENT = 1; break;
case 'F': FLY = 1; break;
case 'l': LOGO = 1; break;
default: break;
case 'a':
ACCIDENT = 1;
break;
case 'F':
FLY = 1;
break;
case 'l':
LOGO = 1;
break;
default:
break;
}
}
}
}
int go(int i)
{
int x;
int x;
int sleep_len = 40000;
if (i > 0) {
@@ -171,23 +180,25 @@ int go(int i)
}
/*
for (i = 1; i < argc; ++i) {
if (*argv[i] == '-') {
option(argv[i] + 1);
}
}
*/
initscr();
signal(SIGINT, SIG_IGN);
noecho();
leaveok(stdscr, TRUE);
scrollok(stdscr, FALSE);
for (i = 1; i < argc; ++i) {
if (*argv[i] == '-') {
option(argv[i] + 1);
}
}
*/
initscr();
signal(SIGINT, SIG_IGN);
noecho();
leaveok(stdscr, TRUE);
scrollok(stdscr, FALSE);
for (x = COLS - 1; ; --x) {
for (x = COLS - 1;; --x) {
if (LOGO == 0) {
if (add_D51(x) == ERR) break;
if (add_D51(x) == ERR)
break;
} else {
if (add_sl(x) == ERR) break;
if (add_sl(x) == ERR)
break;
}
refresh();
if (x == COLS / 4) {
@@ -195,9 +206,9 @@ int go(int i)
} else {
usleep(sleep_len);
}
}
mvcur(0, COLS - 1, LINES - 1, 0);
endwin();
}
mvcur(0, COLS - 1, LINES - 1, 0);
endwin();
return 0;
}
@@ -205,20 +216,20 @@ int go(int i)
int vgo(int i, switch_core_session_t *session)
{
int x;
int x;
int sleep_len = 40000;
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_frame_t *read_frame;
switch_status_t status;
switch_codec_implementation_t read_impl = {0};
switch_codec_t codec = {0};
switch_codec_implementation_t read_impl = { 0 };
switch_codec_t codec = { 0 };
int hangover_hits = 0, hangunder_hits = 0;
int diff_level = 400;
int hangover = 40, hangunder = 15;
int talking = 0;
int energy_level = 500;
int done = 0;
switch_core_session_get_read_impl(session, &read_impl);
switch_core_session_get_read_impl(session, &read_impl);
printf("%s", SWITCH_SEQ_CLEARSCR);
@@ -226,16 +237,16 @@ int vgo(int i, switch_core_session_t *session)
sleep_len = i;
}
initscr();
signal(SIGINT, SIG_IGN);
noecho();
leaveok(stdscr, TRUE);
scrollok(stdscr, FALSE);
initscr();
signal(SIGINT, SIG_IGN);
noecho();
leaveok(stdscr, TRUE);
scrollok(stdscr, FALSE);
if (switch_core_codec_init(&codec,
"L16",
NULL, (int) read_impl.samples_per_second, read_impl.microseconds_per_packet / 1000,
NULL, (int) read_impl.samples_per_second, read_impl.microseconds_per_packet / 1000,
1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL,
switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
return -1;
@@ -243,28 +254,27 @@ int vgo(int i, switch_core_session_t *session)
switch_core_session_set_read_codec(session, &codec);
for (x = COLS - 1; ; --x) {
for (x = COLS - 1;; --x) {
if (!done && !switch_channel_ready(channel)) {
done = 1;
}
if (!done) {
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
if (!SWITCH_READ_ACCEPTABLE(status)) {
done = 1;
}
}
if (!done)
{
if (!done) {
int16_t *fdata = (int16_t *) read_frame->data;
uint32_t samples = read_frame->datalen / sizeof(*fdata);
uint32_t score, count = 0, j = 0;
double energy = 0;
int divisor = 0;
for (count = 0; count < samples; count++) {
energy += abs(fdata[j]);
j += read_impl.number_of_channels;
@@ -275,7 +285,7 @@ int vgo(int i, switch_core_session_t *session)
}
score = (uint32_t) (energy / (samples / divisor));
if (score > energy_level) {
uint32_t diff = score - energy_level;
if (hangover_hits) {
@@ -284,7 +294,7 @@ int vgo(int i, switch_core_session_t *session)
if (diff >= diff_level || ++hangunder_hits >= hangunder) {
hangover_hits = hangunder_hits = 0;
if (!talking) {
talking = 1;
}
@@ -310,22 +320,24 @@ int vgo(int i, switch_core_session_t *session)
}
if (LOGO == 0) {
if (add_D51(x) == ERR) break;
if (add_D51(x) == ERR)
break;
} else {
if (add_sl(x) == ERR) break;
if (add_sl(x) == ERR)
break;
}
refresh();
/*
if (x == COLS / 4) {
sleep(2);
} else {
usleep(sleep_len);
}
*/
}
mvcur(0, COLS - 1, LINES - 1, 0);
endwin();
if (x == COLS / 4) {
sleep(2);
} else {
usleep(sleep_len);
}
*/
}
mvcur(0, COLS - 1, LINES - 1, 0);
endwin();
switch_core_session_set_read_codec(session, NULL);
switch_core_codec_destroy(&codec);
@@ -335,103 +347,114 @@ int vgo(int i, switch_core_session_t *session)
int add_sl(int x)
{
static char *sl[LOGOPATTERNS][LOGOHIGHT + 1]
= {{LOGO1, LOGO2, LOGO3, LOGO4, LWHL11, LWHL12, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL21, LWHL22, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL31, LWHL32, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL41, LWHL42, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL51, LWHL52, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL61, LWHL62, DELLN}};
static char *sl[LOGOPATTERNS][LOGOHIGHT + 1]
= { {LOGO1, LOGO2, LOGO3, LOGO4, LWHL11, LWHL12, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL21, LWHL22, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL31, LWHL32, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL41, LWHL42, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL51, LWHL52, DELLN},
{LOGO1, LOGO2, LOGO3, LOGO4, LWHL61, LWHL62, DELLN}
};
static char *coal[LOGOHIGHT + 1]
= {LCOAL1, LCOAL2, LCOAL3, LCOAL4, LCOAL5, LCOAL6, DELLN};
static char *coal[LOGOHIGHT + 1]
= { LCOAL1, LCOAL2, LCOAL3, LCOAL4, LCOAL5, LCOAL6, DELLN };
static char *car[LOGOHIGHT + 1]
= {LCAR1, LCAR2, LCAR3, LCAR4, LCAR5, LCAR6, DELLN};
static char *car[LOGOHIGHT + 1]
= { LCAR1, LCAR2, LCAR3, LCAR4, LCAR5, LCAR6, DELLN };
int i, y, py1 = 0, py2 = 0, py3 = 0;
if (x < - LOGOLENGTH) return ERR;
y = LINES / 2 - 3;
int i, y, py1 = 0, py2 = 0, py3 = 0;
if (FLY == 1) {
if (x < -LOGOLENGTH)
return ERR;
y = LINES / 2 - 3;
if (FLY == 1) {
y = (x / 6) + LINES - (COLS / 6) - LOGOHIGHT;
py1 = 2; py2 = 4; py3 = 6;
}
py1 = 2;
py2 = 4;
py3 = 6;
}
for (i = 0; i <= LOGOHIGHT; ++i) {
for (i = 0; i <= LOGOHIGHT; ++i) {
my_mvaddstr(y + i, x, sl[(LOGOLENGTH + x) / 3 % LOGOPATTERNS][i]);
my_mvaddstr(y + i + py1, x + 21, coal[i]);
my_mvaddstr(y + i + py2, x + 42, car[i]);
my_mvaddstr(y + i + py3, x + 63, car[i]);
}
if (ACCIDENT == 1) {
}
if (ACCIDENT == 1) {
add_man(y + 1, x + 14);
add_man(y + 1 + py2, x + 45); add_man(y + 1 + py2, x + 53);
add_man(y + 1 + py3, x + 66); add_man(y + 1 + py3, x + 74);
}
add_smoke(y - 1, x + LOGOFUNNEL);
return OK;
add_man(y + 1 + py2, x + 45);
add_man(y + 1 + py2, x + 53);
add_man(y + 1 + py3, x + 66);
add_man(y + 1 + py3, x + 74);
}
add_smoke(y - 1, x + LOGOFUNNEL);
return OK;
}
static int loops = 0;
int add_D51(int x)
{
static char *d51[D51PATTERNS][D51HIGHT + 1]
= {{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL11, D51WHL12, D51WHL13, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL21, D51WHL22, D51WHL23, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL31, D51WHL32, D51WHL33, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL41, D51WHL42, D51WHL43, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL51, D51WHL52, D51WHL53, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL61, D51WHL62, D51WHL63, D51DEL}};
static char *coal[D51HIGHT + 1]
= {COAL01, COAL02, COAL03, COAL04, COAL05,
COAL06, COAL07, COAL08, COAL09, COAL10, COALDEL};
static char *d51[D51PATTERNS][D51HIGHT + 1]
= { {D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL11, D51WHL12, D51WHL13, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL21, D51WHL22, D51WHL23, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL31, D51WHL32, D51WHL33, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL41, D51WHL42, D51WHL43, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL51, D51WHL52, D51WHL53, D51DEL},
{D51STR1, D51STR2, D51STR3, D51STR4, D51STR5, D51STR6, D51STR7,
D51WHL61, D51WHL62, D51WHL63, D51DEL}
};
static char *coal[D51HIGHT + 1]
= { COAL01, COAL02, COAL03, COAL04, COAL05,
COAL06, COAL07, COAL08, COAL09, COAL10, COALDEL
};
static char *acoal[D51HIGHT + 1]
= {COAL01, COAL02, COAL03, COAL04, COAL5A,
COAL06, COAL07, COAL08, COAL09, COAL10, COALDEL};
static char *acoal[D51HIGHT + 1]
= { COAL01, COAL02, COAL03, COAL04, COAL5A,
COAL06, COAL07, COAL08, COAL09, COAL10, COALDEL
};
int y, i, dy = 0;
int y, i, dy = 0;
if (x < - D51LENGTH) return ERR;
y = LINES / 2 - 5;
if (x < -D51LENGTH)
return ERR;
y = LINES / 2 - 5;
if (FLY == 1) {
if (FLY == 1) {
y = (x / 7) + LINES - (COLS / 7) - D51HIGHT;
dy = 1;
}
}
for (i = 0; i <= D51HIGHT; ++i) {
for (i = 0; i <= D51HIGHT; ++i) {
my_mvaddstr(y + i, x, d51[(D51LENGTH + x) % D51PATTERNS][i]);
my_mvaddstr(y + i + dy, x + 53, loops > 60 ? coal[i] : acoal[i]);
loops++;
if (loops == 500) loops = -100;
}
if (ACCIDENT == 1) {
if (loops == 500)
loops = -100;
}
if (ACCIDENT == 1) {
add_man(y + 2, x + 43);
add_man(y + 2, x + 47);
}
add_smoke(y - 1, x + D51FUNNEL);
return OK;
}
add_smoke(y - 1, x + D51FUNNEL);
return OK;
}
int add_man(int y, int x)
{
static char *man[2][2] = {{"", "(O)"}, {"Help!", "\\O/"}};
int i;
static char *man[2][2] = { {"", "(O)"}, {"Help!", "\\O/"} };
int i;
for (i = 0; i < 2; ++i) {
for (i = 0; i < 2; ++i) {
my_mvaddstr(y + i, x, man[(LOGOLENGTH + x) / 12 % 2][i]);
}
}
return 0;
}
@@ -440,45 +463,51 @@ int add_man(int y, int x)
int add_smoke(int y, int x)
#define SMOKEPTNS 16
{
static struct smokes {
static struct smokes {
int y, x;
int ptrn, kind;
} S[1000];
static int sum = 0;
static char *Smoke[2][SMOKEPTNS]
= {{"( )", "( )", "( )", "( )", "( )",
"( )" , "( )" , "( )" , "()" , "()" ,
"O" , "O" , "O" , "O" , "O" ,
" " },
{"(@@@)", "(@@@@)", "(@@@@)", "(@@@)", "(@@)",
"(@@)" , "(@)" , "(@)" , "@@" , "@@" ,
"@" , "@" , "@" , "@" , "@" ,
" " }};
static char *Eraser[SMOKEPTNS]
= {" ", " ", " ", " ", " ",
" " , " " , " " , " " , " " ,
" " , " " , " " , " " , " " ,
" " };
static int dy[SMOKEPTNS] = { 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 };
static int dx[SMOKEPTNS] = {-2, -1, 0, 1, 1, 1, 1, 1, 2, 2,
2, 2, 2, 3, 3, 3 };
int i;
} S[1000];
static int sum = 0;
static char *Smoke[2][SMOKEPTNS]
= { {"( )", "( )", "( )", "( )", "( )",
"( )", "( )", "( )", "()", "()",
"O", "O", "O", "O", "O",
" "},
{"(@@@)", "(@@@@)", "(@@@@)", "(@@@)", "(@@)",
"(@@)", "(@)", "(@)", "@@", "@@",
"@", "@", "@", "@", "@",
" "}
};
static char *Eraser[SMOKEPTNS]
= { " ", " ", " ", " ", " ",
" ", " ", " ", " ", " ",
" ", " ", " ", " ", " ",
" "
};
static int dy[SMOKEPTNS] = { 2, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0
};
static int dx[SMOKEPTNS] = { -2, -1, 0, 1, 1, 1, 1, 1, 2, 2,
2, 2, 2, 3, 3, 3
};
int i;
if (x % 4 == 0) {
if (x % 4 == 0) {
for (i = 0; i < sum; ++i) {
my_mvaddstr(S[i].y, S[i].x, Eraser[S[i].ptrn]);
S[i].y -= dy[S[i].ptrn];
S[i].x += dx[S[i].ptrn];
S[i].y -= dy[S[i].ptrn];
S[i].x += dx[S[i].ptrn];
S[i].ptrn += (S[i].ptrn < SMOKEPTNS - 1) ? 1 : 0;
my_mvaddstr(S[i].y, S[i].x, Smoke[S[i].kind][S[i].ptrn]);
}
my_mvaddstr(y, x, Smoke[sum % 2][0]);
S[sum].y = y; S[sum].x = x;
S[sum].ptrn = 0; S[sum].kind = sum % 2;
sum ++;
}
S[sum].y = y;
S[sum].x = x;
S[sum].ptrn = 0;
S[sum].kind = sum % 2;
sum++;
}
return 0;
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+59 -62
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -28,7 +28,7 @@
* mod_curl.c -- API for performing http queries
*
*/
#include <switch.h>
#include <curl/curl.h>
#include <json.h>
@@ -75,13 +75,12 @@ static size_t file_callback(void *ptr, size_t size, size_t nmemb, void *data)
http_data->bytes += realsize;
if (http_data->bytes > http_data->max_bytes) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Oversized file detected [%d bytes]\n", (int)http_data->bytes);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Oversized file detected [%d bytes]\n", (int) http_data->bytes);
http_data->err = 1;
return 0;
}
http_data->stream.write_function(
&http_data->stream, "%.*s", realsize, ptr);
http_data->stream.write_function(&http_data->stream, "%.*s", realsize, ptr);
return realsize;
}
@@ -90,18 +89,19 @@ static size_t header_callback(void *ptr, size_t size, size_t nmemb, void *data)
register unsigned int realsize = (unsigned int) (size * nmemb);
http_data_t *http_data = data;
char *header = NULL;
header = switch_core_alloc(http_data->pool, realsize+1);
header = switch_core_alloc(http_data->pool, realsize + 1);
switch_copy_string(header, ptr, realsize);
header[realsize] = '\0';
http_data->headers = curl_slist_append(http_data->headers, header);
return realsize;
}
static http_data_t *do_lookup_url(switch_memory_pool_t *pool, const char *url, const char *method, const char *data) {
static http_data_t *do_lookup_url(switch_memory_pool_t *pool, const char *url, const char *method, const char *data)
{
CURL *curl_handle = NULL;
long httpRes = 0;
char hostname[256] = "";
@@ -111,19 +111,19 @@ static http_data_t *do_lookup_url(switch_memory_pool_t *pool, const char *url, c
http_data = switch_core_alloc(pool, sizeof(http_data_t));
memset(http_data, 0, sizeof(http_data_t));
http_data->pool = pool;
http_data->max_bytes = 64000;
SWITCH_STANDARD_STREAM(http_data->stream);
gethostname(hostname, sizeof(hostname));
if (!method) {
method = "get";
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "method: %s, url: %s\n", method, url);
curl_handle = curl_easy_init();
if (!strncasecmp(url, "https", 5)) {
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
@@ -150,54 +150,53 @@ static http_data_t *do_lookup_url(switch_memory_pool_t *pool, const char *url, c
curl_easy_perform(curl_handle);
curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes);
curl_easy_cleanup(curl_handle);
if ( http_data->stream.data &&
!zstr((char *)http_data->stream.data) &&
strcmp(" ", http_data->stream.data) ) {
if (http_data->stream.data && !zstr((char *) http_data->stream.data) && strcmp(" ", http_data->stream.data)) {
http_data->http_response = switch_core_strdup(pool, http_data->stream.data);
}
http_data->http_response_code = httpRes;
switch_safe_free(http_data->stream.data);
return http_data;
}
static char *print_json(switch_memory_pool_t *pool, http_data_t *http_data) {
static char *print_json(switch_memory_pool_t *pool, http_data_t *http_data)
{
struct json_object *top = NULL;
struct json_object *headers = NULL;
char *data = NULL;
struct curl_slist *header = http_data->headers;
top = json_object_new_object();
headers = json_object_new_array();
json_object_object_add(top, "status_code", json_object_new_int(http_data->http_response_code));
if (http_data->http_response) {
json_object_object_add(top, "body", json_object_new_string(http_data->http_response));
}
/* parse header data */
while(header) {
while (header) {
struct json_object *obj = NULL;
/* remove trailing \r */
if ((data=rindex(header->data, '\r'))) {
if ((data = rindex(header->data, '\r'))) {
*data = '\0';
}
if (zstr(header->data)) {
header = header->next;
continue;
}
if ((data = index(header->data, ':'))) {
*data = '\0';
data++;
while(*data == ' ' && *data != '\0') {
while (*data == ' ' && *data != '\0') {
data++;
}
obj = json_object_new_object();
obj = json_object_new_object();
json_object_object_add(obj, "key", json_object_new_string(header->data));
json_object_object_add(obj, "value", json_object_new_string(data));
json_object_array_add(headers, obj);
@@ -223,15 +222,15 @@ static char *print_json(switch_memory_pool_t *pool, http_data_t *http_data) {
}
json_object_object_add(top, "headers", headers);
data = switch_core_strdup(pool, json_object_to_json_string(top));
json_object_put(top); /* should free up all children */
json_object_put(top); /* should free up all children */
return data;
}
SWITCH_STANDARD_APP(curl_app_function)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
char *argv[10] = { 0 };
int argc;
char *mydata = NULL;
@@ -247,8 +246,8 @@ SWITCH_STANDARD_APP(curl_app_function)
struct curl_slist *slist = NULL;
switch_stream_handle_t stream = { 0 };
int i = 0;
if (session) {
pool = switch_core_session_get_pool(session);
} else {
@@ -257,24 +256,23 @@ SWITCH_STANDARD_APP(curl_app_function)
if (!(mydata = switch_core_session_strdup(session, data))) {
return;
}
if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
if (argc == 0) {
switch_goto_status(SWITCH_STATUS_SUCCESS, usage);
}
url = switch_core_strdup(pool, argv[0]);
for (i =1; i < argc; i++) {
for (i = 1; i < argc; i++) {
if (!strcasecmp("headers", argv[i])) {
do_headers = SWITCH_TRUE;
} else if (!strcasecmp("json", argv[i])) {
do_json = SWITCH_TRUE;
} else if ( !strcasecmp("get", argv[i]) ||
!strcasecmp("head", argv[i])) {
} else if (!strcasecmp("get", argv[i]) || !strcasecmp("head", argv[i])) {
method = switch_core_strdup(pool, argv[i]);
} else if (!strcasecmp("post", argv[i])) {
if ( ++i < argc) {
if (++i < argc) {
postdata = switch_core_strdup(pool, argv[i]);
switch_url_decode(postdata);
} else {
@@ -283,7 +281,7 @@ SWITCH_STANDARD_APP(curl_app_function)
}
}
}
http_data = do_lookup_url(pool, url, method, postdata);
if (do_json) {
switch_channel_set_variable(channel, "curl_response_data", print_json(pool, http_data));
@@ -291,7 +289,7 @@ SWITCH_STANDARD_APP(curl_app_function)
SWITCH_STANDARD_STREAM(stream);
if (do_headers) {
slist = http_data->headers;
while(slist) {
while (slist) {
stream.write_function(&stream, "%s\n", slist->data);
slist = slist->next;
}
@@ -300,17 +298,16 @@ SWITCH_STANDARD_APP(curl_app_function)
stream.write_function(&stream, "%s", http_data->http_response ? http_data->http_response : "");
switch_channel_set_variable(channel, "curl_response_data", stream.data);
}
switch_channel_set_variable(channel, "curl_response_code",
switch_core_sprintf(pool, "%ld", http_data->http_response_code));
switch_channel_set_variable(channel, "curl_response_code", switch_core_sprintf(pool, "%ld", http_data->http_response_code));
switch_channel_set_variable(channel, "curl_method", method);
switch_goto_status(SWITCH_STATUS_SUCCESS, done);
usage:
usage:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", SYNTAX);
switch_goto_status(status, done);
done:
done:
switch_safe_free(stream.data);
if (http_data && http_data->headers) {
curl_slist_free_all(http_data->headers);
@@ -319,6 +316,7 @@ done:
switch_core_destroy_memory_pool(&pool);
}
}
SWITCH_STANDARD_API(curl_function)
{
switch_status_t status;
@@ -335,7 +333,7 @@ SWITCH_STANDARD_API(curl_function)
int i = 0;
switch_memory_pool_t *pool = NULL;
if (zstr(cmd)) {
switch_goto_status(SWITCH_STATUS_SUCCESS, usage);
}
@@ -351,20 +349,19 @@ SWITCH_STANDARD_API(curl_function)
if (argc < 1) {
switch_goto_status(SWITCH_STATUS_SUCCESS, usage);
}
url = switch_core_strdup(pool, argv[0]);
for (i =1; i < argc; i++) {
for (i = 1; i < argc; i++) {
if (!strcasecmp("headers", argv[i])) {
do_headers = SWITCH_TRUE;
} else if (!strcasecmp("json", argv[i])) {
do_json = SWITCH_TRUE;
} else if ( !strcasecmp("get", argv[i]) ||
!strcasecmp("head", argv[i])) {
} else if (!strcasecmp("get", argv[i]) || !strcasecmp("head", argv[i])) {
method = switch_core_strdup(pool, argv[i]);
} else if (!strcasecmp("post", argv[i])) {
method = "post";
if ( ++i < argc) {
if (++i < argc) {
postdata = switch_core_strdup(pool, argv[i]);
switch_url_decode(postdata);
} else {
@@ -372,14 +369,14 @@ SWITCH_STANDARD_API(curl_function)
}
}
}
http_data = do_lookup_url(pool, url, method, postdata);
if (do_json) {
stream->write_function(stream, "%s", print_json(pool, http_data));
} else {
if (do_headers) {
slist = http_data->headers;
while(slist) {
while (slist) {
stream->write_function(stream, "%s\n", slist->data);
slist = slist->next;
}
@@ -390,11 +387,11 @@ SWITCH_STANDARD_API(curl_function)
}
switch_goto_status(SWITCH_STATUS_SUCCESS, done);
usage:
usage:
stream->write_function(stream, "-ERR\n%s\n", SYNTAX);
switch_goto_status(status, done);
done:
done:
if (http_data && http_data->headers) {
curl_slist_free_all(http_data->headers);
}
@@ -414,7 +411,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_curl_load)
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
memset(&globals, 0, sizeof(globals));
globals.pool = pool;
SWITCH_ADD_API(api_interface, "curl", "curl API", curl_function, SYNTAX);
+123 -116
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -40,19 +40,16 @@ SWITCH_MODULE_DEFINITION(mod_directory, mod_directory_load, mod_directory_shutdo
static const char *global_cf = "directory.conf";
static char dir_sql[] =
"CREATE TABLE directory_search (\n"
" hostname VARCHAR(255),\n"
" uuid VARCHAR(255),\n"
" extension VARCHAR(255),\n"
" full_name VARCHAR(255),\n"
" full_name_digit VARCHAR(255),\n"
" first_name VARCHAR(255),\n"
" first_name_digit VARCHAR(255),\n"
" last_name VARCHAR(255),\n"
" last_name_digit VARCHAR(255),\n"
" name_visible INTEGER,\n"
" exten_visible INTEGER\n"
");\n";
"CREATE TABLE directory_search (\n"
" hostname VARCHAR(255),\n"
" uuid VARCHAR(255),\n"
" extension VARCHAR(255),\n"
" full_name VARCHAR(255),\n"
" full_name_digit VARCHAR(255),\n"
" first_name VARCHAR(255),\n"
" first_name_digit VARCHAR(255),\n"
" last_name VARCHAR(255),\n"
" last_name_digit VARCHAR(255),\n" " name_visible INTEGER,\n" " exten_visible INTEGER\n" ");\n";
#define DIR_RESULT_ITEM "directory_result_item"
#define DIR_RESULT_SAY_NAME "directory_result_say_name"
@@ -113,51 +110,52 @@ typedef enum {
PFLAG_DESTROY = 1 << 0
} dir_flags_t;
static int digit_matching_keypad(char letter) {
static int digit_matching_keypad(char letter)
{
int result = -1;
switch(toupper(letter)) {
case 'A':
case 'B':
case 'C':
result = 2;
break;
case 'D':
case 'E':
case 'F':
result = 3;
break;
case 'G':
case 'H':
case 'I':
result = 4;
break;
case 'J':
case 'K':
case 'L':
result = 5;
break;
case 'M':
case 'N':
case 'O':
result = 6;
break;
case 'P':
case 'Q':
case 'R':
case 'S':
result = 7;
break;
case 'T':
case 'U':
case 'V':
result = 8;
break;
case 'W':
case 'X':
case 'Y':
case 'Z':
result = 9;
break;
switch (toupper(letter)) {
case 'A':
case 'B':
case 'C':
result = 2;
break;
case 'D':
case 'E':
case 'F':
result = 3;
break;
case 'G':
case 'H':
case 'I':
result = 4;
break;
case 'J':
case 'K':
case 'L':
result = 5;
break;
case 'M':
case 'N':
case 'O':
result = 6;
break;
case 'P':
case 'Q':
case 'R':
case 'S':
result = 7;
break;
case 'T':
case 'U':
case 'V':
result = 8;
break;
case 'W':
case 'X':
case 'Y':
case 'Z':
result = 9;
break;
}
@@ -185,7 +183,7 @@ char *string_to_keypad_digit(const char *in)
if (*d) {
*d = '\0';
}
}
}
return dst;
}
@@ -206,7 +204,7 @@ static switch_status_t directory_execute_sql(char *sql, switch_mutex_t *mutex)
status = switch_core_db_persistant_execute(db, sql, 1);
switch_core_db_close(db);
end:
end:
if (mutex) {
switch_mutex_unlock(mutex);
}
@@ -304,7 +302,7 @@ static switch_bool_t directory_execute_sql_callback(switch_mutex_t *mutex, char
switch_core_db_close(db);
}
end:
end:
if (mutex) {
switch_mutex_unlock(mutex);
}
@@ -337,34 +335,32 @@ dir_profile_t *profile_set_config(dir_profile_t *profile)
profile->config_str_pool.pool = profile->pool;
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "next-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
&profile->next_key, "6", &config_dtmf, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "prev-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
&profile->prev_key, "4", &config_dtmf, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "next-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &profile->next_key, "6", &config_dtmf, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "prev-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &profile->prev_key, "4", &config_dtmf, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "terminator-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
&profile->terminator_key, "#", &config_dtmf, NULL, NULL);
&profile->terminator_key, "#", &config_dtmf, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "switch-order-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
&profile->switch_order_key, "*", &config_dtmf, NULL, NULL);
&profile->switch_order_key, "*", &config_dtmf, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "select-name-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
&profile->select_name_key, "1", &config_dtmf, NULL, NULL);
&profile->select_name_key, "1", &config_dtmf, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "new-search-key", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
&profile->new_search_key, "3", &config_dtmf, NULL, NULL);
&profile->new_search_key, "3", &config_dtmf, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "search-order", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE,
&profile->search_order, "last_name", &profile->config_str_pool, NULL, NULL);
&profile->search_order, "last_name", &profile->config_str_pool, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "digit-timeout", SWITCH_CONFIG_INT, CONFIG_RELOADABLE,
&profile->digit_timeout, 3000, &config_int_digit_timeout, NULL, NULL);
&profile->digit_timeout, 3000, &config_int_digit_timeout, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "min-search-digits", SWITCH_CONFIG_INT, CONFIG_RELOADABLE,
&profile->min_search_digits, 3, &config_int_ht_0, NULL, NULL);
&profile->min_search_digits, 3, &config_int_ht_0, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "max-menu-attempts", SWITCH_CONFIG_INT, CONFIG_RELOADABLE,
&profile->max_menu_attempt, 3, &config_int_ht_0, NULL, NULL);
&profile->max_menu_attempt, 3, &config_int_ht_0, NULL, NULL);
SWITCH_CONFIG_SET_ITEM(profile->config[i++], "max-result", SWITCH_CONFIG_INT, CONFIG_RELOADABLE,
&profile->max_result, 5, &config_int_ht_0, NULL, NULL);
&profile->max_result, 5, &config_int_ht_0, NULL, NULL);
return profile;
}
static dir_profile_t * load_profile(const char *profile_name)
static dir_profile_t *load_profile(const char *profile_name)
{
dir_profile_t *profile = NULL;
switch_xml_t x_profiles, x_profile, cfg, xml = NULL;
@@ -413,7 +409,7 @@ static dir_profile_t * load_profile(const char *profile_name)
switch_core_hash_insert(globals.profile_hash, profile->name, profile);
}
end:
end:
switch_xml_free(xml);
return profile;
@@ -451,7 +447,7 @@ static switch_status_t load_config(switch_bool_t reload)
return SWITCH_STATUS_SUCCESS;
}
static dir_profile_t * get_profile(const char *profile_name)
static dir_profile_t *get_profile(const char *profile_name)
{
dir_profile_t *profile = NULL;
@@ -469,7 +465,8 @@ static dir_profile_t * get_profile(const char *profile_name)
return profile;
}
static switch_status_t populate_database(switch_core_session_t *session, dir_profile_t * profile, const char *domain_name) {
static switch_status_t populate_database(switch_core_session_t *session, dir_profile_t *profile, const char *domain_name)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
char *sql = NULL;
@@ -561,8 +558,9 @@ static switch_status_t populate_database(switch_core_session_t *session, dir_pro
firstNameDigit = string_to_keypad_digit(firstName);
/* add user into DB */
sql = switch_mprintf("insert into directory_search values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%d','%d')",
globals.hostname, switch_core_session_get_uuid(session), id, fullName, fullNameDigit, firstName, firstNameDigit, lastName, lastNameDigit, name_visible, exten_visible);
sql = switch_mprintf("insert into directory_search values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%d','%d')",
globals.hostname, switch_core_session_get_uuid(session), id, fullName, fullNameDigit, firstName, firstNameDigit,
lastName, lastNameDigit, name_visible, exten_visible);
if (sqlvalues) {
sqltmp = sqlvalues;
@@ -580,10 +578,10 @@ static switch_status_t populate_database(switch_core_session_t *session, dir_pro
}
}
}
sql = switch_mprintf("BEGIN;%s;COMMIT;",sqlvalues);
sql = switch_mprintf("BEGIN;%s;COMMIT;", sqlvalues);
directory_execute_sql(sql, profile->mutex);
end:
end:
switch_safe_free(sql);
switch_safe_free(sqlvalues);
switch_event_destroy(&xml_params);
@@ -603,27 +601,27 @@ typedef struct cb_result cbr_t;
static switch_status_t on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
{
switch (itype) {
case SWITCH_INPUT_TYPE_DTMF:
{
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
cbr_t *cbr = (cbr_t *) buf;
cbr->digit = dtmf->digit;
if (dtmf->digit == *cbr->profile->terminator_key || dtmf->digit == *cbr->profile->switch_order_key) {
return SWITCH_STATUS_BREAK;
}
if (strlen(cbr->digits) < sizeof(cbr->digits) - 2) {
int at = strlen(cbr->digits);
cbr->digits[at++] = dtmf->digit;
cbr->digits[at] = '\0';
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "DTMF buffer is full\n");
return SWITCH_STATUS_BREAK;
}
case SWITCH_INPUT_TYPE_DTMF:
{
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
cbr_t *cbr = (cbr_t *) buf;
cbr->digit = dtmf->digit;
if (dtmf->digit == *cbr->profile->terminator_key || dtmf->digit == *cbr->profile->switch_order_key) {
return SWITCH_STATUS_BREAK;
}
break;
default:
break;
if (strlen(cbr->digits) < sizeof(cbr->digits) - 2) {
int at = strlen(cbr->digits);
cbr->digits[at++] = dtmf->digit;
cbr->digits[at] = '\0';
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "DTMF buffer is full\n");
return SWITCH_STATUS_BREAK;
}
}
break;
default:
break;
}
return SWITCH_STATUS_BREAK;
@@ -650,12 +648,12 @@ static switch_status_t listen_entry(switch_core_session_t *session, dir_profile_
}
if (zstr_buf(buf)) {
switch_snprintf(macro, sizeof(macro), "phrase:%s:%d", DIR_RESULT_ITEM, cbt->want+1);
switch_snprintf(macro, sizeof(macro), "phrase:%s:%d", DIR_RESULT_ITEM, cbt->want + 1);
switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), 1, profile->terminator_key);
}
if (!zstr_buf(recorded_name) && zstr_buf(buf)) {
switch_ivr_read(session, 0, 1, recorded_name, NULL, buf, sizeof(buf), 1, profile->terminator_key);
switch_ivr_read(session, 0, 1, recorded_name, NULL, buf, sizeof(buf), 1, profile->terminator_key);
}
if (zstr_buf(recorded_name) && zstr_buf(buf)) {
@@ -667,7 +665,8 @@ static switch_status_t listen_entry(switch_core_session_t *session, dir_profile_
switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), 1, profile->terminator_key);
}
if (zstr_buf(buf)) {
switch_snprintf(macro, sizeof(macro), "phrase:%s:%c,%c,%c,%c", DIR_RESULT_MENU, *profile->select_name_key, *profile->next_key, *profile->prev_key, *profile->new_search_key);
switch_snprintf(macro, sizeof(macro), "phrase:%s:%c,%c,%c,%c", DIR_RESULT_MENU, *profile->select_name_key, *profile->next_key, *profile->prev_key,
*profile->new_search_key);
switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), profile->digit_timeout, profile->terminator_key);
}
@@ -688,7 +687,8 @@ static switch_status_t listen_entry(switch_core_session_t *session, dir_profile_
return SWITCH_STATUS_SUCCESS;
}
switch_status_t gather_name_digit(switch_core_session_t *session, dir_profile_t *profile, search_params_t *params) {
switch_status_t gather_name_digit(switch_core_session_t *session, dir_profile_t *profile, search_params_t *params)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status = SWITCH_STATUS_SUCCESS;
cbr_t cbr;
@@ -707,7 +707,7 @@ switch_status_t gather_name_digit(switch_core_session_t *session, dir_profile_t
/* Gather the user Name */
switch_snprintf(macro, sizeof(macro), "%s:%c", (params->search_by_last_name?"last_name":"first_name"), *profile->switch_order_key);
switch_snprintf(macro, sizeof(macro), "%s:%c", (params->search_by_last_name ? "last_name" : "first_name"), *profile->switch_order_key);
switch_ivr_phrase_macro(session, DIR_INTRO, macro, NULL, &args);
while (switch_channel_ready(channel)) {
@@ -737,7 +737,8 @@ switch_status_t gather_name_digit(switch_core_session_t *session, dir_profile_t
return status;
}
switch_status_t navigate_entrys(switch_core_session_t *session, dir_profile_t *profile, search_params_t *params) {
switch_status_t navigate_entrys(switch_core_session_t *session, dir_profile_t *profile, search_params_t *params)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
char *sql = NULL;
char entry_count[80] = "";
@@ -749,7 +750,10 @@ switch_status_t navigate_entrys(switch_core_session_t *session, dir_profile_t *p
cbt.buf = entry_count;
cbt.len = sizeof(entry_count);
sql = switch_mprintf("select count(*) from directory_search where hostname = '%q' and uuid = '%q' and name_visible = 1 and %s like '%q%%'", globals.hostname, switch_core_session_get_uuid(session), (params->search_by_last_name?"last_name_digit":"first_name_digit"), params->digits);
sql =
switch_mprintf("select count(*) from directory_search where hostname = '%q' and uuid = '%q' and name_visible = 1 and %s like '%q%%'",
globals.hostname, switch_core_session_get_uuid(session), (params->search_by_last_name ? "last_name_digit" : "first_name_digit"),
params->digits);
directory_execute_sql_callback(profile->mutex, sql, sql2str_callback, &cbt);
switch_safe_free(sql);
@@ -773,7 +777,10 @@ switch_status_t navigate_entrys(switch_core_session_t *session, dir_profile_t *p
memset(&listing_cbt, 0, sizeof(listing_cbt));
listing_cbt.params = params;
sql = switch_mprintf("select extension, full_name, last_name, first_name, name_visible, exten_visible from directory_search where hostname = '%q' and uuid = '%q' and name_visible = 1 and %s like '%q%%' order by last_name, first_name", globals.hostname, switch_core_session_get_uuid(session), (params->search_by_last_name?"last_name_digit":"first_name_digit"), params->digits);
sql =
switch_mprintf
("select extension, full_name, last_name, first_name, name_visible, exten_visible from directory_search where hostname = '%q' and uuid = '%q' and name_visible = 1 and %s like '%q%%' order by last_name, first_name",
globals.hostname, switch_core_session_get_uuid(session), (params->search_by_last_name ? "last_name_digit" : "first_name_digit"), params->digits);
for (cur_entry = 0; cur_entry < result_count; cur_entry++) {
listing_cbt.index = 0;
@@ -812,7 +819,7 @@ switch_status_t navigate_entrys(switch_core_session_t *session, dir_profile_t *p
}
}
end:
end:
switch_safe_free(sql);
return status;
@@ -825,8 +832,8 @@ SWITCH_STANDARD_APP(directory_function)
char *argv[6] = { 0 };
char *mydata = NULL;
const char *profile_name = NULL;
const char *domain_name = NULL;
dir_profile_t * profile = NULL;
const char *domain_name = NULL;
dir_profile_t *profile = NULL;
int x = 0;
char *sql = NULL;
search_params_t s_param;
@@ -866,7 +873,7 @@ SWITCH_STANDARD_APP(directory_function)
s_param.search_by_last_name = 0;
}
attempts = profile->max_menu_attempt;
s_param.try_again = 1;
s_param.try_again = 1;
while (switch_channel_ready(channel) && (s_param.try_again && attempts-- > 0)) {
s_param.try_again = 0;
gather_name_digit(session, profile, &s_param);
@@ -895,7 +902,7 @@ SWITCH_STANDARD_APP(directory_function)
sql = switch_mprintf("delete from directory_search where hostname = '%q' and uuid = '%q'", globals.hostname, switch_core_session_get_uuid(session));
directory_execute_sql(sql, profile->mutex);
switch_safe_free(sql);
profile_rwunlock(profile);
profile_rwunlock(profile);
}
SWITCH_MODULE_LOAD_FUNCTION(mod_directory_load)
@@ -954,7 +961,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_directory_shutdown)
switch_mutex_lock(globals.mutex);
while((hi = switch_hash_first(NULL, globals.profile_hash))) {
while ((hi = switch_hash_first(NULL, globals.profile_hash))) {
switch_hash_this(hi, &key, &keylen, &val);
profile = (dir_profile_t *) val;
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -64,7 +64,7 @@ struct dist_list {
static void destroy_node(struct dist_node *node)
{
struct dist_node *old;
while(node) {
while (node) {
old = node;
node = node->next;
if (old->name) {
@@ -78,7 +78,7 @@ static void destroy_list(struct dist_list *list)
{
struct dist_list *old;
while(list) {
while (list) {
old = list;
list = list->next;
destroy_node(old->nodes);
@@ -97,14 +97,14 @@ static struct {
static int load_config(int reloading)
static int load_config(int reloading)
{
struct dist_list *main_list=NULL, *new_list, *old_list=NULL, *lp=NULL;
struct dist_list *main_list = NULL, *new_list, *old_list = NULL, *lp = NULL;
switch_status_t status = SWITCH_STATUS_FALSE;
char *cf = "distributor.conf";
switch_xml_t cfg, xml, lists, list, param;
if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
return SWITCH_STATUS_TERM;
@@ -120,7 +120,7 @@ static int load_config(int reloading)
for (list = switch_xml_child(lists, "list"); list; list = list->next) {
const char *name = switch_xml_attr(list, "name");
const char *tweight = switch_xml_attr(list, "total-weight");
struct dist_node *node, *np=NULL;
struct dist_node *node, *np = NULL;
int target_weight = 10;
int accum = 0;
@@ -128,30 +128,30 @@ static int load_config(int reloading)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing NAME!\n");
continue;
}
if (!zstr(tweight)) {
target_weight = atoi(tweight);
}
switch_zmalloc(new_list, sizeof(*new_list));
new_list->name = strdup(name);
new_list->last = -1;
new_list->target_weight = target_weight;
if (lp) {
lp->next = new_list;
} else {
main_list = new_list;
}
lp = new_list;
for (param = switch_xml_child(list, "node"); param; param = param->next) {
char *name = (char *) switch_xml_attr_soft(param, "name");
char *weight_val = (char *) switch_xml_attr_soft(param, "weight");
int weight = 0, tmp;
if ((tmp = atoi(weight_val)) < 1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Weight %d value incorrect, must be > 0\n", tmp);
continue;
@@ -163,23 +163,25 @@ static int load_config(int reloading)
}
if (accum + tmp > lp->target_weight) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Target Weight %d already met, ignoring subsequent entries.\n", lp->target_weight);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Target Weight %d already met, ignoring subsequent entries.\n",
lp->target_weight);
continue;
}
accum += tmp;
weight = lp->target_weight - tmp;
if (weight < 0 || weight > lp->target_weight) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Weight %d value incorrect, must be between 1 and %d\n", weight, lp->target_weight);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Weight %d value incorrect, must be between 1 and %d\n", weight,
lp->target_weight);
continue;
}
switch_zmalloc(node, sizeof(*node));
node->name = strdup(name);
node->weight = node->cur_weight = weight;
if (np) {
np->next = node;
@@ -198,7 +200,7 @@ static int load_config(int reloading)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Total weight does not add up to total weight %d\n", lp->target_weight);
for(np1 = lp->nodes; np1; np1 = np1->next) {
for (np1 = lp->nodes; np1; np1 = np1->next) {
np1->weight += lp->target_weight - ea;
}
@@ -230,7 +232,7 @@ static int reset_list(struct dist_list *list)
{
struct dist_node *np;
for(np = list->nodes; np; np = np->next) {
for (np = list->nodes; np; np = np->next) {
np->cur_weight = np->weight;
}
list->last = -1;
@@ -243,8 +245,8 @@ static struct dist_node *find_next(struct dist_list *list)
struct dist_node *np, *match = NULL;
int x = 0, mx = 0;
int matches = 0, loops = 0;
for(;;) {
for (;;) {
if (++loops > 1000) {
break;
@@ -255,7 +257,7 @@ static struct dist_node *find_next(struct dist_list *list)
list->last = -1;
}
match = NULL;
for(np = list->nodes; np; np = np->next) {
for (np = list->nodes; np; np = np->next) {
if (np->cur_weight < list->target_weight) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s %d/%d\n", np->name, np->cur_weight, list->target_weight);
matches++;
@@ -274,7 +276,7 @@ static struct dist_node *find_next(struct dist_list *list)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Choose %s\n", match->name);
return match;
}
if (matches) {
list->last = -1;
} else {
@@ -294,7 +296,7 @@ static char *dist_engine(const char *name)
char *str = NULL;
switch_mutex_lock(globals.mod_lock);
for(lp = globals.list; lp; lp = lp->next) {
for (lp = globals.list; lp; lp = lp->next) {
if (!strcasecmp(name, lp->name)) {
np = find_next(lp);
break;
@@ -307,14 +309,14 @@ static char *dist_engine(const char *name)
switch_mutex_unlock(globals.mod_lock);
return str;
}
SWITCH_STANDARD_APP(distributor_exec)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
char *ret = NULL;
if (zstr(data)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "distributor requires an argument\n");
return;
@@ -370,11 +372,12 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_distributor_load)
globals.pool = pool;
load_config(SWITCH_FALSE);
SWITCH_ADD_API(api_interface, "distributor", "Distributor API", distributor_function, "<list name>");
SWITCH_ADD_API(api_interface, "distributor_ctl", "Distributor API", distributor_ctl_function, "[reload]");
SWITCH_ADD_APP(app_interface, "distributor", "Distributor APP", "Distributor APP", distributor_exec, "<list name>", SAF_SUPPORT_NOMEDIA|SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "distributor", "Distributor APP", "Distributor APP", distributor_exec, "<list name>",
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
/* indicate that the module should continue to be loaded */
+186 -163
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -89,7 +89,7 @@ SWITCH_STANDARD_DIALPLAN(inline_dialplan_hunt)
switch_caller_extension_add_application(session, extension, app, data);
}
caller_profile->destination_number = (char *)caller_profile->rdnis;
caller_profile->destination_number = (char *) caller_profile->rdnis;
caller_profile->rdnis = SWITCH_BLANK_STRING;
return extension;
@@ -177,7 +177,8 @@ SWITCH_STANDARD_APP(exe_function)
SWITCH_STANDARD_APP(mkdir_function)
{
switch_dir_make_recursive(data, SWITCH_DEFAULT_DIR_PERMS, switch_core_session_get_pool(session));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s MKDIR: %s\n", switch_channel_get_name(switch_core_session_get_channel(session)), data);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s MKDIR: %s\n",
switch_channel_get_name(switch_core_session_get_channel(session)), data);
}
#define SOFT_HOLD_SYNTAX "<unhold key> [<moh_a>] [<moh_b>]"
@@ -276,7 +277,7 @@ SWITCH_STANDARD_APP(dtmf_bind_function)
if (strchr(argv[2], '1')) {
bind_flags |= SBF_ONCE;
}
if (switch_ivr_bind_dtmf_meta_session(session, kval, bind_flags, argv[3]) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Bind Error!\n");
}
@@ -375,7 +376,7 @@ SWITCH_STANDARD_APP(eavesdrop_function)
if (e_data.total) {
for (x = 0; x < e_data.total && switch_channel_ready(channel); x++) {
/* If we have a group and 1000 concurrent calls, we will flood the logs. This check avoids this */
if ( !require_group )
if (!require_group)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Spy: %s\n", e_data.uuid_list[x]);
if ((file = switch_channel_get_variable(channel, "eavesdrop_indicate_new"))) {
switch_ivr_play_file(session, NULL, file, NULL);
@@ -437,9 +438,9 @@ SWITCH_STANDARD_APP(set_audio_level_function)
mydata = switch_core_session_strdup(session, data);
argc = switch_split(mydata, ' ', argv);
if (argc != 2) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Error. USAGE: %s\n",
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Error. USAGE: %s\n",
switch_core_session_get_name(session), SET_AUDIO_LEVEL_SYNTAX);
return;
}
@@ -447,8 +448,8 @@ SWITCH_STANDARD_APP(set_audio_level_function)
level = atoi(argv[1]);
switch_ivr_session_audio(session, "level", argv[0], level);
}
#define SET_MUTE_SYNTAX "[read|write] [[true|cn level]|false]"
@@ -461,19 +462,19 @@ SWITCH_STANDARD_APP(set_mute_function)
mydata = switch_core_session_strdup(session, data);
argc = switch_split(mydata, ' ', argv);
if (argc != 2) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Error. USAGE: %s\n",
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Error. USAGE: %s\n",
switch_core_session_get_name(session), SET_MUTE_SYNTAX);
return;
}
if ((level = atoi(argv[1])) <= 0) {
level = switch_true(argv[1]);
}
switch_ivr_session_audio(session, "mute", argv[0], level);
}
@@ -731,7 +732,7 @@ SWITCH_STANDARD_APP(presence_function)
return;
}
switch_channel_presence(channel, argv[0], argv[1], argv[2]);
switch_channel_presence(channel, argv[0], argv[1], argv[2]);
}
SWITCH_STANDARD_APP(pre_answer_function)
@@ -787,7 +788,7 @@ SWITCH_STANDARD_APP(deflect_function)
SWITCH_STANDARD_APP(set_function)
{
char *var, *val = NULL;
if (zstr(data)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n");
} else {
@@ -808,7 +809,8 @@ SWITCH_STANDARD_APP(set_function)
expanded = switch_channel_expand_variables(channel, val);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SET [%s]=[%s]\n", switch_channel_get_name(channel), var, expanded ? expanded : "UNDEF");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SET [%s]=[%s]\n", switch_channel_get_name(channel), var,
expanded ? expanded : "UNDEF");
switch_channel_set_variable_var_check(channel, var, expanded, SWITCH_FALSE);
if (expanded && expanded != val) {
@@ -857,7 +859,7 @@ SWITCH_STANDARD_APP(set_profile_var_function)
val = NULL;
}
}
switch_channel_set_profile_var(switch_core_session_get_channel(session), name, val);
}
}
@@ -891,8 +893,8 @@ SWITCH_STANDARD_APP(export_function)
}
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "EXPORT %s[%s]=[%s]\n", local ? "" : "(REMOTE ONLY) ", var_name ? var_name : "",
val ? val : "UNDEF");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "EXPORT %s[%s]=[%s]\n", local ? "" : "(REMOTE ONLY) ",
var_name ? var_name : "", val ? val : "UNDEF");
switch_channel_set_variable(channel, var, val);
if (var && val) {
@@ -999,11 +1001,11 @@ SWITCH_STANDARD_APP(event_function)
while (*p == ' ')
*p++ = '\0';
val = p;
if (!strcasecmp(var,"Event-Name")) {
if (!strcasecmp(var, "Event-Name")) {
switch_name_event(val, &event->event_id);
switch_event_del_header(event, var);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, var, val);
} else if (!strcasecmp(var,"Event-Subclass")) {
} else if (!strcasecmp(var, "Event-Subclass")) {
size_t len = strlen(val) + 1;
void *new = malloc(len);
switch_assert(new);
@@ -1043,7 +1045,8 @@ SWITCH_STANDARD_APP(privacy_function)
switch_clear_flag(caller_profile, SWITCH_CPF_HIDE_NAME);
switch_clear_flag(caller_profile, SWITCH_CPF_HIDE_NUMBER);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "INVALID privacy mode specified. Use a valid mode [no|yes|name|full|number].\n");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
"INVALID privacy mode specified. Use a valid mode [no|yes|name|full|number].\n");
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set Privacy to %s [%d]\n", data, caller_profile->flags);
}
@@ -1112,7 +1115,7 @@ SWITCH_STANDARD_API(strftime_api_function)
SWITCH_STANDARD_API(presence_api_function)
{
switch_event_t *event;
char *lbuf = NULL , *argv[4];
char *lbuf = NULL, *argv[4];
int argc = 0;
switch_event_types_t type = SWITCH_EVENT_PRESENCE_IN;
int need = 4;
@@ -1158,7 +1161,7 @@ SWITCH_STANDARD_API(presence_api_function)
switch_safe_free(lbuf);
return SWITCH_STATUS_SUCCESS;
error:
error:
switch_safe_free(lbuf);
stream->write_function(stream, "Invalid: presence %s", PRESENCE_USAGE);
@@ -1173,8 +1176,7 @@ SWITCH_STANDARD_API(chat_api_function)
if (!zstr(cmd) && (lbuf = strdup(cmd))
&& (argc = switch_separate_string(lbuf, '|', argv, (sizeof(argv) / sizeof(argv[0])))) >= 4) {
if (switch_core_chat_send(argv[0], "dp", argv[1], argv[2], "", argv[3],
!zstr(argv[4]) ? argv[4] : NULL , "") == SWITCH_STATUS_SUCCESS) {
if (switch_core_chat_send(argv[0], "dp", argv[1], argv[2], "", argv[3], !zstr(argv[4]) ? argv[4] : NULL, "") == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "Sent");
} else {
stream->write_function(stream, "Error! Message Not Sent");
@@ -1206,7 +1208,7 @@ SWITCH_STANDARD_APP(ivr_application_function)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_event_t *params;
const char *name = (const char*)data;
const char *name = (const char *) data;
if (channel) {
switch_xml_t cxml = NULL, cfg = NULL, xml_menus = NULL, xml_menu = NULL;
@@ -1234,7 +1236,7 @@ SWITCH_STANDARD_APP(ivr_application_function)
&& switch_ivr_menu_stack_xml_build(xml_ctx, &menu_stack, xml_menus, xml_menu) == SWITCH_STATUS_SUCCESS) {
switch_xml_free(cxml);
cxml = NULL;
switch_ivr_menu_execute(session, menu_stack, (char*)name, NULL);
switch_ivr_menu_execute(session, menu_stack, (char *) name, NULL);
switch_ivr_menu_stack_free(menu_stack);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unable to create menu\n");
@@ -1404,7 +1406,7 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit
for (p = terminators; p && *p; p++) {
if (*p == dtmf->digit) {
switch_snprintf(sbuf, sizeof(sbuf), "%c", *p);
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, sbuf );
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, sbuf);
return SWITCH_STATUS_BREAK;
}
}
@@ -1432,7 +1434,7 @@ SWITCH_STANDARD_APP(sleep_function)
args.input_callback = on_dtmf;
args.buf = buf;
args.buflen = sizeof(buf);
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "" );
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
}
switch_ivr_sleep(session, ms, SWITCH_TRUE, &args);
@@ -1503,7 +1505,7 @@ SWITCH_STANDARD_APP(speak_function)
args.buf = buf;
args.buflen = sizeof(buf);
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "" );
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
switch_ivr_speak_text(session, engine, voice, text, &args);
}
@@ -1582,7 +1584,8 @@ static switch_status_t hanguphook(switch_core_session_t *session)
switch_stream_handle_t stream = { 0 };
SWITCH_STANDARD_STREAM(stream);
switch_api_execute("uuid_bridge", id, NULL, &stream);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "\nHangup Command uuid_bridge(%s):\n%s\n", id, switch_str_nil((char *) stream.data));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "\nHangup Command uuid_bridge(%s):\n%s\n", id,
switch_str_nil((char *) stream.data));
switch_safe_free(stream.data);
}
@@ -1607,7 +1610,7 @@ SWITCH_STANDARD_APP(att_xfer_function)
switch_channel_set_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, bond);
if (switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL)
if (switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL)
!= SWITCH_STATUS_SUCCESS || !peer_session) {
goto end;
}
@@ -1640,13 +1643,13 @@ SWITCH_STANDARD_APP(att_xfer_function)
switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
switch_snprintf(buf, sizeof(buf), "%s %s", switch_core_session_get_uuid(peer_session), switch_core_session_get_uuid(session));
switch_channel_set_variable(b_channel, "xfer_uuids", buf);
switch_snprintf(buf, sizeof(buf), "%s %s", switch_core_session_get_uuid(peer_session), bond);
switch_channel_set_variable(channel, "xfer_uuids", buf);
switch_core_event_hook_add_state_change(session, hanguphook);
switch_core_event_hook_add_state_change(b_session, hanguphook);
switch_core_session_rwunlock(b_session);
}
}
@@ -1654,7 +1657,7 @@ SWITCH_STANDARD_APP(att_xfer_function)
if (!br) {
switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), bond);
}
}
switch_core_session_rwunlock(peer_session);
@@ -1813,11 +1816,11 @@ SWITCH_STANDARD_APP(say_function)
if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
&& (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) == 4) {
args.input_callback = on_dtmf;
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "" );
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
switch_ivr_say(session, argv[3], argv[0], argv[1], argv[2], &args);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", SAY_SYNTAX);
@@ -1841,14 +1844,15 @@ SWITCH_STANDARD_APP(phrase_function)
if ((mdata = strchr(macro, ','))) {
*mdata++ = '\0';
}
lang = switch_channel_get_variable(channel, "language");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Execute %s(%s) lang %s\n", macro, switch_str_nil(mdata), switch_str_nil(lang));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Execute %s(%s) lang %s\n", macro, switch_str_nil(mdata),
switch_str_nil(lang));
args.input_callback = on_dtmf;
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "" );
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
status = switch_ivr_phrase_macro(session, macro, mdata, lang, &args);
} else {
@@ -1878,10 +1882,10 @@ SWITCH_STANDARD_APP(playback_function)
switch_file_handle_t fh = { 0 };
char *p;
const char *file = NULL;
if (data) {
file = switch_core_session_strdup(session, data);
if ((p = strchr(file, '@')) && *(p+1) == '@') {
if ((p = strchr(file, '@')) && *(p + 1) == '@') {
*p = '\0';
p += 2;
if (p && *p) {
@@ -1894,7 +1898,7 @@ SWITCH_STANDARD_APP(playback_function)
args.input_callback = on_dtmf;
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "" );
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
status = switch_ivr_play_file(session, &fh, file, &args);
@@ -1920,8 +1924,8 @@ SWITCH_STANDARD_APP(endless_playback_function)
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_status_t status = SWITCH_STATUS_SUCCESS;
const char *file = data;
while(switch_channel_ready(channel)) {
while (switch_channel_ready(channel)) {
status = switch_ivr_play_file(session, NULL, file, NULL);
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
@@ -1968,7 +1972,7 @@ SWITCH_STANDARD_APP(gentones_function)
args.input_callback = on_dtmf;
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "" );
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
switch_ivr_gentones(session, tone_script, loops, &args);
}
@@ -2060,7 +2064,7 @@ SWITCH_STANDARD_APP(record_function)
args.input_callback = on_dtmf;
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "" );
switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, "");
status = switch_ivr_record_file(session, &fh, path, &args, limit);
@@ -2071,7 +2075,7 @@ SWITCH_STANDARD_APP(record_function)
SWITCH_STANDARD_APP(preprocess_session_function)
{
switch_ivr_preprocess_session(session, (char *)data);
switch_ivr_preprocess_session(session, (char *) data);
}
SWITCH_STANDARD_APP(record_session_function)
@@ -2089,7 +2093,7 @@ SWITCH_STANDARD_APP(record_session_function)
/* Search for a space then a plus followed by only numbers at the end of the path,
if found trim any spaces to the left/right of the plus use the left side as the
path and right side as a time limit on the recording
*/
*/
/* if we find a + and the character before it is a space */
if ((path_end = strrchr(path, '+')) && path_end > path && *(path_end - 1) == ' ') {
@@ -2102,7 +2106,7 @@ SWITCH_STANDARD_APP(record_session_function)
path_end--;
/* trim spaces to the left of the plus */
while(path_end > path && *path_end == ' ') {
while (path_end > path && *path_end == ' ') {
path_end--;
}
@@ -2165,15 +2169,15 @@ static void *SWITCH_THREAD_FUNC camp_music_thread(switch_thread_t *thread, void
args.input_callback = camp_fire;
args.buf = dbuf;
args.buflen = sizeof(dbuf);
switch_core_session_read_lock(session);
/* don't set this to a local_stream:// or you will not be happy */
if ((greet = switch_channel_get_variable(channel, "campon_announce_sound"))) {
status = switch_ivr_play_file(session, NULL, greet, &args);
}
while(stake->running && switch_channel_ready(channel)) {
while (stake->running && switch_channel_ready(channel)) {
if (status != SWITCH_STATUS_BREAK) {
if (!strcasecmp(moh, "silence")) {
status = switch_ivr_collect_digits_callback(session, &args, 0, 0);
@@ -2207,7 +2211,7 @@ SWITCH_STANDARD_APP(audio_bridge_function)
switch_threadattr_t *thd_attr = NULL;
char *camp_data = NULL;
switch_status_t status;
if (zstr(data)) {
return;
}
@@ -2218,7 +2222,7 @@ SWITCH_STANDARD_APP(audio_bridge_function)
if ((v_campon = switch_channel_get_variable(caller_channel, "campon")) && switch_true(v_campon)) {
const char *cid_name = NULL;
const char *cid_number = NULL;
if (!(cid_name = switch_channel_get_variable(caller_channel, "effective_caller_id_name"))) {
cid_name = switch_channel_get_variable(caller_channel, "caller_id_name");
}
@@ -2239,7 +2243,7 @@ SWITCH_STANDARD_APP(audio_bridge_function)
v_campon_timeout = switch_channel_get_variable(caller_channel, "campon_timeout");
v_campon_sleep = switch_channel_get_variable(caller_channel, "campon_sleep");
v_campon_fallback_exten = switch_channel_get_variable(caller_channel, "campon_fallback_exten");
if (v_campon_retries) {
if ((tmp = atoi(v_campon_retries)) > 0) {
campon_retries = tmp;
@@ -2262,10 +2266,10 @@ SWITCH_STANDARD_APP(audio_bridge_function)
camping = 1;
if (cid_name && cid_number) {
camp_data = switch_core_session_sprintf(session, "{origination_caller_id_name='%s',origination_caller_id_number='%s'}%s",
camp_data = switch_core_session_sprintf(session, "{origination_caller_id_name='%s',origination_caller_id_number='%s'}%s",
cid_name, cid_number, data);
} else {
camp_data = (char *)data;
camp_data = (char *) data;
}
if (!(moh = switch_channel_get_variable(caller_channel, "hold_music"))) {
@@ -2275,22 +2279,22 @@ SWITCH_STANDARD_APP(audio_bridge_function)
do {
fail = 0;
status = switch_ivr_originate(NULL, &peer_session, &cause, camp_data, campon_timeout, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL);
if (!switch_channel_ready(caller_channel)) {
fail = 1;
break;
}
if (status == SWITCH_STATUS_SUCCESS) {
camping = 0;
break;
} else {
fail = 1;
}
if (camping) {
if (!thread_started && fail && moh && !switch_channel_test_flag(caller_channel, CF_PROXY_MODE) &&
if (!thread_started && fail && moh && !switch_channel_test_flag(caller_channel, CF_PROXY_MODE) &&
!switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA) &&
!switch_true(switch_channel_get_variable(caller_channel, "bypass_media"))) {
switch_threadattr_create(&thd_attr, switch_core_session_get_pool(session));
@@ -2311,15 +2315,15 @@ SWITCH_STANDARD_APP(audio_bridge_function)
if (fail) {
int64_t wait = campon_sleep * 1000000;
while(stake.running && wait > 0 && switch_channel_ready(caller_channel)) {
while (stake.running && wait > 0 && switch_channel_ready(caller_channel)) {
switch_yield(100000);
wait -= 100000;
}
}
}
} while (camping && switch_channel_ready(caller_channel));
if (thread) {
stake.running = 0;
switch_channel_set_flag(caller_channel, CF_NOT_READY);
@@ -2327,17 +2331,18 @@ SWITCH_STANDARD_APP(audio_bridge_function)
}
switch_channel_clear_flag(caller_channel, CF_NOT_READY);
if (stake.do_xfer && !zstr(v_campon_fallback_exten)) {
switch_ivr_session_transfer(session,
v_campon_fallback_exten,
switch_ivr_session_transfer(session,
v_campon_fallback_exten,
switch_channel_get_variable(caller_channel, "campon_fallback_dialplan"),
switch_channel_get_variable(caller_channel, "campon_fallback_context"));
return;
}
} else {
if ((status = switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL)) != SWITCH_STATUS_SUCCESS) {
if ((status =
switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL)) != SWITCH_STATUS_SUCCESS) {
fail = 1;
}
}
@@ -2350,23 +2355,23 @@ SWITCH_STANDARD_APP(audio_bridge_function)
'true' to continue on all failures.
'false' to not continue.
A list of codes either names or numbers eg "user_busy,normal_temporary_failure,603"
failure_causes acts as the opposite version
failure_causes acts as the opposite version
EXCEPTION... ATTENDED_TRANSFER never is a reason to continue.......
*/
if (cause != SWITCH_CAUSE_ATTENDED_TRANSFER) {
if (continue_on_fail || failure_causes) {
const char *cause_str;
char cause_num[35] = "";
cause_str = switch_channel_cause2str(cause);
switch_snprintf(cause_num, sizeof(cause_num), "%u", cause);
if (failure_causes) {
char *lbuf = switch_core_session_strdup(session, failure_causes);
char *argv[256] = { 0 };
int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0])));
int i, x = 0;
for (i = 0; i < argc; i++) {
if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) {
x++;
@@ -2374,7 +2379,7 @@ SWITCH_STANDARD_APP(audio_bridge_function)
}
}
if (!x) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"Failure causes [%s]: Cause: %s\n", failure_causes, cause_str);
return;
}
@@ -2388,10 +2393,10 @@ SWITCH_STANDARD_APP(audio_bridge_function)
char *argv[256] = { 0 };
int argc = switch_separate_string(lbuf, ',', argv, (sizeof(argv) / sizeof(argv[0])));
int i;
for (i = 0; i < argc; i++) {
if (!strcasecmp(argv[i], cause_str) || !strcasecmp(argv[i], cause_num)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"Continue on fail [%s]: Cause: %s\n", continue_on_fail, cause_str);
return;
}
@@ -2410,7 +2415,7 @@ SWITCH_STANDARD_APP(audio_bridge_function)
}
return;
} else {
if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE)) {
switch_ivr_signal_bridge(session, peer_session);
} else {
@@ -2439,10 +2444,10 @@ SWITCH_STANDARD_APP(audio_bridge_function)
if (switch_true(switch_channel_get_variable(caller_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE))) {
switch_channel_set_flag(caller_channel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
}
switch_ivr_multi_threaded_bridge(session, peer_session, func, a_key, b_key);
}
if (peer_session) {
switch_core_session_rwunlock(peer_session);
}
@@ -2452,17 +2457,19 @@ SWITCH_STANDARD_APP(audio_bridge_function)
/* fake chan_error */
switch_endpoint_interface_t *error_endpoint_interface;
static switch_call_cause_t error_outgoing_channel(switch_core_session_t *session,
switch_event_t *var_event,
switch_caller_profile_t *outbound_profile,
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause);
switch_event_t *var_event,
switch_caller_profile_t *outbound_profile,
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
switch_call_cause_t *cancel_cause);
switch_io_routines_t error_io_routines = {
/*.outgoing_channel */ error_outgoing_channel
};
static switch_call_cause_t error_outgoing_channel(switch_core_session_t *session,
switch_event_t *var_event,
switch_caller_profile_t *outbound_profile,
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
switch_event_t *var_event,
switch_caller_profile_t *outbound_profile,
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
switch_call_cause_t *cancel_cause)
{
switch_call_cause_t cause = switch_channel_str2cause(outbound_profile->destination_number);
if (cause == SWITCH_CAUSE_NONE) {
@@ -2476,17 +2483,19 @@ static switch_call_cause_t error_outgoing_channel(switch_core_session_t *session
/* fake chan_group */
switch_endpoint_interface_t *group_endpoint_interface;
static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session,
switch_event_t *var_event,
switch_caller_profile_t *outbound_profile,
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause);
switch_event_t *var_event,
switch_caller_profile_t *outbound_profile,
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
switch_call_cause_t *cancel_cause);
switch_io_routines_t group_io_routines = {
/*.outgoing_channel */ group_outgoing_channel
};
static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session,
switch_event_t *var_event,
switch_caller_profile_t *outbound_profile,
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
switch_event_t *var_event,
switch_caller_profile_t *outbound_profile,
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
switch_call_cause_t *cancel_cause)
{
char *group = NULL;
switch_call_cause_t cause = SWITCH_CAUSE_NONE;
@@ -2501,33 +2510,32 @@ static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session
group = strdup(outbound_profile->destination_number);
if (!group) goto done;
if (!group)
goto done;
if ((domain = strchr(group, '@'))) {
*domain++ = '\0';
} else {
domain = switch_core_get_variable("domain");
}
if (!domain) {
goto done;
}
if (var_event && (skip=switch_event_get_header(var_event, "group_recurse_variables")) && switch_false(skip)) {
if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) ||
(var = switch_event_get_header(var_event, "leg_timeout"))) {
if (var_event && (skip = switch_event_get_header(var_event, "group_recurse_variables")) && switch_false(skip)) {
if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) || (var = switch_event_get_header(var_event, "leg_timeout"))) {
timelimit = atoi(var);
}
var_event = NULL;
}
template = switch_mprintf("${group_call(%s@%s)}", group, domain);
if (session) {
switch_channel_t *channel = switch_core_session_get_channel(session);
dest = switch_channel_expand_variables(channel, template);
if ((var = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE)) ||
(var = switch_event_get_header(var_event, "leg_timeout"))) {
if ((var = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE)) || (var = switch_event_get_header(var_event, "leg_timeout"))) {
timelimit = atoi(var);
}
} else if (var_event) {
@@ -2542,28 +2550,27 @@ static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session
if (!dest) {
goto done;
}
if (var_event) {
cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name");
cid_num_override = switch_event_get_header(var_event, "origination_caller_id_number");
if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) ||
(var = switch_event_get_header(var_event, "leg_timeout"))) {
if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) || (var = switch_event_get_header(var_event, "leg_timeout"))) {
timelimit = atoi(var);
}
}
if ((flags & SOF_FORKED_DIAL)) {
myflags |= SOF_NOBLOCK;
}
if (switch_ivr_originate(session, new_session, &cause, dest, timelimit, NULL,
if (switch_ivr_originate(session, new_session, &cause, dest, timelimit, NULL,
cid_name_override, cid_num_override, NULL, var_event, myflags, cancel_cause) == SWITCH_STATUS_SUCCESS) {
const char *context;
switch_caller_profile_t *cp;
new_channel = switch_core_session_get_channel(*new_session);
if ((context = switch_channel_get_variable(new_channel, "group_context"))) {
if ((cp = switch_channel_get_caller_profile(new_channel))) {
cp->context = switch_core_strdup(cp->pool, context);
@@ -2578,9 +2585,9 @@ static switch_call_cause_t group_outgoing_channel(switch_core_session_t *session
if (dest && dest != template) {
switch_safe_free(dest);
}
switch_safe_free(template);
switch_safe_free(group);
switch_safe_free(template);
switch_safe_free(group);
if (cause == SWITCH_CAUSE_NONE) {
cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
@@ -2596,7 +2603,8 @@ switch_endpoint_interface_t *user_endpoint_interface;
static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
switch_event_t *var_event,
switch_caller_profile_t *outbound_profile,
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause);
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
switch_call_cause_t *cancel_cause);
switch_io_routines_t user_io_routines = {
/*.outgoing_channel */ user_outgoing_channel
};
@@ -2604,7 +2612,8 @@ switch_io_routines_t user_io_routines = {
static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
switch_event_t *var_event,
switch_caller_profile_t *outbound_profile,
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
switch_call_cause_t *cancel_cause)
{
switch_xml_t x_domain = NULL, xml = NULL, x_user = NULL, x_group = NULL, x_param, x_params;
char *user = NULL, *domain = NULL;
@@ -2622,22 +2631,22 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
user = strdup(outbound_profile->destination_number);
if (!user) goto done;
if (!user)
goto done;
if ((domain = strchr(user, '@'))) {
*domain++ = '\0';
} else {
domain = switch_core_get_variable("domain");
}
if (!domain) {
goto done;
}
if (var_event && (skip=switch_event_get_header(var_event, "user_recurse_variables")) && switch_false(skip)) {
if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) ||
(var = switch_event_get_header(var_event, "leg_timeout"))) {
if (var_event && (skip = switch_event_get_header(var_event, "user_recurse_variables")) && switch_false(skip)) {
if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) || (var = switch_event_get_header(var_event, "leg_timeout"))) {
timelimit = atoi(var);
}
var_event = NULL;
@@ -2744,7 +2753,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
switch_event_dup(&event, var_event);
switch_event_del_header(event, "dialed_user");
switch_event_del_header(event, "dialed_domain");
if ((varval = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) ||
if ((varval = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) ||
(varval = switch_event_get_header(var_event, "leg_timeout"))) {
timelimit = atoi(varval);
}
@@ -2765,10 +2774,12 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
switch_snprintf(stupid, sizeof(stupid), "user/%s", user);
if (switch_stristr(stupid, d_dest)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Waddya Daft? You almost called '%s' in an infinate loop!\n", stupid);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Waddya Daft? You almost called '%s' in an infinate loop!\n",
stupid);
cause = SWITCH_CAUSE_INVALID_IE_CONTENTS;
} else if (switch_ivr_originate(session, new_session, &cause, d_dest, timelimit, NULL,
cid_name_override, cid_num_override, outbound_profile, var_event, myflags, cancel_cause) == SWITCH_STATUS_SUCCESS) {
} else if (switch_ivr_originate(session, new_session, &cause, d_dest, timelimit, NULL,
cid_name_override, cid_num_override, outbound_profile, var_event, myflags,
cancel_cause) == SWITCH_STATUS_SUCCESS) {
const char *context;
switch_caller_profile_t *cp;
@@ -2812,7 +2823,7 @@ static switch_call_cause_t user_outgoing_channel(switch_core_session_t *session,
if (params) {
switch_event_destroy(&params);
}
if (var_event && var_event_orig != var_event) {
switch_event_destroy(&var_event);
}
@@ -2851,7 +2862,7 @@ SWITCH_STANDARD_APP(wait_for_silence_function)
uint32_t thresh, silence_hits, listen_hits, timeout_ms = 0;
int argc;
char *lbuf = NULL;
if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))
&& (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 3) {
thresh = atoi(argv[0]);
@@ -2869,8 +2880,8 @@ SWITCH_STANDARD_APP(wait_for_silence_function)
return;
}
}
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", WAIT_FOR_SILENCE_SYNTAX);
}
@@ -2880,12 +2891,17 @@ static switch_status_t event_chat_send(const char *proto, const char *from, cons
switch_event_t *event;
if (switch_event_create(&event, SWITCH_EVENT_RECV_MESSAGE) == SWITCH_STATUS_SUCCESS) {
if (proto) switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Proto", proto);
if (from) switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "From", from);
if (subject) switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Subject", subject);
if (hint) switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hint", hint);
if (body) switch_event_add_body(event, "%s", body);
if (to) {
if (proto)
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Proto", proto);
if (from)
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "From", from);
if (subject)
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Subject", subject);
if (hint)
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hint", hint);
if (body)
switch_event_add_body(event, "%s", body);
if (to) {
const char *v;
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "To", to);
if ((v = switch_core_get_variable(to))) {
@@ -2899,18 +2915,18 @@ static switch_status_t event_chat_send(const char *proto, const char *from, cons
switch_event_destroy(&event);
}
return SWITCH_STATUS_MEMERR;
}
static switch_status_t api_chat_send(const char *proto, const char *from, const char *to, const char *subject,
const char *body, const char *type, const char *hint)
{
if (to) {
if (to) {
const char *v;
switch_stream_handle_t stream = { 0 };
char *cmd = NULL, *arg;
if (!(v = switch_core_get_variable(to))) {
v = to;
}
@@ -2928,16 +2944,15 @@ static switch_status_t api_chat_send(const char *proto, const char *from, const
switch_api_execute(cmd, arg, NULL, &stream);
if (proto) {
switch_core_chat_send(proto, "api", to, hint && strchr(hint, '/') ? hint : from,
!zstr(type) ? type : NULL, (char *) stream.data, NULL, NULL);
switch_core_chat_send(proto, "api", to, hint && strchr(hint, '/') ? hint : from, !zstr(type) ? type : NULL, (char *) stream.data, NULL, NULL);
}
switch_safe_free(stream.data);
free(cmd);
}
return SWITCH_STATUS_SUCCESS;
}
@@ -2998,7 +3013,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_CHAT(chat_interface, "event", event_chat_send);
SWITCH_ADD_CHAT(chat_interface, "api", api_chat_send);
SWITCH_ADD_API(api_interface, "strepoch", "Convert a date string into epoch time", strepoch_api_function, "<string>");
SWITCH_ADD_API(api_interface, "chat", "chat", chat_api_function, "<proto>|<from>|<to>|<message>|[<content-type>]");
SWITCH_ADD_API(api_interface, "strftime", "strftime", strftime_api_function, "<format_string>");
@@ -3016,7 +3031,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "check_acl", "Check an ip against an ACL list", "Check an ip against an ACL list", check_acl_function,
"<ip> <acl | cidr> [<hangup_cause>]", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "verbose_events", "Make ALL Events verbose.", "Make ALL Events verbose.", verbose_events_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "verbose_events", "Make ALL Events verbose.", "Make ALL Events verbose.", verbose_events_function, "",
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "early_hangup", "Enable early hangup", "", early_hangup_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "sleep", "Pause a channel", SLEEP_LONG_DESC, sleep_function, "<pausemilliseconds>", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "delay_echo", "echo audio at a specified delay", "Delay n ms", delay_function, "<delay ms>", SAF_NONE);
@@ -3027,19 +3043,23 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_APP(app_interface, "answer", "Answer the call", "Answer the call for a channel.", answer_function, "", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "hangup", "Hangup the call", "Hangup the call for a channel.", hangup_function, "[<cause>]", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "set_name", "Name the channel", "Name the channel", set_name_function, "<name>", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "presence", "Send Presence", "Send Presence.", presence_function, "<rpid> <status> [<id>]", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "log", "Logs to the logger", LOG_LONG_DESC, log_function, "<log_level> <log_string>", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "presence", "Send Presence", "Send Presence.", presence_function, "<rpid> <status> [<id>]",
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "log", "Logs to the logger", LOG_LONG_DESC, log_function, "<log_level> <log_string>",
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "info", "Display Call Info", "Display Call Info", info_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "event", "Fire an event", "Fire an event", event_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "sound_test", "Analyze Audio", "Analyze Audio", sound_test_function, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "export", "Export a channel variable across a bridge", EXPORT_LONG_DESC, export_function, "<varname>=<value>",
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "set", "Set a channel variable", SET_LONG_DESC, set_function, "<varname>=<value>", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "set", "Set a channel variable", SET_LONG_DESC, set_function, "<varname>=<value>",
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "set_global", "Set a global variable", SET_GLOBAL_LONG_DESC, set_global_function, "<varname>=<value>",
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "set_profile_var", "Set a caller profile variable", SET_PROFILE_VAR_LONG_DESC, set_profile_var_function,
"<varname>=<value>", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "unset", "Unset a channel variable", UNSET_LONG_DESC, unset_function, "<varname>", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "unset", "Unset a channel variable", UNSET_LONG_DESC, unset_function, "<varname>",
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "ring_ready", "Indicate Ring_Ready", "Indicate Ring_Ready on a channel.", ring_ready_function, "", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "remove_bugs", "Remove media bugs", "Remove all media bugs from a channel.", remove_bugs_function, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "break", "Break", "Set the break flag.", break_function, "", SAF_SUPPORT_NOMEDIA);
@@ -3063,21 +3083,22 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_APP(app_interface, "sched_transfer", SCHED_TRANSF_DESCR, SCHED_TRANSF_DESCR, sched_transfer_function,
"[+]<time> <extension> <dialplan> <context>", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "execute_extension", "Execute an extension", "Execute an extension", exe_function, EXE_SYNTAX, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "sched_heartbeat", "Enable Scheduled Heartbeat", "Enable Scheduled Heartbeat",
SWITCH_ADD_APP(app_interface, "sched_heartbeat", "Enable Scheduled Heartbeat", "Enable Scheduled Heartbeat",
sched_heartbeat_function, SCHED_HEARTBEAT_SYNTAX, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "enable_heartbeat", "Enable Media Heartbeat", "Enable Media Heartbeat",
SWITCH_ADD_APP(app_interface, "enable_heartbeat", "Enable Media Heartbeat", "Enable Media Heartbeat",
heartbeat_function, HEARTBEAT_SYNTAX, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "mkdir", "Create a directory", "Create a directory", mkdir_function, MKDIR_SYNTAX, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "soft_hold", "Put a bridged channel on hold", "Put a bridged channel on hold", soft_hold_function, SOFT_HOLD_SYNTAX,
SAF_NONE);
SWITCH_ADD_APP(app_interface, "bind_meta_app", "Bind a key to an application", "Bind a key to an application", dtmf_bind_function, BIND_SYNTAX,
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "unbind_meta_app", "Unbind a key from an application", "Unbind a key from an application", dtmf_unbind_function,
SWITCH_ADD_APP(app_interface, "unbind_meta_app", "Unbind a key from an application", "Unbind a key from an application", dtmf_unbind_function,
UNBIND_SYNTAX, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "intercept", "intercept", "intercept", intercept_function, INTERCEPT_SYNTAX, SAF_NONE);
SWITCH_ADD_APP(app_interface, "eavesdrop", "eavesdrop on a uuid", "eavesdrop on a uuid", eavesdrop_function, eavesdrop_SYNTAX, SAF_MEDIA_TAP);
SWITCH_ADD_APP(app_interface, "three_way", "three way call with a uuid", "three way call with a uuid", three_way_function, threeway_SYNTAX, SAF_MEDIA_TAP);
SWITCH_ADD_APP(app_interface, "set_user", "Set a User", "Set a User", set_user_function, SET_USER_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC );
SWITCH_ADD_APP(app_interface, "three_way", "three way call with a uuid", "three way call with a uuid", three_way_function, threeway_SYNTAX,
SAF_MEDIA_TAP);
SWITCH_ADD_APP(app_interface, "set_user", "Set a User", "Set a User", set_user_function, SET_USER_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "stop_dtmf", "stop inband dtmf", "Stop detecting inband dtmf.", stop_dtmf_session_function, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "start_dtmf", "Detect dtmf", "Detect inband dtmf on the session", dtmf_session_function, "", SAF_MEDIA_TAP);
SWITCH_ADD_APP(app_interface, "stop_dtmf_generate", "stop inband dtmf generation", "Stop generating inband dtmf.",
@@ -3092,11 +3113,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_APP(app_interface, "park_state", "Park State", "Park State", park_state_function, "", SAF_NONE);
SWITCH_ADD_APP(app_interface, "gentones", "Generate Tones", "Generate tones to the channel", gentones_function, "<tgml_script>[|<loops>]", SAF_NONE);
SWITCH_ADD_APP(app_interface, "playback", "Playback File", "Playback a file to the channel", playback_function, "<path>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "endless_playback", "Playback File Endlessly", "Endlessly Playback a file to the channel",
SWITCH_ADD_APP(app_interface, "endless_playback", "Playback File Endlessly", "Endlessly Playback a file to the channel",
endless_playback_function, "<path>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "att_xfer", "Attended Transfer", "Attended Transfer", att_xfer_function, "<channel_url>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "read", "Read Digits", "Read Digits", read_function, "<min> <max> <file> <var_name> <timeout> <terminators>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "play_and_get_digits", "Play and get Digits", "Play and get Digits",
SWITCH_ADD_APP(app_interface, "play_and_get_digits", "Play and get Digits", "Play and get Digits",
play_and_get_digits_function, "<min> <max> <tries> <timeout> <terminators> <file> <invalid_file> <var_name> <regexp>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "stop_record_session", "Stop Record Session", STOP_SESS_REC_DESC, stop_record_session_function, "<path>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "record_session", "Record Session", SESS_REC_DESC, record_session_function, "<path> [+<timeout>]", SAF_MEDIA_TAP);
@@ -3116,8 +3137,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "say", "say", "say", say_function, SAY_SYNTAX, SAF_NONE);
SWITCH_ADD_APP(app_interface, "wait_for_silence", "wait_for_silence", "wait_for_silence", wait_for_silence_function, WAIT_FOR_SILENCE_SYNTAX, SAF_NONE);
SWITCH_ADD_APP(app_interface, "session_loglevel", "session_loglevel", "session_loglevel", session_loglevel_function, SESSION_LOGLEVEL_SYNTAX, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "wait_for_silence", "wait_for_silence", "wait_for_silence", wait_for_silence_function, WAIT_FOR_SILENCE_SYNTAX,
SAF_NONE);
SWITCH_ADD_APP(app_interface, "session_loglevel", "session_loglevel", "session_loglevel", session_loglevel_function, SESSION_LOGLEVEL_SYNTAX,
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_DIALPLAN(dp_interface, "inline", inline_dialplan_hunt);
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -38,22 +38,22 @@
#include <switch.h>
typedef struct easyroute_results{
char limit[16];
char dialstring[256];
char group[16];
char acctcode[17];
char translated[17];
typedef struct easyroute_results {
char limit[16];
char dialstring[256];
char group[16];
char acctcode[17];
char translated[17];
} easyroute_results_t;
typedef struct route_callback {
char gateway[129];
char group[129];
char techprofile[129];
char limit[129];
char acctcode[129];
char translated[17];
char gateway[129];
char group[129];
char techprofile[129];
char limit[129];
char acctcode[129];
char translated[17];
} route_callback_t;
static struct {
@@ -97,13 +97,13 @@ static switch_status_t load_config(void)
char *cf = "easyroute.conf";
switch_xml_t cfg, xml = NULL, param, settings;
switch_status_t status = SWITCH_STATUS_SUCCESS;
if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
status = SWITCH_STATUS_FALSE;
goto done;
}
if ((settings = switch_xml_child(cfg, "settings"))) {
for (param = switch_xml_child(settings, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
@@ -123,8 +123,8 @@ static switch_status_t load_config(void)
}
}
}
done:
done:
if (zstr(globals.db_username)) {
set_global_db_username("root");
}
@@ -151,7 +151,7 @@ static switch_status_t load_config(void)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Opened ODBC Database!\n");
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected ODBC DSN: %s\n", globals.db_dsn);
if (!globals.custom_query){
if (!globals.custom_query) {
if (switch_odbc_handle_exec(globals.master_odbc, "select count(*) from numbers", NULL, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot find SQL Database! (Where\'s the numbers table\?\?)\n");
}
@@ -163,7 +163,7 @@ static switch_status_t load_config(void)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open ODBC Connection (did you enable it?!)\n");
}
reallydone:
reallydone:
if (xml) {
switch_xml_free(xml);
@@ -177,76 +177,77 @@ static switch_status_t load_config(void)
return status;
}
static char SQL_LOOKUP[] = "SELECT gateways.gateway_ip, gateways.group, gateways.limit, gateways.techprofile, numbers.acctcode, numbers.translated from gateways, numbers where numbers.number = '%q' and numbers.gateway_id = gateways.gateway_id limit 1;";
static char SQL_LOOKUP[] =
"SELECT gateways.gateway_ip, gateways.group, gateways.limit, gateways.techprofile, numbers.acctcode, numbers.translated from gateways, numbers where numbers.number = '%q' and numbers.gateway_id = gateways.gateway_id limit 1;";
static switch_status_t route_lookup(char *dn, easyroute_results_t *results, int noat, char *separator)
{
{
switch_status_t sstatus = SWITCH_STATUS_SUCCESS;
char *sql = NULL;
route_callback_t pdata;
if (!switch_odbc_available()) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT,
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT,
"mod_easyroute requires core ODBC support. Please refer to the documentation on how to enable this\n");
return sstatus;
}
memset(&pdata, 0, sizeof(pdata));
if (!globals.custom_query){
if (!globals.custom_query) {
sql = switch_mprintf(SQL_LOOKUP, dn);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing static Query\n[%s]\n", sql);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing static Query\n[%s]\n", sql);
} else {
sql = switch_mprintf(globals.custom_query, dn);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing custom Query\n[%s]\n", sql);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing custom Query\n[%s]\n", sql);
}
if (globals.mutex){
if (globals.mutex) {
switch_mutex_lock(globals.mutex);
}
/* Do the Query */
if (switch_odbc_handle_callback_exec(globals.master_odbc, sql, route_callback, &pdata, NULL) == SWITCH_ODBC_SUCCESS){
if (switch_odbc_handle_callback_exec(globals.master_odbc, sql, route_callback, &pdata, NULL) == SWITCH_ODBC_SUCCESS) {
char tmp_profile[129];
char tmp_gateway[129];
if (zstr(pdata.limit)) {
switch_set_string(results->limit, "9999" );
switch_set_string(results->limit, "9999");
} else {
switch_set_string(results->limit, pdata.limit );
switch_set_string(results->limit, pdata.limit);
}
if (zstr(pdata.techprofile)){
if (zstr(pdata.techprofile)) {
switch_set_string(tmp_profile, globals.default_techprofile);
} else {
switch_set_string(tmp_profile, pdata.techprofile);
}
if (zstr(pdata.gateway)){
if (zstr(pdata.gateway)) {
switch_set_string(tmp_gateway, globals.default_gateway);
} else {
switch_set_string(tmp_gateway, pdata.gateway);
}
if (zstr(pdata.translated)){
if (zstr(pdata.translated)) {
switch_set_string(results->translated, dn);
} else {
switch_set_string(results->translated, pdata.translated);
}
if (noat) {
switch_snprintf(results->dialstring, 256, "%s/%s%s", tmp_profile , results->translated, tmp_gateway);
switch_snprintf(results->dialstring, 256, "%s/%s%s", tmp_profile, results->translated, tmp_gateway);
} else if (separator) {
switch_snprintf(results->dialstring, 256, "%s/%s%s%s", tmp_profile , results->translated, separator, tmp_gateway);
switch_snprintf(results->dialstring, 256, "%s/%s%s%s", tmp_profile, results->translated, separator, tmp_gateway);
} else {
switch_snprintf(results->dialstring, 256, "%s/%s@%s", tmp_profile , results->translated, tmp_gateway);
switch_snprintf(results->dialstring, 256, "%s/%s@%s", tmp_profile, results->translated, tmp_gateway);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "THE ROUTE [%s]\n", results->dialstring);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "THE ROUTE [%s]\n", results->dialstring);
if (zstr(pdata.group)){
if (zstr(pdata.group)) {
switch_set_string(results->group, "");
} else {
switch_set_string(results->group, pdata.group);
}
if (zstr(pdata.acctcode)){
if (zstr(pdata.acctcode)) {
switch_set_string(results->acctcode, "");
} else {
switch_set_string(results->acctcode, pdata.acctcode);
@@ -254,11 +255,11 @@ static switch_status_t route_lookup(char *dn, easyroute_results_t *results, int
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DB Error Setting Default Route!\n");
switch_set_string(results->limit, "9999");
if (noat){
if (noat) {
switch_snprintf(results->dialstring, 256, "%s/%s%s", globals.default_techprofile, dn, globals.default_gateway);
} else if (separator){
} else if (separator) {
switch_snprintf(results->dialstring, 256, "%s/%s%s%s", globals.default_techprofile, dn, separator, globals.default_gateway);
} else {
} else {
switch_snprintf(results->dialstring, 256, "%s/%s@%s", globals.default_techprofile, dn, globals.default_gateway);
}
switch_set_string(results->group, "");
@@ -267,7 +268,7 @@ static switch_status_t route_lookup(char *dn, easyroute_results_t *results, int
switch_safe_free(sql);
if (globals.mutex){
if (globals.mutex) {
switch_mutex_unlock(globals.mutex);
}
return sstatus;
@@ -278,7 +279,7 @@ SWITCH_STANDARD_APP(easyroute_app_function)
int argc = 0;
char *argv[4] = { 0 };
char *mydata = NULL;
char *destnum = NULL;
char *destnum = NULL;
int noat = 0;
char *separator = NULL;
@@ -289,18 +290,18 @@ SWITCH_STANDARD_APP(easyroute_app_function)
if (!channel) {
return;
}
if (!(mydata = switch_core_session_strdup(session, data))) {
return;
}
if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
destnum = argv[0];
if (argc == 2) {
if (!strcasecmp(argv[1], "noat")) {
noat = 1;
} else if (!strcasecmp(argv[1], "separator")) {
if (argc == 3){
if (argc == 3) {
switch_set_string(separator, argv[2]);
}
}
@@ -325,7 +326,7 @@ SWITCH_STANDARD_API(easyroute_function)
int noat = 0;
easyroute_results_t results;
switch_status_t status = SWITCH_STATUS_SUCCESS;
if (session) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "This function cannot be called from the dialplan.\n");
status = SWITCH_STATUS_FALSE;
@@ -337,39 +338,40 @@ SWITCH_STANDARD_API(easyroute_function)
status = SWITCH_STATUS_SUCCESS;
goto done;
}
if (!cmd || !(mydata = strdup(cmd))) {
stream->write_function(stream, "Usage: easyroute <number>\n");
status = SWITCH_STATUS_SUCCESS;
goto done;
}
if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
destnum = argv[0];
if (argc < 1 || argc > 3){
if (argc < 1 || argc > 3) {
stream->write_function(stream, "Invalid Input!\n");
status = SWITCH_STATUS_SUCCESS;
goto done;
}
}
if (argc == 2) {
if (!strcasecmp(argv[1], "noat")) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Entering noat.\n");
noat = 1;
} else if (!strcasecmp(argv[1], "separator")) {
if (argc == 3){
if (argc == 3) {
switch_set_string(separator, argv[2]);
}
}
}
if (!route_lookup(destnum, &results, noat, separator) == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "No Match!\n");
status = SWITCH_STATUS_SUCCESS;
goto done;
}
if (argc != 2){
if (argc != 2) {
stream->write_function(stream, "Number \tLimit \tGroup \tAcctCode \tDialstring\n");
stream->write_function(stream, "%-10s\t%-10s\t%-10s\t%-10s\t%s\n", destnum, results.limit, results.group, results.acctcode, results.dialstring);
stream->write_function(stream, "%-10s\t%-10s\t%-10s\t%-10s\t%s\n", destnum, results.limit, results.group, results.acctcode,
results.dialstring);
} else {
if (!strncasecmp(argv[1], "dialstring", 10)) {
stream->write_function(stream, "%s", results.dialstring);
@@ -386,12 +388,12 @@ SWITCH_STANDARD_API(easyroute_function)
status = SWITCH_STATUS_SUCCESS;
goto done;
}
}
}
} else {
stream->write_function(stream, "Invalid Input!\n");
}
done:
done:
switch_safe_free(mydata);
return status;
}
@@ -400,21 +402,22 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_easyroute_load)
{
switch_api_interface_t *api_interface;
switch_application_interface_t *app_interface;
memset(&globals, 0, sizeof(globals));
load_config();
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_API(api_interface, "easyroute", "EasyRoute", easyroute_function, "");
SWITCH_ADD_APP(app_interface, "easyroute", "Perform an easyroute lookup", "Perform an easyroute lookup", easyroute_app_function, "<number>", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "easyroute", "Perform an easyroute lookup", "Perform an easyroute lookup", easyroute_app_function, "<number>",
SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_easyroute_shutdown)
{
{
switch_odbc_handle_disconnect(globals.master_odbc);
switch_safe_free(globals.db_username);
switch_safe_free(globals.db_password);
+5 -5
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -251,7 +251,7 @@ static void add_result(enum_query_t *q, int order, int preference, char *service
}
}
static void free_results(enum_record_t **results)
static void free_results(enum_record_t ** results)
{
enum_record_t *fp, *rp;
@@ -447,7 +447,7 @@ static void dnscb(struct dns_ctx *ctx, void *result, void *data)
free(result);
}
static switch_status_t enum_lookup(char *root, char *in, enum_record_t **results)
static switch_status_t enum_lookup(char *root, char *in, enum_record_t ** results)
{
switch_status_t sstatus = SWITCH_STATUS_SUCCESS;
char *name = NULL;
@@ -829,7 +829,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_enum_load)
memset(&globals, 0, sizeof(globals));
do_load();
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_API(api_interface, "enum", "ENUM", enum_function, "");
@@ -850,7 +850,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_enum_shutdown)
if (globals.pool) {
switch_core_destroy_memory_pool(&globals.pool);
}
switch_safe_free(globals.root);
switch_safe_free(globals.isn_root);
+6 -7
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -78,10 +78,10 @@ SWITCH_STANDARD_APP(bcast_function)
switch_port_t mcast_control_port = 6061;
char *mcast_port_str = "34567";
const char *esf_broadcast_ip = NULL, *var;
switch_codec_implementation_t read_impl = {0};
switch_codec_implementation_t read_impl = { 0 };
int mcast_ttl = 1;
switch_core_session_get_read_impl(session, &read_impl);
switch_core_session_get_read_impl(session, &read_impl);
if (!zstr((char *) data)) {
mydata = switch_core_session_strdup(session, data);
@@ -105,7 +105,7 @@ SWITCH_STANDARD_APP(bcast_function)
if (!zstr(argv[2])) {
mcast_control_port = (switch_port_t) atoi(argv[2]);
}
if (!zstr(argv[3])) {
mcast_ttl = atoi(argv[3]);
if (mcast_ttl < 1 || mcast_ttl > 255) {
@@ -136,7 +136,7 @@ SWITCH_STANDARD_APP(bcast_function)
goto fail;
}
if (switch_mcast_hops(socket, (uint8_t)mcast_ttl) != SWITCH_STATUS_SUCCESS) {
if (switch_mcast_hops(socket, (uint8_t) mcast_ttl) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Mutlicast TTL set failed\n");
goto fail;
}
@@ -201,8 +201,7 @@ SWITCH_STANDARD_APP(bcast_function)
mcast_port,
read_impl.ianacode,
read_impl.samples_per_packet,
read_impl.microseconds_per_packet,
(switch_rtp_flag_t) flags, "soft", &err, switch_core_session_get_pool(session));
read_impl.microseconds_per_packet, (switch_rtp_flag_t) flags, "soft", &err, switch_core_session_get_pool(session));
if (!switch_rtp_ready(rtp_session)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "RTP Error\n");
+46 -49
View File
@@ -20,25 +20,24 @@ extern "C" {
#define BLINK 0
typedef enum
{
BLACK,
BLUE,
GREEN,
CYAN,
RED,
MAGENTA,
BROWN,
LIGHTGRAY,
DARKGRAY,
LIGHTBLUE,
LIGHTGREEN,
LIGHTCYAN,
LIGHTRED,
LIGHTMAGENTA,
YELLOW,
WHITE
} COLORS;
typedef enum {
BLACK,
BLUE,
GREEN,
CYAN,
RED,
MAGENTA,
BROWN,
LIGHTGRAY,
DARKGRAY,
LIGHTBLUE,
LIGHTGREEN,
LIGHTCYAN,
LIGHTRED,
LIGHTMAGENTA,
YELLOW,
WHITE
} COLORS;
#define cgets _cgets
@@ -49,17 +48,16 @@ typedef enum
/* blinkvideo */
void clreol (void);
void clrscr (void);
void clreol(void);
void clrscr(void);
int _conio_gettext (int left, int top, int right, int bottom,
char *str);
int _conio_gettext(int left, int top, int right, int bottom, char *str);
/* _conio_kbhit */
void delline (void);
void delline(void);
/* gettextinfo */
void gotoxy(int x, int y);
void gotoxy(int x, int y);
/*
highvideo
insline
@@ -69,9 +67,9 @@ movetext
normvideo
*/
void gotoxy(int x, int y);
void gotoxy(int x, int y);
void puttext (int left, int top, int right, int bottom, char *str);
void puttext(int left, int top, int right, int bottom, char *str);
// Screen Variables
@@ -89,19 +87,19 @@ ScreenUpdateLine
ScreenVisualBell
_set_screen_lines */
void _setcursortype (int type);
void _setcursortype(int type);
void textattr (int _attr);
void textattr(int _attr);
void textbackground (int color);
void textbackground(int color);
void textcolor (int color);
void textcolor(int color);
/* textmode */
int wherex (void);
int wherex(void);
int wherey (void);
int wherey(void);
/* window */
@@ -135,27 +133,26 @@ int wherey (void);
*
*/
char* _cgets (char*);
int _cprintf (const char*, ...);
int _cputs (const char*);
int _cscanf (char*, ...);
char *_cgets(char *);
int _cprintf(const char *, ...);
int _cputs(const char *);
int _cscanf(char *, ...);
int _getch (void);
int _getche (void);
int _kbhit (void);
int _putch (int);
int _ungetch (int);
int _getch(void);
int _getche(void);
int _kbhit(void);
int _putch(int);
int _ungetch(int);
int getch (void);
int getche (void);
int kbhit (void);
int putch (int);
int ungetch (int);
int getch(void);
int getche(void);
int kbhit(void);
int putch(int);
int ungetch(int);
#ifdef __cplusplus
}
#endif
#endif /* _CONIO_H_ */
#endif /* _CONIO_H_ */
+68 -73
View File
@@ -19,7 +19,7 @@ extern "C" {
/* Define type of data to use */
typedef double EXPRTYPE;
typedef double EXPRTYPE;
/* Defines for various things */
@@ -27,101 +27,96 @@ typedef double EXPRTYPE;
#define EXPR_MAXIDENTSIZE 255
/* Error values */
enum
{
EXPR_ERROR_UNKNOWN = -1, /* Unknown error */
EXPR_ERROR_NOERROR = 0, /* No Error */
EXPR_ERROR_MEMORY, /* Memory allocation failed */
EXPR_ERROR_NULLPOINTER, /* Null pointer passed to function */
EXPR_ERROR_NOTFOUND, /* Item not found in a list */
EXPR_ERROR_UNMATCHEDCOMMENT, /* Unmatched comment tags */
EXPR_ERROR_INVALIDCHAR, /* Invalid characters in expression */
EXPR_ERROR_ALREADYEXISTS, /* An item already called create */
EXPR_ERROR_ALREADYPARSEDBAD, /* Expression parsed already, but unsuccessfully. call free or clear */
EXPR_ERROR_ALREADYPARSEDGOOD, /* Expression parsed already, successfully, call free or clear */
EXPR_ERROR_EMPTYEXPR, /* Empty expression string passed to parse */
EXPR_ERROR_UNMATCHEDPAREN, /* Unmatched parenthesis */
EXPR_ERROR_SYNTAX, /* Syntax error in expression */
EXPR_ERROR_MISSINGSEMICOLON, /* Missing semicolon at end of expression */
EXPR_ERROR_BADIDENTIFIER, /* Identifier was to big or not formed right */
EXPR_ERROR_NOSUCHFUNCTION, /* Function does not exist in function list */
EXPR_ERROR_BADNUMBERARGUMENTS, /* Bad number of arguments in a function call */
EXPR_ERROR_BADEXPR, /* This is a bad expression to evaluate. It has not been parsed or has unsuccessfully */
EXPR_ERROR_UNABLETOASSIGN, /* Unable to do an assignment, maybe no variable list */
EXPR_ERROR_DIVBYZERO, /* Attempted a division by zero */
EXPR_ERROR_NOVARLIST, /* No variable list found but one is needed */
EXPR_ERROR_BREAK, /* Expression was broken by break function */
EXPR_ERROR_CONSTANTASSIGN, /* Assignment to a constant */
EXPR_ERROR_REFCONSTANT, /* Constant used as a reference parameter */
EXPR_ERROR_OUTOFRANGE, /* A bad value was passed to a function */
enum {
EXPR_ERROR_UNKNOWN = -1, /* Unknown error */
EXPR_ERROR_NOERROR = 0, /* No Error */
EXPR_ERROR_MEMORY, /* Memory allocation failed */
EXPR_ERROR_NULLPOINTER, /* Null pointer passed to function */
EXPR_ERROR_NOTFOUND, /* Item not found in a list */
EXPR_ERROR_UNMATCHEDCOMMENT, /* Unmatched comment tags */
EXPR_ERROR_INVALIDCHAR, /* Invalid characters in expression */
EXPR_ERROR_ALREADYEXISTS, /* An item already called create */
EXPR_ERROR_ALREADYPARSEDBAD, /* Expression parsed already, but unsuccessfully. call free or clear */
EXPR_ERROR_ALREADYPARSEDGOOD, /* Expression parsed already, successfully, call free or clear */
EXPR_ERROR_EMPTYEXPR, /* Empty expression string passed to parse */
EXPR_ERROR_UNMATCHEDPAREN, /* Unmatched parenthesis */
EXPR_ERROR_SYNTAX, /* Syntax error in expression */
EXPR_ERROR_MISSINGSEMICOLON, /* Missing semicolon at end of expression */
EXPR_ERROR_BADIDENTIFIER, /* Identifier was to big or not formed right */
EXPR_ERROR_NOSUCHFUNCTION, /* Function does not exist in function list */
EXPR_ERROR_BADNUMBERARGUMENTS, /* Bad number of arguments in a function call */
EXPR_ERROR_BADEXPR, /* This is a bad expression to evaluate. It has not been parsed or has unsuccessfully */
EXPR_ERROR_UNABLETOASSIGN, /* Unable to do an assignment, maybe no variable list */
EXPR_ERROR_DIVBYZERO, /* Attempted a division by zero */
EXPR_ERROR_NOVARLIST, /* No variable list found but one is needed */
EXPR_ERROR_BREAK, /* Expression was broken by break function */
EXPR_ERROR_CONSTANTASSIGN, /* Assignment to a constant */
EXPR_ERROR_REFCONSTANT, /* Constant used as a reference parameter */
EXPR_ERROR_OUTOFRANGE, /* A bad value was passed to a function */
EXPR_ERROR_USER /* Custom errors should be larger than this */
};
EXPR_ERROR_USER /* Custom errors should be larger than this */
};
/* Macros */
/* Forward declarations */
typedef struct _exprNode exprNode;
typedef struct _exprFuncList exprFuncList;
typedef struct _exprValList exprValList;
typedef struct _exprObj exprObj;
typedef struct _exprNode exprNode;
typedef struct _exprFuncList exprFuncList;
typedef struct _exprValList exprValList;
typedef struct _exprObj exprObj;
/* Function types */
typedef int (*exprFuncType)(exprObj *obj, exprNode *nodes, int nodecount, EXPRTYPE **refs, int refcount, EXPRTYPE *val);
typedef int (*exprBreakFuncType)(exprObj *obj);
typedef int (*exprFuncType) (exprObj * obj, exprNode * nodes, int nodecount, EXPRTYPE ** refs, int refcount, EXPRTYPE * val);
typedef int (*exprBreakFuncType) (exprObj * obj);
/* Functions */
/* Version information function */
void exprGetVersion(int *major, int *minor);
void exprGetVersion(int *major, int *minor);
/* Functions for function lists */
int exprFuncListCreate(exprFuncList **flist);
int exprFuncListAdd(exprFuncList *flist, char *name, exprFuncType ptr, int min, int max, int refmin, int refmax);
int exprFuncListFree(exprFuncList *flist);
int exprFuncListClear(exprFuncList *flist);
int exprFuncListInit(exprFuncList *flist);
int exprFuncListCreate(exprFuncList ** flist);
int exprFuncListAdd(exprFuncList * flist, char *name, exprFuncType ptr, int min, int max, int refmin, int refmax);
int exprFuncListFree(exprFuncList * flist);
int exprFuncListClear(exprFuncList * flist);
int exprFuncListInit(exprFuncList * flist);
/* Functions for value lists */
int exprValListCreate(exprValList **vlist);
int exprValListAdd(exprValList *vlist, char *name, EXPRTYPE val);
int exprValListSet(exprValList *vlist, char *name, EXPRTYPE val);
int exprValListGet(exprValList *vlist, char *name, EXPRTYPE *val);
int exprValListAddAddress(exprValList *vlist, char *name, EXPRTYPE *addr);
int exprValListGetAddress(exprValList *vlist, char *name, EXPRTYPE **addr);
void *exprValListGetNext(exprValList *vlist, char **name, EXPRTYPE *value, EXPRTYPE** addr, void *cookie);
int exprValListFree(exprValList *vlist);
int exprValListClear(exprValList *vlist);
int exprValListInit(exprValList *vlist);
int exprValListCreate(exprValList ** vlist);
int exprValListAdd(exprValList * vlist, char *name, EXPRTYPE val);
int exprValListSet(exprValList * vlist, char *name, EXPRTYPE val);
int exprValListGet(exprValList * vlist, char *name, EXPRTYPE * val);
int exprValListAddAddress(exprValList * vlist, char *name, EXPRTYPE * addr);
int exprValListGetAddress(exprValList * vlist, char *name, EXPRTYPE ** addr);
void *exprValListGetNext(exprValList * vlist, char **name, EXPRTYPE * value, EXPRTYPE ** addr, void *cookie);
int exprValListFree(exprValList * vlist);
int exprValListClear(exprValList * vlist);
int exprValListInit(exprValList * vlist);
/* Functions for expression objects */
int exprCreate(exprObj **obj, exprFuncList *flist, exprValList *vlist, exprValList *clist,
exprBreakFuncType breaker, void *userdata);
int exprFree(exprObj *obj);
int exprClear(exprObj *obj);
int exprParse(exprObj *obj, char *expr);
int exprEval(exprObj *obj, EXPRTYPE *val);
int exprEvalNode(exprObj *obj, exprNode *nodes, int curnode, EXPRTYPE *val);
exprFuncList *exprGetFuncList(exprObj *obj);
exprValList *exprGetVarList(exprObj *obj);
exprValList *exprGetConstList(exprObj *obj);
exprBreakFuncType exprGetBreakFunc(exprObj *obj);
int exprGetBreakResult(exprObj *obj);
void* exprGetUserData(exprObj *obj);
void exprSetUserData(exprObj *obj, void *userdata);
void exprSetBreakCount(exprObj *obj, int count);
void exprGetErrorPosition(exprObj *obj, int *start, int *end);
int exprCreate(exprObj ** obj, exprFuncList * flist, exprValList * vlist, exprValList * clist, exprBreakFuncType breaker, void *userdata);
int exprFree(exprObj * obj);
int exprClear(exprObj * obj);
int exprParse(exprObj * obj, char *expr);
int exprEval(exprObj * obj, EXPRTYPE * val);
int exprEvalNode(exprObj * obj, exprNode * nodes, int curnode, EXPRTYPE * val);
exprFuncList *exprGetFuncList(exprObj * obj);
exprValList *exprGetVarList(exprObj * obj);
exprValList *exprGetConstList(exprObj * obj);
exprBreakFuncType exprGetBreakFunc(exprObj * obj);
int exprGetBreakResult(exprObj * obj);
void *exprGetUserData(exprObj * obj);
void exprSetUserData(exprObj * obj, void *userdata);
void exprSetBreakCount(exprObj * obj, int count);
void exprGetErrorPosition(exprObj * obj, int *start, int *end);
/* Other useful routines */
int exprValidIdent(char *name);
int exprValidIdent(char *name);
/* Name mangling */
#ifdef __cplusplus
}
#endif
#endif /* __BAVII_EXPREVAL_H */
#endif /* __BAVII_EXPREVAL_H */
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -13,7 +13,7 @@
/* Needed for exprNode */
#include "exprpriv.h"
void* exprAllocMem(size_t size);
void *exprAllocMem(size_t size);
void exprFreeMem(void *data);
exprNode *exprAllocNodes(size_t count);
+137 -153
View File
@@ -30,196 +30,180 @@ extern "C" {
#define EXPR_VERSIONMINOR 7
/* Node types */
enum
{
EXPR_NODETYPE_UNKNOWN = 0,
EXPR_NODETYPE_MULTI,
EXPR_NODETYPE_ADD,
EXPR_NODETYPE_SUBTRACT,
EXPR_NODETYPE_MULTIPLY,
EXPR_NODETYPE_DIVIDE,
EXPR_NODETYPE_EXPONENT,
EXPR_NODETYPE_NEGATE,
EXPR_NODETYPE_VALUE,
EXPR_NODETYPE_VARIABLE,
EXPR_NODETYPE_ASSIGN,
EXPR_NODETYPE_FUNCTION
};
enum {
EXPR_NODETYPE_UNKNOWN = 0,
EXPR_NODETYPE_MULTI,
EXPR_NODETYPE_ADD,
EXPR_NODETYPE_SUBTRACT,
EXPR_NODETYPE_MULTIPLY,
EXPR_NODETYPE_DIVIDE,
EXPR_NODETYPE_EXPONENT,
EXPR_NODETYPE_NEGATE,
EXPR_NODETYPE_VALUE,
EXPR_NODETYPE_VARIABLE,
EXPR_NODETYPE_ASSIGN,
EXPR_NODETYPE_FUNCTION
};
/* Functions can be evaluated directly in EXPREVAL. If fptr
is NULL, type is used to determine what the function is */
enum
{
EXPR_NODEFUNC_UNKNOWN = 0,
EXPR_NODEFUNC_ABS,
EXPR_NODEFUNC_MOD,
EXPR_NODEFUNC_IPART,
EXPR_NODEFUNC_FPART,
EXPR_NODEFUNC_MIN,
EXPR_NODEFUNC_MAX,
EXPR_NODEFUNC_POW,
EXPR_NODEFUNC_SQRT,
EXPR_NODEFUNC_SIN,
EXPR_NODEFUNC_SINH,
EXPR_NODEFUNC_ASIN,
EXPR_NODEFUNC_COS,
EXPR_NODEFUNC_COSH,
EXPR_NODEFUNC_ACOS,
EXPR_NODEFUNC_TAN,
EXPR_NODEFUNC_TANH,
EXPR_NODEFUNC_ATAN,
EXPR_NODEFUNC_ATAN2,
EXPR_NODEFUNC_LOG,
EXPR_NODEFUNC_POW10,
EXPR_NODEFUNC_LN,
EXPR_NODEFUNC_EXP,
EXPR_NODEFUNC_LOGN,
EXPR_NODEFUNC_CEIL,
EXPR_NODEFUNC_FLOOR,
EXPR_NODEFUNC_RAND,
EXPR_NODEFUNC_RANDOM,
EXPR_NODEFUNC_RANDOMIZE,
EXPR_NODEFUNC_DEG,
EXPR_NODEFUNC_RAD,
EXPR_NODEFUNC_RECTTOPOLR,
EXPR_NODEFUNC_RECTTOPOLA,
EXPR_NODEFUNC_POLTORECTX,
EXPR_NODEFUNC_POLTORECTY,
EXPR_NODEFUNC_IF,
EXPR_NODEFUNC_SELECT,
EXPR_NODEFUNC_EQUAL,
EXPR_NODEFUNC_ABOVE,
EXPR_NODEFUNC_BELOW,
EXPR_NODEFUNC_AVG,
EXPR_NODEFUNC_CLIP,
EXPR_NODEFUNC_CLAMP,
EXPR_NODEFUNC_PNTCHANGE,
EXPR_NODEFUNC_POLY,
EXPR_NODEFUNC_AND,
EXPR_NODEFUNC_OR,
EXPR_NODEFUNC_NOT,
EXPR_NODEFUNC_FOR,
EXPR_NODEFUNC_MANY
};
enum {
EXPR_NODEFUNC_UNKNOWN = 0,
EXPR_NODEFUNC_ABS,
EXPR_NODEFUNC_MOD,
EXPR_NODEFUNC_IPART,
EXPR_NODEFUNC_FPART,
EXPR_NODEFUNC_MIN,
EXPR_NODEFUNC_MAX,
EXPR_NODEFUNC_POW,
EXPR_NODEFUNC_SQRT,
EXPR_NODEFUNC_SIN,
EXPR_NODEFUNC_SINH,
EXPR_NODEFUNC_ASIN,
EXPR_NODEFUNC_COS,
EXPR_NODEFUNC_COSH,
EXPR_NODEFUNC_ACOS,
EXPR_NODEFUNC_TAN,
EXPR_NODEFUNC_TANH,
EXPR_NODEFUNC_ATAN,
EXPR_NODEFUNC_ATAN2,
EXPR_NODEFUNC_LOG,
EXPR_NODEFUNC_POW10,
EXPR_NODEFUNC_LN,
EXPR_NODEFUNC_EXP,
EXPR_NODEFUNC_LOGN,
EXPR_NODEFUNC_CEIL,
EXPR_NODEFUNC_FLOOR,
EXPR_NODEFUNC_RAND,
EXPR_NODEFUNC_RANDOM,
EXPR_NODEFUNC_RANDOMIZE,
EXPR_NODEFUNC_DEG,
EXPR_NODEFUNC_RAD,
EXPR_NODEFUNC_RECTTOPOLR,
EXPR_NODEFUNC_RECTTOPOLA,
EXPR_NODEFUNC_POLTORECTX,
EXPR_NODEFUNC_POLTORECTY,
EXPR_NODEFUNC_IF,
EXPR_NODEFUNC_SELECT,
EXPR_NODEFUNC_EQUAL,
EXPR_NODEFUNC_ABOVE,
EXPR_NODEFUNC_BELOW,
EXPR_NODEFUNC_AVG,
EXPR_NODEFUNC_CLIP,
EXPR_NODEFUNC_CLAMP,
EXPR_NODEFUNC_PNTCHANGE,
EXPR_NODEFUNC_POLY,
EXPR_NODEFUNC_AND,
EXPR_NODEFUNC_OR,
EXPR_NODEFUNC_NOT,
EXPR_NODEFUNC_FOR,
EXPR_NODEFUNC_MANY
};
/* Forward declarations */
typedef struct _exprFunc exprFunc;
typedef struct _exprVal exprVal;
typedef struct _exprFunc exprFunc;
typedef struct _exprVal exprVal;
/* Expression object */
struct _exprObj
{
struct _exprFuncList *flist; /* Functions */
struct _exprValList *vlist; /* Variables */
struct _exprValList *clist; /* Constants */
struct _exprNode *headnode; /* Head parsed node */
struct _exprObj {
struct _exprFuncList *flist; /* Functions */
struct _exprValList *vlist; /* Variables */
struct _exprValList *clist; /* Constants */
struct _exprNode *headnode; /* Head parsed node */
exprBreakFuncType breakerfunc; /* Break function type */
exprBreakFuncType breakerfunc; /* Break function type */
void *userdata; /* User data, can be any 32 bit value */
int parsedgood; /* non-zero if successfully parsed */
int parsedbad; /* non-zero if parsed but unsuccessful */
int breakcount; /* how often to check the breaker function */
int breakcur; /* do we check the breaker function yet */
int starterr; /* start position of an error */
int enderr; /* end position of an error */
};
void *userdata; /* User data, can be any 32 bit value */
int parsedgood; /* non-zero if successfully parsed */
int parsedbad; /* non-zero if parsed but unsuccessful */
int breakcount; /* how often to check the breaker function */
int breakcur; /* do we check the breaker function yet */
int starterr; /* start position of an error */
int enderr; /* end position of an error */
};
/* Object for a function */
struct _exprFunc
{
char *fname; /* Name of the function */
exprFuncType fptr; /* Function pointer */
int min, max; /* Min and max args for the function. */
int refmin, refmax; /* Min and max ref. variables for the function */
int type; /* Function node type. exprEvalNOde solves the function */
struct _exprFunc {
char *fname; /* Name of the function */
exprFuncType fptr; /* Function pointer */
int min, max; /* Min and max args for the function. */
int refmin, refmax; /* Min and max ref. variables for the function */
int type; /* Function node type. exprEvalNOde solves the function */
struct _exprFunc *next; /* For linked list */
};
struct _exprFunc *next; /* For linked list */
};
/* Function list object */
struct _exprFuncList
{
struct _exprFunc *head;
};
struct _exprFuncList {
struct _exprFunc *head;
};
/* Object for values */
struct _exprVal
{
char *vname; /* Name of the value */
EXPRTYPE vval; /* Value of the value */
EXPRTYPE *vptr; /* Pointer to a value. Used only if not NULL */
struct _exprVal {
char *vname; /* Name of the value */
EXPRTYPE vval; /* Value of the value */
EXPRTYPE *vptr; /* Pointer to a value. Used only if not NULL */
struct _exprVal *next; /* For linked list */
};
struct _exprVal *next; /* For linked list */
};
/* Value list */
struct _exprValList
{
struct _exprVal *head;
};
struct _exprValList {
struct _exprVal *head;
};
/* Expression node type */
struct _exprNode
{
int type; /* Node type */
struct _exprNode {
int type; /* Node type */
union _data /* Union of info for various types */
{
struct _oper
{
struct _exprNode *nodes; /* Operation arguments */
int nodecount; /* Number of arguments */
} oper;
union _data { /* Union of info for various types */
struct _oper {
struct _exprNode *nodes; /* Operation arguments */
int nodecount; /* Number of arguments */
} oper;
struct _variable
{
EXPRTYPE *vaddr; /* Used if EXPR_FAST_VAR_ACCESS defined */
} variable;
struct _variable {
EXPRTYPE *vaddr; /* Used if EXPR_FAST_VAR_ACCESS defined */
} variable;
struct _value
{
EXPRTYPE value; /* Value if type is value */
} value;
struct _value {
EXPRTYPE value; /* Value if type is value */
} value;
struct _assign /* Assignment struct */
{
EXPRTYPE *vaddr; /* Used if EXPR_FAST_VAR_ACCESS defined */
struct _exprNode *node; /* Node to evaluate */
} assign;
struct _assign { /* Assignment struct */
EXPRTYPE *vaddr; /* Used if EXPR_FAST_VAR_ACCESS defined */
struct _exprNode *node; /* Node to evaluate */
} assign;
struct _function
{
exprFuncType fptr; /* Function pointer */
struct _exprNode *nodes; /* Array of argument nodes */
int nodecount; /* Number of argument nodes */
EXPRTYPE **refs; /* Reference variables */
int refcount; /* Number of variable references (not a reference counter) */
int type; /* Type of function for exprEvalNode if fptr is NULL */
} function;
} data;
};
struct _function {
exprFuncType fptr; /* Function pointer */
struct _exprNode *nodes; /* Array of argument nodes */
int nodecount; /* Number of argument nodes */
EXPRTYPE **refs; /* Reference variables */
int refcount; /* Number of variable references (not a reference counter) */
int type; /* Type of function for exprEvalNode if fptr is NULL */
} function;
} data;
};
/* Functions for function lists */
int exprFuncListAddType(exprFuncList *flist, char *name, int type, int min, int max, int refmin, int refmax);
int exprFuncListGet(exprFuncList *flist, char *name, exprFuncType *ptr, int *type, int *min, int *max, int *refmin, int *refmax);
int exprFuncListAddType(exprFuncList * flist, char *name, int type, int min, int max, int refmin, int refmax);
int exprFuncListGet(exprFuncList * flist, char *name, exprFuncType * ptr, int *type, int *min, int *max, int *refmin, int *refmax);
#ifdef WIN32
#define SWITCH_DECLARE(type) __declspec(dllimport) type __stdcall
#else
#define SWITCH_DECLARE(type) type
#define SWITCH_DECLARE(type) type
#endif
SWITCH_DECLARE(int) switch_isalnum(int c);
SWITCH_DECLARE(int) switch_isalpha(int c);
SWITCH_DECLARE(int) switch_isdigit(int c);
SWITCH_DECLARE(int) switch_isspace(int c);
SWITCH_DECLARE(int) switch_isalnum(int c);
SWITCH_DECLARE(int) switch_isalpha(int c);
SWITCH_DECLARE(int) switch_isdigit(int c);
SWITCH_DECLARE(int) switch_isspace(int c);
#ifdef __cplusplus
}
#endif
#endif /* __BAVII_EXPRPRIV_H */
#endif /* __BAVII_EXPRPRIV_H */
+1 -1
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
+44 -40
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -88,12 +88,12 @@ struct pvt_s {
int tx_page_start;
int tx_page_end;
int done;
/* UNUSED AT THE MOMENT
int enable_t38_reinvite;
*/
*/
};
@@ -141,7 +141,7 @@ static void spanfax_log_message(int level, const char *msg)
/*
* Called at the end of the document
*/
static void phase_e_handler(t30_state_t * s, void *user_data, int result)
static void phase_e_handler(t30_state_t *s, void *user_data, int result)
{
t30_stats_t t;
const char *local_ident;
@@ -153,7 +153,7 @@ static void phase_e_handler(t30_state_t * s, void *user_data, int result)
pvt = (pvt_t *) user_data;
switch_assert(pvt);
session = pvt->session;
switch_assert(session);
@@ -184,8 +184,8 @@ static void phase_e_handler(t30_state_t * s, void *user_data, int result)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote station id: %s\n", far_ident);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Local station id: %s\n", local_ident);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Pages transferred: %i\n",
pvt->app_mode == FUNCTION_TX ? t.pages_rx : t.pages_rx);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Pages transferred: %i\n",
pvt->app_mode == FUNCTION_TX ? t.pages_rx : t.pages_rx);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Total fax pages: %i\n", t.pages_in_file);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Image resolution: %ix%i\n", t.x_resolution, t.y_resolution);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Transfer Rate: %i\n", t.bit_rate);
@@ -195,11 +195,12 @@ static void phase_e_handler(t30_state_t * s, void *user_data, int result)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote vendor: %s\n", switch_str_nil(t30_get_rx_vendor(s)));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "remote model: %s\n", switch_str_nil(t30_get_rx_model(s)));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "==============================================================================\n");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"==============================================================================\n");
/*
Set our channel variables
*/
Set our channel variables
*/
tmp = switch_mprintf("%i", result);
if (tmp) {
@@ -250,15 +251,15 @@ static void phase_e_handler(t30_state_t * s, void *user_data, int result)
}
/* switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING); */
pvt->done = 1;
/*
TODO Fire events
*/
TODO Fire events
*/
}
static switch_status_t spanfax_init(pvt_t * pvt, transport_mode_t trans_mode)
static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
{
switch_core_session_t *session;
@@ -342,7 +343,7 @@ static switch_status_t spanfax_init(pvt_t * pvt, transport_mode_t trans_mode)
Here goes the T.38 SpanDSP initializing functions
T.38 will require a big effort as it needs a different approach
but the pieces are already in place
*/
*/
default:
assert(0); /* Whaaat ? */
break;
@@ -351,7 +352,7 @@ static switch_status_t spanfax_init(pvt_t * pvt, transport_mode_t trans_mode)
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t spanfax_destroy(pvt_t * pvt)
static switch_status_t spanfax_destroy(pvt_t *pvt)
{
int terminate;
t30_state_t *t30;
@@ -403,9 +404,9 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
switch_codec_t write_codec = { 0 };
switch_frame_t *read_frame = { 0 };
switch_frame_t write_frame = { 0 };
switch_codec_implementation_t read_impl = {0};
switch_codec_implementation_t read_impl = { 0 };
int16_t *buf = NULL;
switch_core_session_get_read_impl(session, &read_impl);
switch_core_session_get_read_impl(session, &read_impl);
/* make sure we have a valid channel when starting the FAX application */
channel = switch_core_session_get_channel(session);
@@ -414,7 +415,7 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
if (!switch_channel_media_ready(channel)) {
switch_channel_answer(channel);
}
/* Allocate our structs */
pvt = switch_core_session_alloc(session, sizeof(pvt_t));
@@ -468,8 +469,8 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
pvt->verbose = globals.verbose;
}
if ( (tmp=switch_channel_get_variable(channel, "fax_force_caller")) ) {
if ( switch_true(tmp) ) {
if ((tmp = switch_channel_get_variable(channel, "fax_force_caller"))) {
if (switch_true(tmp)) {
pvt->caller = 1;
} else {
pvt->caller = 0;
@@ -515,7 +516,8 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
pvt->filename = switch_core_session_strdup(session, data);
if (pvt->app_mode == FUNCTION_TX) {
if ((switch_file_exists(pvt->filename, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot send inexistant fax file [%s]\n", switch_str_nil(pvt->filename));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot send inexistant fax file [%s]\n",
switch_str_nil(pvt->filename));
goto done;
}
}
@@ -548,12 +550,12 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
}
/*
*** Initialize the SpanDSP elements ***
*** Initialize the SpanDSP elements ***
Note: we could analyze if a fax was already detected in previous stages
and if so, when T.38 will be supported, send a reinvite in T38_MODE,
bypassing AUDIO_MODE.
*/
Note: we could analyze if a fax was already detected in previous stages
and if so, when T.38 will be supported, send a reinvite in T38_MODE,
bypassing AUDIO_MODE.
*/
if ((spanfax_init(pvt, AUDIO_MODE) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot initialize Fax engine\n");
@@ -563,14 +565,14 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
/*
Note: Disable echocan on the channel, remember to call app "disable_ec" in the dialplan
before invoking fax applications
*/
*/
/*
Note: we are disabling the Jitterbuffer, here, before we answer.
If you have set it to something else and the channel is pre-answered,
it will have no effect. Make sure that if you want more reliable
faxes, it is disabled.
*/
Note: we are disabling the Jitterbuffer, here, before we answer.
If you have set it to something else and the channel is pre-answered,
it will have no effect. Make sure that if you want more reliable
faxes, it is disabled.
*/
switch_channel_set_variable(channel, "jitterbuffer_msec", "0");
@@ -614,7 +616,7 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
}
switch_ivr_sleep(session, 250, SWITCH_TRUE, NULL);
while (switch_channel_ready(channel)) {
int tx = 0;
switch_status_t status;
@@ -628,7 +630,7 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
- call t38_terminal_send_timeout(), sleep for a while
The T.38 stuff can be placed here (and the audio stuff can be skipped)
*/
*/
/* read new audio frame from the channel */
status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
@@ -640,7 +642,7 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
/* Skip CNG frames (auto-generated by FreeSWITCH, usually) */
if (!switch_test_flag(read_frame, SFF_CNG)) {
/* pass the new incoming audio frame to the fax_rx function */
/* pass the new incoming audio frame to the fax_rx function */
if (fax_rx(pvt->fax_state, (int16_t *) read_frame->data, read_frame->samples)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "fax_rx reported an error\n");
goto done;
@@ -670,13 +672,13 @@ void process_fax(switch_core_session_t *session, const char *data, application_m
}
done:
done:
/* Destroy the SpanDSP structures */
spanfax_destroy(pvt);
/* restore the original codecs over the channel */
switch_core_session_set_read_codec(session, NULL);
switch_core_session_set_read_codec(session, NULL);
if (switch_core_codec_ready(&read_codec)) {
switch_core_codec_destroy(&read_codec);
@@ -782,8 +784,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_fax_init)
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_APP(app_interface, "rxfax", "FAX Receive Application", "FAX Receive Application", spanfax_rx_function, SPANFAX_RX_USAGE, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "txfax", "FAX Transmit Application", "FAX Transmit Application", spanfax_tx_function, SPANFAX_TX_USAGE, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "rxfax", "FAX Receive Application", "FAX Receive Application", spanfax_rx_function, SPANFAX_RX_USAGE,
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "txfax", "FAX Transmit Application", "FAX Transmit Application", spanfax_tx_function, SPANFAX_TX_USAGE,
SAF_SUPPORT_NOMEDIA);
memset(&globals, 0, sizeof(globals));
switch_core_new_memory_pool(&globals.pool);
+132 -131
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -90,11 +90,10 @@ static switch_status_t on_dtmf(switch_core_session_t *session, void *input, swit
const char *consumer_exit_key = switch_channel_get_variable(channel, "fifo_consumer_exit_key");
if (switch_channel_test_flag(switch_core_session_get_channel(session), CF_BRIDGE_ORIGINATOR)) {
if ( consumer_exit_key && dtmf->digit == *consumer_exit_key ) {
if (consumer_exit_key && dtmf->digit == *consumer_exit_key) {
switch_channel_hangup(bchan, SWITCH_CAUSE_NORMAL_CLEARING);
return SWITCH_STATUS_BREAK;
}
else if ( !consumer_exit_key && dtmf->digit == '*' ) {
} else if (!consumer_exit_key && dtmf->digit == '*') {
switch_channel_hangup(bchan, SWITCH_CAUSE_NORMAL_CLEARING);
return SWITCH_STATUS_BREAK;
} else if (dtmf->digit == '0') {
@@ -228,8 +227,8 @@ static switch_status_t caller_read_frame_callback(switch_core_session_t *session
args.buflen = sizeof(buf);
if (switch_ivr_play_file(session, NULL, cd->list[cd->index], &args) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
}
return SWITCH_STATUS_FALSE;
}
if (caller_exit_key && *buf == *caller_exit_key) {
cd->abort = 1;
@@ -250,8 +249,8 @@ static switch_status_t consumer_read_frame_callback(switch_core_session_t *sessi
{
fifo_node_t *node, **node_list = (fifo_node_t **) user_data;
int x = 0, total = 0, i = 0;
for (i = 0 ;; i++) {
for (i = 0;; i++) {
if (!(node = node_list[i])) {
break;
}
@@ -288,17 +287,19 @@ switch_cache_db_handle_t *fifo_get_db_handle(void)
{
switch_cache_db_connection_options_t options = { {0} };
switch_cache_db_handle_t *dbh = NULL;
if (!zstr(globals.odbc_dsn)) {
options.odbc_options.dsn = globals.odbc_dsn;
options.odbc_options.user = globals.odbc_user;
options.odbc_options.pass = globals.odbc_pass;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) dbh = NULL;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS)
dbh = NULL;
return dbh;
} else {
options.core_db_options.db_path = globals.dbname;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_CORE_DB, &options) != SWITCH_STATUS_SUCCESS) dbh = NULL;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_CORE_DB, &options) != SWITCH_STATUS_SUCCESS)
dbh = NULL;
return dbh;
}
}
@@ -321,7 +322,7 @@ static switch_status_t fifo_execute_sql(char *sql, switch_mutex_t *mutex)
status = switch_cache_db_execute_sql(dbh, sql, NULL);
end:
switch_cache_db_release_db_handle(&dbh);
if (mutex) {
@@ -336,16 +337,16 @@ static switch_bool_t fifo_execute_sql_callback(switch_mutex_t *mutex, char *sql,
switch_bool_t ret = SWITCH_FALSE;
char *errmsg = NULL;
switch_cache_db_handle_t *dbh = NULL;
if (mutex) {
switch_mutex_lock(mutex);
}
if (!(dbh = fifo_get_db_handle())) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n");
goto end;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n");
goto end;
}
switch_cache_db_execute_sql_callback(dbh, sql, callback, pdata, &errmsg);
if (errmsg) {
@@ -429,7 +430,7 @@ static int node_idle_consumers(fifo_node_t *node)
switch_mutex_unlock(node->mutex);
return total;
}
static switch_status_t hanguphook(switch_core_session_t *session)
@@ -441,9 +442,10 @@ static switch_status_t hanguphook(switch_core_session_t *session)
if (state == CS_HANGUP || state == CS_ROUTING) {
if ((uuid = switch_channel_get_variable(channel, "fifo_outbound_uuid"))) {
switch_snprintf(sql, sizeof(sql), "update fifo_outbound set use_count=use_count-1, outbound_call_count=outbound_call_count+1, next_avail=%ld + lag where uuid='%s'",
(long)switch_epoch_time_now(NULL), uuid);
switch_snprintf(sql, sizeof(sql),
"update fifo_outbound set use_count=use_count-1, outbound_call_count=outbound_call_count+1, next_avail=%ld + lag where uuid='%s'",
(long) switch_epoch_time_now(NULL), uuid);
fifo_execute_sql(sql, globals.sql_mutex);
}
switch_core_event_hook_remove_state_change(session, hanguphook);
@@ -476,7 +478,7 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
switch_mutex_lock(globals.mutex);
node = switch_core_hash_find(globals.fifo_hash, h->node_name);
switch_mutex_unlock(globals.mutex);
if (node) {
switch_mutex_lock(node->mutex);
node->ring_consumer_count++;
@@ -485,18 +487,20 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
switch_snprintf(sql, sizeof(sql), "update fifo_outbound set use_count=use_count+1 where uuid='%s'", h->uuid);
fifo_execute_sql(sql, globals.sql_mutex);
switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS);
switch_assert(ovars);
switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "originate_timeout", "%d", h->timeout);
if (switch_ivr_originate(NULL, &session, &cause, h->originate_string, h->timeout, NULL, NULL, NULL, NULL, ovars, SOF_NONE, NULL) != SWITCH_STATUS_SUCCESS) {
switch_snprintf(sql, sizeof(sql), "update fifo_outbound set use_count=use_count-1, outbound_fail_count=outbound_fail_count+1, next_avail=%ld + lag where uuid='%s'",
(long)switch_epoch_time_now(NULL), h->uuid);
if (switch_ivr_originate(NULL, &session, &cause, h->originate_string, h->timeout, NULL, NULL, NULL, NULL, ovars, SOF_NONE, NULL) !=
SWITCH_STATUS_SUCCESS) {
switch_snprintf(sql, sizeof(sql),
"update fifo_outbound set use_count=use_count-1, outbound_fail_count=outbound_fail_count+1, next_avail=%ld + lag where uuid='%s'",
(long) switch_epoch_time_now(NULL), h->uuid);
fifo_execute_sql(sql, globals.sql_mutex);
goto end;
}
channel = switch_core_session_get_channel(session);
@@ -521,7 +525,8 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
switch_event_destroy(&ovars);
if (node) {
switch_mutex_lock(node->mutex);
if (node->ring_consumer_count-- < 0) node->ring_consumer_count = 0;
if (node->ring_consumer_count-- < 0)
node->ring_consumer_count = 0;
switch_mutex_unlock(node->mutex);
}
switch_core_destroy_memory_pool(&h->pool);
@@ -538,7 +543,7 @@ static int place_call_callback(void *pArg, int argc, char **argv, char **columnN
switch_threadattr_t *thd_attr = NULL;
switch_memory_pool_t *pool;
struct call_helper *h;
switch_core_new_memory_pool(&pool);
h = switch_core_alloc(pool, sizeof(*h));
h->pool = pool;
@@ -554,7 +559,7 @@ static int place_call_callback(void *pArg, int argc, char **argv, char **columnN
switch_thread_create(&thread, thd_attr, o_thread_run, h, h->pool);
(*need)--;
return *need ? 0 : -1;
}
@@ -576,10 +581,10 @@ static void find_consumers(fifo_node_t *node)
static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *obj)
{
fifo_node_t *node;
globals.node_thread_running = 1;
while(globals.node_thread_running == 1) {
while (globals.node_thread_running == 1) {
switch_hash_index_t *hi;
void *val;
const void *var;
@@ -588,21 +593,21 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o
switch_mutex_lock(globals.mutex);
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
if ((node = (fifo_node_t *) val)) {
if (node->has_outbound && node->ready) {
switch_mutex_lock(node->mutex);
ppl_waiting = node_consumer_wait_count(node);
consumer_total = node->consumer_count;
idle_consumers = node_idle_consumers(node);
if ((node = (fifo_node_t *) val)) {
if (node->has_outbound && node->ready) {
switch_mutex_lock(node->mutex);
ppl_waiting = node_consumer_wait_count(node);
consumer_total = node->consumer_count;
idle_consumers = node_idle_consumers(node);
/* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"%s waiting %d consumer_total %d idle_consumers %d ring_consumers %d\n", node->name, ppl_waiting, consumer_total, idle_consumers, node->ring_consumer_count); */
if ((ppl_waiting - node->ring_consumer_count > 0)&& (!consumer_total || !idle_consumers)) {
find_consumers(node);
/* switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"%s waiting %d consumer_total %d idle_consumers %d ring_consumers %d\n", node->name, ppl_waiting, consumer_total, idle_consumers, node->ring_consumer_count); */
if ((ppl_waiting - node->ring_consumer_count > 0) && (!consumer_total || !idle_consumers)) {
find_consumers(node);
}
switch_mutex_unlock(node->mutex);
}
switch_mutex_unlock(node->mutex);
}
}
}
switch_mutex_unlock(globals.mutex);
@@ -611,7 +616,7 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o
}
globals.node_thread_running = 0;
return NULL;
}
@@ -632,7 +637,7 @@ static int stop_node_thread(void)
if (globals.node_thread_running) {
globals.node_thread_running = -1;
while(globals.node_thread_running) {
while (globals.node_thread_running) {
switch_yield(500000);
if (!--sanity) {
return -1;
@@ -643,15 +648,15 @@ static int stop_node_thread(void)
return 0;
}
static void check_cancel(fifo_node_t *node)
static void check_cancel(fifo_node_t *node)
{
int ppl_waiting = node_consumer_wait_count(node);
if (node->ring_consumer_count > 0 && ppl_waiting < 1) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Outbound call count (%d) exceeds required value for queue %s (%d), "
"Ending extraneous calls\n", node->ring_consumer_count, node->name, ppl_waiting);
switch_core_session_hupall_matching_var("fifo_hangup_check", node->name, SWITCH_CAUSE_ORIGINATOR_CANCEL);
}
}
@@ -735,12 +740,12 @@ static uint32_t fifo_add_outbound(const char *node_name, const char *url, uint32
}
switch_mutex_unlock(globals.mutex);
str = switch_mprintf("dial:%s", url);
switch_queue_push(node->fifo_list[priority], (void *) str);
return switch_queue_size(node->fifo_list[priority]);
}
@@ -769,16 +774,16 @@ SWITCH_STANDARD_API(fifo_add_outbound_function)
stream->write_function(stream, "%d", fifo_add_outbound(argv[0], argv[1], priority));
free(data);
return SWITCH_STATUS_SUCCESS;
free(data);
return SWITCH_STATUS_SUCCESS;
fail:
fail:
free(data);
free(data);
stream->write_function(stream, "0");
return SWITCH_STATUS_SUCCESS;
return SWITCH_STATUS_SUCCESS;
}
@@ -868,7 +873,7 @@ SWITCH_STANDARD_APP(fifo_function)
}
}
if (!(node = switch_core_hash_find(globals.fifo_hash, nlist[i]))) {
node = create_node(nlist[i], importance, globals.sql_mutex);
node->ready = 1;
@@ -982,7 +987,7 @@ SWITCH_STANDARD_APP(fifo_function)
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FIFO-Slot", "%d", p);
switch_event_fire(&event);
}
switch_queue_push(node->fifo_list[p], (void *) strdup(uuid));
switch_snprintf(tmp, sizeof(tmp), "%d", switch_queue_size(node->fifo_list[p]));
switch_channel_set_variable(channel, "fifo_position", tmp);
@@ -1300,14 +1305,15 @@ SWITCH_STANDARD_APP(fifo_function)
switch_call_cause_t cause = SWITCH_CAUSE_NONE;
const char *o_announce = NULL;
url = uuid + 5;
if ((o_announce = switch_channel_get_variable(channel, "fifo_outbound_announce"))) {
switch_ivr_play_file(session, NULL, o_announce, NULL);
}
if (switch_ivr_originate(session, &other_session, &cause, url, 120, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL) != SWITCH_STATUS_SUCCESS) {
other_session = NULL;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Originate to [%s] failed, cause: %s\n", url, switch_channel_cause2str(cause));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Originate to [%s] failed, cause: %s\n", url,
switch_channel_cause2str(cause));
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
@@ -1317,7 +1323,7 @@ SWITCH_STANDARD_APP(fifo_function)
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Outbound-URL", url);
switch_event_fire(&event);
}
} else {
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
@@ -1326,7 +1332,7 @@ SWITCH_STANDARD_APP(fifo_function)
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Result", "success");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Outbound-URL", url);
switch_event_fire(&event);
}
}
url = NULL;
free(uuid);
uuid = strdup(switch_core_session_get_uuid(other_session));
@@ -1351,7 +1357,7 @@ SWITCH_STANDARD_APP(fifo_function)
const char *record_template = switch_channel_get_variable(channel, "fifo_record_template");
char *expanded = NULL;
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
@@ -1385,7 +1391,7 @@ SWITCH_STANDARD_APP(fifo_function)
const char *app = switch_channel_get_variable(other_channel, "current_application");
const char *arg = switch_channel_get_variable(other_channel, "current_application_data");
switch_caller_extension_t *extension = NULL;
switch_mutex_lock(node->mutex);
node->caller_count--;
switch_core_hash_delete(node->caller_hash, uuid);
@@ -1454,7 +1460,7 @@ SWITCH_STANDARD_APP(fifo_function)
switch_ivr_multi_threaded_bridge(session, other_session, on_dtmf, other_session, session);
switch_core_media_bug_pause(session);
switch_core_media_bug_pause(other_session);
if (record_template) {
switch_ivr_stop_record_session(session, expanded);
if (expanded != record_template) {
@@ -1487,7 +1493,7 @@ SWITCH_STANDARD_APP(fifo_function)
fifo_consumer_wrapup_sound = switch_channel_get_variable(channel, "fifo_consumer_wrapup_sound");
fifo_consumer_wrapup_key = switch_channel_get_variable(channel, "fifo_consumer_wrapup_key");
sfifo_consumer_wrapup_time = switch_channel_get_variable(channel, "fifo_consumer_wrapup_time");
if (!zstr(sfifo_consumer_wrapup_time)){
if (!zstr(sfifo_consumer_wrapup_time)) {
fifo_consumer_wrapup_time = atoi(sfifo_consumer_wrapup_time);
} else {
fifo_consumer_wrapup_time = 5000;
@@ -1511,15 +1517,15 @@ SWITCH_STANDARD_APP(fifo_function)
args.buflen = sizeof(buf);
switch_ivr_play_file(session, NULL, fifo_consumer_wrapup_sound, &args);
}
if (fifo_consumer_wrapup_time) {
wrapup_time_started = switch_micro_time_now();
}
if (!zstr(fifo_consumer_wrapup_key) && strcmp(buf, fifo_consumer_wrapup_key)) {
while(switch_channel_ready(channel)) {
while (switch_channel_ready(channel)) {
char terminator = 0;
if (fifo_consumer_wrapup_time) {
wrapup_time_elapsed = (switch_micro_time_now() - wrapup_time_started) / 1000;
if (wrapup_time_elapsed > fifo_consumer_wrapup_time) {
@@ -1529,14 +1535,15 @@ SWITCH_STANDARD_APP(fifo_function)
}
}
switch_ivr_collect_digits_count(session, buf, sizeof(buf) - 1, 1, fifo_consumer_wrapup_key, &terminator, 0, 0, (uint32_t) wrapup_time_remaining);
switch_ivr_collect_digits_count(session, buf, sizeof(buf) - 1, 1, fifo_consumer_wrapup_key, &terminator, 0, 0,
(uint32_t) wrapup_time_remaining);
if ((terminator == *fifo_consumer_wrapup_key) || !(switch_channel_ready(channel))) {
break;
}
}
} else if (fifo_consumer_wrapup_time && (zstr(fifo_consumer_wrapup_key) || !strcmp(buf, fifo_consumer_wrapup_key))) {
while(switch_channel_ready(channel)) {
while (switch_channel_ready(channel)) {
wrapup_time_elapsed = (switch_micro_time_now() - wrapup_time_started) / 1000;
if (wrapup_time_elapsed > fifo_consumer_wrapup_time) {
break;
@@ -1546,7 +1553,7 @@ SWITCH_STANDARD_APP(fifo_function)
}
switch_channel_set_variable(channel, "fifo_status", "WAITING");
}
if (do_wait && switch_channel_ready(channel)) {
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
@@ -1556,7 +1563,7 @@ SWITCH_STANDARD_APP(fifo_function)
}
}
}
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, FIFO_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(channel, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "FIFO-Name", argv[0]);
@@ -1577,7 +1584,7 @@ SWITCH_STANDARD_APP(fifo_function)
}
}
done:
done:
switch_mutex_lock(globals.mutex);
if (node && node->ready == FIFO_DELAY_DESTROY && node->consumer_count == 0 && node->caller_count == 0) {
@@ -1636,7 +1643,7 @@ static int xml_callback(void *pArg, int argc, char **argv, char **columnNames)
switch_xml_set_attr_d(x_out, "outbound-call-count", argv[10]);
switch_xml_set_attr_d(x_out, "outbound-fail-count", argv[11]);
switch_xml_set_attr_d(x_out, "next-available", expires);
switch_xml_set_txt_d(x_out, argv[2]);
return 0;
@@ -1657,7 +1664,7 @@ static int xml_outbound(switch_xml_t xml, fifo_node_t *node, char *container, ch
h.verbose = verbose;
fifo_execute_sql_callback(globals.sql_mutex, sql, xml_callback, &h);
switch_safe_free(sql);
return h.cc_off;
@@ -1736,7 +1743,7 @@ static void list_node(fifo_node_t *node, switch_xml_t x_report, int *off, int ve
switch_xml_set_attr_d(x_fifo, "waiting_count", tmp);
switch_snprintf(tmp, sizeof(buffer), "%u", node->importance);
switch_xml_set_attr_d(x_fifo, "importance", tmp);
cc_off = xml_outbound(x_fifo, node, "outbound", "member", cc_off, verbose);
cc_off = xml_hash(x_fifo, node->caller_hash, "callers", "caller", cc_off, verbose);
cc_off = xml_hash(x_fifo, node->consumer_hash, "consumers", "consumer", cc_off, verbose);
@@ -1851,7 +1858,7 @@ SWITCH_STANDARD_API(fifo_api_function)
}
const char outbound_sql[] =
const char outbound_sql[] =
"create table fifo_outbound (\n"
" uuid varchar(255),\n"
" fifo_name varchar(255),\n"
@@ -1861,19 +1868,14 @@ const char outbound_sql[] =
" timeout integer,\n"
" lag integer,\n"
" next_avail integer,\n"
" expires integer,\n"
" static integer,\n"
" outbound_call_count integer,"
" outbound_fail_count integer,"
" hostname varchar(255)\n"
");\n";
" expires integer,\n" " static integer,\n" " outbound_call_count integer," " outbound_fail_count integer," " hostname varchar(255)\n" ");\n";
static switch_status_t load_config(int reload, int del_all)
{
char *cf = "fifo.conf";
switch_xml_t cfg, xml, fifo, fifos, member, settings, param;
switch_status_t status = SWITCH_STATUS_SUCCESS;
switch_status_t status = SWITCH_STATUS_SUCCESS;
char *sql;
switch_bool_t delete_all_outbound_member_on_startup = SWITCH_FALSE;
switch_cache_db_handle_t *dbh = NULL;
@@ -1892,7 +1894,7 @@ static switch_status_t load_config(int reload, int del_all)
var = (char *) switch_xml_attr_soft(param, "name");
val = (char *) switch_xml_attr_soft(param, "value");
if (!strcasecmp(var, "odbc-dsn") && !zstr(val)) {
if (switch_odbc_available()) {
globals.odbc_dsn = switch_core_strdup(globals.pool, val);
@@ -1915,13 +1917,13 @@ static switch_status_t load_config(int reload, int del_all)
globals.dbname = "fifo";
}
if (!(dbh = fifo_get_db_handle())) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot open DB!\n");
goto done;
}
switch_cache_db_test_reactive(dbh, "delete from fifo_outbound where static = 1", "drop table fifo_outbound", outbound_sql);
switch_cache_db_release_db_handle(&dbh);
@@ -1939,12 +1941,12 @@ static switch_status_t load_config(int reload, int del_all)
switch_mutex_unlock(globals.mutex);
}
if ((reload && del_all) || (!reload && delete_all_outbound_member_on_startup) ) {
if ((reload && del_all) || (!reload && delete_all_outbound_member_on_startup)) {
sql = switch_mprintf("delete from fifo_outbound where hostname='%q'", globals.hostname);
} else {
sql = switch_mprintf("delete from fifo_outbound where static=1 and hostname='%q'", globals.hostname);
}
fifo_execute_sql(sql, globals.sql_mutex);
switch_safe_free(sql);
@@ -1959,14 +1961,14 @@ static switch_status_t load_config(int reload, int del_all)
int timeout_i = 60;
int lag_i = 10;
fifo_node_t *node;
name = switch_xml_attr(fifo, "name");
if ((importance = switch_xml_attr(fifo, "importance"))) {
if ((imp = atoi(importance)) < 0) {
imp = 0;
}
}
}
if (!name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "fifo has no name!\n");
@@ -1978,11 +1980,11 @@ static switch_status_t load_config(int reload, int del_all)
node = create_node(name, imp, globals.sql_mutex);
}
switch_mutex_unlock(globals.mutex);
switch_assert(node);
switch_mutex_lock(node->mutex);
for (member = switch_xml_child(fifo, "member"); member; member = member->next) {
const char *simo = switch_xml_attr_soft(member, "simo");
const char *lag = switch_xml_attr_soft(member, "lag");
@@ -2007,12 +2009,12 @@ static switch_status_t load_config(int reload, int del_all)
lag_i = 10;
}
}
name_dup = strdup(node->name);
if ((p = strchr(name_dup, '@'))) {
*p = '\0';
}
if (switch_stristr("origination_caller_id", member->txt)) {
sql = switch_mprintf("insert into fifo_outbound "
"(uuid, fifo_name, originate_string, simo_count, use_count, timeout, lag, "
@@ -2030,7 +2032,7 @@ static switch_status_t load_config(int reload, int del_all)
"'{execute_on_answer=''unset fifo_hangup_check'',fifo_hangup_check=''%q'',origination_caller_id_name=Queue,"
"origination_caller_id_number=''fifo+%q''}%q',%d,%d,%d,%d,0,0,1,0,0,'%q')",
digest, node->name, node->name, name_dup, member->txt, simo_i, 0, timeout_i, lag_i, globals.hostname);
}
switch_assert(sql);
@@ -2038,14 +2040,14 @@ static switch_status_t load_config(int reload, int del_all)
free(sql);
free(name_dup);
node->has_outbound = 1;
}
node->ready = 1;
node->is_static = 1;
switch_mutex_unlock(node->mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s configured\n", node->name);
}
}
switch_xml_free(xml);
@@ -2057,7 +2059,7 @@ static switch_status_t load_config(int reload, int del_all)
void *val, *pop;
fifo_node_t *node;
switch_mutex_lock(globals.mutex);
top:
top:
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
int x = 0;
switch_hash_this(hi, NULL, NULL, &val);
@@ -2076,7 +2078,7 @@ static switch_status_t load_config(int reload, int del_all)
free(pop);
}
}
switch_core_hash_delete(globals.fifo_hash, node->name);
switch_core_hash_destroy(&node->caller_hash);
switch_core_hash_destroy(&node->consumer_hash);
@@ -2099,15 +2101,15 @@ static void fifo_member_add(char *fifo_name, char *originate_string, int simo_co
char digest[SWITCH_MD5_DIGEST_STRING_SIZE] = { 0 };
char *sql, *name_dup, *p;
fifo_node_t *node = NULL;
switch_md5_string(digest, (void *) originate_string, strlen(originate_string));
sql = switch_mprintf("delete from fifo_outbound where fifo_name='%q' and uuid = '%q'", fifo_name, digest);
switch_assert(sql);
fifo_execute_sql(sql, globals.sql_mutex);
free(sql);
switch_mutex_lock(globals.mutex);
if (!(node = switch_core_hash_find(globals.fifo_hash, fifo_name))) {
node = create_node(fifo_name, 0, globals.sql_mutex);
@@ -2115,7 +2117,7 @@ static void fifo_member_add(char *fifo_name, char *originate_string, int simo_co
}
switch_mutex_unlock(globals.mutex);
node->has_outbound = 1;
node->has_outbound = 1;
name_dup = strdup(fifo_name);
if ((p = strchr(name_dup, '@'))) {
@@ -2128,13 +2130,12 @@ static void fifo_member_add(char *fifo_name, char *originate_string, int simo_co
"values ('%q','%q',"
"'{execute_on_answer=''unset fifo_hangup_check'',fifo_hangup_check=''%q'',origination_caller_id_name=Queue,"
"origination_caller_id_number=''fifo+%q''}%q',%d,%d,%d,%d,%d,%ld,0,0,0,'%q')",
digest, fifo_name, fifo_name, name_dup, originate_string, simo_count, 0, timeout, lag, 0, (long)expires, globals.hostname
);
digest, fifo_name, fifo_name, name_dup, originate_string, simo_count, 0, timeout, lag, 0, (long) expires, globals.hostname);
switch_assert(sql);
fifo_execute_sql(sql, globals.sql_mutex);
free(sql);
free(name_dup);
}
static void fifo_member_del(char *fifo_name, char *originate_string)
@@ -2143,7 +2144,7 @@ static void fifo_member_del(char *fifo_name, char *originate_string)
char *sql;
switch_md5_string(digest, (void *) originate_string, strlen(originate_string));
sql = switch_mprintf("delete from fifo_outbound where fifo_name='%q' and uuid = '%q' and hostname='%q'", fifo_name, digest, globals.hostname);
switch_assert(sql);
fifo_execute_sql(sql, globals.sql_mutex);
@@ -2167,7 +2168,7 @@ SWITCH_STANDARD_API(fifo_member_api_function)
return SWITCH_STATUS_FALSE;
}
if (zstr(cmd)){
if (zstr(cmd)) {
stream->write_function(stream, "-USAGE: %s\n", FIFO_MEMBER_API_SYNTAX);
return SWITCH_STATUS_SUCCESS;
}
@@ -2181,11 +2182,11 @@ SWITCH_STANDARD_API(fifo_member_api_function)
stream->write_function(stream, "%s", "-ERR Invalid!\n");
goto done;
}
action = argv[0];
fifo_name = argv[1];
originate_string = argv[2];
if (action && !strcasecmp(action, "add")) {
if (argc > 3) {
simo_count = atoi(argv[3]);
@@ -2208,7 +2209,7 @@ SWITCH_STANDARD_API(fifo_member_api_function)
if (lag < 0) {
lag = 5;
}
fifo_member_add(fifo_name, originate_string, simo_count, timeout, lag, expires);
stream->write_function(stream, "%s", "+OK\n");
} else if (action && !strcasecmp(action, "del")) {
@@ -2240,7 +2241,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load)
}
/* Subscribe to presence request events */
if (switch_event_bind_removable(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY,
if (switch_event_bind_removable(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY,
pres_event_handler, NULL, &globals.node) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't subscribe to presence request events!\n");
return SWITCH_STATUS_GENERR;
@@ -2250,10 +2251,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_fifo_load)
switch_core_hash_init(&globals.fifo_hash, globals.pool);
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
switch_mutex_init(&globals.sql_mutex, SWITCH_MUTEX_NESTED, globals.pool);
globals.running = 1;
if ((status = load_config(0,1)) != SWITCH_STATUS_SUCCESS) {
if ((status = load_config(0, 1)) != SWITCH_STATUS_SUCCESS) {
switch_event_unbind(&globals.node);
switch_event_free_subclass(FIFO_EVENT);
switch_core_hash_destroy(&globals.fifo_hash);
@@ -2287,24 +2288,24 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown)
fifo_node_t *node;
switch_memory_pool_t *pool = globals.pool;
switch_mutex_t *mutex = globals.mutex;
switch_event_unbind(&globals.node);
switch_event_free_subclass(FIFO_EVENT);
switch_mutex_lock(mutex);
globals.running = 0;
/* Cleanup */
if (globals.node_thread_running) {
stop_node_thread();
}
while ((hi = switch_hash_first(NULL, globals.fifo_hash))) {
int x = 0;
switch_hash_this(hi, NULL, NULL, &val);
node = (fifo_node_t *) val;
switch_thread_rwlock_wrlock(node->rwlock);
for (x = 0; x < MAX_PRI; x++) {
while (switch_queue_trypop(node->fifo_list[x], &pop) == SWITCH_STATUS_SUCCESS) {
+4 -4
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -107,7 +107,7 @@ SWITCH_STANDARD_APP(record_fsv_function)
int fd;
switch_mutex_t *mutex = NULL;
switch_codec_t codec, *vid_codec;
switch_codec_implementation_t read_impl = {0};
switch_codec_implementation_t read_impl = { 0 };
switch_core_session_get_read_impl(session, &read_impl);
switch_channel_answer(channel);
@@ -227,8 +227,8 @@ SWITCH_STANDARD_APP(play_fsv_function)
uint32_t ts = 0, last = 0;
switch_timer_t timer = { 0 };
switch_payload_t pt = 0;
switch_codec_implementation_t read_impl = {0};
switch_core_session_get_read_impl(session, &read_impl);
switch_codec_implementation_t read_impl = { 0 };
switch_core_session_get_read_impl(session, &read_impl);
aud_buffer = switch_core_session_alloc(session, SWITCH_RECOMMENDED_BUFFER_SIZE);
vid_buffer = switch_core_session_alloc(session, SWITCH_RECOMMENDED_BUFFER_SIZE);
+196 -226
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -122,7 +122,7 @@ struct profile_obj {
switch_bool_t profile_has_intrastate;
switch_bool_t profile_has_intralata;
switch_bool_t profile_has_npanxx;
switch_bool_t reorder_by_rate;
switch_bool_t quote_in_list;
switch_bool_t info_in_headers;
@@ -173,21 +173,21 @@ static const char *do_cid(switch_memory_pool_t *pool, const char *cid, const cha
char *src_regex = NULL;
char *dst_regex = NULL;
switch_channel_t *channel = NULL;
if (!zstr(cid)) {
len = strlen(cid);
} else {
goto done;
}
src = switch_core_strdup(pool, cid);
/* check that this is a valid regexp and split the string */
if ((src[0] == '/') && src[len-1] == '/') {
if ((src[0] == '/') && src[len - 1] == '/') {
/* strip leading / trailing slashes */
src[len-1] = '\0';
src[len - 1] = '\0';
src++;
/* break on first / */
dst = strchr(src, '/');
*dst = '\0';
@@ -216,12 +216,12 @@ static const char *do_cid(switch_memory_pool_t *pool, const char *cid, const cha
switch_safe_free(tmp_regex);
dst = dst_regex;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "expanded src: %s, dst: %s\n", src, dst);
}
if ((proceed = switch_regex_perform(number, src, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
len = (uint32_t) (strlen(src) + strlen(dst) + 10) * proceed; /* guestimate size */
len = (uint32_t) (strlen(src) + strlen(dst) + 10) * proceed; /* guestimate size */
if (!(substituted = switch_core_alloc(pool, len))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Memory Error!\n");
goto done;
@@ -233,77 +233,71 @@ static const char *do_cid(switch_memory_pool_t *pool, const char *cid, const cha
}
switch_regex_safe_free(re);
return substituted;
done:
done:
switch_regex_safe_free(re);
return number;
}
static char *get_bridge_data(switch_memory_pool_t *pool, char *dialed_number, char *caller_id, lcr_route cur_route, profile_t *profile, switch_core_session_t *session)
static char *get_bridge_data(switch_memory_pool_t *pool, char *dialed_number, char *caller_id, lcr_route cur_route, profile_t *profile,
switch_core_session_t *session)
{
size_t lstrip;
size_t tstrip;
size_t tstrip;
char *data = NULL;
char *destination_number = NULL;
char *orig_destination_number = NULL;
char *orig_destination_number = NULL;
char *codec = NULL;
char *cid = NULL;
char *header = NULL;
char *user_rate = NULL;
orig_destination_number = destination_number = switch_core_strdup(pool, dialed_number);
tstrip = ((cur_route->digit_len - cur_route->tstrip) + 1);
lstrip = cur_route->lstrip;
if (cur_route->tstrip > 0) {
if (strlen(destination_number) > tstrip) {
destination_number[tstrip] = '\0';
}
else {
} else {
destination_number[0] = '\0';
}
}
}
}
if (cur_route->lstrip > 0) {
if (strlen(destination_number) > lstrip) {
destination_number += lstrip;
}
else {
} else {
destination_number[0] = '\0';
}
}
}
codec = "";
if (!zstr(cur_route->codec)) {
codec = switch_core_sprintf(pool, ",absolute_codec_string=%s", cur_route->codec);
}
cid = "";
if (!zstr(cur_route->cid)) {
cid = switch_core_sprintf(pool, ",origination_caller_id_number=%s",
do_cid(pool, cur_route->cid, caller_id, session));
cid = switch_core_sprintf(pool, ",origination_caller_id_number=%s", do_cid(pool, cur_route->cid, caller_id, session));
}
header = "";
if (profile->info_in_headers) {
header = switch_core_sprintf(pool, ",sip_h_X-LCR-INFO=lcr_rate=%s;lcr_carrier=%s",
cur_route->rate_str,
cur_route->carrier_name);
header = switch_core_sprintf(pool, ",sip_h_X-LCR-INFO=lcr_rate=%s;lcr_carrier=%s", cur_route->rate_str, cur_route->carrier_name);
}
if (zstr(cur_route->user_rate_str)) {
user_rate = "";
} else {
user_rate = switch_core_sprintf(pool, ",lcr_user_rate=%s", cur_route->user_rate_str);
}
data = switch_core_sprintf(pool, "[lcr_carrier=%s,lcr_rate=%s%s%s%s%s]%s%s%s%s%s"
, cur_route->carrier_name, cur_route->rate_str
, user_rate, codec, cid, header
, cur_route->gw_prefix, cur_route->prefix
, destination_number, cur_route->suffix, cur_route->gw_suffix);
data =
switch_core_sprintf(pool, "[lcr_carrier=%s,lcr_rate=%s%s%s%s%s]%s%s%s%s%s", cur_route->carrier_name, cur_route->rate_str, user_rate, codec, cid,
header, cur_route->gw_prefix, cur_route->prefix, destination_number, cur_route->suffix, cur_route->gw_suffix);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Returning Dialstring %s\n", data);
return data;
}
@@ -311,13 +305,13 @@ static char *get_bridge_data(switch_memory_pool_t *pool, char *dialed_number, ch
static profile_t *locate_profile(const char *profile_name)
{
profile_t *profile = NULL;
if (zstr(profile_name)) {
profile = globals.default_profile;
} else if (!(profile = switch_core_hash_find(globals.profile_hash, profile_name))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error invalid profile %s\n", profile_name);
}
return profile;
}
@@ -365,7 +359,7 @@ static switch_status_t process_max_lengths(max_obj_t *maxes, lcr_route routes, c
if (current->digit_str != NULL) {
if (current->digit_len > maxes->digit_str) {
maxes->digit_str = current->digit_len;
}
}
}
if (current->rate_str != NULL) {
this_len = strlen(current->rate_str);
@@ -374,7 +368,7 @@ static switch_status_t process_max_lengths(max_obj_t *maxes, lcr_route routes, c
}
}
if (current->codec != NULL) {
this_len= strlen(current->codec);
this_len = strlen(current->codec);
if (this_len > maxes->codec) {
maxes->codec = this_len;
}
@@ -393,13 +387,14 @@ static switch_cache_db_handle_t *lcr_get_db_handle(void)
{
switch_cache_db_connection_options_t options = { {0} };
switch_cache_db_handle_t *dbh = NULL;
if (!zstr(globals.odbc_dsn)) {
options.odbc_options.dsn = globals.odbc_dsn;
options.odbc_options.user = globals.odbc_user;
options.odbc_options.pass = globals.odbc_pass;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) dbh = NULL;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS)
dbh = NULL;
}
return dbh;
}
@@ -430,23 +425,23 @@ static switch_bool_t set_db_random()
db_random = "random()";
return SWITCH_TRUE;
}
return SWITCH_FALSE;
}
/* make a new string with digits only */
static char *string_digitsonly(switch_memory_pool_t *pool, const char *str)
static char *string_digitsonly(switch_memory_pool_t *pool, const char *str)
{
char *p, *np, *newstr;
size_t len;
p = (char *)str;
p = (char *) str;
len = strlen(str);
newstr = switch_core_alloc(pool, len+1);
newstr = switch_core_alloc(pool, len + 1);
np = newstr;
while(*p) {
while (*p) {
if (switch_isdigit(*p)) {
*np = *p;
np++;
@@ -478,14 +473,10 @@ static char *expand_digits(switch_memory_pool_t *pool, char *digits, switch_bool
digit_len = strlen(digits);
digits_copy = switch_core_strdup(pool, digits);
for (n = digit_len; n > 0; n--) {
digits_copy[n] = '\0';
dig_stream.write_function(&dig_stream, "%s%s%s%s",
(n==digit_len ? "" : ", "),
(quote ? "'" : ""),
digits_copy,
(quote ? "'" : ""));
dig_stream.write_function(&dig_stream, "%s%s%s%s", (n == digit_len ? "" : ", "), (quote ? "'" : ""), digits_copy, (quote ? "'" : ""));
}
ret = switch_core_strdup(pool, dig_stream.data);
@@ -496,42 +487,41 @@ static char *expand_digits(switch_memory_pool_t *pool, char *digits, switch_bool
/* format the custom sql */
static char *format_custom_sql(const char *custom_sql, callback_t *cb_struct, const char *digits)
{
char * tmpSQL = NULL;
char * newSQL = NULL;
char *tmpSQL = NULL;
char *newSQL = NULL;
switch_channel_t *channel;
/* first replace %s with digits to maintain backward compat */
if (cb_struct->profile->custom_sql_has_percent == SWITCH_TRUE) {
tmpSQL = switch_string_replace(custom_sql, "%q", digits);
newSQL = tmpSQL;
}
/* expand the vars */
if (cb_struct->profile->custom_sql_has_vars == SWITCH_TRUE) {
if (cb_struct->session) {
channel = switch_core_session_get_channel(cb_struct->session);
switch_assert(channel);
/*
newSQL = switch_channel_expand_variables_escape(channel,
tmpSQL ? tmpSQL : custom_sql,
escape_sql);
*/
newSQL = switch_channel_expand_variables(channel,
tmpSQL ? tmpSQL : custom_sql);
newSQL = switch_channel_expand_variables_escape(channel,
tmpSQL ? tmpSQL : custom_sql,
escape_sql);
*/
newSQL = switch_channel_expand_variables(channel, tmpSQL ? tmpSQL : custom_sql);
} else if (cb_struct->event) {
/* use event system to expand vars */
newSQL = switch_event_expand_headers(cb_struct->event, tmpSQL ? tmpSQL : custom_sql);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(cb_struct->session), SWITCH_LOG_CRIT,
"mod_lcr called without a valid session while using a custom_sql that has channel variables.\n");
"mod_lcr called without a valid session while using a custom_sql that has channel variables.\n");
}
}
if (tmpSQL != newSQL) {
switch_safe_free(tmpSQL);
}
if (newSQL == NULL) {
return (char *) custom_sql;
} else {
@@ -543,10 +533,10 @@ static switch_bool_t lcr_execute_sql_callback(char *sql, switch_core_db_callback
{
switch_bool_t retval = SWITCH_FALSE;
switch_cache_db_handle_t *dbh = NULL;
if (globals.odbc_dsn && (dbh = lcr_get_db_handle())) {
if (switch_cache_db_execute_sql_callback(dbh, sql, callback, pdata, NULL)
== SWITCH_ODBC_FAIL) {
== SWITCH_ODBC_FAIL) {
retval = SWITCH_FALSE;
} else {
retval = SWITCH_TRUE;
@@ -562,23 +552,21 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
lcr_route current = NULL;
callback_t *cbt = (callback_t *) pArg;
char *key = NULL;
switch_memory_pool_t *pool = cbt->pool;
if (argc < LCR_QUERY_COLS_REQUIRED) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT,
"Unexpected number of columns returned for SQL. Returned column count: %d. "
"If using a custom sql for this profile, verify it is correct. Otherwise file a bug report.\n",
argc);
"Unexpected number of columns returned for SQL. Returned column count: %d. "
"If using a custom sql for this profile, verify it is correct. Otherwise file a bug report.\n", argc);
return SWITCH_STATUS_GENERR;
}
if (zstr(argv[LCR_GW_PREFIX_PLACE]) && zstr(argv[LCR_GW_SUFFIX_PLACE]) ) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"There's no way to dial this Gateway: Carrier: \"%s\" Prefix: \"%s\", Suffix \"%s\"\n",
switch_str_nil(argv[LCR_CARRIER_PLACE]),
switch_str_nil(argv[LCR_GW_PREFIX_PLACE]), switch_str_nil(argv[LCR_GW_SUFFIX_PLACE]));
if (zstr(argv[LCR_GW_PREFIX_PLACE]) && zstr(argv[LCR_GW_SUFFIX_PLACE])) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"There's no way to dial this Gateway: Carrier: \"%s\" Prefix: \"%s\", Suffix \"%s\"\n",
switch_str_nil(argv[LCR_CARRIER_PLACE]), switch_str_nil(argv[LCR_GW_PREFIX_PLACE]), switch_str_nil(argv[LCR_GW_SUFFIX_PLACE]));
return SWITCH_STATUS_SUCCESS;
}
@@ -590,7 +578,7 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
additional->suffix = switch_core_strdup(pool, switch_str_nil(argv[LCR_SUFFIX_PLACE]));
additional->prefix = switch_core_strdup(pool, switch_str_nil(argv[LCR_PREFIX_PLACE]));
additional->carrier_name = switch_core_strdup(pool, switch_str_nil(argv[LCR_CARRIER_PLACE]));
additional->rate = (float)atof(switch_str_nil(argv[LCR_RATE_PLACE]));
additional->rate = (float) atof(switch_str_nil(argv[LCR_RATE_PLACE]));
additional->rate_str = switch_core_sprintf(pool, "%0.5f", additional->rate);
additional->gw_prefix = switch_core_strdup(pool, switch_str_nil(argv[LCR_GW_PREFIX_PLACE]));
additional->gw_suffix = switch_core_strdup(pool, switch_str_nil(argv[LCR_GW_SUFFIX_PLACE]));
@@ -603,7 +591,7 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
additional->cid = switch_core_strdup(pool, switch_str_nil(argv[LCR_CID_PLACE]));
}
if (argc > LCR_USER_RATE_PLACE) {
additional->user_rate = (float)atof(switch_str_nil(argv[LCR_USER_RATE_PLACE]));
additional->user_rate = (float) atof(switch_str_nil(argv[LCR_USER_RATE_PLACE]));
additional->user_rate_str = switch_core_sprintf(pool, "%0.5f", additional->user_rate);
}
additional->dialstring = get_bridge_data(pool, cbt->lookup_number, cbt->cid, additional, cbt->profile, cbt->session);
@@ -620,14 +608,12 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
return SWITCH_STATUS_SUCCESS;
}
for (current = cbt->head; current; current = current->next) {
key = switch_core_sprintf(pool, "%s:%s", additional->gw_prefix, additional->gw_suffix);
if (switch_core_hash_find(cbt->dedup_hash, key)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"Ignoring Duplicate route for termination point (%s)\n",
key);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Ignoring Duplicate route for termination point (%s)\n", key);
break;
}
@@ -647,13 +633,12 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
if (current->rate > additional->rate) {
/* insert myself here */
if (current->prev != NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding %s before %s\n",
additional->carrier_name, current->carrier_name);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding %s before %s\n", additional->carrier_name, current->carrier_name);
current->prev->next = additional;
} else {
/* put this one at the head */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Inserting %s to list head before %s\n",
additional->carrier_name, current->carrier_name);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Inserting %s to list head before %s\n",
additional->carrier_name, current->carrier_name);
cbt->head = additional;
}
additional->next = current;
@@ -665,7 +650,7 @@ static int route_add_callback(void *pArg, int argc, char **argv, char **columnNa
break;
} else if (current->next == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "adding %s to end of list after %s\n",
additional->carrier_name, current->carrier_name);
additional->carrier_name, current->carrier_name);
current->next = additional;
additional->prev = current;
if (switch_core_hash_insert(cbt->dedup_hash, key, additional) != SWITCH_STATUS_SUCCESS) {
@@ -683,7 +668,7 @@ static int intrastatelata_callback(void *pArg, int argc, char **argv, char **col
{
int count = 0;
callback_t *cbt = (callback_t *) pArg;
count = atoi(argv[1]);
if (count == 1) {
if (!strcmp(argv[0], "state")) {
@@ -693,19 +678,19 @@ static int intrastatelata_callback(void *pArg, int argc, char **argv, char **col
}
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Type: %s, Count: %d\n", argv[0], count);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Type: %s, Count: %d\n", argv[0], count);
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t is_intrastatelata(callback_t *cb_struct)
{
char *sql = NULL;
/* extract npa nxx - make some assumptions about format:
e164 format without the +
NANP only (so 11 digits starting with 1)
*/
e164 format without the +
NANP only (so 11 digits starting with 1)
*/
if (!cb_struct->lookup_number || (strlen(cb_struct->lookup_number) != 11 && *cb_struct->lookup_number != '1')) {
/* dest doesn't appear to be NANP number */
return SWITCH_STATUS_GENERR;
@@ -714,29 +699,28 @@ static switch_status_t is_intrastatelata(callback_t *cb_struct)
/* cid not NANP */
return SWITCH_STATUS_GENERR;
}
/* assume that if the area code (plus leading 1) are the same we're intrastate */
/* probably a bad assumption */
/*
if (!strncmp(cb_struct->lookup_number, cb_struct->cid, 4)) {
cb_struct->intrastate = SWITCH_TRUE;
return SWITCH_STATUS_SUCCESS;
}
*/
if (!strncmp(cb_struct->lookup_number, cb_struct->cid, 4)) {
cb_struct->intrastate = SWITCH_TRUE;
return SWITCH_STATUS_SUCCESS;
}
*/
sql = switch_core_sprintf(cb_struct->pool,
"SELECT 'state', count(DISTINCT state) FROM npa_nxx_company_ocn WHERE (npa=%3.3s AND nxx=%3.3s) OR (npa=%3.3s AND nxx=%3.3s)"
" UNION "
"SELECT 'lata', count(DISTINCT lata) FROM npa_nxx_company_ocn WHERE (npa=%3.3s AND nxx=%3.3s) OR (npa=%3.3s AND nxx=%3.3s)",
cb_struct->lookup_number+1, cb_struct->lookup_number+4,
cb_struct->cid+1, cb_struct->cid+4,
cb_struct->lookup_number+1, cb_struct->lookup_number+4,
cb_struct->cid+1, cb_struct->cid+4);
"SELECT 'state', count(DISTINCT state) FROM npa_nxx_company_ocn WHERE (npa=%3.3s AND nxx=%3.3s) OR (npa=%3.3s AND nxx=%3.3s)"
" UNION "
"SELECT 'lata', count(DISTINCT lata) FROM npa_nxx_company_ocn WHERE (npa=%3.3s AND nxx=%3.3s) OR (npa=%3.3s AND nxx=%3.3s)",
cb_struct->lookup_number + 1, cb_struct->lookup_number + 4,
cb_struct->cid + 1, cb_struct->cid + 4,
cb_struct->lookup_number + 1, cb_struct->lookup_number + 4, cb_struct->cid + 1, cb_struct->cid + 4);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(cb_struct->session), SWITCH_LOG_DEBUG, "SQL: %s\n", sql);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(cb_struct->session), SWITCH_LOG_DEBUG, "SQL: %s\n", sql);
return (lcr_execute_sql_callback(sql, intrastatelata_callback, cb_struct));
return(lcr_execute_sql_callback(sql, intrastatelata_callback, cb_struct));
}
static switch_status_t lcr_do_lookup(callback_t *cb_struct)
@@ -752,26 +736,26 @@ static switch_status_t lcr_do_lookup(callback_t *cb_struct)
char *safe_sql = NULL;
char *rate_field = NULL;
char *user_rate_field = NULL;
switch_assert(cb_struct->lookup_number != NULL);
digits_copy = string_digitsonly(cb_struct->pool, digits);
if (zstr(digits_copy)) {
return SWITCH_STATUS_GENERR;
}
/* allocate the dedup hash */
if (switch_core_hash_init(&cb_struct->dedup_hash, cb_struct->pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(cb_struct->session), SWITCH_LOG_ERROR, "Error initializing the dedup hash\n");
return SWITCH_STATUS_GENERR;
}
digits_expanded = expand_digits(cb_struct->pool, digits_copy, cb_struct->profile->quote_in_list);
if (profile->profile_has_npanxx == SWITCH_TRUE) {
is_intrastatelata(cb_struct);
}
/* set our rate field based on env and profile */
if (cb_struct->intralata == SWITCH_TRUE && profile->profile_has_intralata == SWITCH_TRUE) {
rate_field = switch_core_strdup(cb_struct->pool, "intralata_rate");
@@ -785,7 +769,7 @@ static switch_status_t lcr_do_lookup(callback_t *cb_struct)
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(cb_struct->session), SWITCH_LOG_DEBUG, "intra routing [state:%d lata:%d] so rate field is [%s]\n",
cb_struct->intrastate, cb_struct->intralata, rate_field);
/* set some channel vars if we have a session */
if (cb_struct->session) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(cb_struct->session), SWITCH_LOG_DEBUG, "we have a session\n");
@@ -822,10 +806,10 @@ static switch_status_t lcr_do_lookup(callback_t *cb_struct)
/* channel_expand_variables returned the same string to us, no need to free */
switch_safe_free(safe_sql);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(cb_struct->session), SWITCH_LOG_DEBUG, "SQL: %s\n", (char *)sql_stream.data);
lookup_status = lcr_execute_sql_callback((char *)sql_stream.data, route_add_callback, cb_struct);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(cb_struct->session), SWITCH_LOG_DEBUG, "SQL: %s\n", (char *) sql_stream.data);
lookup_status = lcr_execute_sql_callback((char *) sql_stream.data, route_add_callback, cb_struct);
switch_safe_free(sql_stream.data);
switch_event_safe_destroy(&cb_struct->event);
@@ -848,16 +832,15 @@ static switch_bool_t test_profile(char *lcr_profile)
switch_event_create(&event, SWITCH_EVENT_MESSAGE);
routes.event = event;
routes.pool = pool;
if (!(routes.profile = locate_profile(lcr_profile))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown profile: %s\n", lcr_profile);
return SWITCH_FALSE;
}
routes.lookup_number = "15555551212";
routes.cid = "18005551212";
return (lcr_do_lookup(&routes) == SWITCH_STATUS_SUCCESS) ?
SWITCH_TRUE : SWITCH_FALSE;
return (lcr_do_lookup(&routes) == SWITCH_STATUS_SUCCESS) ? SWITCH_TRUE : SWITCH_FALSE;
}
static switch_status_t lcr_load_config()
@@ -893,19 +876,16 @@ static switch_status_t lcr_load_config()
}
}
}
/* initialize sql here, 'cause we need to verify custom_sql for each profile below */
if (globals.odbc_dsn) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG
, "dsn is \"%s\", user is \"%s\"\n"
, globals.odbc_dsn, globals.odbc_user
);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "dsn is \"%s\", user is \"%s\"\n", globals.odbc_dsn, globals.odbc_user);
if (!(dbh = lcr_get_db_handle())) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open ODBC Database!\n");
switch_goto_status(SWITCH_STATUS_FALSE, done);
}
}
if (set_db_random() == SWITCH_TRUE) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Database RANDOM function set to %s\n", db_random);
} else {
@@ -926,7 +906,7 @@ static switch_status_t lcr_load_config()
char *custom_sql = NULL;
int argc, x = 0;
char *argv[4] = { 0 };
SWITCH_STANDARD_STREAM(order_by);
for (param = switch_xml_child(x_profile, "param"); param; param = param->next) {
@@ -934,12 +914,12 @@ static switch_status_t lcr_load_config()
var = (char *) switch_xml_attr_soft(param, "name");
val = (char *) switch_xml_attr_soft(param, "value");
if (!strcasecmp(var, "order_by") && !zstr(val)) {
if (!strcasecmp(var, "order_by") && !zstr(val)) {
thisorder = &order_by;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "param val is %s\n", val);
if ((argc = switch_separate_string(val, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
for (x=0; x<argc; x++) {
for (x = 0; x < argc; x++) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "arg #%d/%d is %s\n", x, argc, argv[x]);
if (!zstr(argv[x])) {
if (!strcasecmp(argv[x], "quality")) {
@@ -976,37 +956,37 @@ static switch_status_t lcr_load_config()
quote_in_list = val;
}
}
if (zstr(name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No name specified.\n");
} else {
profile = switch_core_alloc(globals.pool, sizeof(*profile));
memset(profile, 0, sizeof(profile_t));
profile->name = switch_core_strdup(globals.pool, name);
if (!zstr((char *)order_by.data)) {
profile->order_by = switch_core_strdup(globals.pool, (char *)order_by.data);
if (!zstr((char *) order_by.data)) {
profile->order_by = switch_core_strdup(globals.pool, (char *) order_by.data);
} else {
/* default to rate */
profile->order_by = ", ${lcr_rate_field}";
}
if (!zstr(id_s)) {
profile->id = (uint16_t)atoi(id_s);
profile->id = (uint16_t) atoi(id_s);
}
/* SWITCH_STANDARD_STREAM doesn't use pools. but we only have to free sql_stream.data */
SWITCH_STANDARD_STREAM(sql_stream);
if (zstr(custom_sql)) {
/* use default sql */
sql_stream.write_function(&sql_stream,
"SELECT l.digits, c.carrier_name, l.${lcr_rate_field}, cg.prefix AS gw_prefix, cg.suffix AS gw_suffix, l.lead_strip, l.trail_strip, l.prefix, l.suffix "
);
sql_stream.write_function(&sql_stream,
"SELECT l.digits, c.carrier_name, l.${lcr_rate_field}, cg.prefix AS gw_prefix, cg.suffix AS gw_suffix, l.lead_strip, l.trail_strip, l.prefix, l.suffix ");
if (db_check("SELECT codec from carrier_gateway limit 1") == SWITCH_TRUE) {
sql_stream.write_function(&sql_stream, ", cg.codec ");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "codec field defined.\n");
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "codec field not defined, please update your lcr carrier_gateway database schema.\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"codec field not defined, please update your lcr carrier_gateway database schema.\n");
}
if (db_check("SELECT cid from lcr limit 1") == SWITCH_TRUE) {
sql_stream.write_function(&sql_stream, ", l.cid ");
@@ -1014,41 +994,38 @@ static switch_status_t lcr_load_config()
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "cid field not defined, please update your lcr database schema.\n");
}
sql_stream.write_function(&sql_stream, "FROM lcr l JOIN carriers c ON l.carrier_id=c.id JOIN carrier_gateway cg ON c.id=cg.carrier_id WHERE c.enabled = '1' AND cg.enabled = '1' AND l.enabled = '1' AND digits IN (");
sql_stream.write_function(&sql_stream,
"FROM lcr l JOIN carriers c ON l.carrier_id=c.id JOIN carrier_gateway cg ON c.id=cg.carrier_id WHERE c.enabled = '1' AND cg.enabled = '1' AND l.enabled = '1' AND digits IN (");
sql_stream.write_function(&sql_stream, "${lcr_query_expanded_digits}");
sql_stream.write_function(&sql_stream, ") AND CURRENT_TIMESTAMP BETWEEN date_start AND date_end ");
if (profile->id > 0) {
sql_stream.write_function(&sql_stream, "AND lcr_profile=%d ", profile->id);
}
sql_stream.write_function(&sql_stream, "ORDER BY digits DESC%s",
profile->order_by);
sql_stream.write_function(&sql_stream, "ORDER BY digits DESC%s", profile->order_by);
if (db_random) {
sql_stream.write_function(&sql_stream, ", %s", db_random);
}
sql_stream.write_function(&sql_stream, ";");
custom_sql = sql_stream.data;
}
profile->profile_has_intralata = db_check("SELECT intralata_rate FROM lcr LIMIT 1");
if (profile->profile_has_intralata != SWITCH_TRUE) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"no \"intralata_rate\" field found in the \"lcr\" table, routing by intralata rates will be disabled until the field is added and mod_lcr is reloaded\n"
);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"no \"intralata_rate\" field found in the \"lcr\" table, routing by intralata rates will be disabled until the field is added and mod_lcr is reloaded\n");
}
profile->profile_has_intrastate = db_check("SELECT intrastate_rate FROM lcr LIMIT 1");
if (profile->profile_has_intrastate != SWITCH_TRUE) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"no \"intrastate_rate\" field found in the \"lcr\" table, routing by intrastate rates will be disabled until the field is added and mod_lcr is reloaded\n"
);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"no \"intrastate_rate\" field found in the \"lcr\" table, routing by intrastate rates will be disabled until the field is added and mod_lcr is reloaded\n");
}
profile->profile_has_npanxx = db_check("SELECT npa, nxx, state FROM npa_nxx_company_ocn LIMIT 1");
if (profile->profile_has_npanxx != SWITCH_TRUE) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"no \"npa_nxx_company_ocn\" table found in the \"lcr\" database, automatic intrastate detection will be disabled until the table is added and mod_lcr is reloaded\n"
);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"no \"npa_nxx_company_ocn\" table found in the \"lcr\" database, automatic intrastate detection will be disabled until the table is added and mod_lcr is reloaded\n");
}
if (switch_string_var_check_const(custom_sql) || switch_string_has_escaped_data(custom_sql)) {
@@ -1057,20 +1034,20 @@ static switch_status_t lcr_load_config()
if (strstr(custom_sql, "%")) {
profile->custom_sql_has_percent = SWITCH_TRUE;
}
profile->custom_sql = switch_core_strdup(globals.pool, (char *)custom_sql);
profile->custom_sql = switch_core_strdup(globals.pool, (char *) custom_sql);
if (!zstr(reorder_by_rate)) {
profile->reorder_by_rate = switch_true(reorder_by_rate);
}
if (!zstr(info_in_headers)) {
profile->info_in_headers = switch_true(info_in_headers);
}
if (!zstr(quote_in_list)) {
profile->quote_in_list = switch_true(quote_in_list);
}
switch_core_hash_insert(globals.profile_hash, profile->name, profile);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Loaded lcr profile %s.\n", profile->name);
/* test the profile */
@@ -1083,7 +1060,7 @@ static switch_status_t lcr_load_config()
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Removing INVALID Profile %s.\n", profile->name);
switch_core_hash_delete(globals.profile_hash, profile->name);
}
}
switch_safe_free(order_by.data);
switch_safe_free(sql_stream.data);
@@ -1091,7 +1068,7 @@ static switch_status_t lcr_load_config()
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "No lcr profiles defined.\n");
}
/* define default profile */
if (!globals.default_profile) {
profile = switch_core_alloc(globals.pool, sizeof(*profile));
@@ -1102,7 +1079,7 @@ static switch_status_t lcr_load_config()
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting system defined default profile.");
}
done:
done:
switch_cache_db_release_db_handle(&dbh);
switch_xml_free(xml);
return status;
@@ -1138,17 +1115,17 @@ SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt)
intralata = switch_channel_get_variable(channel, "intralata");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "intrastate channel var is [%s]\n", intrastate);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "intralata channel var is [%s]\n", intralata);
if (!zstr(intralata) && !strcasecmp((char *)intralata, "true")) {
if (!zstr(intralata) && !strcasecmp((char *) intralata, "true")) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Select routes based on intralata rates\n");
routes.intralata = SWITCH_FALSE;
} else if (!zstr(intrastate) && !strcasecmp((char *)intrastate, "true")) {
} else if (!zstr(intrastate) && !strcasecmp((char *) intrastate, "true")) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Select routes based on intrastate rates\n");
routes.intrastate = SWITCH_TRUE;
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Select routes based on interstate rates\n");
routes.intrastate = SWITCH_FALSE;
}
if (!caller_profile) {
caller_profile = switch_channel_get_caller_profile(channel);
}
@@ -1173,7 +1150,7 @@ SWITCH_STANDARD_DIALPLAN(lcr_dialplan_hunt)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "LCR lookup failed for %s\n", caller_profile->destination_number);
}
end:
end:
if (!session) {
switch_core_destroy_memory_pool(&pool);
}
@@ -1184,9 +1161,9 @@ void str_repeat(size_t how_many, char *what, switch_stream_handle_t *str_stream)
{
size_t i;
/*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "repeating %d of '%s'\n", (int)how_many, what);*/
for (i=0; i<how_many; i++) {
/*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "repeating %d of '%s'\n", (int)how_many, what); */
for (i = 0; i < how_many; i++) {
str_stream->write_function(str_stream, "%s", what);
}
}
@@ -1227,9 +1204,8 @@ SWITCH_STANDARD_APP(lcr_app_function)
routes.pool = pool;
intra = switch_channel_get_variable(channel, "intrastate");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "intrastate channel var is [%s]\n",
zstr(intra) ? "undef" : intra);
if (zstr(intra) || strcasecmp((char *)intra, "true")) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "intrastate channel var is [%s]\n", zstr(intra) ? "undef" : intra);
if (zstr(intra) || strcasecmp((char *) intra, "true")) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Select routes based on interstate rates\n");
routes.intrastate = SWITCH_FALSE;
} else {
@@ -1248,7 +1224,7 @@ SWITCH_STANDARD_APP(lcr_app_function)
if (argc > 1) {
lcr_profile = argv[1];
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "LCR Lookup on %s using profile %s\n", dest, lcr_profile);
routes.lookup_number = dest;
if (caller_profile) {
@@ -1258,7 +1234,7 @@ SWITCH_STANDARD_APP(lcr_app_function)
}
}
if (!(routes.profile = locate_profile(lcr_profile))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Unknown profile: %s\n", lcr_profile);
goto end;
@@ -1289,16 +1265,17 @@ SWITCH_STANDARD_APP(lcr_app_function)
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "LCR lookup failed for %s\n", dest);
}
}
end:
end:
if (!session) {
switch_core_destroy_memory_pool(&pool);
}
}
static void write_data(switch_stream_handle_t *stream, switch_bool_t as_xml, const char *key, const char *data, int indent, int maxlen) {
static void write_data(switch_stream_handle_t *stream, switch_bool_t as_xml, const char *key, const char *data, int indent, int maxlen)
{
if (as_xml) {
str_repeat(indent*2, " ", stream);
str_repeat(indent * 2, " ", stream);
stream->write_function(stream, "<%s>%s</%s>\n", key, data, key);
} else {
stream->write_function(stream, " | %s", data);
@@ -1320,15 +1297,13 @@ SWITCH_STANDARD_API(dialplan_lcr_function)
switch_event_t *event;
switch_status_t lookup_status = SWITCH_STATUS_SUCCESS;
switch_bool_t as_xml = SWITCH_FALSE;
int rowcount=0;
int rowcount = 0;
if (zstr(cmd)) {
goto usage;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG
, "data passed to lcr is [%s]\n", cmd
);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "data passed to lcr is [%s]\n", cmd);
if (session) {
pool = switch_core_session_get_pool(session);
@@ -1339,7 +1314,7 @@ SWITCH_STANDARD_API(dialplan_lcr_function)
cb_struct.event = event;
}
cb_struct.pool = pool;
mydata = switch_core_strdup(pool, cmd);
if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
@@ -1350,29 +1325,27 @@ SWITCH_STANDARD_API(dialplan_lcr_function)
}
if (argc > 2) {
int i;
for (i=2; i<argc; i++) {
for (i = 2; i < argc; i++) {
if (!strcasecmp(argv[i], "intrastate")) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Select routes based on intrastate rates\n");
cb_struct.intrastate = SWITCH_TRUE;
} else if (!strcasecmp(argv[i], "as")) {
i++;
if (argv[i] && !strcasecmp(argv[i], "xml")) {
as_xml = SWITCH_TRUE;
} else {
goto usage;
}
as_xml = SWITCH_TRUE;
} else {
goto usage;
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set Caller ID to [%s]\n", argv[i]);
/* the only other option we have right now is caller id */
cb_struct.cid = switch_core_strdup(pool, argv[i]);
}
}
}
}
if (zstr(cb_struct.cid)) {
cb_struct.cid = "18005551212";
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING
, "Using default CID [%s]\n", cb_struct.cid
);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Using default CID [%s]\n", cb_struct.cid);
}
@@ -1432,7 +1405,7 @@ SWITCH_STANDARD_API(dialplan_lcr_function)
if (as_xml) {
stream->write_function(stream, " <row id=\"%d\">\n", rowcount);
}
write_data(stream, as_xml, "prefix", current->digit_str, 2, maximum_lengths.digit_str);
write_data(stream, as_xml, "carrier_name", current->carrier_name, 2, maximum_lengths.carrier_name);
write_data(stream, as_xml, "rate", current->rate_str, 2, maximum_lengths.rate);
@@ -1447,7 +1420,7 @@ SWITCH_STANDARD_API(dialplan_lcr_function)
} else {
write_data(stream, as_xml, "cid", "", 2, maximum_lengths.cid);
}
write_data(stream, as_xml, "dialstring", current->dialstring, 2, maximum_lengths.dialstring);
if (as_xml) {
@@ -1473,14 +1446,14 @@ SWITCH_STANDARD_API(dialplan_lcr_function)
}
}
end:
end:
if (!session) {
if (pool) {
switch_core_destroy_memory_pool(&pool);
}
}
return SWITCH_STATUS_SUCCESS;
usage:
usage:
stream->write_function(stream, "USAGE: %s\n", LCR_SYNTAX);
goto end;
}
@@ -1509,7 +1482,7 @@ SWITCH_STANDARD_API(dialplan_lcr_admin_function)
for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val);
profile = (profile_t *) val;
stream->write_function(stream, "Name:\t\t%s\n", profile->name);
if (zstr(profile->custom_sql)) {
stream->write_function(stream, " ID:\t\t%d\n", profile->id);
@@ -1522,12 +1495,9 @@ SWITCH_STANDARD_API(dialplan_lcr_admin_function)
stream->write_function(stream, " has intrastate:\t%s\n", profile->profile_has_intrastate ? "true" : "false");
stream->write_function(stream, " has intralata:\t%s\n", profile->profile_has_intralata ? "true" : "false");
stream->write_function(stream, " has npanxx:\t%s\n", profile->profile_has_npanxx ? "true" : "false");
stream->write_function(stream, " Reorder rate:\t%s\n",
profile->reorder_by_rate ? "enabled" : "disabled");
stream->write_function(stream, " Info in headers:\t%s\n",
profile->info_in_headers ? "enabled" : "disabled");
stream->write_function(stream, " Quote IN() List:\t%s\n",
profile->quote_in_list ? "enabled" : "disabled");
stream->write_function(stream, " Reorder rate:\t%s\n", profile->reorder_by_rate ? "enabled" : "disabled");
stream->write_function(stream, " Info in headers:\t%s\n", profile->info_in_headers ? "enabled" : "disabled");
stream->write_function(stream, " Quote IN() List:\t%s\n", profile->quote_in_list ? "enabled" : "disabled");
stream->write_function(stream, "\n");
}
} else {
@@ -1536,20 +1506,20 @@ SWITCH_STANDARD_API(dialplan_lcr_admin_function)
}
switch_safe_free(mydata);
return SWITCH_STATUS_SUCCESS;
usage:
usage:
switch_safe_free(mydata);
stream->write_function(stream, "-ERR %s\n", LCR_ADMIN_SYNTAX);
return SWITCH_STATUS_SUCCESS;
}
SWITCH_MODULE_LOAD_FUNCTION(mod_lcr_load)
{
switch_api_interface_t *dialplan_lcr_api_interface;
switch_api_interface_t *dialplan_lcr_api_admin_interface;
switch_application_interface_t *app_interface;
switch_dialplan_interface_t *dp_interface;
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
if (!switch_odbc_available()) {
@@ -1573,7 +1543,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_lcr_load)
SWITCH_ADD_APP(app_interface, "lcr", "Perform an LCR lookup", "Perform an LCR lookup",
lcr_app_function, "<number>", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC);
SWITCH_ADD_DIALPLAN(dp_interface, "lcr", lcr_dialplan_hunt);
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
+140 -153
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -51,12 +51,12 @@ static struct {
char *odbc_pass;
switch_mutex_t *mutex;
switch_mutex_t *limit_hash_mutex;
switch_hash_t *limit_hash;
switch_hash_t *limit_hash;
switch_mutex_t *db_hash_mutex;
switch_hash_t *db_hash;
switch_hash_t *db_hash;
} globals;
typedef struct {
typedef struct {
uint32_t total_usage;
uint32_t rate_usage;
time_t last_check;
@@ -68,43 +68,33 @@ typedef struct {
static char limit_sql[] =
"CREATE TABLE limit_data (\n"
" hostname VARCHAR(255),\n"
" realm VARCHAR(255),\n"
" id VARCHAR(255),\n"
" uuid VARCHAR(255)\n"
");\n";
" hostname VARCHAR(255),\n" " realm VARCHAR(255),\n" " id VARCHAR(255),\n" " uuid VARCHAR(255)\n" ");\n";
static char db_sql[] =
"CREATE TABLE db_data (\n"
" hostname VARCHAR(255),\n"
" realm VARCHAR(255),\n"
" data_key VARCHAR(255),\n"
" data VARCHAR(255)\n"
");\n";
" hostname VARCHAR(255),\n" " realm VARCHAR(255),\n" " data_key VARCHAR(255),\n" " data VARCHAR(255)\n" ");\n";
static char group_sql[] =
"CREATE TABLE group_data (\n"
" hostname VARCHAR(255),\n"
" groupname VARCHAR(255),\n"
" url VARCHAR(255)\n"
");\n";
"CREATE TABLE group_data (\n" " hostname VARCHAR(255),\n" " groupname VARCHAR(255),\n" " url VARCHAR(255)\n" ");\n";
switch_cache_db_handle_t *limit_get_db_handle(void)
{
switch_cache_db_connection_options_t options = { {0} };
switch_cache_db_handle_t *dbh = NULL;
if (!zstr(globals.odbc_dsn)) {
options.odbc_options.dsn = globals.odbc_dsn;
options.odbc_options.user = globals.odbc_user;
options.odbc_options.pass = globals.odbc_pass;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS) dbh = NULL;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) != SWITCH_STATUS_SUCCESS)
dbh = NULL;
return dbh;
} else {
options.core_db_options.db_path = globals.dbname;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_CORE_DB, &options) != SWITCH_STATUS_SUCCESS) dbh = NULL;
if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_CORE_DB, &options) != SWITCH_STATUS_SUCCESS)
dbh = NULL;
return dbh;
}
}
@@ -127,7 +117,7 @@ static switch_status_t limit_execute_sql(char *sql, switch_mutex_t *mutex)
status = switch_cache_db_execute_sql(dbh, sql, NULL);
end:
switch_cache_db_release_db_handle(&dbh);
if (mutex) {
@@ -142,16 +132,16 @@ static switch_bool_t limit_execute_sql_callback(switch_mutex_t *mutex, char *sql
switch_bool_t ret = SWITCH_FALSE;
char *errmsg = NULL;
switch_cache_db_handle_t *dbh = NULL;
if (mutex) {
switch_mutex_lock(mutex);
}
if (!(dbh = limit_get_db_handle())) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n");
goto end;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n");
goto end;
}
switch_cache_db_execute_sql_callback(dbh, sql, callback, pdata, &errmsg);
if (errmsg) {
@@ -174,8 +164,8 @@ static switch_bool_t limit_execute_sql_callback(switch_mutex_t *mutex, char *sql
static switch_xml_config_string_options_t limit_config_dsn = { NULL, 0, "[^:]+:[^:]+:.+" };
static switch_xml_config_item_t config_settings[] = {
SWITCH_CONFIG_ITEM("odbc-dsn", SWITCH_CONFIG_STRING, 0, &globals.odbc_dsn, NULL, &limit_config_dsn,
"dsn:username:password", "If set, the ODBC DSN used by the limit and db applications"),
SWITCH_CONFIG_ITEM("odbc-dsn", SWITCH_CONFIG_STRING, 0, &globals.odbc_dsn, NULL, &limit_config_dsn,
"dsn:username:password", "If set, the ODBC DSN used by the limit and db applications"),
SWITCH_CONFIG_ITEM_END()
};
@@ -184,13 +174,13 @@ static switch_status_t do_config()
switch_cache_db_handle_t *dbh = NULL;
switch_status_t status = SWITCH_STATUS_SUCCESS;
char *sql = NULL;
limit_config_dsn.pool = globals.pool;
if (switch_xml_config_parse_module_settings("limit.conf", SWITCH_FALSE, config_settings) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_TERM;
}
if (globals.odbc_dsn) {
if ((globals.odbc_user = strchr(globals.odbc_dsn, ':'))) {
*globals.odbc_user++ = '\0';
@@ -203,7 +193,7 @@ static switch_status_t do_config()
globals.odbc_dsn = globals.odbc_user = globals.odbc_pass;
}
}
if (zstr(globals.odbc_dsn)) {
globals.dbname = "call_limit";
@@ -225,16 +215,16 @@ static switch_status_t do_config()
NULL
};
switch_cache_db_test_reactive(dbh, "select * from limit_data", NULL, limit_sql);
switch_cache_db_test_reactive(dbh, "select * from db_data", NULL, db_sql);
switch_cache_db_test_reactive(dbh, "select * from group_data", NULL, group_sql);
for (x = 0; indexes[x]; x++) {
switch_cache_db_execute_sql(dbh, indexes[x], NULL);
}
switch_cache_db_release_db_handle(&dbh);
sql = switch_mprintf("delete from limit_data where hostname='%q';", globals.hostname);
@@ -248,7 +238,7 @@ static switch_status_t do_config()
static void limit_fire_event(const char *realm, const char *key, uint32_t usage, uint32_t rate, uint32_t max, uint32_t ratemax)
{
switch_event_t *event;
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, LIMIT_EVENT_USAGE) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "realm", realm);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "key", key);
@@ -268,8 +258,7 @@ static switch_status_t db_state_handler(switch_core_session_t *session)
const char *vval = switch_channel_get_variable(channel, LIMIT_IGNORE_TRANSFER_VARIABLE);
if (state >= CS_HANGUP || (state == CS_ROUTING && !switch_true(vval))) {
sql = switch_mprintf("delete from limit_data where uuid='%q';",
switch_core_session_get_uuid(session));
sql = switch_mprintf("delete from limit_data where uuid='%q';", switch_core_session_get_uuid(session));
limit_execute_sql(sql, globals.mutex);
switch_safe_free(sql);
switch_core_event_hook_remove_state_change(session, db_state_handler);
@@ -279,47 +268,46 @@ static switch_status_t db_state_handler(switch_core_session_t *session)
return SWITCH_STATUS_SUCCESS;
}
static switch_status_t hash_state_handler(switch_core_session_t *session)
static switch_status_t hash_state_handler(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_channel_state_t state = switch_channel_get_state(channel);
limit_hash_private_t *pvt = switch_channel_get_private(channel, "limit_hash");
const char *vval = switch_channel_get_variable(channel, LIMIT_IGNORE_TRANSFER_VARIABLE);
/* The call is either hung up, or is going back into the dialplan, decrement appropriate couters */
if (state >= CS_HANGUP || (state == CS_ROUTING && !switch_true(vval))) {
if (state >= CS_HANGUP || (state == CS_ROUTING && !switch_true(vval))) {
switch_hash_index_t *hi;
switch_mutex_lock(globals.limit_hash_mutex);
/* Loop through the channel's hashtable which contains mapping to all the limit_hash_item_t referenced by that channel */
while((hi = switch_hash_first(NULL, pvt->hash)))
{
while ((hi = switch_hash_first(NULL, pvt->hash))) {
void *val = NULL;
const void *key;
switch_ssize_t keylen;
limit_hash_item_t *item = NULL;
switch_hash_this(hi, &key, &keylen, &val);
item = (limit_hash_item_t*)val;
item->total_usage--;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s is now %d\n", (const char*)key, item->total_usage);
if (item->total_usage == 0) {
item = (limit_hash_item_t *) val;
item->total_usage--;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s is now %d\n", (const char *) key, item->total_usage);
if (item->total_usage == 0) {
/* Noone is using this item anymore */
switch_core_hash_delete(globals.limit_hash, (const char*)key);
switch_core_hash_delete(globals.limit_hash, (const char *) key);
free(item);
}
switch_core_hash_delete(pvt->hash, (const char*)key);
switch_core_hash_delete(pvt->hash, (const char *) key);
}
/* Remove handler */
switch_core_event_hook_remove_state_change(session, hash_state_handler);
switch_mutex_unlock(globals.limit_hash_mutex);
}
return SWITCH_STATUS_SUCCESS;
}
@@ -474,21 +462,21 @@ SWITCH_STANDARD_APP(hash_function)
char *mydata = NULL;
char *hash_key = NULL;
char *value = NULL;
switch_mutex_lock(globals.db_hash_mutex);
if (!zstr(data)) {
mydata = strdup(data);
switch_assert(mydata);
argc = switch_separate_string(mydata, '/', argv, (sizeof(argv) / sizeof(argv[0])));
}
if (argc < 3 || !argv[0]) {
goto usage;
}
hash_key = switch_mprintf("%s_%s", argv[1], argv[2]);
if (!strcasecmp(argv[0], "insert")) {
if (argc < 4) {
goto usage;
@@ -508,13 +496,13 @@ SWITCH_STANDARD_APP(hash_function)
} else {
goto usage;
}
goto done;
usage:
usage:
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "USAGE: hash %s\n", HASH_USAGE);
done:
done:
switch_mutex_unlock(globals.db_hash_mutex);
switch_safe_free(mydata);
switch_safe_free(hash_key);
@@ -536,13 +524,13 @@ SWITCH_STANDARD_API(hash_api_function)
switch_assert(mydata);
argc = switch_separate_string(mydata, '/', argv, (sizeof(argv) / sizeof(argv[0])));
}
if (argc < 3 || !argv[0]) {
goto usage;
}
hash_key = switch_mprintf("%s_%s", argv[1], argv[2]);
if (!strcasecmp(argv[0], "insert")) {
if (argc < 4) {
goto usage;
@@ -570,17 +558,17 @@ SWITCH_STANDARD_API(hash_api_function)
} else {
goto usage;
}
goto done;
usage:
usage:
stream->write_function(stream, "-ERR Usage: hash %s\n", HASH_API_USAGE);
done:
done:
switch_mutex_unlock(globals.db_hash_mutex);
switch_safe_free(mydata);
switch_safe_free(hash_key);
return SWITCH_STATUS_SUCCESS;
}
@@ -649,7 +637,7 @@ SWITCH_STANDARD_API(group_api_function)
limit_execute_sql_callback(NULL, sql, group_callback, &cbt);
switch_safe_free(sql);
*(buf + (strlen(buf) - 1)) = '\0';
stream->write_function(stream, "%s", buf);
@@ -729,9 +717,9 @@ static switch_bool_t do_limit(switch_core_session_t *session, const char *realm,
got = atoi(buf);
if (max < 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s_%s is now %d\n", realm, id, got+1);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s_%s is now %d\n", realm, id, got + 1);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s_%s is now %d/%d\n", realm, id, got+1, max);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s_%s is now %d/%d\n", realm, id, got + 1, max);
}
if (max >= 0 && got + 1 > max) {
@@ -746,7 +734,7 @@ static switch_bool_t do_limit(switch_core_session_t *session, const char *realm,
switch_core_session_get_uuid(session));
limit_execute_sql(sql, NULL);
switch_safe_free(sql);
{
const char *susage = switch_core_session_sprintf(session, "%d", ++got);
@@ -787,8 +775,8 @@ SWITCH_STANDARD_APP(limit_function)
realm = argv[0];
id = argv[1];
/* Accept '-' as unlimited (act as counter)*/
/* Accept '-' as unlimited (act as counter) */
if (argv[2][0] == '-') {
max = -1;
} else {
@@ -796,7 +784,7 @@ SWITCH_STANDARD_APP(limit_function)
if (max < 0) {
max = 0;
}
}
}
if (argc >= 4) {
@@ -808,12 +796,12 @@ SWITCH_STANDARD_APP(limit_function)
if (!do_limit(session, realm, id, max)) {
/* Limit exceeded */
if (*xfer_exten == '!') {
switch_channel_hangup(channel, switch_channel_str2cause(xfer_exten+1));
switch_channel_hangup(channel, switch_channel_str2cause(xfer_exten + 1));
} else {
switch_ivr_session_transfer(session, xfer_exten, argv[4], argv[5]);
}
}
}
/* !\brief Releases usage of a limit_-controlled ressource */
@@ -821,8 +809,7 @@ static void limit_release(switch_core_session_t *session, const char *realm, con
{
char *sql = NULL;
sql = switch_mprintf("delete from limit_data where uuid='%q' and realm='%q' and id like '%q'",
switch_core_session_get_uuid(session), realm, id);
sql = switch_mprintf("delete from limit_data where uuid='%q' and realm='%q' and id like '%q'", switch_core_session_get_uuid(session), realm, id);
limit_execute_sql(sql, globals.mutex);
switch_safe_free(sql);
}
@@ -845,16 +832,16 @@ SWITCH_STANDARD_APP(limit_execute_function)
mydata = switch_core_session_strdup(session, data);
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
}
if (argc < 2) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "USAGE: limit_execute %s\n", LIMITEXECUTE_USAGE);
return;
}
realm = argv[0];
id = argv[1];
/* Accept '-' as unlimited (act as counter)*/
/* Accept '-' as unlimited (act as counter) */
if (argv[2][0] == '-') {
max = -1;
} else {
@@ -862,7 +849,7 @@ SWITCH_STANDARD_APP(limit_execute_function)
if (max < 0) {
max = 0;
}
}
}
app = argv[3];
@@ -915,7 +902,7 @@ SWITCH_STANDARD_API(limit_usage_function)
stream->write_function(stream, "%s", buf);
end:
end:
switch_safe_free(mydata);
return SWITCH_STATUS_SUCCESS;
}
@@ -937,22 +924,21 @@ static switch_bool_t do_limit_hash(switch_core_session_t *session, const char *r
time_t now = switch_epoch_time_now(NULL);
limit_hash_private_t *pvt = NULL;
uint8_t increment = 1;
hashkey = switch_core_session_sprintf(session, "%s_%s", realm, id);
switch_mutex_lock(globals.limit_hash_mutex);
/* Check if that realm+id has ever been checked */
if (!(item = (limit_hash_item_t*)switch_core_hash_find(globals.limit_hash, hashkey))) {
if (!(item = (limit_hash_item_t *) switch_core_hash_find(globals.limit_hash, hashkey))) {
/* No, create an empty structure and add it, then continue like as if it existed */
item = (limit_hash_item_t*)malloc(sizeof(limit_hash_item_t));
item = (limit_hash_item_t *) malloc(sizeof(limit_hash_item_t));
switch_assert(item);
memset(item, 0, sizeof(limit_hash_item_t));
switch_core_hash_insert(globals.limit_hash, hashkey, item);
}
/* Did we already run on this channel before? */
if ((pvt = switch_channel_get_private(channel, "limit_hash")))
{
if ((pvt = switch_channel_get_private(channel, "limit_hash"))) {
/* Yes, but check if we did that realm+id
If we didnt, allow incrementing the counter.
If we did, dont touch it but do the validation anyways
@@ -960,7 +946,7 @@ static switch_bool_t do_limit_hash(switch_core_session_t *session, const char *r
increment = !switch_core_hash_find(pvt->hash, hashkey);
} else {
/* This is the first limit check on this channel, create a hashtable, set our prviate data and add a state handler */
pvt = (limit_hash_private_t*)switch_core_session_alloc(session, sizeof(limit_hash_private_t));
pvt = (limit_hash_private_t *) switch_core_session_alloc(session, sizeof(limit_hash_private_t));
memset(pvt, 0, sizeof(limit_hash_private_t));
switch_core_hash_init(&pvt->hash, switch_core_session_get_pool(session));
switch_channel_set_private(channel, "limit_hash", pvt);
@@ -974,13 +960,14 @@ static switch_bool_t do_limit_hash(switch_core_session_t *session, const char *r
/* Always increment rate when its checked as it doesnt depend on the channel */
item->rate_usage++;
if ((max >= 0) && (item->rate_usage > (uint32_t)max)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s exceeds maximum rate of %d/%ds, now at %d\n", hashkey, max, interval, item->rate_usage);
if ((max >= 0) && (item->rate_usage > (uint32_t) max)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s exceeds maximum rate of %d/%ds, now at %d\n",
hashkey, max, interval, item->rate_usage);
status = SWITCH_FALSE;
goto end;
}
}
} else if ((max >= 0) && (item->total_usage + increment > (uint32_t)max)) {
} else if ((max >= 0) && (item->total_usage + increment > (uint32_t) max)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s is already at max value (%d)\n", hashkey, item->total_usage);
status = SWITCH_FALSE;
goto end;
@@ -994,12 +981,13 @@ static switch_bool_t do_limit_hash(switch_core_session_t *session, const char *r
if (max == -1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s is now %d\n", hashkey, item->total_usage);
} else if (interval == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s is now %d/%d\n", hashkey, item->total_usage, max);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s is now %d/%d\n", hashkey, item->total_usage, max);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s is now %d/%d for the last %d seconds\n", hashkey, item->rate_usage, max, interval);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s is now %d/%d for the last %d seconds\n", hashkey,
item->rate_usage, max, interval);
}
limit_fire_event(realm, id, item->total_usage, item->rate_usage, max, max >=0 ? (uint32_t)max : 0);
limit_fire_event(realm, id, item->total_usage, item->rate_usage, max, max >= 0 ? (uint32_t) max : 0);
}
/* Save current usage & rate into channel variables so it can be used later in the dialplan, or added to CDR records */
@@ -1016,7 +1004,7 @@ static switch_bool_t do_limit_hash(switch_core_session_t *session, const char *r
switch_core_event_hook_add_state_change(session, hash_state_handler);
end:
end:
switch_mutex_unlock(globals.limit_hash_mutex);
return status;
}
@@ -1028,28 +1016,28 @@ static void limit_hash_release(switch_core_session_t *session, const char *realm
limit_hash_private_t *pvt = switch_channel_get_private(channel, "limit_hash");
limit_hash_item_t *item = NULL;
char *hashkey = NULL;
if (!pvt || !pvt->hash) {
return;
}
hashkey = switch_core_session_sprintf(session, "%s_%s", realm, id);
switch_mutex_lock(globals.limit_hash_mutex);
if ((item = (limit_hash_item_t*)switch_core_hash_find(pvt->hash, hashkey))) {
item->total_usage--;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s is now %d\n", (const char*)hashkey, item->total_usage);
if ((item = (limit_hash_item_t *) switch_core_hash_find(pvt->hash, hashkey))) {
item->total_usage--;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Usage for %s is now %d\n", (const char *) hashkey, item->total_usage);
switch_core_hash_delete(pvt->hash, hashkey);
if (item->total_usage == 0) {
if (item->total_usage == 0) {
/* Noone is using this item anymore */
switch_core_hash_delete(globals.limit_hash, (const char*)hashkey);
switch_core_hash_delete(globals.limit_hash, (const char *) hashkey);
free(item);
}
}
switch_mutex_unlock(globals.limit_hash_mutex);
}
@@ -1072,29 +1060,28 @@ SWITCH_STANDARD_APP(limit_hash_function)
mydata = switch_core_session_strdup(session, data);
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
}
if (argc < 2) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "USAGE: limit_hash %s\n", LIMITHASH_USAGE);
return;
}
realm = argv[0];
id = argv[1];
/* If max is omitted or negative, only act as a counter and skip maximum checks */
if (argc > 2) {
if (argv[2][0] == '-') {
max = -1;
} else {
char *szinterval = NULL;
if ((szinterval = strchr(argv[2], '/')))
{
if ((szinterval = strchr(argv[2], '/'))) {
*szinterval++ = '\0';
interval = atoi(szinterval);
}
max = atoi(argv[2]);
if (max < 0) {
max = 0;
}
@@ -1106,11 +1093,11 @@ SWITCH_STANDARD_APP(limit_hash_function)
} else {
xfer_exten = limit_def_xfer_exten;
}
if (!do_limit_hash(session, realm, id, max, interval)) {
/* Limit exceeded */
if (*xfer_exten == '!') {
switch_channel_hangup(channel, switch_channel_str2cause(xfer_exten+1));
switch_channel_hangup(channel, switch_channel_str2cause(xfer_exten + 1));
} else {
switch_ivr_session_transfer(session, xfer_exten, argv[4], argv[5]);
}
@@ -1137,23 +1124,22 @@ SWITCH_STANDARD_APP(limit_hash_execute_function)
mydata = switch_core_session_strdup(session, data);
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
}
if (argc < 5) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "USAGE: limit_hash_execute %s\n", LIMITHASHEXECUTE_USAGE);
return;
}
realm = argv[0];
id = argv[1];
/* Accept '-' as unlimited (act as counter)*/
/* Accept '-' as unlimited (act as counter) */
if (argv[2][0] == '-') {
max = -1;
} else {
char *szinterval = NULL;
if ((szinterval = strchr(argv[2], '/')))
{
if ((szinterval = strchr(argv[2], '/'))) {
*szinterval++ = '\0';
interval = atoi(szinterval);
}
@@ -1162,9 +1148,9 @@ SWITCH_STANDARD_APP(limit_hash_execute_function)
if (max < 0) {
max = 0;
}
}
}
app = argv[3];
app_arg = argv[4];
@@ -1191,31 +1177,31 @@ SWITCH_STANDARD_API(limit_hash_usage_function)
uint32_t count = 0;
switch_mutex_lock(globals.limit_hash_mutex);
if (!zstr(cmd)) {
mydata = strdup(cmd);
switch_assert(mydata);
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
}
if (argc < 2) {
stream->write_function(stream, "USAGE: limit_hash_usage %s\n", LIMIT_HASH_USAGE_USAGE);
goto end;
}
hash_key = switch_mprintf("%s_%s", argv[0], argv[1]);
if ((item = switch_core_hash_find(globals.limit_hash, hash_key))) {
count = item->total_usage;
}
}
stream->write_function(stream, "%d", count);
end:
end:
switch_safe_free(mydata);
switch_safe_free(hash_key);
switch_mutex_unlock(globals.limit_hash_mutex);
return SWITCH_STATUS_SUCCESS;
}
@@ -1231,11 +1217,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_limit_load)
if (switch_event_reserve_subclass(LIMIT_EVENT_USAGE) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldnt register event subclass \"%s\"",
LIMIT_EVENT_USAGE);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldnt register event subclass \"%s\"", LIMIT_EVENT_USAGE);
return SWITCH_STATUS_FALSE;
}
if ((status = do_config() != SWITCH_STATUS_SUCCESS)) {
return status;
}
@@ -1248,18 +1233,20 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_limit_load)
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_APP(app_interface, "limit", "Limit", LIMIT_DESC, limit_function, LIMIT_USAGE, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "limit_execute", "Limit", LIMITEXECUTE_USAGE, limit_execute_function, LIMITEXECUTE_USAGE, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "limit_hash", "Limit (hash)", LIMITHASH_DESC, limit_hash_function, LIMITHASH_USAGE, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "limit_hash_execute", "Limit (hash)", LIMITHASHEXECUTE_USAGE, limit_hash_execute_function, LIMITHASHEXECUTE_USAGE, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "limit_hash_execute", "Limit (hash)", LIMITHASHEXECUTE_USAGE, limit_hash_execute_function, LIMITHASHEXECUTE_USAGE,
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "db", "Insert to the db", DB_DESC, db_function, DB_USAGE, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "hash", "Insert into the hashtable", HASH_DESC, hash_function, HASH_USAGE, SAF_SUPPORT_NOMEDIA)
SWITCH_ADD_APP(app_interface, "group", "Manage a group", GROUP_DESC, group_function, GROUP_USAGE, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "group", "Manage a group", GROUP_DESC, group_function, GROUP_USAGE, SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_API(commands_api_interface, "limit_hash_usage", "Gets the usage count of a limited resource", limit_hash_usage_function, LIMIT_HASH_USAGE_USAGE);
SWITCH_ADD_API(commands_api_interface, "limit_hash_usage", "Gets the usage count of a limited resource", limit_hash_usage_function,
LIMIT_HASH_USAGE_USAGE);
SWITCH_ADD_API(commands_api_interface, "limit_usage", "Gets the usage count of a limited resource", limit_usage_function, "<realm> <id>");
SWITCH_ADD_API(commands_api_interface, "db", "db get/set", db_api_function, "[insert|delete|select]/<realm>/<key>/<value>");
switch_console_set_complete("add db insert");
@@ -1279,13 +1266,13 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_limit_load)
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_limit_shutdown)
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_limit_shutdown)
{
switch_event_free_subclass(LIMIT_EVENT_USAGE);
switch_xml_config_cleanup(config_settings);
switch_mutex_destroy(globals.mutex);
switch_mutex_destroy(globals.limit_hash_mutex);
switch_mutex_destroy(globals.db_hash_mutex);
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -42,11 +42,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_memcache_load);
SWITCH_MODULE_DEFINITION(mod_memcache, mod_memcache_load, mod_memcache_shutdown, NULL);
static char *SYNTAX = "memcache <set|replace|add> <key> <value> [expiration [flags]]\n"
"memcache <get|getflags> <key>\n"
"memcache <delete> <key>\n"
"memcache <increment|decrement> <key> [offset [expires [flags]]]\n"
"memcache <flush>\n"
"memcache <status> [verbose]\n";
"memcache <get|getflags> <key>\n"
"memcache <delete> <key>\n" "memcache <increment|decrement> <key> [offset [expires [flags]]]\n" "memcache <flush>\n" "memcache <status> [verbose]\n";
static struct {
memcached_st *memcached;
@@ -55,7 +52,8 @@ static struct {
static switch_event_node_t *NODE = NULL;
static switch_status_t config_callback_memcached(switch_xml_config_item_t *data, const char *newvalue, switch_config_callback_type_t callback_type, switch_bool_t changed)
static switch_status_t config_callback_memcached(switch_xml_config_item_t *data, const char *newvalue, switch_config_callback_type_t callback_type,
switch_bool_t changed)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
memcached_server_st *memcached_server = NULL;
@@ -64,23 +62,23 @@ static switch_status_t config_callback_memcached(switch_xml_config_item_t *data,
const char *memcached_str = NULL;
memcached_return rc;
unsigned int servercount;
if ((callback_type == CONFIG_LOAD || callback_type == CONFIG_RELOAD) && changed) {
memcached_str = newvalue;
/* initialize main ptr */
memcached_server = memcached_servers_parse(memcached_str);
if (!memcached_server) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to initialize memcached data structure (server_list).\n");
switch_goto_status(SWITCH_STATUS_GENERR, end);
}
if ((servercount = memcached_server_list_count(memcached_server)) == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No memcache servers defined. Server string: %s.\n", memcached_str);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%u servers defined (%s).\n", servercount, memcached_str);
}
/* setup memcached */
newmemcached = memcached_create(NULL);
if (!newmemcached) {
@@ -93,16 +91,16 @@ static switch_status_t config_callback_memcached(switch_xml_config_item_t *data,
switch_goto_status(SWITCH_STATUS_GENERR, end);
}
/* memcached_behavior_set(newmemcached, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1); */
/* swap pointers */
oldmemcached = globals.memcached;
globals.memcached = newmemcached;
newmemcached = NULL;
}
switch_goto_status(SWITCH_STATUS_SUCCESS, end);
end:
end:
if (memcached_server) {
memcached_server_list_free(memcached_server);
}
@@ -115,12 +113,13 @@ end:
return status;
}
static switch_xml_config_string_options_t config_opt_memcache_servers = {NULL, 0, NULL}; /* anything ok */
static switch_xml_config_string_options_t config_opt_memcache_servers = { NULL, 0, NULL }; /* anything ok */
static switch_xml_config_item_t instructions[] = {
/* parameter name type reloadable pointer default value options structure */
SWITCH_CONFIG_ITEM_CALLBACK("memcache-servers", SWITCH_CONFIG_STRING, CONFIG_REQUIRED | CONFIG_RELOAD, &globals.memcached_str, "", config_callback_memcached, &config_opt_memcache_servers,
"host,host:port,host", "List of memcached servers."),
SWITCH_CONFIG_ITEM_CALLBACK("memcache-servers", SWITCH_CONFIG_STRING, CONFIG_REQUIRED | CONFIG_RELOAD, &globals.memcached_str, "",
config_callback_memcached, &config_opt_memcache_servers,
"host,host:port,host", "List of memcached servers."),
SWITCH_CONFIG_ITEM_END()
};
@@ -129,8 +128,8 @@ static switch_status_t do_config(switch_bool_t reload)
if (switch_xml_config_parse_module_settings("memcache.conf", reload, instructions) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_GENERR;
}
return SWITCH_STATUS_SUCCESS;
}
@@ -154,42 +153,42 @@ SWITCH_STANDARD_API(memcache_function)
time_t expires = 0;
uint32_t flags = 0;
unsigned int server_count = 0;
memcached_return rc;
memcached_st *memcached = NULL;
memcached_stat_st *stat = NULL;
memcached_server_st *server_list;
if (zstr(cmd)) {
goto usage;
}
mydata = strdup(cmd);
if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
if (argc < 1) {
goto usage;
}
/* clone memcached struct so we're thread safe */
memcached = memcached_clone(NULL, globals.memcached);
if (!memcached) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error cloning memcached object");
stream->write_function(stream, "-ERR Error cloning memcached object\n");
}
subcmd = argv[0];
if ((!strcasecmp(subcmd, "set") || !strcasecmp(subcmd, "replace") || !strcasecmp(subcmd, "add")) && argc > 2) {
key = argv[1];
val = argv[2];
if (argc > 3) {
expires_str = argv[3];
expires = (time_t)strtol(expires_str, NULL, 10);
expires = (time_t) strtol(expires_str, NULL, 10);
}
if (argc > 4) {
flags_str = argv[4];
flags = (uint32_t)strtol(flags_str, NULL, 16);
flags = (uint32_t) strtol(flags_str, NULL, 16);
}
if (!strcasecmp(subcmd, "set")) {
rc = memcached_set(memcached, key, strlen(key), val, strlen(val), expires, flags);
@@ -198,7 +197,7 @@ SWITCH_STANDARD_API(memcache_function)
} else if (!strcasecmp(subcmd, "add")) {
rc = memcached_add(memcached, key, strlen(key), val, strlen(val), expires, flags);
}
if (rc == MEMCACHED_SUCCESS) {
stream->write_function(stream, "+OK\n");
} else {
@@ -206,10 +205,10 @@ SWITCH_STANDARD_API(memcache_function)
}
} else if (!strcasecmp(subcmd, "get") && argc > 1) {
key = argv[1];
val = memcached_get(memcached, key, strlen(key), &string_length, &flags, &rc);
if (rc == MEMCACHED_SUCCESS) {
stream->write_function(stream, "%.*s", (int)string_length, val);
stream->write_function(stream, "%.*s", (int) string_length, val);
} else {
switch_safe_free(val);
switch_goto_status(SWITCH_STATUS_SUCCESS, mcache_error);
@@ -217,7 +216,7 @@ SWITCH_STANDARD_API(memcache_function)
switch_safe_free(val);
} else if (!strcasecmp(subcmd, "getflags") && argc > 1) {
key = argv[1];
val = memcached_get(memcached, key, strlen(key), &string_length, &flags, &rc);
if (rc == MEMCACHED_SUCCESS) {
stream->write_function(stream, "%x", flags);
@@ -234,20 +233,20 @@ SWITCH_STANDARD_API(memcache_function)
key = argv[1];
if (argc > 2) {
offset = (unsigned int)strtol(argv[2], NULL, 10);
offset = (unsigned int) strtol(argv[2], NULL, 10);
svalue = argv[2];
} else {
svalue = "1";
}
if (argc > 3) {
expires_str = argv[3];
expires = (time_t)strtol(expires_str, NULL, 10);
expires = (time_t) strtol(expires_str, NULL, 10);
}
if (argc > 4) {
flags_str = argv[4];
flags = (uint32_t)strtol(flags_str, NULL, 16);
flags = (uint32_t) strtol(flags_str, NULL, 16);
}
if (!strcasecmp(subcmd, "increment")) {
increment = SWITCH_TRUE;
rc = memcached_increment(memcached, key, strlen(key), offset, &ivalue);
@@ -259,18 +258,20 @@ SWITCH_STANDARD_API(memcache_function)
/* ok, trying to incr / decr a value that doesn't exist yet.
Try to add an appropriate initial value. If someone else beat
us to it, then redo incr/decr. Otherwise we're good.
*/
*/
rc = memcached_add(memcached, key, strlen(key), (increment) ? svalue : "0", strlen(svalue), expires, flags);
if (rc == MEMCACHED_SUCCESS) {
ivalue = (increment) ? offset : 0;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Initialized inc/dec memcache key: %s to value %d\n", key, offset);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Initialized inc/dec memcache key: %s to value %d\n", key,
offset);
} else {
if (increment) {
rc = memcached_increment(memcached, key, strlen(key), offset, &ivalue);
} else {
rc = memcached_decrement(memcached, key, strlen(key), offset, &ivalue);
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Someone else created incr/dec memcache key, resubmitting inc/dec request.\n");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"Someone else created incr/dec memcache key, resubmitting inc/dec request.\n");
}
}
if (rc == MEMCACHED_SUCCESS) {
@@ -282,7 +283,7 @@ SWITCH_STANDARD_API(memcache_function)
key = argv[1];
if (argc > 2) {
expires_str = argv[3];
expires = (time_t)strtol(expires_str, NULL, 10);
expires = (time_t) strtol(expires_str, NULL, 10);
}
rc = memcached_delete(memcached, key, strlen(key), expires);
if (rc == MEMCACHED_SUCCESS) {
@@ -293,7 +294,7 @@ SWITCH_STANDARD_API(memcache_function)
} else if (!strcasecmp(subcmd, "flush")) {
if (argc > 1) {
expires_str = argv[3];
expires = (time_t)strtol(expires_str, NULL, 10);
expires = (time_t) strtol(expires_str, NULL, 10);
}
rc = memcached_flush(memcached, expires);
if (rc == MEMCACHED_SUCCESS) {
@@ -310,7 +311,7 @@ SWITCH_STANDARD_API(memcache_function)
verbose = SWITCH_TRUE;
}
}
stream->write_function(stream, "Lib version: %s\n", memcached_lib_version());
stat = memcached_stat(memcached, NULL, &rc);
if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_SOME_ERRORS) {
@@ -320,13 +321,14 @@ SWITCH_STANDARD_API(memcache_function)
server_count = memcached_server_count(memcached);
stream->write_function(stream, "Servers: %d\n", server_count);
for (x = 0; x < server_count; x++) {
stream->write_function(stream, " %s (%u)\n", memcached_server_name(memcached, server_list[x]), memcached_server_port(memcached, server_list[x]));
stream->write_function(stream, " %s (%u)\n", memcached_server_name(memcached, server_list[x]),
memcached_server_port(memcached, server_list[x]));
if (verbose == SWITCH_TRUE) {
char **list;
char **ptr;
char *value;
memcached_return rc2;
list = memcached_stat_get_keys(memcached, &stat[x], &rc);
for (ptr = list; *ptr; ptr++) {
value = memcached_stat_get_value(memcached, &stat[x], *ptr, &rc2);
@@ -343,25 +345,26 @@ SWITCH_STANDARD_API(memcache_function)
}
switch_goto_status(SWITCH_STATUS_SUCCESS, done);
mcache_error:
mcache_error:
if (rc != MEMCACHED_NOTFOUND) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error while running command %s: %s\n", subcmd, memcached_strerror(memcached, rc));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error while running command %s: %s\n", subcmd,
memcached_strerror(memcached, rc));
}
stream->write_function(stream, "-ERR %s\n", memcached_strerror(memcached, rc));
goto done;
usage:
usage:
stream->write_function(stream, "-ERR\n%s\n", SYNTAX);
switch_goto_status(SWITCH_STATUS_SUCCESS, done);
done:
done:
if (memcached) {
memcached_quit(memcached);
memcached_free(memcached);
}
switch_safe_free(mydata);
switch_safe_free(stat);
return status;
}
@@ -375,12 +378,12 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_memcache_load)
memset(&globals, 0, sizeof(globals));
do_config(SWITCH_FALSE);
if ((switch_event_bind_removable(modname, SWITCH_EVENT_RELOADXML, NULL, event_handler, NULL, &NODE) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind event!\n");
return SWITCH_STATUS_TERM;
}
SWITCH_ADD_API(api_interface, "memcache", "Memcache API", memcache_function, "syntax");
/* indicate that the module should continue to be loaded */
@@ -397,9 +400,9 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_memcache_shutdown)
if (globals.memcached) {
memcached_free(globals.memcached);
}
switch_event_unbind(&NODE);
return SWITCH_STATUS_SUCCESS;
}
@@ -53,31 +53,28 @@
static char SQL_LOOKUP[] = "SELECT %s FROM %s WHERE %s='%s'";
static char SQL_SAVE[] = "UPDATE %s SET %s=%s-%f WHERE %s='%s'";
typedef struct
{
switch_time_t lastts; /* Last time we did any billing */
float total; /* Total amount billed so far */
typedef struct {
switch_time_t lastts; /* Last time we did any billing */
float total; /* Total amount billed so far */
switch_time_t pausets; /* Timestamp of when a pause action started. 0 if not paused */
float bill_adjustments; /* Adjustments to make to the next billing, based on pause/resume events */
switch_time_t pausets; /* Timestamp of when a pause action started. 0 if not paused */
float bill_adjustments; /* Adjustments to make to the next billing, based on pause/resume events */
} nibble_data_t;
typedef struct nibblebill_results
{
float balance;
typedef struct nibblebill_results {
float balance;
float percall_max; /* Overrides global on a per-user level */
float lowbal_amt; /* ditto */
float percall_max; /* Overrides global on a per-user level */
float lowbal_amt; /* ditto */
} nibblebill_results_t;
/* Keep track of our config, event hooks and database connection variables, for this module only */
static struct
{
static struct {
/* Memory */
switch_memory_pool_t *pool;
switch_memory_pool_t *pool;
/* Event hooks */
switch_event_node_t *node;
@@ -86,15 +83,15 @@ static struct
switch_mutex_t *mutex;
/* Global billing config options */
float percall_max_amt; /* Per-call billing limit (safety check, for fraud) */
char *percall_action; /* Exceeded length of per-call action */
float lowbal_amt; /* When we warn them they are near depletion */
char *lowbal_action; /* Low balance action */
float nobal_amt; /* Minimum amount that must remain in the account */
char *nobal_action; /* Drop action */
float percall_max_amt; /* Per-call billing limit (safety check, for fraud) */
char *percall_action; /* Exceeded length of per-call action */
float lowbal_amt; /* When we warn them they are near depletion */
char *lowbal_action; /* Low balance action */
float nobal_amt; /* Minimum amount that must remain in the account */
char *nobal_action; /* Drop action */
/* Other options */
int global_heartbeat; /* Supervise and bill every X seconds, 0 means off */
int global_heartbeat; /* Supervise and bill every X seconds, 0 means off */
/* Database settings */
char *db_username;
@@ -135,7 +132,7 @@ static int nibblebill_callback(void *pArg, int argc, char **argv, char **columnN
{
nibblebill_results_t *cbt = (nibblebill_results_t *) pArg;
cbt->balance = (float)atof(argv[0]);
cbt->balance = (float) atof(argv[0]);
return 0;
}
@@ -145,13 +142,13 @@ static switch_status_t load_config(void)
char *cf = "nibblebill.conf";
switch_xml_t cfg, xml = NULL, param, settings;
switch_status_t status = SWITCH_STATUS_SUCCESS;
if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
status = SWITCH_STATUS_SUCCESS; /* We don't fail because we can still write to a text file or buffer */
status = SWITCH_STATUS_SUCCESS; /* We don't fail because we can still write to a text file or buffer */
goto setdefaults;
}
if ((settings = switch_xml_child(cfg, "settings"))) {
for (param = switch_xml_child(settings, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
@@ -172,23 +169,23 @@ static switch_status_t load_config(void)
} else if (!strcasecmp(var, "percall_action")) {
set_global_percall_action(val);
} else if (!strcasecmp(var, "percall_max_amt")) {
globals.percall_max_amt = (float)atof(val);
globals.percall_max_amt = (float) atof(val);
} else if (!strcasecmp(var, "lowbal_action")) {
set_global_lowbal_action(val);
} else if (!strcasecmp(var, "lowbal_amt")) {
globals.lowbal_amt = (float)atof(val);
globals.lowbal_amt = (float) atof(val);
} else if (!strcasecmp(var, "nobal_action")) {
set_global_nobal_action(val);
} else if (!strcasecmp(var, "nobal_amt")) {
globals.nobal_amt = (float)atof(val);
globals.nobal_amt = (float) atof(val);
} else if (!strcasecmp(var, "global_heartbeat")) {
globals.global_heartbeat = atoi(val);
}
}
}
/* Set defaults for any variables still not set */
setdefaults:
setdefaults:
if (zstr(globals.db_username)) {
set_global_db_username("bandwidth.com");
}
@@ -218,7 +215,7 @@ setdefaults:
}
if (switch_odbc_handle_connect(globals.master_odbc) != SWITCH_ODBC_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT,
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT,
"Cannot connect to ODBC driver/database %s (user: %s / pass %s)!\n",
globals.db_dsn, globals.db_username, globals.db_password);
status = SWITCH_STATUS_FALSE;
@@ -232,7 +229,7 @@ setdefaults:
"ODBC does not appear to be installed in the core. You need to run ./configure --enable-core-odbc-support\n");
}
done:
done:
if (xml) {
switch_xml_free(xml);
}
@@ -241,7 +238,7 @@ done:
void debug_event_handler(switch_event_t *event)
{
if (!event) {
if (!event) {
return;
}
@@ -305,8 +302,9 @@ static switch_status_t bill_event(float billamount, const char *billaccount)
return SWITCH_STATUS_SUCCESS;
}
switch_snprintf(sql, 1024, SQL_SAVE, globals.db_table, globals.db_column_cash, globals.db_column_cash, billamount, globals.db_column_account, billaccount);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing update query\n[%s]\n", sql);
switch_snprintf(sql, 1024, SQL_SAVE, globals.db_table, globals.db_column_cash, globals.db_column_cash, billamount, globals.db_column_account,
billaccount);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Doing update query\n[%s]\n", sql);
if (switch_odbc_handle_exec(globals.master_odbc, sql, &stmt, NULL) != SWITCH_ODBC_SUCCESS) {
char *err_str;
@@ -347,9 +345,9 @@ static float get_balance(const char *billaccount)
/* Successfully retrieved! */
balance = pdata.balance;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Retrieved current balance for account %s (balance = %f)\n", billaccount, balance);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Retrieved current balance for account %s (balance = %f)\n", billaccount, balance);
}
return balance;
}
@@ -394,7 +392,8 @@ static switch_status_t do_billing(switch_core_session_t *session)
return SWITCH_STATUS_SUCCESS;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Attempting to bill at $%s per minute to account %s\n", billrate, billaccount);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Attempting to bill at $%s per minute to account %s\n", billrate,
billaccount);
/* Get caller profile info from channel */
profile = switch_channel_get_caller_profile(channel);
@@ -409,10 +408,11 @@ static switch_status_t do_billing(switch_core_session_t *session)
/* See if this person has enough money left to continue the call */
balance = get_balance(billaccount);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Comparing %f to hangup balance of %f\n", balance, globals.nobal_amt);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Comparing %f to hangup balance of %f\n", balance, globals.nobal_amt);
if (balance <= globals.nobal_amt) {
/* Not enough money - reroute call to nobal location */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Balance of %f fell below allowed amount of %f! (Account %s)\n", balance, globals.nobal_amt, billaccount);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Balance of %f fell below allowed amount of %f! (Account %s)\n",
balance, globals.nobal_amt, billaccount);
transfer_call(session, globals.nobal_action);
}
@@ -443,7 +443,7 @@ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Compar
memset(nibble_data, 0, sizeof(*nibble_data));
/* Setup new billing data (based on call answer time, in case this module started late with active calls) */
nibble_data->lastts = profile->times->answered; /* Set the initial answer time to match when the call was really answered */
nibble_data->lastts = profile->times->answered; /* Set the initial answer time to match when the call was really answered */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Beginning new billing on %s\n", uuid);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Last successful billing time was %s\n", date);
@@ -452,13 +452,15 @@ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Compar
switch_time_exp_lt(&tm, nibble_data->lastts);
switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%d seconds passed since last bill time of %s\n", (int) ((ts - nibble_data->lastts) / 1000000), date);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%d seconds passed since last bill time of %s\n",
(int) ((ts - nibble_data->lastts) / 1000000), date);
if ((ts - nibble_data->lastts) >= 0) {
/* Convert billrate into microseconds and multiply by # of microseconds that have passed since last *successful* bill */
billamount = ((float)atof(billrate) / 1000000 / 60) * ((ts - nibble_data->lastts)) - nibble_data->bill_adjustments;
billamount = ((float) atof(billrate) / 1000000 / 60) * ((ts - nibble_data->lastts)) - nibble_data->bill_adjustments;
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Billing $%f to %s (Call: %s / %f so far)\n", billamount, billaccount, uuid, nibble_data->total);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Billing $%f to %s (Call: %s / %f so far)\n", billamount, billaccount,
uuid, nibble_data->total);
/* DO ODBC BILLING HERE and reset counters if it's successful! */
if (bill_event(billamount, billaccount) == SWITCH_STATUS_SUCCESS) {
@@ -474,7 +476,8 @@ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Compar
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failed to log to database!\n");
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Just tried to bill %s negative minutes! That should be impossible.\n", uuid);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Just tried to bill %s negative minutes! That should be impossible.\n",
uuid);
}
/* Update the last time we billed */
@@ -488,7 +491,8 @@ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Compar
balance = get_balance(billaccount);
if (balance <= globals.nobal_amt) {
/* Not enough money - reroute call to nobal location */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Balance of %f fell below allowed amount of %f! (Account %s)\n", balance, globals.nobal_amt, billaccount);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Balance of %f fell below allowed amount of %f! (Account %s)\n",
balance, globals.nobal_amt, billaccount);
/* IMPORTANT: Billing must be paused before the transfer occurs! This prevents infinite loops, since the transfer will result */
/* in nibblebill checking the call again in the routing process for an allowed balance! */
@@ -496,7 +500,7 @@ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Compar
nibblebill_pause(session);
transfer_call(session, globals.nobal_action);
}
}
}
/* Done changing - release lock */
@@ -515,18 +519,18 @@ static void event_handler(switch_event_t *event)
switch_core_session_t *session;
char *uuid;
if (!event){
if (!event) {
/* We should never get here - it means an event came in without the event info */
return;
}
/* Make sure everything is sane */
if (!(uuid = switch_event_get_header(event, "Unique-ID"))){
if (!(uuid = switch_event_get_header(event, "Unique-ID"))) {
/* Donde esta channel? */
return;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received request via %s!\n", switch_event_name (event->event_id));
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received request via %s!\n", switch_event_name(event->event_id));
/* Display debugging info */
if (switch_event_get_header(event, "nibble_debug")) {
@@ -594,12 +598,14 @@ static void nibblebill_resume(switch_core_session_t *session)
nibble_data = (nibble_data_t *) switch_channel_get_private(channel, "_nibble_data_");
if (!nibble_data) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Can't resume - channel is not initialized for billing (This is expected at hangup time)!\n");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"Can't resume - channel is not initialized for billing (This is expected at hangup time)!\n");
return;
}
if (nibble_data->pausets == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Can't resume - channel is not paused! (This is expected at hangup time)\n");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
"Can't resume - channel is not paused! (This is expected at hangup time)\n");
return;
}
@@ -611,8 +617,9 @@ static void nibblebill_resume(switch_core_session_t *session)
billrate = switch_channel_get_variable(channel, "nibble_rate");
/* Calculate how much was "lost" to billings during pause - we do this here because you never know when the billrate may change during a call */
nibble_data->bill_adjustments += ((float)atof(billrate) / 1000000 / 60) * ((ts - nibble_data->pausets));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Resumed billing! Subtracted %f from this billing cycle.\n", (atof(billrate) / 1000000 / 60) * ((ts - nibble_data->pausets)));
nibble_data->bill_adjustments += ((float) atof(billrate) / 1000000 / 60) * ((ts - nibble_data->pausets));
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Resumed billing! Subtracted %f from this billing cycle.\n",
(atof(billrate) / 1000000 / 60) * ((ts - nibble_data->pausets)));
nibble_data->pausets = 0;
@@ -699,7 +706,7 @@ static void nibblebill_adjust(switch_core_session_t *session, float amount)
}
/* Variables kept in FS but relevant only to this module */
billaccount = switch_channel_get_variable(channel, "nibble_account");
/* Return if there's no billing information on this session */
@@ -725,7 +732,7 @@ SWITCH_STANDARD_APP(nibblebill_app_function)
if (!zstr(data) && (lbuf = strdup(data))
&& (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
if (!strcasecmp(argv[0], "adjust") && argc == 2) {
nibblebill_adjust(session, (float)atof(argv[1]));
nibblebill_adjust(session, (float) atof(argv[1]));
} else if (!strcasecmp(argv[0], "flush")) {
do_billing(session);
} else if (!strcasecmp(argv[0], "pause")) {
@@ -760,7 +767,7 @@ SWITCH_STANDARD_API(nibblebill_api_function)
channel = switch_core_session_get_channel(psession);
if (!strcasecmp(argv[1], "adjust") && argc == 3) {
nibblebill_adjust(psession, (float)atof(argv[2]));
nibblebill_adjust(psession, (float) atof(argv[2]));
} else if (!strcasecmp(argv[1], "flush")) {
do_billing(psession);
} else if (!strcasecmp(argv[1], "pause")) {
@@ -805,7 +812,7 @@ static switch_status_t sched_billing(switch_core_session_t *session)
static switch_status_t process_hangup(switch_core_session_t *session)
{
/* Resume any paused billings, just in case */
// nibblebill_resume(session);
// nibblebill_resume(session);
/* Now go handle like normal billing */
do_billing(session);
@@ -813,17 +820,19 @@ static switch_status_t process_hangup(switch_core_session_t *session)
return SWITCH_STATUS_SUCCESS;
}
switch_state_handler_table_t nibble_state_handler =
{
/* on_init */ NULL,
/* on_routing */ process_hangup, /* Need to add a check here for anything in their account before routing */
/* on_execute */ sched_billing, /* Turn on heartbeat for this session and do an initial account check */
/* on_hangup */ process_hangup, /* On hangup - most important place to go bill */
/* on_exch_media */ sched_billing,
/* on_soft_exec */ NULL,
/* on_consume_med */ NULL,
/* on_hibernate */ NULL,
/* on_reset */ NULL
switch_state_handler_table_t nibble_state_handler = {
/* on_init */ NULL,
/* on_routing */ process_hangup,
/* Need to add a check here for anything in their account before routing */
/* on_execute */ sched_billing,
/* Turn on heartbeat for this session and do an initial account check */
/* on_hangup */ process_hangup,
/* On hangup - most important place to go bill */
/* on_exch_media */ sched_billing,
/* on_soft_exec */ NULL,
/* on_consume_med */ NULL,
/* on_hibernate */ NULL,
/* on_reset */ NULL
};
SWITCH_MODULE_LOAD_FUNCTION(mod_nibblebill_load)
@@ -831,13 +840,13 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_nibblebill_load)
switch_api_interface_t *api_interface;
switch_application_interface_t *app_interface;
/* Set every byte in this structure to 0 */
/* Set every byte in this structure to 0 */
memset(&globals, 0, sizeof(globals));
globals.pool = pool;
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
load_config();
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
@@ -845,13 +854,16 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_nibblebill_load)
SWITCH_ADD_API(api_interface, "nibblebill", "Manage billing parameters for a channel/call", nibblebill_api_function, API_SYNTAX);
/* Add dialplan applications */
SWITCH_ADD_APP(app_interface, "nibblebill", "Handle billing for the current channel/call", "Pause, resume, reset, adjust, flush, heartbeat commands to handle billing.", nibblebill_app_function, APP_SYNTAX, SAF_NONE | SAF_ROUTING_EXEC);
SWITCH_ADD_APP(app_interface, "nibblebill", "Handle billing for the current channel/call",
"Pause, resume, reset, adjust, flush, heartbeat commands to handle billing.", nibblebill_app_function, APP_SYNTAX,
SAF_NONE | SAF_ROUTING_EXEC);
/* register state handlers for billing */
switch_core_add_state_handler(&nibble_state_handler);
/* bind to heartbeat events */
if (switch_event_bind_removable(modname, SWITCH_EVENT_SESSION_HEARTBEAT, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL, &globals.node) != SWITCH_STATUS_SUCCESS) {
if (switch_event_bind_removable(modname, SWITCH_EVENT_SESSION_HEARTBEAT, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL, &globals.node) !=
SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind event to monitor for session heartbeats!\n");
return SWITCH_STATUS_GENERR;
}
@@ -861,7 +873,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_nibblebill_load)
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_nibblebill_shutdown)
{
{
switch_event_unbind(&globals.node);
switch_core_remove_state_handler(&nibble_state_handler);
switch_odbc_handle_disconnect(globals.master_odbc);
+3 -3
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -184,9 +184,9 @@ SWITCH_STANDARD_APP(rss_function)
switch_input_args_t args = { 0 };
const char *vcf = NULL;
char *chanvars = switch_channel_build_param_string(channel, NULL, NULL);
switch_codec_implementation_t read_impl = {0};
switch_codec_implementation_t read_impl = { 0 };
uint32_t rate, interval;
switch_core_session_get_read_impl(session, &read_impl);
switch_core_session_get_read_impl(session, &read_impl);
interval = read_impl.microseconds_per_packet / 1000;
if ((vcf = switch_channel_get_variable(channel, "rss_alt_config"))) {
+32 -28
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -55,42 +55,46 @@ static struct {
int integer;
} globals;
static switch_status_t config_callback_siptrace(switch_xml_config_item_t *data, switch_config_callback_type_t callback_type, switch_bool_t changed)
static switch_status_t config_callback_siptrace(switch_xml_config_item_t *data, switch_config_callback_type_t callback_type, switch_bool_t changed)
{
switch_bool_t value = *(switch_bool_t*)data->ptr;
switch_bool_t value = *(switch_bool_t *) data->ptr;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "In siptrace callback: value %s changed %s\n",
value ? "true" : "false", changed ? "true" : "false");
value ? "true" : "false", changed ? "true" : "false");
/*
if ((callback_type == CONFIG_LOG || callback_type == CONFIG_RELOAD) && changed) {
nua_set_params(((sofia_profile_t*)data->functiondata)->nua, TPTAG_LOG(value), TAG_END());
}
*/
if ((callback_type == CONFIG_LOG || callback_type == CONFIG_RELOAD) && changed) {
nua_set_params(((sofia_profile_t*)data->functiondata)->nua, TPTAG_LOG(value), TAG_END());
}
*/
return SWITCH_STATUS_SUCCESS;
}
static switch_xml_config_string_options_t config_opt_codec_negotiation = { NULL, 0, "greedy|generous|evil" };
/* enforce_min, min, enforce_max, max */
static switch_xml_config_int_options_t config_opt_integer = { SWITCH_TRUE, 0, SWITCH_TRUE, 10 };
static switch_xml_config_enum_item_t config_opt_codec_negotiation_enum[] = {
{ "greedy", CODEC_NEGOTIATION_GREEDY },
{ "generous", CODEC_NEGOTIATION_GENEROUS },
{ "evil", CODEC_NEGOTIATION_EVIL },
{ NULL, 0 }
static switch_xml_config_enum_item_t config_opt_codec_negotiation_enum[] = {
{"greedy", CODEC_NEGOTIATION_GREEDY},
{"generous", CODEC_NEGOTIATION_GENEROUS},
{"evil", CODEC_NEGOTIATION_EVIL},
{NULL, 0}
};
static switch_xml_config_item_t instructions[] = {
/* parameter name type reloadable pointer default value options structure */
SWITCH_CONFIG_ITEM("codec-negotiation-str", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &globals.codec_negotiation_str, "greedy", &config_opt_codec_negotiation, \
"greedy|generous|evil", "Specifies the codec negotiation scheme to be used."),
SWITCH_CONFIG_ITEM("codec-negotiation", SWITCH_CONFIG_ENUM, CONFIG_RELOADABLE, &globals.codec_negotiation, (void*)CODEC_NEGOTIATION_GREEDY, &config_opt_codec_negotiation_enum,
"greedy|generous|evil", "Specifies the codec negotiation scheme to be used."),
SWITCH_CONFIG_ITEM_CALLBACK("sip-trace", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &globals.sip_trace, (void*)SWITCH_FALSE, (switch_xml_config_callback_t)config_callback_siptrace, NULL,
"yes|no", "If enabled, print out sip messages on the console."),
SWITCH_CONFIG_ITEM("integer", SWITCH_CONFIG_INT, CONFIG_RELOADABLE, &globals.integer, (void*)100, &config_opt_integer,
NULL, NULL),
SWITCH_CONFIG_ITEM("codec-negotiation-str", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &globals.codec_negotiation_str, "greedy",
&config_opt_codec_negotiation,
"greedy|generous|evil", "Specifies the codec negotiation scheme to be used."),
SWITCH_CONFIG_ITEM("codec-negotiation", SWITCH_CONFIG_ENUM, CONFIG_RELOADABLE, &globals.codec_negotiation, (void *) CODEC_NEGOTIATION_GREEDY,
&config_opt_codec_negotiation_enum,
"greedy|generous|evil", "Specifies the codec negotiation scheme to be used."),
SWITCH_CONFIG_ITEM_CALLBACK("sip-trace", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &globals.sip_trace, (void *) SWITCH_FALSE,
(switch_xml_config_callback_t) config_callback_siptrace, NULL,
"yes|no", "If enabled, print out sip messages on the console."),
SWITCH_CONFIG_ITEM("integer", SWITCH_CONFIG_INT, CONFIG_RELOADABLE, &globals.integer, (void *) 100, &config_opt_integer,
NULL, NULL),
SWITCH_CONFIG_ITEM_END()
};
@@ -102,14 +106,14 @@ static switch_status_t do_config(switch_bool_t reload)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not open skel.conf\n");
return SWITCH_STATUS_FALSE;
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(skel_function)
{
do_config(SWITCH_TRUE);
return SWITCH_STATUS_SUCCESS;
}
@@ -121,9 +125,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skel_load)
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n");
do_config(SWITCH_FALSE);
SWITCH_ADD_API(api_interface, "skel", "Skel API", skel_function, "syntax");
/* indicate that the module should continue to be loaded */
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -65,17 +65,18 @@ static switch_bool_t capture_callback(switch_media_bug_t *bug, void *user_data,
break;
case SWITCH_ABC_TYPE_READ:
if (cb->buffer) {
uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE];
switch_frame_t frame = { 0 };
frame.data = data;
frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
if (switch_mutex_trylock(cb->mutex) == SWITCH_STATUS_SUCCESS) {
while (switch_core_media_bug_read(bug, &frame, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS && !switch_test_flag((&frame), SFF_CNG)) {
if (frame.datalen) switch_buffer_slide_write(cb->buffer, frame.data, frame.datalen);
if (frame.datalen)
switch_buffer_slide_write(cb->buffer, frame.data, frame.datalen);
}
switch_mutex_unlock(cb->mutex);
}
@@ -95,7 +96,7 @@ static switch_status_t start_capture(switch_core_session_t *session, unsigned in
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_media_bug_t *bug;
switch_status_t status;
switch_codec_implementation_t read_impl = {0};
switch_codec_implementation_t read_impl = { 0 };
struct cap_cb *cb;
switch_size_t bytes;
switch_bind_flag_t bind_flags = 0;
@@ -109,8 +110,8 @@ static switch_status_t start_capture(switch_core_session_t *session, unsigned in
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Must be at least 5 seconds!\n");
return SWITCH_STATUS_FALSE;
}
switch_core_session_get_read_impl(session, &read_impl);
switch_core_session_get_read_impl(session, &read_impl);
if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
return SWITCH_STATUS_FALSE;
@@ -118,7 +119,7 @@ static switch_status_t start_capture(switch_core_session_t *session, unsigned in
cb = switch_core_session_alloc(session, sizeof(*cb));
cb->base = switch_core_session_strdup(session, base);
bytes = read_impl.samples_per_second * seconds * 2;
switch_buffer_create_dynamic(&cb->buffer, bytes, bytes, bytes);
@@ -132,7 +133,7 @@ static switch_status_t start_capture(switch_core_session_t *session, unsigned in
switch_ivr_bind_dtmf_meta_session(session, 7, bind_flags, "snapshot::snap");
switch_channel_set_private(channel, "snapshot", bug);
return SWITCH_STATUS_SUCCESS;
}
@@ -141,11 +142,11 @@ static switch_status_t do_snap(switch_core_session_t *session)
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_media_bug_t *bug = switch_channel_get_private(channel, "snapshot");
char *file;
switch_file_handle_t fh = {0};
switch_codec_implementation_t read_impl = {0};
switch_file_handle_t fh = { 0 };
switch_codec_implementation_t read_impl = { 0 };
switch_size_t bytes_read;
int16_t pdata[4096] = {0};
int16_t pdata[4096] = { 0 };
if (bug) {
switch_time_exp_t tm;
switch_size_t retsize;
@@ -158,19 +159,17 @@ static switch_status_t do_snap(switch_core_session_t *session)
switch_time_exp_lt(&tm, switch_time_make(switch_epoch_time_now(NULL), 0));
switch_strftime(date, &retsize, sizeof(date), "%Y_%m_%d_%H_%M_%S", &tm);
file = switch_core_session_sprintf(session, "%s%s%s_%s.wav", SWITCH_GLOBAL_dirs.sounds_dir,
SWITCH_PATH_SEPARATOR, cb->base, date);
file = switch_core_session_sprintf(session, "%s%s%s_%s.wav", SWITCH_GLOBAL_dirs.sounds_dir, SWITCH_PATH_SEPARATOR, cb->base, date);
switch_core_session_get_read_impl(session, &read_impl);
fh.channels = 0;
fh.native_rate = read_impl.actual_samples_per_second;
if (switch_core_file_open(&fh,
file,
0,
read_impl.actual_samples_per_second,
SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error opening %s\n", file);
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
@@ -180,7 +179,7 @@ static switch_status_t do_snap(switch_core_session_t *session)
switch_mutex_lock(cb->mutex);
while ((bytes_read = switch_buffer_read(cb->buffer, pdata, sizeof(pdata)))) {
switch_size_t samples = bytes_read / 2;
if (switch_core_file_write(&fh, pdata, &samples) != SWITCH_STATUS_SUCCESS) {
break;
}
@@ -205,8 +204,8 @@ SWITCH_STANDARD_APP(snapshot_app_function)
if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))) {
argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
}
}
if (argc < 1) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", SNAP_SYNTAX);
return;
@@ -240,7 +239,7 @@ SWITCH_STANDARD_APP(snapshot_app_function)
}
start_capture(session, seconds, flags, base);
}
if (!strcasecmp(argv[0], "snap")) {
@@ -276,7 +275,7 @@ SWITCH_STANDARD_API(snapshot_function)
const char *base = argv[3];
int seconds = 5;
switch_media_bug_flag_t flags = SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_PING;
if (sec) {
int tmp = atoi(sec);
if (tmp > 5) {
@@ -297,7 +296,7 @@ SWITCH_STANDARD_API(snapshot_function)
if (!base) {
base = "mod_snapshot";
}
status = start_capture(lsession, seconds, flags, base);
}
@@ -311,7 +310,7 @@ SWITCH_STANDARD_API(snapshot_function)
stream->write_function(stream, "-ERR Operation Failed\n");
}
done:
done:
switch_safe_free(mycmd);
return SWITCH_STATUS_SUCCESS;
@@ -327,7 +326,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_snapshot_load)
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n");
SWITCH_ADD_API(api_interface, "uuid_snapshot", "Snapshot API", snapshot_function, SNAP_API_SYNTAX);
SWITCH_ADD_APP(app_interface, "snapshot", "", "", snapshot_app_function, SNAP_SYNTAX, SAF_SUPPORT_NOMEDIA);
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -55,42 +55,46 @@ static struct {
int integer;
} globals;
static switch_status_t config_callback_siptrace(switch_xml_config_item_t *data, switch_config_callback_type_t callback_type, switch_bool_t changed)
static switch_status_t config_callback_siptrace(switch_xml_config_item_t *data, switch_config_callback_type_t callback_type, switch_bool_t changed)
{
switch_bool_t value = *(switch_bool_t*)data->ptr;
switch_bool_t value = *(switch_bool_t *) data->ptr;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "In siptrace callback: value %s changed %s\n",
value ? "true" : "false", changed ? "true" : "false");
value ? "true" : "false", changed ? "true" : "false");
/*
if ((callback_type == CONFIG_LOG || callback_type == CONFIG_RELOAD) && changed) {
nua_set_params(((sofia_profile_t*)data->functiondata)->nua, TPTAG_LOG(value), TAG_END());
}
*/
if ((callback_type == CONFIG_LOG || callback_type == CONFIG_RELOAD) && changed) {
nua_set_params(((sofia_profile_t*)data->functiondata)->nua, TPTAG_LOG(value), TAG_END());
}
*/
return SWITCH_STATUS_SUCCESS;
}
static switch_xml_config_string_options_t config_opt_codec_negotiation = { NULL, 0, "greedy|generous|evil" };
/* enforce_min, min, enforce_max, max */
static switch_xml_config_int_options_t config_opt_integer = { SWITCH_TRUE, 0, SWITCH_TRUE, 10 };
static switch_xml_config_enum_item_t config_opt_codec_negotiation_enum[] = {
{ "greedy", CODEC_NEGOTIATION_GREEDY },
{ "generous", CODEC_NEGOTIATION_GENEROUS },
{ "evil", CODEC_NEGOTIATION_EVIL },
{ NULL, 0 }
static switch_xml_config_enum_item_t config_opt_codec_negotiation_enum[] = {
{"greedy", CODEC_NEGOTIATION_GREEDY},
{"generous", CODEC_NEGOTIATION_GENEROUS},
{"evil", CODEC_NEGOTIATION_EVIL},
{NULL, 0}
};
static switch_xml_config_item_t instructions[] = {
/* parameter name type reloadable pointer default value options structure */
SWITCH_CONFIG_ITEM("codec-negotiation-str", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &globals.codec_negotiation_str, "greedy", &config_opt_codec_negotiation, \
"greedy|generous|evil", "Specifies the codec negotiation scheme to be used."),
SWITCH_CONFIG_ITEM("codec-negotiation", SWITCH_CONFIG_ENUM, CONFIG_RELOADABLE, &globals.codec_negotiation, (void*)CODEC_NEGOTIATION_GREEDY, &config_opt_codec_negotiation_enum,
"greedy|generous|evil", "Specifies the codec negotiation scheme to be used."),
SWITCH_CONFIG_ITEM_CALLBACK("sip-trace", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &globals.sip_trace, (void*)SWITCH_FALSE, (switch_xml_config_callback_t)config_callback_siptrace, NULL,
"yes|no", "If enabled, print out sip messages on the console."),
SWITCH_CONFIG_ITEM("integer", SWITCH_CONFIG_INT, CONFIG_RELOADABLE, &globals.integer, (void*)100, &config_opt_integer,
NULL, NULL),
SWITCH_CONFIG_ITEM("codec-negotiation-str", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &globals.codec_negotiation_str, "greedy",
&config_opt_codec_negotiation,
"greedy|generous|evil", "Specifies the codec negotiation scheme to be used."),
SWITCH_CONFIG_ITEM("codec-negotiation", SWITCH_CONFIG_ENUM, CONFIG_RELOADABLE, &globals.codec_negotiation, (void *) CODEC_NEGOTIATION_GREEDY,
&config_opt_codec_negotiation_enum,
"greedy|generous|evil", "Specifies the codec negotiation scheme to be used."),
SWITCH_CONFIG_ITEM_CALLBACK("sip-trace", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &globals.sip_trace, (void *) SWITCH_FALSE,
(switch_xml_config_callback_t) config_callback_siptrace, NULL,
"yes|no", "If enabled, print out sip messages on the console."),
SWITCH_CONFIG_ITEM("integer", SWITCH_CONFIG_INT, CONFIG_RELOADABLE, &globals.integer, (void *) 100, &config_opt_integer,
NULL, NULL),
SWITCH_CONFIG_ITEM_END()
};
@@ -102,14 +106,14 @@ static switch_status_t do_config(switch_bool_t reload)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not open snipe_hunt.conf\n");
return SWITCH_STATUS_FALSE;
}
return SWITCH_STATUS_SUCCESS;
}
SWITCH_STANDARD_API(snipe_hunt_function)
{
do_config(SWITCH_TRUE);
return SWITCH_STATUS_SUCCESS;
}
@@ -121,9 +125,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_snipe_hunt_load)
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n");
do_config(SWITCH_FALSE);
SWITCH_ADD_API(api_interface, "snipe_hunt", "Snipe_Hunt API", snipe_hunt_function, "syntax");
/* indicate that the module should continue to be loaded */
+10 -15
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -33,14 +33,9 @@
SWITCH_MODULE_LOAD_FUNCTION(mod_snom_load);
SWITCH_MODULE_DEFINITION(mod_snom, mod_snom_load, NULL, NULL);
static switch_bool_t snom_bind_key(const char *key,
const char *light,
const char *label,
const char *user,
const char *host,
const char *profile,
const char *action_name,
const char *action)
static switch_bool_t snom_bind_key(const char *key,
const char *light,
const char *label, const char *user, const char *host, const char *profile, const char *action_name, const char *action)
{
switch_event_t *event;
@@ -61,7 +56,7 @@ static switch_bool_t snom_bind_key(const char *key,
}
return SWITCH_TRUE;
}
return SWITCH_FALSE;
}
@@ -92,17 +87,17 @@ SWITCH_STANDARD_API(snom_bind_key_api_function)
if (argc < 6) {
goto err;
}
if (snom_bind_key(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7])) {
stream->write_function(stream, "+OK %s\n", cmd);
goto end;
}
err:
err:
stream->write_function(stream, "-Error %s\n", KEY_BIND_SYNTAX);
end:
end:
free(mydata);
@@ -122,7 +117,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_snom_load)
SWITCH_ADD_API(commands_api_interface, "snom_bind_key", "Bind a key", snom_bind_key_api_function, KEY_BIND_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "snom_url", "url", snom_url_api_function, URL_SYNTAX);
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
+77 -77
View File
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -39,10 +39,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spy_load);
SWITCH_MODULE_DEFINITION(mod_spy, mod_spy_load, mod_spy_shutdown, NULL);
struct mod_spy_globals {
switch_memory_pool_t* pool;
switch_event_node_t* node;
switch_hash_t* spy_hash;
switch_thread_rwlock_t* spy_hash_lock;
switch_memory_pool_t *pool;
switch_event_node_t *node;
switch_hash_t *spy_hash;
switch_thread_rwlock_t *spy_hash_lock;
uint32_t spy_count;
} globals;
@@ -50,14 +50,14 @@ static switch_status_t spy_on_hangup(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
char* data = switch_channel_get_private(channel,"_userspy_");
char *data = switch_channel_get_private(channel, "_userspy_");
switch_thread_rwlock_wrlock(globals.spy_hash_lock);
if ((switch_core_hash_delete(globals.spy_hash,data) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,"No such key in userspy: %s \n",data);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,"Userspy deactivated on %s\n",data);
if ((switch_core_hash_delete(globals.spy_hash, data) != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No such key in userspy: %s \n", data);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Userspy deactivated on %s\n", data);
globals.spy_count--;
}
@@ -68,16 +68,16 @@ static switch_status_t spy_on_hangup(switch_core_session_t *session)
static switch_status_t spy_on_exchange_media(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
const char* spy_uuid = switch_channel_get_variable(channel,"spy_uuid");
const char *spy_uuid = switch_channel_get_variable(channel, "spy_uuid");
if (spy_uuid) {
if (switch_ivr_eavesdrop_session(session,spy_uuid,NULL,ED_DTMF) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,"Can't eavesdrop on uuid %s\n",spy_uuid);
if (switch_ivr_eavesdrop_session(session, spy_uuid, NULL, ED_DTMF) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't eavesdrop on uuid %s\n", spy_uuid);
}
}
switch_channel_set_state(channel,CS_PARK);
return SWITCH_STATUS_FALSE;
switch_channel_set_state(channel, CS_PARK);
return SWITCH_STATUS_FALSE;
}
static switch_status_t spy_on_park(switch_core_session_t *session)
@@ -85,7 +85,7 @@ static switch_status_t spy_on_park(switch_core_session_t *session)
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *moh = switch_channel_get_variable(channel, "hold_music");
while(switch_channel_ready(channel) && switch_channel_get_state(channel) == CS_PARK) {
while (switch_channel_ready(channel) && switch_channel_get_state(channel) == CS_PARK) {
if (moh) {
switch_status_t status = switch_ivr_play_file(session, NULL, moh, NULL);
if (!SWITCH_READ_ACCEPTABLE(status)) {
@@ -98,13 +98,13 @@ static switch_status_t spy_on_park(switch_core_session_t *session)
static const switch_state_handler_table_t spy_state_handlers = {
/*.on_init */ NULL,
/*.on_routing */ NULL,
/*.on_execute */ NULL,
/*.on_hangup */ spy_on_hangup,
/*.on_exchange_media */ spy_on_exchange_media,
/*.on_soft_execute */ NULL,
/*.on_consume_media */ NULL,
/*.on_init */ NULL,
/*.on_routing */ NULL,
/*.on_execute */ NULL,
/*.on_hangup */ spy_on_hangup,
/*.on_exchange_media */ spy_on_exchange_media,
/*.on_soft_execute */ NULL,
/*.on_consume_media */ NULL,
/* on_hibernate */ NULL,
/* on reset */ NULL,
/* on_park */ spy_on_park,
@@ -113,29 +113,29 @@ static const switch_state_handler_table_t spy_state_handlers = {
SWITCH_STANDARD_API(dump_hash)
{
switch_hash_index_t *hi;
const void* key;
void* val;
const void *key;
void *val;
switch_thread_rwlock_rdlock(globals.spy_hash_lock);
for (hi = switch_hash_first(NULL,globals.spy_hash);hi; hi = switch_hash_next(hi)){
switch_hash_this(hi,&key,NULL,&val);
stream->write_function(stream,"%s : %s\n",(char*)key,(const char*)val);
for (hi = switch_hash_first(NULL, globals.spy_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &key, NULL, &val);
stream->write_function(stream, "%s : %s\n", (char *) key, (const char *) val);
}
stream->write_function(stream,"\n%d total spy\n",globals.spy_count);
stream->write_function(stream, "\n%d total spy\n", globals.spy_count);
switch_thread_rwlock_unlock(globals.spy_hash_lock);
return SWITCH_STATUS_SUCCESS;
}
static void event_handler(switch_event_t* event)
static void event_handler(switch_event_t *event)
{
switch_core_session_t *session = NULL;
switch_channel_t *channel;
char *username[2] = {0};
char* domain[2] = {0};
char *username[2] = { 0 };
char *domain[2] = { 0 };
char key[512];
char* uuid = NULL, *my_uuid = NULL;
char *uuid = NULL, *my_uuid = NULL;
int i;
switch_thread_rwlock_rdlock(globals.spy_hash_lock);
@@ -144,22 +144,22 @@ static void event_handler(switch_event_t* event)
goto done;
}
username[0] = switch_event_get_header(event,"Caller-Username");
domain[0] = switch_event_get_header(event,"variable_domain_name");
domain[1] = switch_event_get_header(event,"variable_dialed_domain");
username[1] = switch_event_get_header(event,"variable_dialed_user");
username[0] = switch_event_get_header(event, "Caller-Username");
domain[0] = switch_event_get_header(event, "variable_domain_name");
domain[1] = switch_event_get_header(event, "variable_dialed_domain");
username[1] = switch_event_get_header(event, "variable_dialed_user");
for (i = 0; i < 2; i++) {
if (username[i] && domain[i]) {
switch_snprintf(key,sizeof(key),"%s@%s",username[i],domain[i]);
switch_snprintf(key, sizeof(key), "%s@%s", username[i], domain[i]);
if ((uuid = switch_core_hash_find(globals.spy_hash,key))) {
if ((uuid = switch_core_hash_find(globals.spy_hash, key))) {
break;
}
}
}
done:
done:
switch_thread_rwlock_unlock(globals.spy_hash_lock);
if (!uuid) {
@@ -169,64 +169,64 @@ static void event_handler(switch_event_t* event)
session = switch_core_session_locate(uuid);
channel = switch_core_session_get_channel(session);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,"UserSpy retrieved uuid %s for key %s, activating eavesdrop \n",uuid,key);
my_uuid = switch_event_get_header(event,"Unique-ID");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key);
my_uuid = switch_event_get_header(event, "Unique-ID");
switch_channel_set_variable(channel,"spy_uuid",my_uuid);
switch_channel_set_variable(channel, "spy_uuid", my_uuid);
switch_channel_set_state(channel,CS_EXCHANGE_MEDIA);
switch_channel_set_flag(channel,CF_BREAK);
switch_channel_set_state(channel, CS_EXCHANGE_MEDIA);
switch_channel_set_flag(channel, CF_BREAK);
switch_core_session_rwunlock(session);
}
#define USERSPY_SYNTAX "<user@domain> [uuid]"
SWITCH_STANDARD_APP(userspy_function)
SWITCH_STANDARD_APP(userspy_function)
{
int argc = 0;
char* argv[2] = {0};
char* params = NULL;
char *argv[2] = { 0 };
char *params = NULL;
if (!zstr(data) && (params = switch_core_session_strdup(session,data))) {
if (!zstr(data) && (params = switch_core_session_strdup(session, data))) {
if ((argc = switch_separate_string(params, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 1) {
switch_channel_t *channel = switch_core_session_get_channel(session);
char* uuid = switch_core_session_get_uuid(session);
char *uuid = switch_core_session_get_uuid(session);
switch_status_t status;
switch_thread_rwlock_wrlock(globals.spy_hash_lock);
if (switch_core_hash_find(globals.spy_hash,argv[0])) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,"Spy already exists for %s\n",argv[0]);
switch_channel_hangup(channel,SWITCH_CAUSE_NORMAL_CLEARING);
if (switch_core_hash_find(globals.spy_hash, argv[0])) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Spy already exists for %s\n", argv[0]);
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
switch_thread_rwlock_unlock(globals.spy_hash_lock);
return;
}
status = switch_core_hash_insert(globals.spy_hash,argv[0],(void*) uuid);
status = switch_core_hash_insert(globals.spy_hash, argv[0], (void *) uuid);
if ((status != SWITCH_STATUS_SUCCESS)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,"Cant insert to spy hash\n");
switch_channel_hangup(channel,SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED);
switch_thread_rwlock_unlock(globals.spy_hash_lock);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cant insert to spy hash\n");
switch_channel_hangup(channel, SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED);
switch_thread_rwlock_unlock(globals.spy_hash_lock);
return;
}
globals.spy_count++;
switch_thread_rwlock_unlock(globals.spy_hash_lock);
switch_channel_set_private(channel,"_userspy_",(void*) argv[0]);
switch_channel_add_state_handler(channel,&spy_state_handlers);
switch_channel_set_private(channel, "_userspy_", (void *) argv[0]);
switch_channel_add_state_handler(channel, &spy_state_handlers);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE,"UserSpy activated on %s \n",argv[0]);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "UserSpy activated on %s \n", argv[0]);
if (argv[1]) {
switch_channel_set_variable(channel,"spy_uuid",argv[1]);
switch_channel_set_state(channel,CS_EXCHANGE_MEDIA);
switch_channel_set_variable(channel, "spy_uuid", argv[1]);
switch_channel_set_state(channel, CS_EXCHANGE_MEDIA);
return;
}
switch_channel_set_state(channel,CS_PARK);
switch_channel_set_state(channel, CS_PARK);
return;
}
return;
@@ -244,15 +244,15 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spy_load)
globals.pool = pool;
switch_core_hash_init(&globals.spy_hash,pool);
switch_thread_rwlock_create(&globals.spy_hash_lock,pool);
switch_core_hash_init(&globals.spy_hash, pool);
switch_thread_rwlock_create(&globals.spy_hash_lock, pool);
globals.spy_count = 0;
switch_event_bind_removable(modname, SWITCH_EVENT_CHANNEL_BRIDGE, NULL, event_handler, NULL, &globals.node);
SWITCH_ADD_APP(app_interface,"userspy","Spy on a user constantly","Spy on a user constantly",userspy_function,USERSPY_SYNTAX,SAF_NONE);
SWITCH_ADD_API(api_interface,"userspy_show","Show current spies",dump_hash,"userspy_show");
SWITCH_ADD_APP(app_interface, "userspy", "Spy on a user constantly", "Spy on a user constantly", userspy_function, USERSPY_SYNTAX, SAF_NONE);
SWITCH_ADD_API(api_interface, "userspy_show", "Show current spies", dump_hash, "userspy_show");
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
@@ -261,12 +261,12 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_spy_shutdown)
{
int sanity = 0;
while (globals.spy_count) {
switch_cond_next();
if (++sanity >= 60000) {
break;
}
}
while (globals.spy_count) {
switch_cond_next();
if (++sanity >= 60000) {
break;
}
}
switch_event_unbind(&globals.node);
switch_core_hash_destroy(&globals.spy_hash);
+39 -45
View File
@@ -14,7 +14,7 @@
#if defined (FFTReal_CURRENT_HEADER)
#error Recursive inclusion of FFTReal header file.
#error Recursive inclusion of FFTReal header file.
#endif
#define FFTReal_CURRENT_HEADER
@@ -25,89 +25,83 @@
#if defined (_MSC_VER)
#pragma pack (push, 8)
#endif // _MSC_VER
#endif // _MSC_VER
class FFTReal
{
class FFTReal {
/*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
public:
public:
/* Change this typedef to use a different floating point type in your FFTs
(i.e. float, double or long double). */
typedef float flt_t;
(i.e. float, double or long double). */
typedef float flt_t;
explicit FFTReal (const long length);
~FFTReal ();
void do_fft (flt_t f [], const flt_t x []) const;
void do_ifft (const flt_t f [], flt_t x []) const;
void rescale (flt_t x []) const;
explicit FFTReal(const long length);
~FFTReal();
void do_fft(flt_t f[], const flt_t x[]) const;
void do_ifft(const flt_t f[], flt_t x[]) const;
void rescale(flt_t x[]) const;
/*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
private:
private:
/* Bit-reversed look-up table nested class */
class BitReversedLUT
{
public:
explicit BitReversedLUT (const int nbr_bits);
~BitReversedLUT ();
const long * get_ptr () const
{
class BitReversedLUT {
public:
explicit BitReversedLUT(const int nbr_bits);
~BitReversedLUT();
const long *get_ptr() const {
return (_ptr);
}
private:
long * _ptr;
} private:
long *_ptr;
};
/* Trigonometric look-up table nested class */
class TrigoLUT
{
public:
explicit TrigoLUT (const int nbr_bits);
~TrigoLUT ();
const flt_t * get_ptr (const int level) const
{
class TrigoLUT {
public:
explicit TrigoLUT(const int nbr_bits);
~TrigoLUT();
const flt_t *get_ptr(const int level) const {
return (_ptr + (1L << (level - 1)) - 4);
};
private:
flt_t * _ptr;
private:
flt_t *_ptr;
};
const BitReversedLUT _bit_rev_lut;
const TrigoLUT _trigo_lut;
const flt_t _sqrt2_2;
const long _length;
const int _nbr_bits;
flt_t * _buffer_ptr;
const BitReversedLUT _bit_rev_lut;
const TrigoLUT _trigo_lut;
const flt_t _sqrt2_2;
const long _length;
const int _nbr_bits;
flt_t *_buffer_ptr;
/*\\\ FORBIDDEN MEMBER FUNCTIONS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
private:
private:
FFTReal (const FFTReal &other);
const FFTReal& operator = (const FFTReal &other);
int operator == (const FFTReal &other);
int operator != (const FFTReal &other);
FFTReal(const FFTReal & other);
const FFTReal & operator =(const FFTReal & other);
int operator ==(const FFTReal & other);
int operator !=(const FFTReal & other);
};
#if defined (_MSC_VER)
#pragma pack (pop)
#endif // _MSC_VER
#endif // _MSC_VER
#endif // FFTReal_HEADER_INCLUDED
#endif // FFTReal_HEADER_INCLUDED
#undef FFTReal_CURRENT_HEADER
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -54,40 +54,42 @@ SWITCH_STANDARD_APP(t38gateway_start_function);
/*! Type that holds codec information. */
typedef struct {
/*! The sampling rate of the audio stream. */
int rate;
/*! The number of channels. */
int channels;
/*! The sampling rate of the audio stream. */
int rate;
/*! The number of channels. */
int channels;
} t38gateway_codec_info_t;
/*! Type that holds session information pertinent to the t38gateway module. */
typedef struct {
/*! Internal FreeSWITCH session. */
switch_core_session_t *session;
/*! Codec information for the session. */
t38gateway_codec_info_t t38gateway_codec;
t38_gateway_state_t *t38;
t38_core_state_t *t38_core;
udptl_state_t *udptl;
/*! Internal FreeSWITCH session. */
switch_core_session_t *session;
/*! Codec information for the session. */
t38gateway_codec_info_t t38gateway_codec;
t38_gateway_state_t *t38;
t38_core_state_t *t38_core;
udptl_state_t *udptl;
} t38gateway_session_info_t;
static int tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
{
t38gateway_session_info_t *t;
t38gateway_session_info_t *t;
t = (t38gateway_session_info_t *) user_data;
return 0;
t = (t38gateway_session_info_t *) user_data;
return 0;
}
/*- End of function --------------------------------------------------------*/
static int rx_packet_handler(void *user_data, const uint8_t *buf, int len, int seq_no)
{
t38gateway_session_info_t *t;
t38gateway_session_info_t *t;
t = (t38gateway_session_info_t *) user_data;
t38_core_rx_ifp_packet(t->t38_core, buf, len, seq_no);
return 0;
t = (t38gateway_session_info_t *) user_data;
t38_core_rx_ifp_packet(t->t38_core, buf, len, seq_no);
return 0;
}
/*- End of function --------------------------------------------------------*/
/*! \brief The callback function that is called when new audio data becomes available
@@ -98,39 +100,39 @@ static int rx_packet_handler(void *user_data, const uint8_t *buf, int len, int s
* @param type The switch callback type.
* @return The success or failure of the function.
*/
static switch_bool_t t38gateway_callback(switch_media_bug_t * bug, void *user_data, switch_abc_type_t type)
static switch_bool_t t38gateway_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
t38gateway_session_info_t *t38gateway_info;
switch_codec_t *read_codec;
switch_frame_t *frame;
int16_t *amp;
t38gateway_session_info_t *t38gateway_info;
switch_codec_t *read_codec;
switch_frame_t *frame;
int16_t *amp;
t38gateway_info = (t38gateway_session_info_t *) user_data;
if (t38gateway_info == NULL) {
return SWITCH_FALSE;
}
t38gateway_info = (t38gateway_session_info_t *) user_data;
if (t38gateway_info == NULL) {
return SWITCH_FALSE;
}
switch (type) {
case SWITCH_ABC_TYPE_INIT:
read_codec = switch_core_session_get_read_codec(t38gateway_info->session);
t38gateway_info->t38gateway_codec.rate = read_codec->implementation->samples_per_second;
t38gateway_info->t38gateway_codec.channels = read_codec->implementation->number_of_channels;
break;
case SWITCH_ABC_TYPE_READ_PING:
case SWITCH_ABC_TYPE_CLOSE:
break;
case SWITCH_ABC_TYPE_READ:
frame = switch_core_media_bug_get_read_replace_frame(bug);
amp = (int16_t *) frame->data;
t38_gateway_rx(t38gateway_info->t38, amp, frame->samples);
break;
case SWITCH_ABC_TYPE_WRITE:
case SWITCH_ABC_TYPE_READ_REPLACE:
case SWITCH_ABC_TYPE_WRITE_REPLACE:
break;
}
switch (type) {
case SWITCH_ABC_TYPE_INIT:
read_codec = switch_core_session_get_read_codec(t38gateway_info->session);
t38gateway_info->t38gateway_codec.rate = read_codec->implementation->samples_per_second;
t38gateway_info->t38gateway_codec.channels = read_codec->implementation->number_of_channels;
break;
case SWITCH_ABC_TYPE_READ_PING:
case SWITCH_ABC_TYPE_CLOSE:
break;
case SWITCH_ABC_TYPE_READ:
frame = switch_core_media_bug_get_read_replace_frame(bug);
amp = (int16_t *) frame->data;
t38_gateway_rx(t38gateway_info->t38, amp, frame->samples);
break;
case SWITCH_ABC_TYPE_WRITE:
case SWITCH_ABC_TYPE_READ_REPLACE:
case SWITCH_ABC_TYPE_WRITE_REPLACE:
break;
}
return SWITCH_TRUE;
return SWITCH_TRUE;
}
/*! \brief FreeSWITCH module loading function
@@ -140,19 +142,19 @@ static switch_bool_t t38gateway_callback(switch_media_bug_t * bug, void *user_da
*/
SWITCH_MODULE_LOAD_FUNCTION(mod_t38gateway_load)
{
switch_application_interface_t *app_interface;
switch_api_interface_t *api_interface;
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_application_interface_t *app_interface;
switch_api_interface_t *api_interface;
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "T.38 gateway enabled\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "T.38 gateway enabled\n");
SWITCH_ADD_APP(app_interface, "t38gateway", "T.38 gateway", "T.38 gateway", t38gateway_start_function, "[start] [stop]", SAF_NONE);
SWITCH_ADD_APP(app_interface, "t38gateway", "T.38 gateway", "T.38 gateway", t38gateway_start_function, "[start] [stop]", SAF_NONE);
SWITCH_ADD_API(api_interface, "t38gateway", "T.38 gateway", t38gateway_api_main, T38GATEWAY_SYNTAX);
SWITCH_ADD_API(api_interface, "t38gateway", "T.38 gateway", t38gateway_api_main, T38GATEWAY_SYNTAX);
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
/*! \brief FreeSWITCH application handler function.
@@ -163,48 +165,48 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_t38gateway_load)
*/
SWITCH_STANDARD_APP(t38gateway_start_function)
{
switch_media_bug_t *bug;
switch_status_t status;
switch_channel_t *channel;
t38gateway_session_info_t *t38gateway_info;
switch_media_bug_t *bug;
switch_status_t status;
switch_channel_t *channel;
t38gateway_session_info_t *t38gateway_info;
if (session == NULL)
return;
if (session == NULL)
return;
channel = switch_core_session_get_channel(session);
channel = switch_core_session_get_channel(session);
/* Is this channel already set? */
bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_t38gateway_");
/* If yes */
if (bug != NULL) {
/* If we have a stop remove audio bug */
if (strcasecmp(data, "stop") == 0) {
switch_channel_set_private(channel, "_t38gateway_", NULL);
switch_core_media_bug_remove(session, &bug);
return;
}
/* Is this channel already set? */
bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_t38gateway_");
/* If yes */
if (bug != NULL) {
/* If we have a stop remove audio bug */
if (strcasecmp(data, "stop") == 0) {
switch_channel_set_private(channel, "_t38gateway_", NULL);
switch_core_media_bug_remove(session, &bug);
return;
}
/* We have already started */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot run 2 at once on the same channel!\n");
/* We have already started */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot run 2 at once on the same channel!\n");
return;
}
return;
}
t38gateway_info = (t38gateway_session_info_t *) switch_core_session_alloc(session, sizeof(t38gateway_session_info_t));
t38gateway_info = (t38gateway_session_info_t *) switch_core_session_alloc(session, sizeof(t38gateway_session_info_t));
t38gateway_info->session = session;
t38gateway_info->t38 = t38_gateway_init(NULL, tx_packet_handler, (void *) t38gateway_info);
t38gateway_info->t38_core = t38_gateway_get_t38_core_state(t38gateway_info->t38);
t38gateway_info->udptl = udptl_init(NULL, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3, rx_packet_handler, (void *) t38gateway_info);
t38gateway_info->session = session;
t38gateway_info->t38 = t38_gateway_init(NULL, tx_packet_handler, (void *) t38gateway_info);
t38gateway_info->t38_core = t38_gateway_get_t38_core_state(t38gateway_info->t38);
t38gateway_info->udptl = udptl_init(NULL, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3, rx_packet_handler, (void *) t38gateway_info);
status = switch_core_media_bug_add(session, t38gateway_callback, t38gateway_info, 0, SMBF_READ_STREAM, &bug);
status = switch_core_media_bug_add(session, t38gateway_callback, t38gateway_info, 0, SMBF_READ_STREAM, &bug);
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failure hooking to stream\n");
return;
}
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failure hooking to stream\n");
return;
}
switch_channel_set_private(channel, "_t38gateway_", bug);
switch_channel_set_private(channel, "_t38gateway_", bug);
}
/*! \brief Called when the module shuts down
@@ -214,9 +216,9 @@ SWITCH_STANDARD_APP(t38gateway_start_function)
*/
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_t38gateway_shutdown)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "T.38 gateway disabled\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "T.38 gateway disabled\n");
return SWITCH_STATUS_SUCCESS;
return SWITCH_STATUS_SUCCESS;
}
/*! \brief FreeSWITCH API handler function.
@@ -228,110 +230,110 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_t38gateway_shutdown)
*/
SWITCH_STANDARD_API(t38gateway_api_main)
{
switch_core_session_t *t38gateway_session;
switch_media_bug_t *bug;
t38gateway_session_info_t *t38gateway_info;
switch_channel_t *channel;
switch_status_t status;
int argc;
char *argv[T38GATEWAY_PARAMS];
char *ccmd;
char *uuid;
char *command;
switch_core_session_t *t38gateway_session;
switch_media_bug_t *bug;
t38gateway_session_info_t *t38gateway_info;
switch_channel_t *channel;
switch_status_t status;
int argc;
char *argv[T38GATEWAY_PARAMS];
char *ccmd;
char *uuid;
char *command;
/* No command? Display usage */
if (cmd == NULL) {
stream->write_function(stream, "-USAGE: %s\n", T38GATEWAY_SYNTAX);
return SWITCH_STATUS_SUCCESS;
}
/* No command? Display usage */
if (cmd == NULL) {
stream->write_function(stream, "-USAGE: %s\n", T38GATEWAY_SYNTAX);
return SWITCH_STATUS_SUCCESS;
}
/* Duplicated contents of original string */
ccmd = strdup(cmd);
/* Separate the arguments */
argc = switch_separate_string(ccmd, ' ', argv, T38GATEWAY_PARAMS);
/* Duplicated contents of original string */
ccmd = strdup(cmd);
/* Separate the arguments */
argc = switch_separate_string(ccmd, ' ', argv, T38GATEWAY_PARAMS);
/* If we don't have the expected number of parameters
* display usage */
if (argc != T38GATEWAY_PARAMS) {
stream->write_function(stream, "-USAGE: %s\n", T38GATEWAY_SYNTAX);
switch_safe_free(ccmd);
return SWITCH_STATUS_SUCCESS;
}
/* If we don't have the expected number of parameters
* display usage */
if (argc != T38GATEWAY_PARAMS) {
stream->write_function(stream, "-USAGE: %s\n", T38GATEWAY_SYNTAX);
switch_safe_free(ccmd);
return SWITCH_STATUS_SUCCESS;
}
uuid = argv[0];
command = argv[1];
uuid = argv[0];
command = argv[1];
/* using uuid locate a reference to the FreeSWITCH session */
t38gateway_session = switch_core_session_locate(uuid);
/* using uuid locate a reference to the FreeSWITCH session */
t38gateway_session = switch_core_session_locate(uuid);
/* If the session was not found exit */
if (t38gateway_session == NULL) {
switch_safe_free(ccmd);
stream->write_function(stream, "-USAGE: %s\n", T38GATEWAY_SYNTAX);
return SWITCH_STATUS_FALSE;
}
/* If the session was not found exit */
if (t38gateway_session == NULL) {
switch_safe_free(ccmd);
stream->write_function(stream, "-USAGE: %s\n", T38GATEWAY_SYNTAX);
return SWITCH_STATUS_FALSE;
}
/* Get current channel of the session to tag the session
* This indicates that our module is present */
channel = switch_core_session_get_channel(t38gateway_session);
/* Get current channel of the session to tag the session
* This indicates that our module is present */
channel = switch_core_session_get_channel(t38gateway_session);
/* Is this channel already set? */
bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_t38gateway_");
/* If yes */
if (bug != NULL) {
/* If we have a stop remove audio bug */
if (strcasecmp(command, "stop") == 0) {
switch_channel_set_private(channel, "_t38gateway_", NULL);
switch_core_media_bug_remove(t38gateway_session, &bug);
switch_safe_free(ccmd);
stream->write_function(stream, "+OK\n");
return SWITCH_STATUS_SUCCESS;
}
/* Is this channel already set? */
bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_t38gateway_");
/* If yes */
if (bug != NULL) {
/* If we have a stop remove audio bug */
if (strcasecmp(command, "stop") == 0) {
switch_channel_set_private(channel, "_t38gateway_", NULL);
switch_core_media_bug_remove(t38gateway_session, &bug);
switch_safe_free(ccmd);
stream->write_function(stream, "+OK\n");
return SWITCH_STATUS_SUCCESS;
}
/* We have already started */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot run 2 at once on the same channel!\n");
/* We have already started */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot run 2 at once on the same channel!\n");
switch_safe_free(ccmd);
return SWITCH_STATUS_FALSE;
}
switch_safe_free(ccmd);
return SWITCH_STATUS_FALSE;
}
/* If we don't see the expected start exit */
if (strcasecmp(command, "start") != 0) {
switch_safe_free(ccmd);
stream->write_function(stream, "-USAGE: %s\n", T38GATEWAY_SYNTAX);
return SWITCH_STATUS_FALSE;
}
/* If we don't see the expected start exit */
if (strcasecmp(command, "start") != 0) {
switch_safe_free(ccmd);
stream->write_function(stream, "-USAGE: %s\n", T38GATEWAY_SYNTAX);
return SWITCH_STATUS_FALSE;
}
/* Allocate memory attached to this FreeSWITCH session for
* use in the callback routine and to store state information */
t38gateway_info = (t38gateway_session_info_t *) switch_core_session_alloc(t38gateway_session, sizeof(t38gateway_session_info_t));
/* Allocate memory attached to this FreeSWITCH session for
* use in the callback routine and to store state information */
t38gateway_info = (t38gateway_session_info_t *) switch_core_session_alloc(t38gateway_session, sizeof(t38gateway_session_info_t));
/* Set initial values and states */
t38gateway_info->session = t38gateway_session;
t38gateway_info->t38 = t38_gateway_init(NULL, tx_packet_handler, (void *) t38gateway_info);
t38gateway_info->t38_core = t38_gateway_get_t38_core_state(t38gateway_info->t38);
t38gateway_info->udptl = udptl_init(NULL, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3, rx_packet_handler, (void *) t38gateway_info);
/* Set initial values and states */
t38gateway_info->session = t38gateway_session;
t38gateway_info->t38 = t38_gateway_init(NULL, tx_packet_handler, (void *) t38gateway_info);
t38gateway_info->t38_core = t38_gateway_get_t38_core_state(t38gateway_info->t38);
t38gateway_info->udptl = udptl_init(NULL, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3, rx_packet_handler, (void *) t38gateway_info);
/* Add a media bug that allows me to intercept the
* reading leg of the audio stream */
status = switch_core_media_bug_add(t38gateway_session, t38gateway_callback, t38gateway_info, 0, SMBF_READ_STREAM, &bug);
/* Add a media bug that allows me to intercept the
* reading leg of the audio stream */
status = switch_core_media_bug_add(t38gateway_session, t38gateway_callback, t38gateway_info, 0, SMBF_READ_STREAM, &bug);
/* If adding a media bug fails exit */
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failure hooking to stream\n");
/* If adding a media bug fails exit */
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failure hooking to stream\n");
switch_safe_free(ccmd);
return SWITCH_STATUS_FALSE;
}
switch_safe_free(ccmd);
return SWITCH_STATUS_FALSE;
}
/* Set the t38gateway tag to detect an existing t38gateway media bug */
switch_channel_set_private(channel, "_t38gateway_", bug);
/* Set the t38gateway tag to detect an existing t38gateway media bug */
switch_channel_set_private(channel, "_t38gateway_", bug);
/* Everything went according to plan! Notify the user */
stream->write_function(stream, "+OK\n");
/* Everything went according to plan! Notify the user */
stream->write_function(stream, "+OK\n");
switch_safe_free(ccmd);
return SWITCH_STATUS_SUCCESS;
switch_safe_free(ccmd);
return SWITCH_STATUS_SUCCESS;
}
+426 -459
View File
@@ -36,561 +36,528 @@
static int decode_length(const uint8_t *buf, int limit, int *len, int *pvalue)
{
if (*len >= limit)
return -1;
if ((buf[*len] & 0x80) == 0)
{
*pvalue = buf[(*len)++];
return 0;
}
if ((buf[*len] & 0x40) == 0)
{
if (*len >= limit - 1)
return -1;
*pvalue = (buf[(*len)++] & 0x3F) << 8;
*pvalue |= buf[(*len)++];
return 0;
}
*pvalue = (buf[(*len)++] & 0x3F) << 14;
/* Indicate we have a fragment */
return 1;
if (*len >= limit)
return -1;
if ((buf[*len] & 0x80) == 0) {
*pvalue = buf[(*len)++];
return 0;
}
if ((buf[*len] & 0x40) == 0) {
if (*len >= limit - 1)
return -1;
*pvalue = (buf[(*len)++] & 0x3F) << 8;
*pvalue |= buf[(*len)++];
return 0;
}
*pvalue = (buf[(*len)++] & 0x3F) << 14;
/* Indicate we have a fragment */
return 1;
}
/*- End of function --------------------------------------------------------*/
static int decode_open_type(const uint8_t *buf, int limit, int *len, const uint8_t **p_object, int *p_num_octets)
static int decode_open_type(const uint8_t *buf, int limit, int *len, const uint8_t ** p_object, int *p_num_octets)
{
int octet_cnt;
int octet_idx;
int stat;
int i;
const uint8_t **pbuf;
int octet_cnt;
int octet_idx;
int stat;
int i;
const uint8_t **pbuf;
for (octet_idx = 0, *p_num_octets = 0; ; octet_idx += octet_cnt)
{
if ((stat = decode_length(buf, limit, len, &octet_cnt)) < 0)
return -1;
if (octet_cnt > 0)
{
*p_num_octets += octet_cnt;
for (octet_idx = 0, *p_num_octets = 0;; octet_idx += octet_cnt) {
if ((stat = decode_length(buf, limit, len, &octet_cnt)) < 0)
return -1;
if (octet_cnt > 0) {
*p_num_octets += octet_cnt;
pbuf = &p_object[octet_idx];
i = 0;
/* Make sure the buffer contains at least the number of bits requested */
if ((*len + octet_cnt) > limit)
return -1;
pbuf = &p_object[octet_idx];
i = 0;
/* Make sure the buffer contains at least the number of bits requested */
if ((*len + octet_cnt) > limit)
return -1;
*pbuf = &buf[*len];
*len += octet_cnt;
}
if (stat == 0)
break;
}
return 0;
*pbuf = &buf[*len];
*len += octet_cnt;
}
if (stat == 0)
break;
}
return 0;
}
/*- End of function --------------------------------------------------------*/
static int encode_length(uint8_t *buf, int *len, int value)
{
int multiplier;
int multiplier;
if (value < 0x80)
{
/* 1 octet */
buf[(*len)++] = value;
return value;
}
if (value < 0x4000)
{
/* 2 octets */
/* Set the first bit of the first octet */
buf[(*len)++] = ((0x8000 | value) >> 8) & 0xFF;
buf[(*len)++] = value & 0xFF;
return value;
}
/* Fragmentation */
multiplier = (value < 0x10000) ? (value >> 14) : 4;
/* Set the first 2 bits of the octet */
buf[(*len)++] = 0xC0 | multiplier;
return multiplier << 14;
if (value < 0x80) {
/* 1 octet */
buf[(*len)++] = value;
return value;
}
if (value < 0x4000) {
/* 2 octets */
/* Set the first bit of the first octet */
buf[(*len)++] = ((0x8000 | value) >> 8) & 0xFF;
buf[(*len)++] = value & 0xFF;
return value;
}
/* Fragmentation */
multiplier = (value < 0x10000) ? (value >> 14) : 4;
/* Set the first 2 bits of the octet */
buf[(*len)++] = 0xC0 | multiplier;
return multiplier << 14;
}
/*- End of function --------------------------------------------------------*/
static int encode_open_type(uint8_t *buf, int *len, const uint8_t *data, int num_octets)
{
int enclen;
int octet_idx;
uint8_t zero_byte;
int enclen;
int octet_idx;
uint8_t zero_byte;
/* If open type is of zero length, add a single zero byte (10.1) */
if (num_octets == 0)
{
zero_byte = 0;
data = &zero_byte;
num_octets = 1;
}
/* Encode the open type */
for (octet_idx = 0; ; num_octets -= enclen, octet_idx += enclen)
{
if ((enclen = encode_length(buf, len, num_octets)) < 0)
return -1;
if (enclen > 0)
{
memcpy(&buf[*len], &data[octet_idx], enclen);
*len += enclen;
}
if (enclen >= num_octets)
break;
}
/* If open type is of zero length, add a single zero byte (10.1) */
if (num_octets == 0) {
zero_byte = 0;
data = &zero_byte;
num_octets = 1;
}
/* Encode the open type */
for (octet_idx = 0;; num_octets -= enclen, octet_idx += enclen) {
if ((enclen = encode_length(buf, len, num_octets)) < 0)
return -1;
if (enclen > 0) {
memcpy(&buf[*len], &data[octet_idx], enclen);
*len += enclen;
}
if (enclen >= num_octets)
break;
}
return 0;
return 0;
}
/*- End of function --------------------------------------------------------*/
int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len)
{
int stat;
int stat2;
int i;
int j;
int k;
int l;
int m;
int x;
int limit;
int which;
int ptr;
int count;
int total_count;
int seq_no;
const uint8_t *msg;
const uint8_t *data;
int msg_len;
int repaired[16];
const uint8_t *bufs[16];
int lengths[16];
int span;
int entries;
int stat;
int stat2;
int i;
int j;
int k;
int l;
int m;
int x;
int limit;
int which;
int ptr;
int count;
int total_count;
int seq_no;
const uint8_t *msg;
const uint8_t *data;
int msg_len;
int repaired[16];
const uint8_t *bufs[16];
int lengths[16];
int span;
int entries;
ptr = 0;
/* Decode seq_number */
if (ptr + 2 > len)
return -1;
seq_no = (buf[0] << 8) | buf[1];
ptr += 2;
/* Break out the primary packet */
if ((stat = decode_open_type(buf, len, &ptr, &msg, &msg_len)) != 0)
return -1;
/* Decode error_recovery */
if (ptr + 1 > len)
return -1;
/* Our buffers cannot tolerate overlength packets */
if (msg_len > LOCAL_FAX_MAX_DATAGRAM)
return -1;
/* Update any missed slots in the buffer */
for (i = s->rx_seq_no; seq_no > i; i++)
{
x = i & UDPTL_BUF_MASK;
s->rx[x].buf_len = -1;
s->rx[x].fec_len[0] = 0;
s->rx[x].fec_span = 0;
s->rx[x].fec_entries = 0;
}
/* Save the new packet. Pure redundancy mode won't use this, but some systems will switch
into FEC mode after sending some redundant packets. */
x = seq_no & UDPTL_BUF_MASK;
memcpy(s->rx[x].buf, msg, msg_len);
s->rx[x].buf_len = msg_len;
s->rx[x].fec_len[0] = 0;
s->rx[x].fec_span = 0;
s->rx[x].fec_entries = 0;
if ((buf[ptr++] & 0x80) == 0)
{
/* Secondary packet mode for error recovery */
/* We might have the packet we want, but we need to check through
the redundant stuff, and verify the integrity of the UDPTL.
This greatly reduces our chances of accepting garbage. */
total_count = 0;
do
{
if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0)
return -1;
for (i = 0; i < count; i++)
{
if ((stat = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0)
return -1;
}
total_count += count;
}
while (stat2 > 0);
/* We should now be exactly at the end of the packet. If not, this is a fault. */
if (ptr != len)
return -1;
if (seq_no > s->rx_seq_no)
{
/* We received a later packet than we expected, so we need to check if we can fill in the gap from the
secondary packets. */
/* Step through in reverse order, so we go oldest to newest */
for (i = total_count; i > 0; i--)
{
if (seq_no - i >= s->rx_seq_no)
{
/* This one wasn't seen before */
/* Decode the secondary packet */
ptr = 0;
/* Decode seq_number */
if (ptr + 2 > len)
return -1;
seq_no = (buf[0] << 8) | buf[1];
ptr += 2;
/* Break out the primary packet */
if ((stat = decode_open_type(buf, len, &ptr, &msg, &msg_len)) != 0)
return -1;
/* Decode error_recovery */
if (ptr + 1 > len)
return -1;
/* Our buffers cannot tolerate overlength packets */
if (msg_len > LOCAL_FAX_MAX_DATAGRAM)
return -1;
/* Update any missed slots in the buffer */
for (i = s->rx_seq_no; seq_no > i; i++) {
x = i & UDPTL_BUF_MASK;
s->rx[x].buf_len = -1;
s->rx[x].fec_len[0] = 0;
s->rx[x].fec_span = 0;
s->rx[x].fec_entries = 0;
}
/* Save the new packet. Pure redundancy mode won't use this, but some systems will switch
into FEC mode after sending some redundant packets. */
x = seq_no & UDPTL_BUF_MASK;
memcpy(s->rx[x].buf, msg, msg_len);
s->rx[x].buf_len = msg_len;
s->rx[x].fec_len[0] = 0;
s->rx[x].fec_span = 0;
s->rx[x].fec_entries = 0;
if ((buf[ptr++] & 0x80) == 0) {
/* Secondary packet mode for error recovery */
/* We might have the packet we want, but we need to check through
the redundant stuff, and verify the integrity of the UDPTL.
This greatly reduces our chances of accepting garbage. */
total_count = 0;
do {
if ((stat2 = decode_length(buf, len, &ptr, &count)) < 0)
return -1;
for (i = 0; i < count; i++) {
if ((stat = decode_open_type(buf, len, &ptr, &bufs[total_count + i], &lengths[total_count + i])) != 0)
return -1;
}
total_count += count;
}
while (stat2 > 0);
/* We should now be exactly at the end of the packet. If not, this is a fault. */
if (ptr != len)
return -1;
if (seq_no > s->rx_seq_no) {
/* We received a later packet than we expected, so we need to check if we can fill in the gap from the
secondary packets. */
/* Step through in reverse order, so we go oldest to newest */
for (i = total_count; i > 0; i--) {
if (seq_no - i >= s->rx_seq_no) {
/* This one wasn't seen before */
/* Decode the secondary packet */
#if defined(UDPTL_DEBUG)
fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]);
fprintf(stderr, "Secondary %d, len %d\n", seq_no - i, lengths[i - 1]);
#endif
/* Save the new packet. Redundancy mode won't use this, but some systems will switch into
FEC mode after sending some redundant packets, and this may then be important. */
x = (seq_no - i) & UDPTL_BUF_MASK;
memcpy(s->rx[x].buf, bufs[i - 1], lengths[i - 1]);
s->rx[x].buf_len = lengths[i - 1];
s->rx[x].fec_len[0] = 0;
s->rx[x].fec_span = 0;
s->rx[x].fec_entries = 0;
if (s->rx_packet_handler(s->user_data, bufs[i - 1], lengths[i - 1], seq_no - i) < 0)
fprintf(stderr, "Bad IFP\n");
}
}
}
}
else
{
/* FEC mode for error recovery */
/* Save the new packet. Redundancy mode won't use this, but some systems will switch into
FEC mode after sending some redundant packets, and this may then be important. */
x = (seq_no - i) & UDPTL_BUF_MASK;
memcpy(s->rx[x].buf, bufs[i - 1], lengths[i - 1]);
s->rx[x].buf_len = lengths[i - 1];
s->rx[x].fec_len[0] = 0;
s->rx[x].fec_span = 0;
s->rx[x].fec_entries = 0;
if (s->rx_packet_handler(s->user_data, bufs[i - 1], lengths[i - 1], seq_no - i) < 0)
fprintf(stderr, "Bad IFP\n");
}
}
}
} else {
/* FEC mode for error recovery */
/* Decode the FEC packets */
/* The span is defined as an unconstrained integer, but will never be more
than a small value. */
if (ptr + 2 > len)
return -1;
if (buf[ptr++] != 1)
return -1;
span = buf[ptr++];
/* Decode the FEC packets */
/* The span is defined as an unconstrained integer, but will never be more
than a small value. */
if (ptr + 2 > len)
return -1;
if (buf[ptr++] != 1)
return -1;
span = buf[ptr++];
x = seq_no & UDPTL_BUF_MASK;
x = seq_no & UDPTL_BUF_MASK;
s->rx[x].fec_span = span;
s->rx[x].fec_span = span;
memset(repaired, 0, sizeof(repaired));
repaired[x] = TRUE;
memset(repaired, 0, sizeof(repaired));
repaired[x] = TRUE;
/* The number of entries is defined as a length, but will only ever be a small
value. Treat it as such. */
if (ptr + 1 > len)
return -1;
entries = buf[ptr++];
s->rx[x].fec_entries = entries;
/* The number of entries is defined as a length, but will only ever be a small
value. Treat it as such. */
if (ptr + 1 > len)
return -1;
entries = buf[ptr++];
s->rx[x].fec_entries = entries;
/* Decode the elements */
for (i = 0; i < entries; i++)
{
if ((stat = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0)
return -1;
if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM)
return -1;
/* Decode the elements */
for (i = 0; i < entries; i++) {
if ((stat = decode_open_type(buf, len, &ptr, &data, &s->rx[x].fec_len[i])) != 0)
return -1;
if (s->rx[x].fec_len[i] > LOCAL_FAX_MAX_DATAGRAM)
return -1;
/* Save the new FEC data */
memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]);
/* Save the new FEC data */
memcpy(s->rx[x].fec[i], data, s->rx[x].fec_len[i]);
#if 0
fprintf(stderr, "FEC: ");
for (j = 0; j < s->rx[x].fec_len[i]; j++)
fprintf(stderr, "%02X ", data[j]);
fprintf(stderr, "\n");
fprintf(stderr, "FEC: ");
for (j = 0; j < s->rx[x].fec_len[i]; j++)
fprintf(stderr, "%02X ", data[j]);
fprintf(stderr, "\n");
#endif
}
/* We should now be exactly at the end of the packet. If not, this is a fault. */
if (ptr != len)
return -1;
/* See if we can reconstruct anything which is missing */
/* TODO: this does not comprehensively hunt back and repair everything that is possible */
for (l = x; l != ((x - (16 - span*entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK)
{
if (s->rx[l].fec_len[0] <= 0)
continue;
for (m = 0; m < s->rx[l].fec_entries; m++)
{
limit = (l + m) & UDPTL_BUF_MASK;
for (which = -1, k = (limit - s->rx[l].fec_span*s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK)
{
if (s->rx[k].buf_len <= 0)
which = (which == -1) ? k : -2;
}
if (which >= 0)
{
/* Repairable */
for (j = 0; j < s->rx[l].fec_len[m]; j++)
{
s->rx[which].buf[j] = s->rx[l].fec[m][j];
for (k = (limit - s->rx[l].fec_span*s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit; k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK)
s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0;
}
s->rx[which].buf_len = s->rx[l].fec_len[m];
repaired[which] = TRUE;
}
}
}
/* Now play any new packets forwards in time */
for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++)
{
if (repaired[l])
{
}
/* We should now be exactly at the end of the packet. If not, this is a fault. */
if (ptr != len)
return -1;
/* See if we can reconstruct anything which is missing */
/* TODO: this does not comprehensively hunt back and repair everything that is possible */
for (l = x; l != ((x - (16 - span * entries)) & UDPTL_BUF_MASK); l = (l - 1) & UDPTL_BUF_MASK) {
if (s->rx[l].fec_len[0] <= 0)
continue;
for (m = 0; m < s->rx[l].fec_entries; m++) {
limit = (l + m) & UDPTL_BUF_MASK;
for (which = -1, k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit;
k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK) {
if (s->rx[k].buf_len <= 0)
which = (which == -1) ? k : -2;
}
if (which >= 0) {
/* Repairable */
for (j = 0; j < s->rx[l].fec_len[m]; j++) {
s->rx[which].buf[j] = s->rx[l].fec[m][j];
for (k = (limit - s->rx[l].fec_span * s->rx[l].fec_entries) & UDPTL_BUF_MASK; k != limit;
k = (k + s->rx[l].fec_entries) & UDPTL_BUF_MASK)
s->rx[which].buf[j] ^= (s->rx[k].buf_len > j) ? s->rx[k].buf[j] : 0;
}
s->rx[which].buf_len = s->rx[l].fec_len[m];
repaired[which] = TRUE;
}
}
}
/* Now play any new packets forwards in time */
for (l = (x + 1) & UDPTL_BUF_MASK, j = seq_no - UDPTL_BUF_MASK; l != x; l = (l + 1) & UDPTL_BUF_MASK, j++) {
if (repaired[l]) {
#if defined(UDPTL_DEBUG)
fprintf(stderr, "Fixed packet %d, len %d\n", j, l);
fprintf(stderr, "Fixed packet %d, len %d\n", j, l);
#endif
if (s->rx_packet_handler(s->user_data, s->rx[l].buf, s->rx[l].buf_len, j) < 0)
fprintf(stderr, "Bad IFP\n");
}
}
}
/* If packets are received out of sequence, we may have already processed this packet from the error
recovery information in a packet already received. */
if (seq_no >= s->rx_seq_no)
{
/* Decode the primary packet */
if (s->rx_packet_handler(s->user_data, s->rx[l].buf, s->rx[l].buf_len, j) < 0)
fprintf(stderr, "Bad IFP\n");
}
}
}
/* If packets are received out of sequence, we may have already processed this packet from the error
recovery information in a packet already received. */
if (seq_no >= s->rx_seq_no) {
/* Decode the primary packet */
#if defined(UDPTL_DEBUG)
fprintf(stderr, "Primary packet %d, len %d\n", seq_no, msg_len);
fprintf(stderr, "Primary packet %d, len %d\n", seq_no, msg_len);
#endif
if (s->rx_packet_handler(s->user_data, msg, msg_len, seq_no) < 0)
fprintf(stderr, "Bad IFP\n");
}
if (s->rx_packet_handler(s->user_data, msg, msg_len, seq_no) < 0)
fprintf(stderr, "Bad IFP\n");
}
s->rx_seq_no = (seq_no + 1) & 0xFFFF;
return 0;
s->rx_seq_no = (seq_no + 1) & 0xFFFF;
return 0;
}
/*- End of function --------------------------------------------------------*/
int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int msg_len)
{
uint8_t fec[LOCAL_FAX_MAX_DATAGRAM];
int i;
int j;
int seq;
int entry;
int entries;
int span;
int m;
int len;
int limit;
int high_tide;
uint8_t fec[LOCAL_FAX_MAX_DATAGRAM];
int i;
int j;
int seq;
int entry;
int entries;
int span;
int m;
int len;
int limit;
int high_tide;
/* UDPTL cannot cope with zero length messages, and our buffering for redundancy limits their
maximum length. */
if (msg_len < 1 || msg_len > LOCAL_FAX_MAX_DATAGRAM)
return -1;
seq = s->tx_seq_no & 0xFFFF;
/* UDPTL cannot cope with zero length messages, and our buffering for redundancy limits their
maximum length. */
if (msg_len < 1 || msg_len > LOCAL_FAX_MAX_DATAGRAM)
return -1;
seq = s->tx_seq_no & 0xFFFF;
/* Map the sequence number to an entry in the circular buffer */
entry = seq & UDPTL_BUF_MASK;
/* Map the sequence number to an entry in the circular buffer */
entry = seq & UDPTL_BUF_MASK;
/* We save the message in a circular buffer, for generating FEC or
redundancy sets later on. */
s->tx[entry].buf_len = msg_len;
memcpy(s->tx[entry].buf, msg, msg_len);
/* Build the UDPTL packet */
/* We save the message in a circular buffer, for generating FEC or
redundancy sets later on. */
s->tx[entry].buf_len = msg_len;
memcpy(s->tx[entry].buf, msg, msg_len);
len = 0;
/* Encode the sequence number */
buf[len++] = (seq >> 8) & 0xFF;
buf[len++] = seq & 0xFF;
/* Build the UDPTL packet */
/* Encode the primary packet */
if (encode_open_type(buf, &len, msg, msg_len) < 0)
return -1;
len = 0;
/* Encode the sequence number */
buf[len++] = (seq >> 8) & 0xFF;
buf[len++] = seq & 0xFF;
/* Encode the appropriate type of error recovery information */
switch (s->error_correction_scheme)
{
case UDPTL_ERROR_CORRECTION_NONE:
/* Encode the error recovery type */
buf[len++] = 0x00;
/* The number of entries will always be zero, so it is pointless allowing
for the fragmented case here. */
if (encode_length(buf, &len, 0) < 0)
return -1;
break;
case UDPTL_ERROR_CORRECTION_REDUNDANCY:
/* Encode the error recovery type */
buf[len++] = 0x00;
if (s->tx_seq_no > s->error_correction_entries)
entries = s->error_correction_entries;
else
entries = s->tx_seq_no;
/* The number of entries will always be small, so it is pointless allowing
for the fragmented case here. */
if (encode_length(buf, &len, entries) < 0)
return -1;
/* Encode the elements */
for (i = 0; i < entries; i++)
{
j = (entry - i - 1) & UDPTL_BUF_MASK;
if (encode_open_type(buf, &len, s->tx[j].buf, s->tx[j].buf_len) < 0)
return -1;
}
break;
case UDPTL_ERROR_CORRECTION_FEC:
span = s->error_correction_span;
entries = s->error_correction_entries;
if (seq < s->error_correction_span*s->error_correction_entries)
{
/* In the initial stages, wind up the FEC smoothly */
entries = seq/s->error_correction_span;
if (seq < s->error_correction_span)
span = 0;
}
/* Encode the error recovery type */
buf[len++] = 0x80;
/* Span is defined as an inconstrained integer, which it dumb. It will only
ever be a small value. Treat it as such. */
buf[len++] = 1;
buf[len++] = span;
/* The number of entries is defined as a length, but will only ever be a small
value. Treat it as such. */
buf[len++] = entries;
for (m = 0; m < entries; m++)
{
/* Make an XOR'ed entry the maximum length */
limit = (entry + m) & UDPTL_BUF_MASK;
high_tide = 0;
for (i = (limit - span*entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK)
{
if (high_tide < s->tx[i].buf_len)
{
for (j = 0; j < high_tide; j++)
fec[j] ^= s->tx[i].buf[j];
for ( ; j < s->tx[i].buf_len; j++)
fec[j] = s->tx[i].buf[j];
high_tide = s->tx[i].buf_len;
}
else
{
for (j = 0; j < s->tx[i].buf_len; j++)
fec[j] ^= s->tx[i].buf[j];
}
}
if (encode_open_type(buf, &len, fec, high_tide) < 0)
return -1;
}
break;
}
/* Encode the primary packet */
if (encode_open_type(buf, &len, msg, msg_len) < 0)
return -1;
if (s->verbose)
fprintf(stderr, "\n");
s->tx_seq_no++;
return len;
/* Encode the appropriate type of error recovery information */
switch (s->error_correction_scheme) {
case UDPTL_ERROR_CORRECTION_NONE:
/* Encode the error recovery type */
buf[len++] = 0x00;
/* The number of entries will always be zero, so it is pointless allowing
for the fragmented case here. */
if (encode_length(buf, &len, 0) < 0)
return -1;
break;
case UDPTL_ERROR_CORRECTION_REDUNDANCY:
/* Encode the error recovery type */
buf[len++] = 0x00;
if (s->tx_seq_no > s->error_correction_entries)
entries = s->error_correction_entries;
else
entries = s->tx_seq_no;
/* The number of entries will always be small, so it is pointless allowing
for the fragmented case here. */
if (encode_length(buf, &len, entries) < 0)
return -1;
/* Encode the elements */
for (i = 0; i < entries; i++) {
j = (entry - i - 1) & UDPTL_BUF_MASK;
if (encode_open_type(buf, &len, s->tx[j].buf, s->tx[j].buf_len) < 0)
return -1;
}
break;
case UDPTL_ERROR_CORRECTION_FEC:
span = s->error_correction_span;
entries = s->error_correction_entries;
if (seq < s->error_correction_span * s->error_correction_entries) {
/* In the initial stages, wind up the FEC smoothly */
entries = seq / s->error_correction_span;
if (seq < s->error_correction_span)
span = 0;
}
/* Encode the error recovery type */
buf[len++] = 0x80;
/* Span is defined as an inconstrained integer, which it dumb. It will only
ever be a small value. Treat it as such. */
buf[len++] = 1;
buf[len++] = span;
/* The number of entries is defined as a length, but will only ever be a small
value. Treat it as such. */
buf[len++] = entries;
for (m = 0; m < entries; m++) {
/* Make an XOR'ed entry the maximum length */
limit = (entry + m) & UDPTL_BUF_MASK;
high_tide = 0;
for (i = (limit - span * entries) & UDPTL_BUF_MASK; i != limit; i = (i + entries) & UDPTL_BUF_MASK) {
if (high_tide < s->tx[i].buf_len) {
for (j = 0; j < high_tide; j++)
fec[j] ^= s->tx[i].buf[j];
for (; j < s->tx[i].buf_len; j++)
fec[j] = s->tx[i].buf[j];
high_tide = s->tx[i].buf_len;
} else {
for (j = 0; j < s->tx[i].buf_len; j++)
fec[j] ^= s->tx[i].buf[j];
}
}
if (encode_open_type(buf, &len, fec, high_tide) < 0)
return -1;
}
break;
}
if (s->verbose)
fprintf(stderr, "\n");
s->tx_seq_no++;
return len;
}
/*- End of function --------------------------------------------------------*/
int udptl_set_error_correction(udptl_state_t *s,
int ec_scheme,
int span,
int entries)
int udptl_set_error_correction(udptl_state_t *s, int ec_scheme, int span, int entries)
{
switch (ec_scheme)
{
case UDPTL_ERROR_CORRECTION_FEC:
case UDPTL_ERROR_CORRECTION_REDUNDANCY:
case UDPTL_ERROR_CORRECTION_NONE:
s->error_correction_scheme = ec_scheme;
break;
case -1:
/* Just don't change the scheme */
break;
default:
return -1;
}
if (span >= 0)
s->error_correction_span = span;
if (entries >= 0)
s->error_correction_entries = entries;
return 0;
switch (ec_scheme) {
case UDPTL_ERROR_CORRECTION_FEC:
case UDPTL_ERROR_CORRECTION_REDUNDANCY:
case UDPTL_ERROR_CORRECTION_NONE:
s->error_correction_scheme = ec_scheme;
break;
case -1:
/* Just don't change the scheme */
break;
default:
return -1;
}
if (span >= 0)
s->error_correction_span = span;
if (entries >= 0)
s->error_correction_entries = entries;
return 0;
}
/*- End of function --------------------------------------------------------*/
int udptl_get_error_correction(udptl_state_t *s,
int *ec_scheme,
int *span,
int *entries)
int udptl_get_error_correction(udptl_state_t *s, int *ec_scheme, int *span, int *entries)
{
if (ec_scheme)
*ec_scheme = s->error_correction_scheme;
if (span)
*span = s->error_correction_span;
if (entries)
*entries = s->error_correction_entries;
return 0;
if (ec_scheme)
*ec_scheme = s->error_correction_scheme;
if (span)
*span = s->error_correction_span;
if (entries)
*entries = s->error_correction_entries;
return 0;
}
/*- End of function --------------------------------------------------------*/
int udptl_set_local_max_datagram(udptl_state_t *s, int max_datagram)
{
s->local_max_datagram_size = max_datagram;
return 0;
s->local_max_datagram_size = max_datagram;
return 0;
}
/*- End of function --------------------------------------------------------*/
int udptl_get_local_max_datagram(udptl_state_t *s)
{
return s->local_max_datagram_size;
return s->local_max_datagram_size;
}
/*- End of function --------------------------------------------------------*/
int udptl_set_far_max_datagram(udptl_state_t *s, int max_datagram)
{
s->far_max_datagram_size = max_datagram;
return 0;
s->far_max_datagram_size = max_datagram;
return 0;
}
/*- End of function --------------------------------------------------------*/
int udptl_get_far_max_datagram(udptl_state_t *s)
{
return s->far_max_datagram_size;
return s->far_max_datagram_size;
}
/*- End of function --------------------------------------------------------*/
udptl_state_t *udptl_init(udptl_state_t *s,
int ec_scheme,
int span,
int entries,
udptl_rx_packet_handler_t rx_packet_handler,
void *user_data)
udptl_state_t *udptl_init(udptl_state_t *s, int ec_scheme, int span, int entries, udptl_rx_packet_handler_t rx_packet_handler, void *user_data)
{
int i;
int i;
if (rx_packet_handler == NULL)
return NULL;
if (rx_packet_handler == NULL)
return NULL;
if (s == NULL)
{
if ((s = (udptl_state_t *) malloc(sizeof(*s))) == NULL)
return NULL;
}
memset(s, 0, sizeof(*s));
s->error_correction_scheme = ec_scheme;
s->error_correction_span = span;
s->error_correction_entries = entries;
s->far_max_datagram_size = LOCAL_FAX_MAX_DATAGRAM;
s->local_max_datagram_size = LOCAL_FAX_MAX_DATAGRAM;
if (s == NULL) {
if ((s = (udptl_state_t *) malloc(sizeof(*s))) == NULL)
return NULL;
}
memset(s, 0, sizeof(*s));
memset(&s->rx, 0, sizeof(s->rx));
memset(&s->tx, 0, sizeof(s->tx));
for (i = 0; i <= UDPTL_BUF_MASK; i++)
{
s->rx[i].buf_len = -1;
s->tx[i].buf_len = -1;
}
s->error_correction_scheme = ec_scheme;
s->error_correction_span = span;
s->error_correction_entries = entries;
s->rx_packet_handler = rx_packet_handler;
s->user_data = user_data;
s->far_max_datagram_size = LOCAL_FAX_MAX_DATAGRAM;
s->local_max_datagram_size = LOCAL_FAX_MAX_DATAGRAM;
return s;
memset(&s->rx, 0, sizeof(s->rx));
memset(&s->tx, 0, sizeof(s->tx));
for (i = 0; i <= UDPTL_BUF_MASK; i++) {
s->rx[i].buf_len = -1;
s->tx[i].buf_len = -1;
}
s->rx_packet_handler = rx_packet_handler;
s->user_data = user_data;
return s;
}
/*- End of function --------------------------------------------------------*/
int udptl_release(udptl_state_t *s)
{
return 0;
return 0;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/
+50 -67
View File
@@ -30,71 +30,66 @@
#define UDPTL_BUF_MASK 15
typedef int (udptl_rx_packet_handler_t)(void *user_data, const uint8_t msg[], int len, int seq_no);
typedef int (udptl_rx_packet_handler_t) (void *user_data, const uint8_t msg[], int len, int seq_no);
typedef struct
{
int buf_len;
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
typedef struct {
int buf_len;
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
} udptl_fec_tx_buffer_t;
typedef struct
{
int buf_len;
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
int fec_len[LOCAL_FAX_MAX_FEC_PACKETS];
uint8_t fec[LOCAL_FAX_MAX_FEC_PACKETS][LOCAL_FAX_MAX_DATAGRAM];
int fec_span;
int fec_entries;
typedef struct {
int buf_len;
uint8_t buf[LOCAL_FAX_MAX_DATAGRAM];
int fec_len[LOCAL_FAX_MAX_FEC_PACKETS];
uint8_t fec[LOCAL_FAX_MAX_FEC_PACKETS][LOCAL_FAX_MAX_DATAGRAM];
int fec_span;
int fec_entries;
} udptl_fec_rx_buffer_t;
struct udptl_state_s
{
udptl_rx_packet_handler_t *rx_packet_handler;
void *user_data;
struct udptl_state_s {
udptl_rx_packet_handler_t *rx_packet_handler;
void *user_data;
/*! This option indicates the error correction scheme used in transmitted UDPTL
packets. */
int error_correction_scheme;
/*! This option indicates the error correction scheme used in transmitted UDPTL
packets. */
int error_correction_scheme;
/*! This option indicates the number of error correction entries transmitted in
UDPTL packets. */
int error_correction_entries;
/*! This option indicates the number of error correction entries transmitted in
UDPTL packets. */
int error_correction_entries;
/*! This option indicates the span of the error correction entries in transmitted
UDPTL packets (FEC only). */
int error_correction_span;
/*! This option indicates the span of the error correction entries in transmitted
UDPTL packets (FEC only). */
int error_correction_span;
/*! This option indicates the maximum size of a datagram that can be accepted by
the remote device. */
int far_max_datagram_size;
/*! This option indicates the maximum size of a datagram that can be accepted by
the remote device. */
int far_max_datagram_size;
/*! This option indicates the maximum size of a datagram that we are prepared to
accept. */
int local_max_datagram_size;
/*! This option indicates the maximum size of a datagram that we are prepared to
accept. */
int local_max_datagram_size;
int verbose;
int verbose;
int tx_seq_no;
int rx_seq_no;
int rx_expected_seq_no;
int tx_seq_no;
int rx_seq_no;
int rx_expected_seq_no;
udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK + 1];
udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK + 1];
udptl_fec_tx_buffer_t tx[UDPTL_BUF_MASK + 1];
udptl_fec_rx_buffer_t rx[UDPTL_BUF_MASK + 1];
};
enum
{
UDPTL_ERROR_CORRECTION_NONE,
UDPTL_ERROR_CORRECTION_FEC,
UDPTL_ERROR_CORRECTION_REDUNDANCY
enum {
UDPTL_ERROR_CORRECTION_NONE,
UDPTL_ERROR_CORRECTION_FEC,
UDPTL_ERROR_CORRECTION_REDUNDANCY
};
typedef struct udptl_state_s udptl_state_t;
#if defined(__cplusplus)
extern "C"
{
extern "C" {
#endif
/*! \brief Process an arriving UDPTL packet.
@@ -102,7 +97,7 @@ extern "C"
\param buf The UDPTL packet buffer.
\param len The length of the packet.
\return 0 for OK. */
int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len);
int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len);
/*! \brief Construct a UDPTL packet, ready for transmission.
\param s The UDPTL context.
@@ -110,7 +105,7 @@ int udptl_rx_packet(udptl_state_t *s, const uint8_t buf[], int len);
\param msg The primary packet.
\param len The length of the primary packet.
\return The length of the constructed UDPTL packet. */
int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int msg_len);
int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int msg_len);
/*! \brief Change the error correction settings of a UDPTL context.
\param s The UDPTL context.
@@ -118,10 +113,7 @@ int udptl_build_packet(udptl_state_t *s, uint8_t buf[], const uint8_t msg[], int
\param span The packet span over which error correction should be applied.
\param entries The number of error correction entries to include in packets.
\return 0 for OK. */
int udptl_set_error_correction(udptl_state_t *s,
int ec_scheme,
int span,
int entries);
int udptl_set_error_correction(udptl_state_t *s, int ec_scheme, int span, int entries);
/*! \brief Check the error correction settings of a UDPTL context.
\param s The UDPTL context.
@@ -129,18 +121,15 @@ int udptl_set_error_correction(udptl_state_t *s,
\param span The packet span over which error correction is being applied.
\param entries The number of error correction being included in packets.
\return 0 for OK. */
int udptl_get_error_correction(udptl_state_t *s,
int *ec_scheme,
int *span,
int *entries);
int udptl_get_error_correction(udptl_state_t *s, int *ec_scheme, int *span, int *entries);
int udptl_set_local_max_datagram(udptl_state_t *s, int max_datagram);
int udptl_set_local_max_datagram(udptl_state_t *s, int max_datagram);
int udptl_get_local_max_datagram(udptl_state_t *s);
int udptl_get_local_max_datagram(udptl_state_t *s);
int udptl_set_far_max_datagram(udptl_state_t *s, int max_datagram);
int udptl_set_far_max_datagram(udptl_state_t *s, int max_datagram);
int udptl_get_far_max_datagram(udptl_state_t *s);
int udptl_get_far_max_datagram(udptl_state_t *s);
/*! \brief Initialise a UDPTL context.
\param s The UDPTL context.
@@ -150,21 +139,15 @@ int udptl_get_far_max_datagram(udptl_state_t *s);
\param rx_packet_handler The callback function, used to report arriving IFP packets.
\param user_data An opaque pointer supplied to rx_packet_handler.
\return A pointer to the UDPTL context, or NULL if there was a problem. */
udptl_state_t *udptl_init(udptl_state_t *s,
int ec_scheme,
int span,
int entries,
udptl_rx_packet_handler_t rx_packet_handler,
void *user_data);
udptl_state_t *udptl_init(udptl_state_t *s, int ec_scheme, int span, int entries, udptl_rx_packet_handler_t rx_packet_handler, void *user_data);
/*! \brief Release a UDPTL context.
\param s The UDPTL context.
\return 0 for OK. */
int udptl_release(udptl_state_t *s);
int udptl_release(udptl_state_t *s);
#if defined(__cplusplus)
}
#endif
#endif
/*- End of file ------------------------------------------------------------*/
@@ -1,6 +1,6 @@
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
@@ -87,10 +87,11 @@ static int next_id(valet_lot_t *lot, int min, int max, int in)
int i, r = 0, m;
char buf[128] = "";
if (!min) min = 1;
if (!min)
min = 1;
switch_mutex_lock(globals.mutex);
for(i = min ; (i < max || max == 0) ; i++) {
for (i = min; (i < max || max == 0); i++) {
switch_snprintf(buf, sizeof(buf), "%d", i);
m = !!switch_core_hash_find(lot->hash, buf);
@@ -131,7 +132,7 @@ SWITCH_STANDARD_APP(valet_parking_function)
lot = valet_find_lot(lot_name);
switch_assert(lot);
if (!strcasecmp(ext, "auto")) {
if (!strcasecmp(ext, "auto")) {
const char *io = argv[2];
const char *min = argv[3];
const char *max = argv[4];
@@ -165,7 +166,7 @@ SWITCH_STANDARD_APP(valet_parking_function)
switch_mutex_unlock(lot->mutex);
return;
}
switch_snprintf(dtmf_buf, sizeof(dtmf_buf), "%d", id);
ext = dtmf_buf;
} else if (!strcasecmp(ext, "ask")) {
@@ -174,28 +175,28 @@ SWITCH_STANDARD_APP(valet_parking_function)
int max = 11;
int to = 10000;
int i;
tmp = argv[2] ? argv[2] : switch_channel_get_variable(channel, "valet_ext_min");
if (tmp) {
if ((i = atoi(tmp)) > 0) {
min = i;
}
}
tmp = argv[3] ? argv[3] : switch_channel_get_variable(channel, "valet_ext_max");
if (tmp) {
if ((i = atoi(tmp)) > 0) {
max = i;
}
}
tmp = argv[4] ? argv[4] : switch_channel_get_variable(channel, "valet_ext_to");
if (tmp) {
if ((i = atoi(tmp)) > 0) {
to = i;
}
}
tmp = argv[5] ? argv[5] : switch_channel_get_variable(channel, "valet_ext_prompt");
if (tmp) {
prompt = tmp;
@@ -211,7 +212,7 @@ SWITCH_STANDARD_APP(valet_parking_function)
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
}
}
switch_mutex_lock(lot->mutex);
if ((uuid = switch_core_hash_find(lot->hash, ext))) {
switch_core_session_t *b_session;
@@ -224,7 +225,7 @@ SWITCH_STANDARD_APP(valet_parking_function)
switch_channel_event_set_data(switch_core_session_get_channel(b_session), event);
switch_event_fire(&event);
switch_core_session_rwunlock(b_session);
switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), uuid);
switch_mutex_unlock(lot->mutex);
return;
@@ -241,7 +242,7 @@ SWITCH_STANDARD_APP(valet_parking_function)
if ((uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
switch_core_session_t *b_session;
if ((b_session = switch_core_session_locate(uuid))) {
switch_ivr_phrase_macro(session, "valet_announce_ext", tmp, NULL, NULL);
switch_ivr_session_transfer(b_session, dest, "inline", NULL);
@@ -254,8 +255,8 @@ SWITCH_STANDARD_APP(valet_parking_function)
switch_ivr_phrase_macro(session, "valet_announce_ext", tmp, NULL, NULL);
}
if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, VALET_EVENT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Lot-Name", lot_name);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Extension", ext);
@@ -263,14 +264,15 @@ SWITCH_STANDARD_APP(valet_parking_function)
switch_event_fire(&event);
}
if (!(tmp = switch_channel_get_variable(channel, "valet_hold_music"))) {
tmp = switch_channel_get_variable(channel, "hold_music");
}
if (tmp) music = tmp;
if (tmp)
music = tmp;
switch_core_hash_insert(lot->hash, ext, switch_core_session_get_uuid(session));
args.input_callback = valet_on_dtmf;
args.buf = dbuf;
args.buflen = sizeof(dbuf);
@@ -293,7 +295,7 @@ SWITCH_STANDARD_API(valet_info_function)
{
switch_hash_index_t *hi;
const void *var;
void *val;
void *val;
char *name;
valet_lot_t *lot;
@@ -310,9 +312,10 @@ SWITCH_STANDARD_API(valet_info_function)
switch_hash_this(hi, &var, NULL, &val);
name = (char *) var;
lot = (valet_lot_t *) val;
if (!zstr(cmd) && strcasecmp(cmd, name)) continue;
if (!zstr(cmd) && strcasecmp(cmd, name))
continue;
stream->write_function(stream, " <lot name=\"%s\">\n", name);
for (i_hi = switch_hash_first(NULL, lot->hash); i_hi; i_hi = switch_hash_next(i_hi)) {
+350 -352
View File
@@ -128,50 +128,50 @@ SWITCH_STANDARD_APP(vmd_start_function);
/*! Type that holds state information about the beep. */
typedef enum vmd_state {
BEEP_DETECTED, BEEP_NOT_DETECTED
BEEP_DETECTED, BEEP_NOT_DETECTED
} vmd_state_t;
/*! Type that holds data for 5 points of discreet energy separation */
typedef struct vmd_point {
double freq;
double ampl;
double freq;
double ampl;
} vmd_point_t;
/*! Type that holds codec information. */
typedef struct vmd_codec_info {
/*! The sampling rate of the audio stream. */
int rate;
/*! The number of channels. */
int channels;
/*! The sampling rate of the audio stream. */
int rate;
/*! The number of channels. */
int channels;
} vmd_codec_info_t;
/*! Type that holds session information pertinent to the vmd module. */
typedef struct vmd_session_info {
/*! State of the session. */
vmd_state_t state;
/*! Snapshot of DESA samples. */
vmd_point_t points[POINTS];
/*! Internal FreeSWITCH session. */
switch_core_session_t *session;
/*! Codec information for the session. */
vmd_codec_info_t vmd_codec;
/*! Current position in the snapshot. */
unsigned int pos;
/*! Frequency aproximation of a detected beep. */
double beep_freq;
/*! A count of how long a distinct beep was detected
* by the discreet energy separation algorithm. */
switch_size_t timestamp;
/*! State of the session. */
vmd_state_t state;
/*! Snapshot of DESA samples. */
vmd_point_t points[POINTS];
/*! Internal FreeSWITCH session. */
switch_core_session_t *session;
/*! Codec information for the session. */
vmd_codec_info_t vmd_codec;
/*! Current position in the snapshot. */
unsigned int pos;
/*! Frequency aproximation of a detected beep. */
double beep_freq;
/*! A count of how long a distinct beep was detected
* by the discreet energy separation algorithm. */
switch_size_t timestamp;
/*! The MIN_TIME to use for this call */
int minTime;
} vmd_session_info_t;
static switch_bool_t process_data(vmd_session_info_t * vmd_info, switch_frame_t * frame);
static switch_bool_t vmd_callback(switch_media_bug_t * bug, void *user_data, switch_abc_type_t type);
static switch_bool_t process_data(vmd_session_info_t *vmd_info, switch_frame_t *frame);
static switch_bool_t vmd_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type);
static double freq_estimator(double *x);
static double ampl_estimator(double *x);
static void convert_pts(int16_t * i_pts, double *d_pts, int16_t max);
static void find_beep(vmd_session_info_t * vmd_info, switch_frame_t * frame);
static void convert_pts(int16_t *i_pts, double *d_pts, int16_t max);
static void find_beep(vmd_session_info_t *vmd_info, switch_frame_t *frame);
static double median(double *m, int n);
/*
@@ -187,40 +187,40 @@ static double median(double *m, int n);
* @param type The switch callback type.
* @return The success or failure of the function.
*/
static switch_bool_t vmd_callback(switch_media_bug_t * bug, void *user_data, switch_abc_type_t type)
static switch_bool_t vmd_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
{
vmd_session_info_t *vmd_info;
switch_codec_t *read_codec;
switch_frame_t *frame;
vmd_session_info_t *vmd_info;
switch_codec_t *read_codec;
switch_frame_t *frame;
vmd_info = (vmd_session_info_t *) user_data;
if (vmd_info == NULL) {
return SWITCH_FALSE;
}
vmd_info = (vmd_session_info_t *) user_data;
if (vmd_info == NULL) {
return SWITCH_FALSE;
}
switch (type) {
switch (type) {
case SWITCH_ABC_TYPE_INIT:
read_codec = switch_core_session_get_read_codec(vmd_info->session);
vmd_info->vmd_codec.rate = read_codec->implementation->samples_per_second;
vmd_info->vmd_codec.channels = read_codec->implementation->number_of_channels;
break;
case SWITCH_ABC_TYPE_INIT:
read_codec = switch_core_session_get_read_codec(vmd_info->session);
vmd_info->vmd_codec.rate = read_codec->implementation->samples_per_second;
vmd_info->vmd_codec.channels = read_codec->implementation->number_of_channels;
break;
case SWITCH_ABC_TYPE_READ_PING:
case SWITCH_ABC_TYPE_CLOSE:
case SWITCH_ABC_TYPE_READ:
case SWITCH_ABC_TYPE_WRITE:
break;
case SWITCH_ABC_TYPE_READ_PING:
case SWITCH_ABC_TYPE_CLOSE:
case SWITCH_ABC_TYPE_READ:
case SWITCH_ABC_TYPE_WRITE:
break;
case SWITCH_ABC_TYPE_READ_REPLACE:
frame = switch_core_media_bug_get_read_replace_frame(bug);
return process_data(vmd_info, frame);
case SWITCH_ABC_TYPE_READ_REPLACE:
frame = switch_core_media_bug_get_read_replace_frame(bug);
return process_data(vmd_info, frame);
case SWITCH_ABC_TYPE_WRITE_REPLACE:
break;
}
case SWITCH_ABC_TYPE_WRITE_REPLACE:
break;
}
return SWITCH_TRUE;
return SWITCH_TRUE;
}
/*! \brief Process and convert data to be used by the find_beep() function
@@ -230,23 +230,23 @@ static switch_bool_t vmd_callback(switch_media_bug_t * bug, void *user_data, swi
* @param frame The audio data.
* @return The success or failure of the function.
*/
static switch_bool_t process_data(vmd_session_info_t * vmd_info, switch_frame_t * frame)
static switch_bool_t process_data(vmd_session_info_t *vmd_info, switch_frame_t *frame)
{
uint32_t i;
unsigned int j;
double pts[P];
int16_t *data;
int16_t max;
switch_ssize_t len;
uint32_t i;
unsigned int j;
double pts[P];
int16_t *data;
int16_t max;
switch_ssize_t len;
len = frame->samples * sizeof(int16_t);
data = (int16_t *) frame->data;
len = frame->samples * sizeof(int16_t);
data = (int16_t *) frame->data;
for (max = (int16_t) abs(data[0]), i = 1; i < frame->samples; i++) {
if ((int16_t) abs(data[i]) > max) {
max = (int16_t) abs(data[i]);
}
}
for (max = (int16_t) abs(data[0]), i = 1; i < frame->samples; i++) {
if ((int16_t) abs(data[i]) > max) {
max = (int16_t) abs(data[i]);
}
}
/*
if (vmd_info->data_len != len){
@@ -269,16 +269,16 @@ static switch_bool_t process_data(vmd_session_info_t * vmd_info, switch_frame_t
}
*/
for (i = 0, j = vmd_info->pos; i < frame->samples; j++, j %= POINTS, i += 5) {
/* convert_pts(vmd_info->data + i, pts); */
convert_pts(data + i, pts, max);
vmd_info->points[j].freq = TO_HZ(freq_estimator(pts));
vmd_info->points[j].ampl = ampl_estimator(pts);
vmd_info->pos = j % POINTS;
find_beep(vmd_info, frame);
}
for (i = 0, j = vmd_info->pos; i < frame->samples; j++, j %= POINTS, i += 5) {
/* convert_pts(vmd_info->data + i, pts); */
convert_pts(data + i, pts, max);
vmd_info->points[j].freq = TO_HZ(freq_estimator(pts));
vmd_info->points[j].ampl = ampl_estimator(pts);
vmd_info->pos = j % POINTS;
find_beep(vmd_info, frame);
}
return SWITCH_TRUE;
return SWITCH_TRUE;
}
/*! \brief Find voicemail beep in the audio stream
@@ -288,98 +288,96 @@ static switch_bool_t process_data(vmd_session_info_t * vmd_info, switch_frame_t
* @param frame The audio data.
* @return The success or failure of the function.
*/
static void find_beep(vmd_session_info_t * vmd_info, switch_frame_t * frame)
static void find_beep(vmd_session_info_t *vmd_info, switch_frame_t *frame)
{
int i;
int c;
double m[POINTS];
double med;
unsigned int j = (vmd_info->pos + 1) % POINTS;
unsigned int k = j;
switch_event_t *event;
switch_status_t status;
switch_event_t *event_copy;
switch_channel_t *channel = switch_core_session_get_channel(vmd_info->session);
int i;
int c;
double m[POINTS];
double med;
unsigned int j = (vmd_info->pos + 1) % POINTS;
unsigned int k = j;
switch_event_t *event;
switch_status_t status;
switch_event_t *event_copy;
switch_channel_t *channel = switch_core_session_get_channel(vmd_info->session);
switch (vmd_info->state) {
case BEEP_DETECTED:
for (c = 0, i = 0; i < POINTS; j++, j %= POINTS, i++) {
vmd_info->timestamp++;
if (vmd_info->points[j].freq < TOLERANCE_T(vmd_info->beep_freq) &&
vmd_info->points[j].freq > TOLERANCE_B(vmd_info->beep_freq)) {
c++;
vmd_info->beep_freq = (vmd_info->beep_freq * 0.95) + (vmd_info->points[j].freq * 0.05);
}
}
switch (vmd_info->state) {
case BEEP_DETECTED:
for (c = 0, i = 0; i < POINTS; j++, j %= POINTS, i++) {
vmd_info->timestamp++;
if (vmd_info->points[j].freq < TOLERANCE_T(vmd_info->beep_freq) && vmd_info->points[j].freq > TOLERANCE_B(vmd_info->beep_freq)) {
c++;
vmd_info->beep_freq = (vmd_info->beep_freq * 0.95) + (vmd_info->points[j].freq * 0.05);
}
}
if (c < (POINTS - MAX_CHIRP)) {
vmd_info->state = BEEP_NOT_DETECTED;
if (vmd_info->timestamp < (switch_size_t)vmd_info->minTime) {
break;
}
if (c < (POINTS - MAX_CHIRP)) {
vmd_info->state = BEEP_NOT_DETECTED;
if (vmd_info->timestamp < (switch_size_t) vmd_info->minTime) {
break;
}
status = switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, VMD_EVENT_BEEP);
if (status != SWITCH_STATUS_SUCCESS) {
return;
}
status = switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, VMD_EVENT_BEEP);
if (status != SWITCH_STATUS_SUCCESS) {
return;
}
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Beep-Status", "stop");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Beep-Time", "%d", (int) vmd_info->timestamp / POINTS);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(vmd_info->session));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Frequency", "%6.4lf", vmd_info->beep_freq);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "vmd");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Beep-Status", "stop");
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Beep-Time", "%d", (int) vmd_info->timestamp / POINTS);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(vmd_info->session));
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Frequency", "%6.4lf", vmd_info->beep_freq);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "vmd");
if ((switch_event_dup(&event_copy, event)) != SWITCH_STATUS_SUCCESS) {
return;
}
if ((switch_event_dup(&event_copy, event)) != SWITCH_STATUS_SUCCESS) {
return;
}
switch_core_session_queue_event(vmd_info->session, &event);
switch_event_fire(&event_copy);
switch_core_session_queue_event(vmd_info->session, &event);
switch_event_fire(&event_copy);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(vmd_info->session), SWITCH_LOG_INFO, "<<< VMD - Beep Detected >>>\n");
switch_channel_set_variable(channel, "vmd_detect", "TRUE");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(vmd_info->session), SWITCH_LOG_INFO, "<<< VMD - Beep Detected >>>\n");
switch_channel_set_variable(channel, "vmd_detect", "TRUE");
vmd_info->timestamp = 0;
}
vmd_info->timestamp = 0;
}
break;
break;
case BEEP_NOT_DETECTED:
case BEEP_NOT_DETECTED:
for (i = 0; i < POINTS; k++, k %= POINTS, i++) {
m[i] = vmd_info->points[k].freq;
if (ISNAN(m[i])) {
m[i] = 0.0;
}
}
for (i = 0; i < POINTS; k++, k %= POINTS, i++) {
m[i] = vmd_info->points[k].freq;
if (ISNAN(m[i])) {
m[i] = 0.0;
}
}
med = median(m, POINTS);
if (ISNAN(med)) {
for (i = 0; i < POINTS; i++) {
if (!ISNAN(m[i])) {
med = m[i];
break;
}
}
}
med = median(m, POINTS);
if (ISNAN(med)) {
for (i = 0; i < POINTS; i++) {
if (!ISNAN(m[i])) {
med = m[i];
break;
}
}
}
for (c = 0, i = 0; i < POINTS; j++, j %= POINTS, i++) {
if (vmd_info->points[j].freq < TOLERANCE_T(med) && vmd_info->points[j].freq > TOLERANCE_B(med)) {
if (vmd_info->points[j].ampl > MIN_AMPL &&
vmd_info->points[j].freq > MIN_FREQ && vmd_info->points[j].freq < MAX_FREQ) {
c++;
}
}
}
for (c = 0, i = 0; i < POINTS; j++, j %= POINTS, i++) {
if (vmd_info->points[j].freq < TOLERANCE_T(med) && vmd_info->points[j].freq > TOLERANCE_B(med)) {
if (vmd_info->points[j].ampl > MIN_AMPL && vmd_info->points[j].freq > MIN_FREQ && vmd_info->points[j].freq < MAX_FREQ) {
c++;
}
}
}
if (c >= VALID) {
vmd_info->state = BEEP_DETECTED;
vmd_info->beep_freq = med;
vmd_info->timestamp = 0;
}
if (c >= VALID) {
vmd_info->state = BEEP_DETECTED;
vmd_info->beep_freq = med;
vmd_info->timestamp = 0;
}
break;
}
break;
}
}
/*! \brief Find the median of an array of doubles
@@ -390,65 +388,65 @@ static void find_beep(vmd_session_info_t * vmd_info, switch_frame_t * frame)
*/
static double median(double *m, int n)
{
int i;
int less;
int greater;
int equal;
double min;
double max;
double guess;
double maxltguess;
double mingtguess;
int i;
int less;
int greater;
int equal;
double min;
double max;
double guess;
double maxltguess;
double mingtguess;
min = max = m[0];
min = max = m[0];
for (i = 1; i < n; i++) {
if (m[i] < min)
min = m[i];
if (m[i] > max)
max = m[i];
}
for (i = 1; i < n; i++) {
if (m[i] < min)
min = m[i];
if (m[i] > max)
max = m[i];
}
for (;;) {
guess = (min + max) / 2;
less = 0;
greater = 0;
equal = 0;
maxltguess = min;
mingtguess = max;
for (;;) {
guess = (min + max) / 2;
less = 0;
greater = 0;
equal = 0;
maxltguess = min;
mingtguess = max;
for (i = 0; i < n; i++) {
if (m[i] < guess) {
less++;
if (m[i] > maxltguess) {
maxltguess = m[i];
}
} else if (m[i] > guess) {
greater++;
if (m[i] < mingtguess) {
mingtguess = m[i];
}
} else {
equal++;
}
}
for (i = 0; i < n; i++) {
if (m[i] < guess) {
less++;
if (m[i] > maxltguess) {
maxltguess = m[i];
}
} else if (m[i] > guess) {
greater++;
if (m[i] < mingtguess) {
mingtguess = m[i];
}
} else {
equal++;
}
}
if (less <= (n + 1) / 2 && greater <= (n + 1) / 2) {
break;
} else if (less > greater) {
max = maxltguess;
} else {
min = mingtguess;
}
}
if (less <= (n + 1) / 2 && greater <= (n + 1) / 2) {
break;
} else if (less > greater) {
max = maxltguess;
} else {
min = mingtguess;
}
}
if (less >= (n + 1) / 2) {
return maxltguess;
} else if (less + equal >= (n + 1) / 2) {
return guess;
}
if (less >= (n + 1) / 2) {
return maxltguess;
} else if (less + equal >= (n + 1) / 2) {
return guess;
}
return mingtguess;
return mingtguess;
}
/*! \brief Convert many points for Signed L16 to relative floating point
@@ -459,13 +457,13 @@ static double median(double *m, int n)
* @param max The maximum value in the entire audio frame.
* @return Nothing.
*/
static void convert_pts(int16_t * i_pts, double *d_pts, int16_t max)
static void convert_pts(int16_t *i_pts, double *d_pts, int16_t max)
{
int i;
for (i = 0; i < P; i++) {
/*! Signed L16 to relative floating point conversion */
d_pts[i] = ((((double) (i_pts[i]) + (double) max) / (double) (2 * max)) - 0.5) * 2.0;
}
int i;
for (i = 0; i < P; i++) {
/*! Signed L16 to relative floating point conversion */
d_pts[i] = ((((double) (i_pts[i]) + (double) max) / (double) (2 * max)) - 0.5) * 2.0;
}
}
/*! \brief Amplitude estimator for DESA-2
@@ -478,12 +476,12 @@ static void convert_pts(int16_t * i_pts, double *d_pts, int16_t max)
*/
double ampl_estimator(double *x)
{
double freq_sq;
double freq_sq;
freq_sq = freq_estimator(x);
freq_sq *= freq_sq;
freq_sq = freq_estimator(x);
freq_sq *= freq_sq;
return sqrt(PSI(x) / sin(freq_sq));
return sqrt(PSI(x) / sin(freq_sq));
}
/*! \brief The DESA-2 algorithm
@@ -500,12 +498,12 @@ double ampl_estimator(double *x)
*/
double freq_estimator(double *x)
{
return 0.5 * acos((((x[2] * x[2]) - (x[0] * x[4]))
- ((x[1] * x[1]) - (x[0] * x[2]))
- ((x[3] * x[3]) - (x[2] * x[4])))
/ (2.0 * ((x[2] * x[2]) - (x[1] * x[3])))
return 0.5 * acos((((x[2] * x[2]) - (x[0] * x[4]))
- ((x[1] * x[1]) - (x[0] * x[2]))
- ((x[3] * x[3]) - (x[2] * x[4])))
/ (2.0 * ((x[2] * x[2]) - (x[1] * x[3])))
);
);
}
/*! \brief FreeSWITCH module loading function
@@ -515,19 +513,19 @@ double freq_estimator(double *x)
*/
SWITCH_MODULE_LOAD_FUNCTION(mod_vmd_load)
{
switch_application_interface_t *app_interface;
switch_api_interface_t *api_interface;
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_application_interface_t *app_interface;
switch_api_interface_t *api_interface;
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Voicemail detection enabled\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Voicemail detection enabled\n");
SWITCH_ADD_APP(app_interface, "vmd", "Detect beeps", "Detect voicemail beeps", vmd_start_function, "[start] [stop]", SAF_NONE);
SWITCH_ADD_APP(app_interface, "vmd", "Detect beeps", "Detect voicemail beeps", vmd_start_function, "[start] [stop]", SAF_NONE);
SWITCH_ADD_API(api_interface, "vmd", "Detected voicemail beeps", vmd_api_main, VMD_SYNTAX);
SWITCH_ADD_API(api_interface, "vmd", "Detected voicemail beeps", vmd_api_main, VMD_SYNTAX);
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
/*! \brief FreeSWITCH application handler function.
@@ -538,59 +536,59 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_vmd_load)
*/
SWITCH_STANDARD_APP(vmd_start_function)
{
switch_media_bug_t *bug;
switch_status_t status;
switch_channel_t *channel;
vmd_session_info_t *vmd_info;
int i;
switch_media_bug_t *bug;
switch_status_t status;
switch_channel_t *channel;
vmd_session_info_t *vmd_info;
int i;
const char *minTimeString;
int mintime = 0;
if (session == NULL)
return;
if (session == NULL)
return;
channel = switch_core_session_get_channel(session);
channel = switch_core_session_get_channel(session);
/* Is this channel already set? */
bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_vmd_");
/* If yes */
if (bug != NULL) {
/* If we have a stop remove audio bug */
if (strcasecmp(data, "stop") == 0) {
switch_channel_set_private(channel, "_vmd_", NULL);
switch_core_media_bug_remove(session, &bug);
return;
}
/* Is this channel already set? */
bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_vmd_");
/* If yes */
if (bug != NULL) {
/* If we have a stop remove audio bug */
if (strcasecmp(data, "stop") == 0) {
switch_channel_set_private(channel, "_vmd_", NULL);
switch_core_media_bug_remove(session, &bug);
return;
}
/* We have already started */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot run 2 at once on the same channel!\n");
/* We have already started */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot run 2 at once on the same channel!\n");
return;
}
return;
}
vmd_info = (vmd_session_info_t *) switch_core_session_alloc(session, sizeof(vmd_session_info_t)
);
vmd_info = (vmd_session_info_t *) switch_core_session_alloc(session, sizeof(vmd_session_info_t)
);
vmd_info->state = BEEP_NOT_DETECTED;
vmd_info->session = session;
vmd_info->pos = 0;
/*
vmd_info->data = NULL;
vmd_info->data_len = 0;
*/
for (i = 0; i < POINTS; i++) {
vmd_info->points[i].freq = 0.0;
vmd_info->points[i].ampl = 0.0;
}
vmd_info->state = BEEP_NOT_DETECTED;
vmd_info->session = session;
vmd_info->pos = 0;
/*
vmd_info->data = NULL;
vmd_info->data_len = 0;
*/
for (i = 0; i < POINTS; i++) {
vmd_info->points[i].freq = 0.0;
vmd_info->points[i].ampl = 0.0;
}
status = switch_core_media_bug_add(session, vmd_callback, vmd_info, 0, SMBF_READ_REPLACE, &bug);
status = switch_core_media_bug_add(session, vmd_callback, vmd_info, 0, SMBF_READ_REPLACE, &bug);
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failure hooking to stream\n");
return;
}
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failure hooking to stream\n");
return;
}
switch_channel_set_private(channel, "_vmd_", bug);
switch_channel_set_private(channel, "_vmd_", bug);
if ((minTimeString = switch_channel_get_variable(channel, "vmd_min_time")) && (mintime = atoi(minTimeString))) {
vmd_info->minTime = mintime;
@@ -598,7 +596,7 @@ SWITCH_STANDARD_APP(vmd_start_function)
vmd_info->minTime = MIN_TIME;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "MIN_TIME for call: %d\n",vmd_info->minTime);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "MIN_TIME for call: %d\n", vmd_info->minTime);
}
/*! \brief Called when the module shuts down
@@ -608,9 +606,9 @@ SWITCH_STANDARD_APP(vmd_start_function)
*/
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_vmd_shutdown)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Voicemail detection disabled\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Voicemail detection disabled\n");
return SWITCH_STATUS_SUCCESS;
return SWITCH_STATUS_SUCCESS;
}
/*! \brief FreeSWITCH API handler function.
@@ -622,121 +620,121 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_vmd_shutdown)
*/
SWITCH_STANDARD_API(vmd_api_main)
{
switch_core_session_t *vmd_session = NULL;
switch_media_bug_t *bug;
vmd_session_info_t *vmd_info;
switch_channel_t *channel;
switch_status_t status;
int argc;
char *argv[VMD_PARAMS];
char *ccmd = NULL;
char *uuid;
char *command;
int i;
switch_core_session_t *vmd_session = NULL;
switch_media_bug_t *bug;
vmd_session_info_t *vmd_info;
switch_channel_t *channel;
switch_status_t status;
int argc;
char *argv[VMD_PARAMS];
char *ccmd = NULL;
char *uuid;
char *command;
int i;
/* No command? Display usage */
if (zstr(cmd)) {
stream->write_function(stream, "-USAGE: %s\n", VMD_SYNTAX);
return SWITCH_STATUS_SUCCESS;
}
/* No command? Display usage */
if (zstr(cmd)) {
stream->write_function(stream, "-USAGE: %s\n", VMD_SYNTAX);
return SWITCH_STATUS_SUCCESS;
}
/* Duplicated contents of original string */
ccmd = strdup(cmd);
/* Separate the arguments */
argc = switch_separate_string(ccmd, ' ', argv, VMD_PARAMS);
/* Duplicated contents of original string */
ccmd = strdup(cmd);
/* Separate the arguments */
argc = switch_separate_string(ccmd, ' ', argv, VMD_PARAMS);
/* If we don't have the expected number of parameters
* display usage */
if (argc != VMD_PARAMS) {
stream->write_function(stream, "-USAGE: %s\n", VMD_SYNTAX);
/* If we don't have the expected number of parameters
* display usage */
if (argc != VMD_PARAMS) {
stream->write_function(stream, "-USAGE: %s\n", VMD_SYNTAX);
goto end;
}
}
uuid = argv[0];
command = argv[1];
uuid = argv[0];
command = argv[1];
/* using uuid locate a reference to the FreeSWITCH session */
vmd_session = switch_core_session_locate(uuid);
/* using uuid locate a reference to the FreeSWITCH session */
vmd_session = switch_core_session_locate(uuid);
/* If the session was not found exit */
if (vmd_session == NULL) {
stream->write_function(stream, "-USAGE: %s\n", VMD_SYNTAX);
/* If the session was not found exit */
if (vmd_session == NULL) {
stream->write_function(stream, "-USAGE: %s\n", VMD_SYNTAX);
goto end;
}
}
/* Get current channel of the session to tag the session
* This indicates that our module is present */
channel = switch_core_session_get_channel(vmd_session);
/* Get current channel of the session to tag the session
* This indicates that our module is present */
channel = switch_core_session_get_channel(vmd_session);
/* Is this channel already set? */
bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_vmd_");
/* If yes */
if (bug != NULL) {
/* If we have a stop remove audio bug */
if (strcasecmp(command, "stop") == 0) {
switch_channel_set_private(channel, "_vmd_", NULL);
switch_core_media_bug_remove(vmd_session, &bug);
switch_safe_free(ccmd);
stream->write_function(stream, "+OK\n");
/* Is this channel already set? */
bug = (switch_media_bug_t *) switch_channel_get_private(channel, "_vmd_");
/* If yes */
if (bug != NULL) {
/* If we have a stop remove audio bug */
if (strcasecmp(command, "stop") == 0) {
switch_channel_set_private(channel, "_vmd_", NULL);
switch_core_media_bug_remove(vmd_session, &bug);
switch_safe_free(ccmd);
stream->write_function(stream, "+OK\n");
goto end;
}
}
/* We have already started */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot run 2 at once on the same channel!\n");
/* We have already started */
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot run 2 at once on the same channel!\n");
goto end;
}
}
/* If we don't see the expected start exit */
if (strcasecmp(command, "start") != 0) {
stream->write_function(stream, "-USAGE: %s\n", VMD_SYNTAX);
/* If we don't see the expected start exit */
if (strcasecmp(command, "start") != 0) {
stream->write_function(stream, "-USAGE: %s\n", VMD_SYNTAX);
goto end;
}
}
/* Allocate memory attached to this FreeSWITCH session for
* use in the callback routine and to store state information */
vmd_info = (vmd_session_info_t *) switch_core_session_alloc(vmd_session, sizeof(vmd_session_info_t)
);
/* Allocate memory attached to this FreeSWITCH session for
* use in the callback routine and to store state information */
vmd_info = (vmd_session_info_t *) switch_core_session_alloc(vmd_session, sizeof(vmd_session_info_t)
);
/* Set initial values and states */
vmd_info->state = BEEP_NOT_DETECTED;
vmd_info->session = vmd_session;
vmd_info->pos = 0;
/* Set initial values and states */
vmd_info->state = BEEP_NOT_DETECTED;
vmd_info->session = vmd_session;
vmd_info->pos = 0;
/*
vmd_info->data = NULL;
vmd_info->data_len = 0;
*/
for (i = 0; i < POINTS; i++) {
vmd_info->points[i].freq = 0.0;
vmd_info->points[i].ampl = 0.0;
}
for (i = 0; i < POINTS; i++) {
vmd_info->points[i].freq = 0.0;
vmd_info->points[i].ampl = 0.0;
}
/* Add a media bug that allows me to intercept the
* reading leg of the audio stream */
status = switch_core_media_bug_add(vmd_session, vmd_callback, vmd_info, 0, SMBF_READ_REPLACE, &bug);
/* Add a media bug that allows me to intercept the
* reading leg of the audio stream */
status = switch_core_media_bug_add(vmd_session, vmd_callback, vmd_info, 0, SMBF_READ_REPLACE, &bug);
/* If adding a media bug fails exit */
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failure hooking to stream\n");
goto end;
}
/* If adding a media bug fails exit */
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failure hooking to stream\n");
goto end;
}
/* Set the vmd tag to detect an existing vmd media bug */
switch_channel_set_private(channel, "_vmd_", bug);
/* Set the vmd tag to detect an existing vmd media bug */
switch_channel_set_private(channel, "_vmd_", bug);
/* Everything went according to plan! Notify the user */
stream->write_function(stream, "+OK\n");
/* Everything went according to plan! Notify the user */
stream->write_function(stream, "+OK\n");
end:
end:
if (vmd_session) {
switch_core_session_rwunlock(vmd_session);
}
switch_safe_free(ccmd);
switch_safe_free(ccmd);
return SWITCH_STATUS_SUCCESS;
return SWITCH_STATUS_SUCCESS;
}
File diff suppressed because it is too large. Load diff