mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-14 05:18:31 +00:00
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:
1 parent
7b347417e5
commit
886e1ddb4d
229 files changed
+20252
-20192
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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(¶ms);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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,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
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"))) {
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 ------------------------------------------------------------*/
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
Reference in new issue
Block a user