From 10d468a684fd49584a97d1b990a9b804eff54a65 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Wed, 14 Jul 2010 11:48:33 -0400 Subject: [PATCH 01/17] mod_hash: remove unneeded initializer --- src/mod/applications/mod_hash/mod_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c index 8179690928..ef72b04add 100644 --- a/src/mod/applications/mod_hash/mod_hash.c +++ b/src/mod/applications/mod_hash/mod_hash.c @@ -486,7 +486,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_hash_load) SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_hash_shutdown) { - switch_hash_index_t *hi = NULL; + switch_hash_index_t *hi; switch_scheduler_del_task_group("mod_hash"); From c5ad49da173d3da502af76c91742cc534585d944 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Fri, 16 Jul 2010 22:50:58 -0400 Subject: [PATCH 02/17] mod_hash: begin working on remote support --- libs/esl/src/esl_event.c | 2 +- libs/esl/src/include/esl_event.h | 2 +- src/mod/applications/mod_hash/mod_hash.c | 237 ++++++++++++++++++++++- 3 files changed, 235 insertions(+), 6 deletions(-) diff --git a/libs/esl/src/esl_event.c b/libs/esl/src/esl_event.c index 0999f90e0f..2e1d8a302a 100644 --- a/libs/esl/src/esl_event.c +++ b/libs/esl/src/esl_event.c @@ -307,7 +307,7 @@ static esl_status_t esl_event_base_add_header(esl_event_t *event, esl_stack_t st header = ALLOC(sizeof(*header)); esl_assert(header); - if ((event->flags & EF_UNIQ_HEADERS)) { + if ((event->flags & ESL_UNIQ_HEADERS)) { esl_event_del_header(event, header_name); } diff --git a/libs/esl/src/include/esl_event.h b/libs/esl/src/include/esl_event.h index 7df4c2175b..cf3793a5d9 100644 --- a/libs/esl/src/include/esl_event.h +++ b/libs/esl/src/include/esl_event.h @@ -172,7 +172,7 @@ struct esl_event { }; typedef enum { - EF_UNIQ_HEADERS = (1 << 0) + ESL_UNIQ_HEADERS = (1 << 0) } esl_event_flag_t; diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c index ef72b04add..c6faf1d390 100644 --- a/src/mod/applications/mod_hash/mod_hash.c +++ b/src/mod/applications/mod_hash/mod_hash.c @@ -34,12 +34,14 @@ */ #include +#include "esl.h" #define LIMIT_HASH_CLEANUP_INTERVAL 900 SWITCH_MODULE_LOAD_FUNCTION(mod_hash_load); +SWITCH_MODULE_RUNTIME_FUNCTION(mod_hash_runtime); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_hash_shutdown); -SWITCH_MODULE_DEFINITION(mod_hash, mod_hash_load, mod_hash_shutdown, NULL); +SWITCH_MODULE_DEFINITION(mod_hash, mod_hash_load, mod_hash_shutdown, mod_hash_runtime); /* CORE STUFF */ static struct { @@ -48,6 +50,8 @@ static struct { switch_hash_t *limit_hash; switch_thread_rwlock_t *db_hash_rwlock; switch_hash_t *db_hash; + switch_thread_rwlock_t *remote_hash_rwlock; + switch_hash_t *remote_hash; } globals; typedef struct { @@ -70,6 +74,33 @@ typedef struct { switch_hash_t *hash; } limit_hash_private_t; +typedef enum { + REMOTE_OFF = 0, /* Thread not running */ + REMOTE_DOWN, /* Cannot connect to remote instance */ + REMOTE_UP /* All good */ +} limit_remote_state_t; + +typedef struct { + const char *name; + const char *host; + const char *username; + const char *password; + int port; + + int interval; + + esl_handle_t handle; + + switch_hash_t *index; + switch_thread_rwlock_t *rwlock; + switch_memory_pool_t *pool; + + switch_bool_t running; + switch_thread_t *thread; + + limit_remote_state_t state; +} limit_remote_t; + /* \brief Enforces limit_hash restrictions * \param session current session * \param realm limit realm @@ -440,8 +471,201 @@ SWITCH_STANDARD_API(hash_api_function) return SWITCH_STATUS_SUCCESS; } -/* INIT/DEINIT STUFF */ +#define HASH_DUMP_SYNTAX "all|limit|db" +SWITCH_STANDARD_API(hash_dump_function) +{ + int mode; + switch_hash_index_t *hi; + + if (zstr(cmd)) { + stream->write_function(stream, "Usage: "HASH_DUMP_SYNTAX"\n"); + return SWITCH_STATUS_SUCCESS; + } + + if (!strcmp(cmd, "all")) { + mode = 3; + } else if (!strcmp(cmd, "limit")) { + mode = 2; + } else if (!strcmp(cmd, "db")) { + mode = 1; + } else { + stream->write_function(stream, "Usage: "HASH_DUMP_SYNTAX"\n"); + return SWITCH_STATUS_SUCCESS; + } + + + if (mode & 1) { + switch_thread_rwlock_rdlock(globals.limit_hash_rwlock); + for (hi = switch_hash_first(NULL, globals.limit_hash); hi; hi = switch_hash_next(hi)) { + void *val = NULL; + const void *key; + switch_ssize_t keylen; + limit_hash_item_t *item; + switch_hash_this(hi, &key, &keylen, &val); + + item = (limit_hash_item_t *)val; + stream->write_function(stream, "L/%s/%d/%d/%d/%d\n", key, item->total_usage, item->rate_usage, item->interval, item->last_check); + } + switch_thread_rwlock_unlock(globals.limit_hash_rwlock); + } + + if (mode & 2) { + switch_thread_rwlock_rdlock(globals.db_hash_rwlock); + for (hi = switch_hash_first(NULL, globals.db_hash); hi; hi = switch_hash_next(hi)) { + void *val = NULL; + const void *key; + switch_ssize_t keylen; + switch_hash_this(hi, &key, &keylen, &val); + + stream->write_function(stream, "D/%s/%s\n", key, (char*)val); + } + switch_thread_rwlock_unlock(globals.db_hash_rwlock); + } + + + return SWITCH_STATUS_SUCCESS; +} + +limit_remote_t *limit_remote_create(const char *name, const char *host, uint16_t port, const char *username, const char *password, int interval) +{ + limit_remote_t *r; + switch_memory_pool_t *pool; + + switch_thread_rwlock_rdlock(globals.remote_hash_rwlock); + if (switch_core_hash_find(globals.remote_hash, name)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Already have a remote instance named %s\n", name); + switch_thread_rwlock_unlock(globals.remote_hash_rwlock); + return NULL; + } + switch_thread_rwlock_unlock(globals.remote_hash_rwlock); + + if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { + return NULL; + } + + r = switch_core_alloc(pool, sizeof(limit_remote_t)); + r->pool = pool; + r->name = switch_core_strdup(r->pool, name); + r->host = switch_core_strdup(r->pool, host); + r->port = port; + r->username = switch_core_strdup(r->pool, username); + r->password = switch_core_strdup(r->pool, password); + r->interval = interval; + + switch_thread_rwlock_create(&r->rwlock, pool); + switch_core_hash_init(&r->index, pool); + + switch_thread_rwlock_rdlock(globals.remote_hash_rwlock); + switch_core_hash_insert(globals.remote_hash, name, r); + switch_thread_rwlock_unlock(globals.remote_hash_rwlock); + + return r; +} + +void limit_remote_destroy(limit_remote_t **r) +{ + if (r && *r) { + switch_hash_index_t *hi; + + (*r)->state = REMOTE_OFF; + + if ((*r)->thread) { + switch_thread_join(NULL, (*r)->thread); + } + + switch_thread_rwlock_wrlock((*r)->rwlock); + + /* Free hashtable data */ + for (hi = switch_hash_first(NULL, globals.remote_hash); hi; hi = switch_hash_next(hi)) { + void *val; + const void *key; + switch_ssize_t keylen; + switch_hash_this(hi, &key, &keylen, &val); + + free(val); + } + + switch_thread_rwlock_unlock((*r)->rwlock); + switch_thread_rwlock_destroy((*r)->rwlock); + + switch_core_destroy_memory_pool(&((*r)->pool)); + *r = NULL; + } +} + +static void *SWITCH_THREAD_FUNC limit_remote_thread(switch_thread_t *thread, void *obj) +{ + limit_remote_t *remote = (limit_remote_t*)obj; + while (remote->state > REMOTE_OFF) { + if (remote->state == REMOTE_OFF) { + if (esl_connect(&remote->handle, remote->host, remote->port, remote->username, remote->password) == ESL_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to remote FreeSWITCH at %s:%d\n", + remote->host, remote->port); + + remote->state = REMOTE_UP; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't connect to remote FreeSWITCH at %s;%d\n", + remote->host, remote->port); + } + } else { + if (esl_send_recv(&remote->handle, "api hash_dump limit") != SWITCH_STATUS_SUCCESS) { + esl_disconnect(&remote->handle); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Disconnected from remote FreeSWITCH at %s:%d\n", + remote->host, remote->port); + memset(&remote->handle, 0, sizeof(remote->handle)); + } else { + const char *data = remote->handle.last_sr_reply; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RECV: %s\n", data); + } + } + + switch_yield(remote->interval * 1000); + } + + remote->thread = NULL; + + return NULL; +} + +static void do_config() +{ + switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL; + if ((xml = switch_xml_open_cfg("hash.conf", &cfg, NULL))) { + if ((x_lists = switch_xml_child(cfg, "remotes"))) { + for (x_list = switch_xml_child(x_lists, "remote"); x_list; x_list = x_list->next) { + const char *name = switch_xml_attr(x_list, "name"); + const char *host = switch_xml_attr(x_list, "host"); + const char *szport = switch_xml_attr(x_list, "port"); + const char *username = switch_xml_attr(x_list, "username"); + const char *password = switch_xml_attr(x_list, "password"); + const char *szinterval = switch_xml_attr(x_list, "interval"); + int port = 0, interval = 0; + limit_remote_t *remote; + switch_threadattr_t *thd_attr = NULL; + + if (!zstr(szport)) { + port = atoi(szport); + } + + if (!zstr(szinterval)) { + interval = atoi(szinterval); + } + + remote = limit_remote_create(name, host, port, username, password, interval); + + remote->state = REMOTE_DOWN; + + switch_threadattr_create(&thd_attr, remote->pool); + switch_threadattr_detach_set(thd_attr, 1); + switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); + switch_thread_create(&remote->thread, thd_attr, limit_remote_thread, remote, remote->pool); + } + } + } +} + +/* INIT/DEINIT STUFF */ SWITCH_MODULE_LOAD_FUNCTION(mod_hash_load) { switch_application_interface_t *app_interface; @@ -460,8 +684,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_hash_load) switch_thread_rwlock_create(&globals.limit_hash_rwlock, globals.pool); switch_thread_rwlock_create(&globals.db_hash_rwlock, globals.pool); + switch_thread_rwlock_create(&globals.remote_hash_rwlock, globals.pool); switch_core_hash_init(&globals.limit_hash, pool); switch_core_hash_init(&globals.db_hash, pool); + switch_core_hash_init(&globals.remote_hash, globals.pool); /* connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); @@ -474,13 +700,16 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_hash_load) SWITCH_ADD_APP(app_interface, "hash", "Insert into the hashtable", HASH_DESC, hash_function, HASH_USAGE, SAF_SUPPORT_NOMEDIA) SWITCH_ADD_API(commands_api_interface, "hash", "hash get/set", hash_api_function, "[insert|delete|select]///"); + SWITCH_ADD_API(commands_api_interface, "hash_dump", "dump hash/limit_hash data (used for synchronization)", hash_dump_function, HASH_DUMP_SYNTAX); + switch_console_set_complete("add hash insert"); switch_console_set_complete("add hash delete"); switch_console_set_complete("add hash select"); + + do_config(); /* indicate that the module should continue to be loaded */ - return SWITCH_STATUS_SUCCESS; - + return SWITCH_STATUS_SUCCESS; } From a55747aae2b8c6dd0ab3902f6377a7cef4138705 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Fri, 16 Jul 2010 22:57:24 -0400 Subject: [PATCH 03/17] mod_hash: remove runtime function properly --- src/mod/applications/mod_hash/mod_hash.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c index c6faf1d390..0be78670e7 100644 --- a/src/mod/applications/mod_hash/mod_hash.c +++ b/src/mod/applications/mod_hash/mod_hash.c @@ -39,9 +39,8 @@ #define LIMIT_HASH_CLEANUP_INTERVAL 900 SWITCH_MODULE_LOAD_FUNCTION(mod_hash_load); -SWITCH_MODULE_RUNTIME_FUNCTION(mod_hash_runtime); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_hash_shutdown); -SWITCH_MODULE_DEFINITION(mod_hash, mod_hash_load, mod_hash_shutdown, mod_hash_runtime); +SWITCH_MODULE_DEFINITION(mod_hash, mod_hash_load, mod_hash_shutdown, NULL); /* CORE STUFF */ static struct { From 9f7e98e01fd81b58b75a3ba581505b0150252f23 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Fri, 16 Jul 2010 23:06:27 -0400 Subject: [PATCH 04/17] add missing makefile --- src/mod/applications/mod_hash/Makefile | 4 ++++ src/mod/applications/mod_hash/mod_hash.c | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 src/mod/applications/mod_hash/Makefile diff --git a/src/mod/applications/mod_hash/Makefile b/src/mod/applications/mod_hash/Makefile new file mode 100644 index 0000000000..0ee5f7731f --- /dev/null +++ b/src/mod/applications/mod_hash/Makefile @@ -0,0 +1,4 @@ +LOCAL_CFLAGS=-I../../../../libs/esl/src/include +LOCAL_LDFLAGS=-L../../../../libs/esl -lesl +BASE=../../../.. +include $(BASE)/build/modmake.rules diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c index 0be78670e7..0d86c4d591 100644 --- a/src/mod/applications/mod_hash/mod_hash.c +++ b/src/mod/applications/mod_hash/mod_hash.c @@ -597,14 +597,14 @@ static void *SWITCH_THREAD_FUNC limit_remote_thread(switch_thread_t *thread, voi { limit_remote_t *remote = (limit_remote_t*)obj; while (remote->state > REMOTE_OFF) { - if (remote->state == REMOTE_OFF) { + if (remote->state != REMOTE_UP) { if (esl_connect(&remote->handle, remote->host, remote->port, remote->username, remote->password) == ESL_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to remote FreeSWITCH at %s:%d\n", remote->host, remote->port); remote->state = REMOTE_UP; } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't connect to remote FreeSWITCH at %s;%d\n", + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't connect to remote FreeSWITCH at %s:%d\n", remote->host, remote->port); } } else { @@ -661,6 +661,7 @@ static void do_config() switch_thread_create(&remote->thread, thd_attr, limit_remote_thread, remote, remote->pool); } } + switch_xml_free(xml); } } From 83891a11d497da5a5beb83bb9464ed6c42b4036e Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Fri, 16 Jul 2010 23:35:03 -0400 Subject: [PATCH 05/17] update --- src/mod/applications/mod_hash/mod_hash.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c index 0d86c4d591..782c980085 100644 --- a/src/mod/applications/mod_hash/mod_hash.c +++ b/src/mod/applications/mod_hash/mod_hash.c @@ -484,9 +484,9 @@ SWITCH_STANDARD_API(hash_dump_function) if (!strcmp(cmd, "all")) { mode = 3; } else if (!strcmp(cmd, "limit")) { - mode = 2; - } else if (!strcmp(cmd, "db")) { mode = 1; + } else if (!strcmp(cmd, "db")) { + mode = 2; } else { stream->write_function(stream, "Usage: "HASH_DUMP_SYNTAX"\n"); return SWITCH_STATUS_SUCCESS; @@ -608,13 +608,14 @@ static void *SWITCH_THREAD_FUNC limit_remote_thread(switch_thread_t *thread, voi remote->host, remote->port); } } else { - if (esl_send_recv(&remote->handle, "api hash_dump limit") != SWITCH_STATUS_SUCCESS) { + if (esl_send_recv(&remote->handle, "api hash_dump limit") != ESL_SUCCESS) { esl_disconnect(&remote->handle); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Disconnected from remote FreeSWITCH at %s:%d\n", remote->host, remote->port); memset(&remote->handle, 0, sizeof(remote->handle)); + remote->state = REMOTE_DOWN; } else { - const char *data = remote->handle.last_sr_reply; + const char *data = esl_event_get_header(remote->handle.last_sr_event, "reply-text"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RECV: %s\n", data); } } From f66ac8906bb41b67772051dcf06a6fbab707079c Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Sat, 17 Jul 2010 01:14:11 -0400 Subject: [PATCH 06/17] mod_hash: remote sync in working state --- src/mod/applications/mod_hash/mod_hash.c | 159 +++++++++++++++++++++-- 1 file changed, 146 insertions(+), 13 deletions(-) diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c index 782c980085..5e21e33108 100644 --- a/src/mod/applications/mod_hash/mod_hash.c +++ b/src/mod/applications/mod_hash/mod_hash.c @@ -54,10 +54,11 @@ static struct { } globals; typedef struct { - uint32_t total_usage; - uint32_t rate_usage; - time_t last_check; - uint32_t interval; + uint32_t total_usage; /* < Total */ + uint32_t rate_usage; /* < Current rate usage */ + time_t last_check; /* < Last rate check */ + uint32_t interval; /* < Interval used on last rate check */ + uint32_t last_update; /* < Last updated timestamp (rate or total) */ } limit_hash_item_t; struct callback { @@ -74,9 +75,9 @@ typedef struct { } limit_hash_private_t; typedef enum { - REMOTE_OFF = 0, /* Thread not running */ - REMOTE_DOWN, /* Cannot connect to remote instance */ - REMOTE_UP /* All good */ + REMOTE_OFF = 0, /* < Thread not running */ + REMOTE_DOWN, /* 0) { item->interval = interval; if (item->last_check <= (now - interval)) { @@ -164,7 +170,7 @@ SWITCH_LIMIT_INCR(limit_incr_hash) goto end; } } - } else if ((max >= 0) && (item->total_usage + increment > (uint32_t) max)) { + } else if ((max >= 0) && (item->total_usage + increment + remote_usage.total_usage > (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_STATUS_GENERR; goto end; @@ -225,6 +231,19 @@ SWITCH_HASH_DELETE_FUNC(limit_hash_cleanup_delete_callback) { return SWITCH_FALSE; } +SWITCH_HASH_DELETE_FUNC(limit_hash_remote_cleanup_callback) +{ + limit_hash_item_t *item = (limit_hash_item_t *) val; + switch_time_t now = (switch_time_t)(intptr_t)pData; + + if (item->last_update != now) { + free(item); + return SWITCH_TRUE; + } + + return SWITCH_FALSE; +} + /* !\brief Periodically checks for unused limit entries and frees them */ SWITCH_STANDARD_SCHED_FUNC(limit_hash_cleanup_callback) { @@ -300,14 +319,19 @@ SWITCH_LIMIT_USAGE(limit_usage_hash) char *hash_key = NULL; limit_hash_item_t *item = NULL; int count = 0; + limit_hash_item_t remote_usage; switch_thread_rwlock_rdlock(globals.limit_hash_rwlock); hash_key = switch_mprintf("%s_%s", realm, resource); + remote_usage = get_remote_usage(hash_key); + + count = remote_usage.total_usage; + *rcount = remote_usage.rate_usage; if ((item = switch_core_hash_find(globals.limit_hash, hash_key))) { - count = item->total_usage; - *rcount = item->rate_usage; + count += item->total_usage; + *rcount += item->rate_usage; } switch_safe_free(hash_key); @@ -576,7 +600,7 @@ void limit_remote_destroy(limit_remote_t **r) switch_thread_rwlock_wrlock((*r)->rwlock); /* Free hashtable data */ - for (hi = switch_hash_first(NULL, globals.remote_hash); hi; hi = switch_hash_next(hi)) { + for (hi = switch_hash_first(NULL, (*r)->index); hi; hi = switch_hash_next(hi)) { void *val; const void *key; switch_ssize_t keylen; @@ -593,6 +617,41 @@ void limit_remote_destroy(limit_remote_t **r) } } +/* Compute the usage sum of a resource on remote boxes */ +static limit_hash_item_t get_remote_usage(const char *key) { + limit_hash_item_t usage = { 0 }; + switch_hash_index_t *hi; + + switch_thread_rwlock_rdlock(globals.remote_hash_rwlock); + for (hi = switch_hash_first(NULL, globals.remote_hash); hi; hi = switch_hash_next(hi)) { + void *val; + const void *hashkey; + switch_ssize_t keylen; + limit_remote_t *remote; + limit_hash_item_t *item; + switch_hash_this(hi, &hashkey, &keylen, &val); + + remote = (limit_remote_t *)val; + if (remote->state != REMOTE_UP) { + continue; + } + + switch_thread_rwlock_rdlock(remote->rwlock); + if ((item = switch_core_hash_find(remote->index, key))) { + usage.total_usage += item->total_usage; + usage.rate_usage += item->rate_usage; + if (!usage.last_check) { + usage.last_check = item->last_check; + } + } + switch_thread_rwlock_unlock(remote->rwlock); + } + + switch_thread_rwlock_unlock(globals.remote_hash_rwlock); + + return usage; +} + static void *SWITCH_THREAD_FUNC limit_remote_thread(switch_thread_t *thread, void *obj) { limit_remote_t *remote = (limit_remote_t*)obj; @@ -614,9 +673,58 @@ static void *SWITCH_THREAD_FUNC limit_remote_thread(switch_thread_t *thread, voi remote->host, remote->port); memset(&remote->handle, 0, sizeof(remote->handle)); remote->state = REMOTE_DOWN; + /* Delete all remote tracking entries */ + switch_thread_rwlock_wrlock(remote->rwlock); + switch_core_hash_delete_multi(remote->index, limit_hash_remote_cleanup_callback, NULL); + switch_thread_rwlock_unlock(remote->rwlock); } else { - const char *data = esl_event_get_header(remote->handle.last_sr_event, "reply-text"); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RECV: %s\n", data); + if (!zstr(remote->handle.last_sr_event->body)) { + char *data = strdup(remote->handle.last_sr_event->body); + char *p = data, *p2; + switch_time_t now = switch_epoch_time_now(NULL); + while (p && *p) { + /* We are getting the limit data as: + L/a_c/1/0/0/0 + */ + if ((p2 = strchr(p, '\n'))) { + *p2++ = '\0'; + } + + /* Now p points at the beginning of the current line, + p2 at the start of the next one */ + if (*p == 'L') { /* Limit data */ + char *argv[5]; + int argc = switch_split(p+2, '/', argv); + + if (argc < 5) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Protocol error: missing argument in line: %s\n", p); + } else { + limit_hash_item_t *item; + switch_thread_rwlock_wrlock(remote->rwlock); + if (!(item = switch_core_hash_find(remote->index, argv[0]))) { + item = malloc(sizeof(*item)); + switch_core_hash_insert(remote->index, argv[0], item); + } + item->total_usage = atoi(argv[1]); + item->rate_usage = atoi(argv[2]); + item->interval = atoi(argv[3]); + item->last_check = atoi(argv[4]); + item->last_update = now; + switch_thread_rwlock_unlock(remote->rwlock); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Imported key %s %d %d/%d (%d - %d)\n", + argv[0], item->total_usage, item->rate_usage, item->interval, (int)item->last_check, (int)item->last_update); + } + } + + p = p2; + } + free(data); + + /* Now free up anything that wasnt in this update since it means their usage is 0 */ + switch_thread_rwlock_wrlock(remote->rwlock); + switch_core_hash_delete_multi(remote->index, limit_hash_remote_cleanup_callback, (void*)(intptr_t)now); + switch_thread_rwlock_unlock(remote->rwlock); + } } } @@ -717,9 +825,34 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_hash_load) SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_hash_shutdown) { switch_hash_index_t *hi; + switch_bool_t remote_clean = SWITCH_TRUE; switch_scheduler_del_task_group("mod_hash"); + /* Kill remote connections, destroy needs a wrlock so we unlock after finding a pointer */ + while(remote_clean) { + void *val; + const void *key; + switch_ssize_t keylen; + limit_remote_t *item = NULL; + + switch_thread_rwlock_rdlock(globals.remote_hash_rwlock); + if ((hi = switch_hash_first(NULL, globals.remote_hash))) { + switch_hash_this(hi, &key, &keylen, &val); + item = (limit_remote_t *)val; + } + switch_thread_rwlock_unlock(globals.remote_hash_rwlock); + + if (!item) { + remote_clean = SWITCH_FALSE; + } else { + limit_remote_destroy(&item); + switch_thread_rwlock_wrlock(globals.remote_hash_rwlock); + switch_core_hash_delete(globals.remote_hash, key); + switch_thread_rwlock_unlock(globals.remote_hash_rwlock); + } + } + switch_thread_rwlock_wrlock(globals.limit_hash_rwlock); switch_thread_rwlock_wrlock(globals.db_hash_rwlock); From 71650ae1e87e330d2ea5e35ac73610ca88bf1393 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 19 Jul 2010 08:38:56 -0500 Subject: [PATCH 07/17] FSBUILD-291 fix Windows build of mod_freetdm --- libs/freetdm/mod_freetdm/mod_freetdm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 6224c7aea0..6233feffbd 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -1158,12 +1158,12 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-ANI-TON"); if (sipvar) { - caller_data.ani.type = atoi(sipvar); + caller_data.ani.type = (uint8_t)atoi(sipvar); } sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-ANI-Plan"); if (sipvar) { - caller_data.ani.plan = atoi(sipvar); + caller_data.ani.plan = (uint8_t)atoi(sipvar); } sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-ANI2"); @@ -1178,12 +1178,12 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-DNIS-TON"); if (sipvar) { - caller_data.dnis.type = atoi(sipvar); + caller_data.dnis.type = (uint8_t)atoi(sipvar); } sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-DNIS-Plan"); if (sipvar) { - caller_data.dnis.plan = atoi(sipvar); + caller_data.dnis.plan = (uint8_t)atoi(sipvar); } sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDNIS"); @@ -1193,22 +1193,22 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDNIS-TON"); if (sipvar) { - caller_data.rdnis.type = atoi(sipvar); + caller_data.rdnis.type = (uint8_t)atoi(sipvar); } sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDNIS-Plan"); if (sipvar) { - caller_data.rdnis.plan = atoi(sipvar); + caller_data.rdnis.plan = (uint8_t)atoi(sipvar); } sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-Screen"); if (sipvar) { - caller_data.screen = atoi(sipvar); + caller_data.screen = (uint8_t)atoi(sipvar); } sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-Presentation"); if (sipvar) { - caller_data.pres = atoi(sipvar); + caller_data.pres = (uint8_t)atoi(sipvar); } } From 90f33b83dc9e3d9df9f9d151920140e297592a95 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Mon, 19 Jul 2010 10:22:40 -0400 Subject: [PATCH 08/17] don't create the remote thread detached so we can join it --- src/mod/applications/mod_hash/mod_hash.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c index 5e21e33108..2eda0f4cdd 100644 --- a/src/mod/applications/mod_hash/mod_hash.c +++ b/src/mod/applications/mod_hash/mod_hash.c @@ -684,7 +684,7 @@ static void *SWITCH_THREAD_FUNC limit_remote_thread(switch_thread_t *thread, voi switch_time_t now = switch_epoch_time_now(NULL); while (p && *p) { /* We are getting the limit data as: - L/a_c/1/0/0/0 + L/key/usage/rate/interval/last_checked */ if ((p2 = strchr(p, '\n'))) { *p2++ = '\0'; @@ -693,7 +693,7 @@ static void *SWITCH_THREAD_FUNC limit_remote_thread(switch_thread_t *thread, voi /* Now p points at the beginning of the current line, p2 at the start of the next one */ if (*p == 'L') { /* Limit data */ - char *argv[5]; + char *argv[5]; int argc = switch_split(p+2, '/', argv); if (argc < 5) { @@ -711,8 +711,9 @@ static void *SWITCH_THREAD_FUNC limit_remote_thread(switch_thread_t *thread, voi item->last_check = atoi(argv[4]); item->last_update = now; switch_thread_rwlock_unlock(remote->rwlock); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Imported key %s %d %d/%d (%d - %d)\n", - argv[0], item->total_usage, item->rate_usage, item->interval, (int)item->last_check, (int)item->last_update); + + /*switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Imported key %s %d %d/%d (%d - %d)\n", + argv[0], item->total_usage, item->rate_usage, item->interval, (int)item->last_check, (int)item->last_update);*/ } } @@ -765,7 +766,7 @@ static void do_config() remote->state = REMOTE_DOWN; switch_threadattr_create(&thd_attr, remote->pool); - switch_threadattr_detach_set(thd_attr, 1); + //switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_thread_create(&remote->thread, thd_attr, limit_remote_thread, remote, remote->pool); } From 7036c9b8cd5793ee50d24f9e94b80f159be0c8f7 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Mon, 19 Jul 2010 11:05:10 -0400 Subject: [PATCH 09/17] mod_hash: add api function --- src/mod/applications/mod_hash/mod_hash.c | 92 +++++++++++++++++++++++- 1 file changed, 89 insertions(+), 3 deletions(-) diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c index 2eda0f4cdd..9608865238 100644 --- a/src/mod/applications/mod_hash/mod_hash.c +++ b/src/mod/applications/mod_hash/mod_hash.c @@ -80,6 +80,18 @@ typedef enum { REMOTE_UP /* < All good */ } limit_remote_state_t; +static inline const char *state_str(limit_remote_state_t state) { + switch (state) { + case REMOTE_OFF: + return "Off"; + case REMOTE_DOWN: + return "Down"; + case REMOTE_UP: + return "Up"; + } + return ""; +} + typedef struct { const char *name; const char *host; @@ -102,6 +114,9 @@ typedef struct { } limit_remote_t; static limit_hash_item_t get_remote_usage(const char *key); +void limit_remote_destroy(limit_remote_t **r); +static void do_config(switch_bool_t reload); + /* \brief Enforces limit_hash restrictions * \param session current session @@ -550,6 +565,66 @@ SWITCH_STANDARD_API(hash_dump_function) return SWITCH_STATUS_SUCCESS; } +#define HASH_REMOTE_SYNTAX "list|kill [name]|rescan" +SWITCH_STANDARD_API(hash_remote_function) +{ + int argc; + char *argv[10]; + char *dup = NULL; + + if (!zstr(cmd)) { + dup = strdup(cmd); + } + + argc = switch_split(dup, ' ', argv); + if (argv[0] && !strcmp(argv[0], "list")) { + switch_hash_index_t *hi; + stream->write_function(stream, "Remote connections:\nName\tState\n"); + + switch_thread_rwlock_rdlock(globals.remote_hash_rwlock); + for (hi = switch_hash_first(NULL, globals.remote_hash); hi; hi = switch_hash_next(hi)) { + void *val; + const void *key; + switch_ssize_t keylen; + limit_remote_t *item; + switch_hash_this(hi, &key, &keylen, &val); + + item = (limit_remote_t *)val; + stream->write_function(stream, "%s\t%s\n", item->name, state_str(item->state)); + } + switch_thread_rwlock_unlock(globals.remote_hash_rwlock); + stream->write_function(stream, "+OK\n"); + + } else if (argv[0] && !strcmp(argv[0], "kill")) { + const char *name = argv[1]; + limit_remote_t *remote; + if (zstr(name)) { + stream->write_function(stream, "-ERR "HASH_REMOTE_SYNTAX"\n"); + goto done; + } + switch_thread_rwlock_rdlock(globals.remote_hash_rwlock); + remote = switch_core_hash_find(globals.remote_hash, name); + switch_thread_rwlock_unlock(globals.remote_hash_rwlock); + + limit_remote_destroy(&remote); + + switch_thread_rwlock_wrlock(globals.remote_hash_rwlock); + switch_core_hash_delete(globals.remote_hash, name); + switch_thread_rwlock_unlock(globals.remote_hash_rwlock); + + stream->write_function(stream, "+OK\n"); + } else if (argv[0] && !strcmp(argv[0], "rescan")) { + do_config(SWITCH_TRUE); + stream->write_function(stream, "+OK\n"); + } + +done: + if (dup) { + free(dup); + } + return SWITCH_STATUS_SUCCESS; +} + limit_remote_t *limit_remote_create(const char *name, const char *host, uint16_t port, const char *username, const char *password, int interval) { limit_remote_t *r; @@ -594,7 +669,8 @@ void limit_remote_destroy(limit_remote_t **r) (*r)->state = REMOTE_OFF; if ((*r)->thread) { - switch_thread_join(NULL, (*r)->thread); + switch_status_t retval; + switch_thread_join(&retval, (*r)->thread); } switch_thread_rwlock_wrlock((*r)->rwlock); @@ -737,7 +813,7 @@ static void *SWITCH_THREAD_FUNC limit_remote_thread(switch_thread_t *thread, voi return NULL; } -static void do_config() +static void do_config(switch_bool_t reload) { switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, cfg = NULL; if ((xml = switch_xml_open_cfg("hash.conf", &cfg, NULL))) { @@ -752,6 +828,15 @@ static void do_config() int port = 0, interval = 0; limit_remote_t *remote; switch_threadattr_t *thd_attr = NULL; + + if (reload) { + switch_thread_rwlock_rdlock(globals.remote_hash_rwlock); + if (switch_core_hash_find(globals.remote_hash, name)) { + switch_thread_rwlock_unlock(globals.remote_hash_rwlock); + continue; + } + switch_thread_rwlock_unlock(globals.remote_hash_rwlock); + } if (!zstr(szport)) { port = atoi(szport); @@ -811,12 +896,13 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_hash_load) SWITCH_ADD_APP(app_interface, "hash", "Insert into the hashtable", HASH_DESC, hash_function, HASH_USAGE, SAF_SUPPORT_NOMEDIA) SWITCH_ADD_API(commands_api_interface, "hash", "hash get/set", hash_api_function, "[insert|delete|select]///"); SWITCH_ADD_API(commands_api_interface, "hash_dump", "dump hash/limit_hash data (used for synchronization)", hash_dump_function, HASH_DUMP_SYNTAX); + SWITCH_ADD_API(commands_api_interface, "hash_remote", "hash remote", hash_remote_function, HASH_REMOTE_SYNTAX); switch_console_set_complete("add hash insert"); switch_console_set_complete("add hash delete"); switch_console_set_complete("add hash select"); - do_config(); + do_config(SWITCH_FALSE); /* indicate that the module should continue to be loaded */ return SWITCH_STATUS_SUCCESS; From 67713fd6c2c6f650806d2177833e9bdd6bb7939d Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Mon, 19 Jul 2010 11:10:32 -0400 Subject: [PATCH 10/17] mod_hash: fix syntax messages and add console autocomplete --- src/mod/applications/mod_hash/mod_hash.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c index 9608865238..1a1abd2149 100644 --- a/src/mod/applications/mod_hash/mod_hash.c +++ b/src/mod/applications/mod_hash/mod_hash.c @@ -599,7 +599,7 @@ SWITCH_STANDARD_API(hash_remote_function) const char *name = argv[1]; limit_remote_t *remote; if (zstr(name)) { - stream->write_function(stream, "-ERR "HASH_REMOTE_SYNTAX"\n"); + stream->write_function(stream, "-ERR Usage: "HASH_REMOTE_SYNTAX"\n"); goto done; } switch_thread_rwlock_rdlock(globals.remote_hash_rwlock); @@ -616,6 +616,9 @@ SWITCH_STANDARD_API(hash_remote_function) } else if (argv[0] && !strcmp(argv[0], "rescan")) { do_config(SWITCH_TRUE); stream->write_function(stream, "+OK\n"); + } else { + stream->write_function(stream, "-ERR Usage: "HASH_REMOTE_SYNTAX"\n"); + } done: @@ -902,6 +905,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_hash_load) switch_console_set_complete("add hash delete"); switch_console_set_complete("add hash select"); + switch_console_set_complete("add hash_remote list"); + switch_console_set_complete("add hash_remote kill"); + switch_console_set_complete("add hash_remote rescan"); + do_config(SWITCH_FALSE); /* indicate that the module should continue to be loaded */ From f10eebf86f2e4f2f3eb4e79c304775d3d8446cc5 Mon Sep 17 00:00:00 2001 From: Rupa Schomaker Date: Mon, 19 Jul 2010 10:13:48 -0500 Subject: [PATCH 11/17] FSCORE-632 - limit not decrementing properly --- src/switch_limit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) mode change 100755 => 100644 src/switch_limit.c diff --git a/src/switch_limit.c b/src/switch_limit.c old mode 100755 new mode 100644 index 810d83b105..f76e1de1c0 --- a/src/switch_limit.c +++ b/src/switch_limit.c @@ -98,8 +98,8 @@ static switch_status_t limit_state_handler(switch_core_session_t *session) switch_limit_release(argv[x], session, NULL, NULL); } switch_core_event_hook_remove_state_change(session, limit_state_handler); - /* Remove limit_realm variable so we register another hook if limit is called again */ - switch_channel_set_variable(channel, "limit_realm", NULL); + /* Remove limit_backend variable so we register another hook if limit is called again */ + switch_channel_set_variable(channel, LIMIT_BACKEND_VARIABLE, NULL); free(mydata); } From 6d8c0b197e0b255c2e2d3878a73a73fbe8c7f53f Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Mon, 19 Jul 2010 11:24:01 -0400 Subject: [PATCH 12/17] mod_hash: change tab spacing for api, remove unnecessary log at every connection attempt in case a box is down --- src/mod/applications/mod_hash/mod_hash.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c index 1a1abd2149..ae5f56d5a2 100644 --- a/src/mod/applications/mod_hash/mod_hash.c +++ b/src/mod/applications/mod_hash/mod_hash.c @@ -579,7 +579,7 @@ SWITCH_STANDARD_API(hash_remote_function) argc = switch_split(dup, ' ', argv); if (argv[0] && !strcmp(argv[0], "list")) { switch_hash_index_t *hi; - stream->write_function(stream, "Remote connections:\nName\tState\n"); + stream->write_function(stream, "Remote connections:\nName\t\t\tState\n"); switch_thread_rwlock_rdlock(globals.remote_hash_rwlock); for (hi = switch_hash_first(NULL, globals.remote_hash); hi; hi = switch_hash_next(hi)) { @@ -590,7 +590,7 @@ SWITCH_STANDARD_API(hash_remote_function) switch_hash_this(hi, &key, &keylen, &val); item = (limit_remote_t *)val; - stream->write_function(stream, "%s\t%s\n", item->name, state_str(item->state)); + stream->write_function(stream, "%s\t\t\t%s\n", item->name, state_str(item->state)); } switch_thread_rwlock_unlock(globals.remote_hash_rwlock); stream->write_function(stream, "+OK\n"); @@ -741,9 +741,6 @@ static void *SWITCH_THREAD_FUNC limit_remote_thread(switch_thread_t *thread, voi remote->host, remote->port); remote->state = REMOTE_UP; - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't connect to remote FreeSWITCH at %s:%d\n", - remote->host, remote->port); } } else { if (esl_send_recv(&remote->handle, "api hash_dump limit") != ESL_SUCCESS) { From 51bc65e299dccc5a6f9d587792e0f2e2ff5cf12c Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Mon, 19 Jul 2010 11:26:53 -0400 Subject: [PATCH 13/17] mod_hash: add hash.conf.xml --- conf/autoload_configs/hash.conf.xml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 conf/autoload_configs/hash.conf.xml diff --git a/conf/autoload_configs/hash.conf.xml b/conf/autoload_configs/hash.conf.xml new file mode 100644 index 0000000000..1b54a451b9 --- /dev/null +++ b/conf/autoload_configs/hash.conf.xml @@ -0,0 +1,6 @@ + + + + + + From dc37716a295a8fa2b18da836b179c5daa7e5c3a9 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Mon, 19 Jul 2010 11:37:52 -0400 Subject: [PATCH 14/17] mod_hash: oops, that meant to be commented out --- conf/autoload_configs/hash.conf.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/autoload_configs/hash.conf.xml b/conf/autoload_configs/hash.conf.xml index 1b54a451b9..95b7928775 100644 --- a/conf/autoload_configs/hash.conf.xml +++ b/conf/autoload_configs/hash.conf.xml @@ -1,6 +1,6 @@ - + From 52c278c2e1b820e4a5f329a83f50757ab5248fde Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Mon, 19 Jul 2010 11:50:15 -0400 Subject: [PATCH 15/17] mod_hash: fix null check on API --- src/mod/applications/mod_hash/mod_hash.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c index ae5f56d5a2..126d9f3a26 100644 --- a/src/mod/applications/mod_hash/mod_hash.c +++ b/src/mod/applications/mod_hash/mod_hash.c @@ -572,10 +572,13 @@ SWITCH_STANDARD_API(hash_remote_function) char *argv[10]; char *dup = NULL; - if (!zstr(cmd)) { - dup = strdup(cmd); + if (zstr(cmd)) { + stream->write_function(stream, "-ERR Usage: "HASH_REMOTE_SYNTAX"\n"); + return SWITCH_STATUS_SUCCESS; } + dup = strdup(cmd); + argc = switch_split(dup, ' ', argv); if (argv[0] && !strcmp(argv[0], "list")) { switch_hash_index_t *hi; From 26358d67966b0dd2e54a213a4b1cc3c5163ccb72 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 19 Jul 2010 10:58:50 -0500 Subject: [PATCH 16/17] FSCORE-635 --- src/switch_rtp.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 0d4420eabe..a123d93eea 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -2077,10 +2077,12 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t rtp_session->stats.inbound.packet_count++; } - if (rtp_session->recv_te && rtp_session->recv_msg.header.pt == rtp_session->recv_te) { + if ((rtp_session->recv_te && rtp_session->recv_msg.header.pt == rtp_session->recv_te) || + *bytes < rtp_header_len || + switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) || switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL)) { return SWITCH_STATUS_SUCCESS; } - + if (rtp_session->jb && rtp_session->recv_msg.header.version == 2 && *bytes) { if (rtp_session->recv_msg.header.m && rtp_session->recv_msg.header.pt != rtp_session->recv_te && @@ -2532,7 +2534,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL)) { *flags |= SFF_UDPTL_PACKET; } - + ret = (int) bytes; goto end; } @@ -2540,6 +2542,12 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ if (bytes) { rtp_session->missed_count = 0; + if (bytes < rtp_header_len) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring invalid RTP packet size of %ld bytes.\n", (long)bytes); + bytes = 0; + goto do_continue; + } + if (rtp_session->recv_msg.header.pt && (rtp_session->recv_msg.header.pt == rtp_session->cng_pt || rtp_session->recv_msg.header.pt == 13)) { return_cng_frame(); } @@ -2667,7 +2675,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ we put up with as much as we can so we don't have to deal with being punished for doing it right. Nice guys finish last! */ - if (bytes && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) && + if (bytes > rtp_header_len && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PASS_RFC2833) && rtp_session->recv_msg.header.pt == rtp_session->recv_te) { switch_size_t len = bytes - rtp_header_len; unsigned char *packet = (unsigned char *) rtp_session->recv_msg.body; @@ -2959,7 +2967,9 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_read(switch_rtp_t *rtp_session, void *datalen = 0; return SWITCH_STATUS_BREAK; } else { - bytes -= rtp_header_len; + if (bytes > rtp_header_len) { + bytes -= rtp_header_len; + } } *datalen = bytes; @@ -3069,7 +3079,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp if (bytes < 0) { frame->datalen = 0; return bytes == -2 ? SWITCH_STATUS_TIMEOUT : SWITCH_STATUS_GENERR; - } else if (bytes == 0) { + } else if (bytes < rtp_header_len) { frame->datalen = 0; return SWITCH_STATUS_BREAK; } else { @@ -3098,7 +3108,9 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read(switch_rtp_t *rtp_sessi *datalen = 0; return SWITCH_STATUS_GENERR; } else { - bytes -= rtp_header_len; + if (bytes > rtp_header_len) { + bytes -= rtp_header_len; + } } *datalen = bytes; @@ -3126,7 +3138,9 @@ static int rtp_common_write(switch_rtp_t *rtp_session, send_msg->header.pt = rtp_session->te; } data = send_msg->body; - datalen -= rtp_header_len; + if (datalen > rtp_header_len) { + datalen -= rtp_header_len; + } } else { uint8_t m = 0; From c8e8f26552fede1cea6812f8db5fc765eb87fc96 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 19 Jul 2010 11:04:52 -0500 Subject: [PATCH 17/17] fifo tweak --- src/mod/applications/mod_fifo/mod_fifo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 58d7879aaf..9ab15345a6 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1115,7 +1115,7 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void char nstr[256] = ""; if (strcasecmp(codec, "PCMU") && strcasecmp(codec, "PCMA")) { - switch_snprintf(nstr, sizeof(nstr), "%s@%si@%sh,PCMU,PCMA", codec, ptime, rate); + switch_snprintf(nstr, sizeof(nstr), "%s@%si@%sh,PCMU@%di,PCMA@%di", codec, ptime, rate, ptime, ptime); } else { switch_snprintf(nstr, sizeof(nstr), "%s@%si@%sh", codec, ptime, rate); }