From 7ead440fa01228f3546d6c7d85a13b141f5b4d2d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 19 Nov 2012 18:23:05 -0600 Subject: [PATCH 01/30] bump --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 52d884f090..15c91a976a 100644 --- a/configure.in +++ b/configure.in @@ -3,10 +3,10 @@ # Must change all of the below together # For a release, set revision for that tagged release as well and uncomment -AC_INIT([freeswitch], [1.3.5], bugs@freeswitch.org) +AC_INIT([freeswitch], [1.3.6b], bugs@freeswitch.org) AC_SUBST(SWITCH_VERSION_MAJOR, [1]) AC_SUBST(SWITCH_VERSION_MINOR, [3]) -AC_SUBST(SWITCH_VERSION_MICRO, [5]) +AC_SUBST(SWITCH_VERSION_MICRO, [6b]) AC_SUBST(SWITCH_VERSION_REVISION, []) AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, []) From 93b5f7fdfd786e468bb87bb1175fa7b3378bc86f Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 19 Nov 2012 23:32:41 -0600 Subject: [PATCH 02/30] FS-4099 FS-4847 --- src/switch_core.c | 5665 +++++++++++++++++++++++---------------------- 1 file changed, 2834 insertions(+), 2831 deletions(-) diff --git a/src/switch_core.c b/src/switch_core.c index 4682d3c002..9bbb11956d 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1,2831 +1,2834 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2012, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * - * The Initial Developer of the Original Code is - * Anthony Minessale II - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Anthony Minessale II - * Michael Jerris - * Paul D. Tinsley - * Marcel Barbulescu - * Joseph Sullivan - * - * - * switch_core.c -- Main Core Library - * - */ - - - -#include -#include -#include -#include -#include -#include "private/switch_core_pvt.h" -#include -#ifndef WIN32 -#include -#ifdef HAVE_SETRLIMIT -#include -#endif -#endif -#include - - -SWITCH_DECLARE_DATA switch_directories SWITCH_GLOBAL_dirs = { 0 }; - -/* The main runtime obj we keep this hidden for ourselves */ -struct switch_runtime runtime = { 0 }; -static void switch_load_core_config(const char *file); - -static void send_heartbeat(void) -{ - switch_event_t *event; - switch_core_time_duration_t duration; - - switch_core_measure_time(switch_core_uptime(), &duration); - - if (switch_event_create(&event, SWITCH_EVENT_HEARTBEAT) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready"); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Up-Time", - "%u year%s, " - "%u day%s, " - "%u hour%s, " - "%u minute%s, " - "%u second%s, " - "%u millisecond%s, " - "%u microsecond%s", - duration.yr, duration.yr == 1 ? "" : "s", - duration.day, duration.day == 1 ? "" : "s", - duration.hr, duration.hr == 1 ? "" : "s", - duration.min, duration.min == 1 ? "" : "s", - duration.sec, duration.sec == 1 ? "" : "s", - duration.ms, duration.ms == 1 ? "" : "s", duration.mms, duration.mms == 1 ? "" : "s"); - - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Version", SWITCH_VERSION_FULL); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Uptime-msec", "%"SWITCH_TIME_T_FMT, switch_core_uptime() / 1000); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Count", "%u", switch_core_session_count()); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Max-Sessions", "%u", switch_core_session_limit(0)); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec", "%u", runtime.sps); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Since-Startup", "%" SWITCH_SIZE_T_FMT, switch_core_session_id() - 1); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Idle-CPU", "%f", switch_core_idle_cpu()); - switch_event_fire(&event); - } -} - -static char main_ip4[256] = ""; -static char main_ip6[256] = ""; - -static void check_ip(void) -{ - char guess_ip4[256] = ""; - char guess_ip6[256] = ""; - char old_ip4[256] = ""; - char old_ip6[256] = ""; - int ok4 = 1, ok6 = 1; - int mask = 0; - - gethostname(runtime.hostname, sizeof(runtime.hostname)); - switch_core_set_variable("hostname", runtime.hostname); - - switch_find_local_ip(guess_ip4, sizeof(guess_ip4), &mask, AF_INET); - switch_find_local_ip(guess_ip6, sizeof(guess_ip6), NULL, AF_INET6); - - if (!*main_ip4) { - switch_set_string(main_ip4, guess_ip4); - } else { - if (!(ok4 = !strcmp(main_ip4, guess_ip4))) { - struct in_addr in; - - in.s_addr = mask; - switch_set_string(old_ip4, main_ip4); - switch_set_string(main_ip4, guess_ip4); - switch_core_set_variable("local_ip_v4", guess_ip4); - switch_core_set_variable("local_mask_v4", inet_ntoa(in)); - } - } - - if (!*main_ip6) { - switch_set_string(main_ip6, guess_ip6); - } else { - if (!(ok6 = !strcmp(main_ip6, guess_ip6))) { - switch_set_string(old_ip6, main_ip6); - switch_set_string(main_ip6, guess_ip6); - switch_core_set_variable("local_ip_v6", guess_ip6); - } - } - - if (!ok4 || !ok6) { - switch_event_t *event; - - if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "condition", "network-address-change"); - if (!ok4) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v4", old_ip4); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v4", main_ip4); - } - if (!ok6) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v6", old_ip6); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v6", main_ip6); - } - switch_event_fire(&event); - } - } -} - -SWITCH_STANDARD_SCHED_FUNC(heartbeat_callback) -{ - send_heartbeat(); - - /* reschedule this task */ - task->runtime = switch_epoch_time_now(NULL) + 20; -} - - -SWITCH_STANDARD_SCHED_FUNC(check_ip_callback) -{ - check_ip(); - - /* reschedule this task */ - task->runtime = switch_epoch_time_now(NULL) + 60; -} - - -SWITCH_DECLARE(switch_status_t) switch_core_set_console(const char *console) -{ - if ((runtime.console = fopen(console, "a")) == 0) { - fprintf(stderr, "Cannot open output file %s.\n", console); - return SWITCH_STATUS_FALSE; - } - - return SWITCH_STATUS_SUCCESS; -} - -SWITCH_DECLARE(FILE *) switch_core_get_console(void) -{ - return runtime.console; -} - -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -SWITCH_DECLARE(void) switch_core_screen_size(int *x, int *y) -{ - -#ifdef WIN32 - CONSOLE_SCREEN_BUFFER_INFO csbi; - int ret; - - if ((ret = GetConsoleScreenBufferInfo(GetStdHandle( STD_OUTPUT_HANDLE ), &csbi))) { - if (x) *x = csbi.dwSize.X; - if (y) *y = csbi.dwSize.Y; - } - -#elif defined(TIOCGWINSZ) - struct winsize w; - ioctl(0, TIOCGWINSZ, &w); - - if (x) *x = w.ws_col; - if (y) *y = w.ws_row; -#else - if (x) *x = 80; - if (y) *y = 24; -#endif - -} - -SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel_t channel) -{ - FILE *handle = stdout; - - switch (channel) { - case SWITCH_CHANNEL_ID_LOG: - case SWITCH_CHANNEL_ID_LOG_CLEAN: - handle = runtime.console; - break; - default: - handle = runtime.console; - break; - } - - return handle; -} - - -SWITCH_DECLARE(void) switch_core_remove_state_handler(const switch_state_handler_table_t *state_handler) -{ - int index, tmp_index = 0; - const switch_state_handler_table_t *tmp[SWITCH_MAX_STATE_HANDLERS + 1] = { 0 }; - - switch_mutex_lock(runtime.global_mutex); - - for (index = 0; index < runtime.state_handler_index; index++) { - const switch_state_handler_table_t *cur = runtime.state_handlers[index]; - runtime.state_handlers[index] = NULL; - if (cur == state_handler) { - continue; - } - tmp[tmp_index++] = cur; - } - - runtime.state_handler_index = 0; - - for (index = 0; index < tmp_index; index++) { - runtime.state_handlers[runtime.state_handler_index++] = tmp[index]; - } - switch_mutex_unlock(runtime.global_mutex); -} - - -SWITCH_DECLARE(int) switch_core_add_state_handler(const switch_state_handler_table_t *state_handler) -{ - int index; - - switch_mutex_lock(runtime.global_mutex); - index = runtime.state_handler_index++; - - if (runtime.state_handler_index >= SWITCH_MAX_STATE_HANDLERS) { - index = -1; - } else { - runtime.state_handlers[index] = state_handler; - } - - switch_mutex_unlock(runtime.global_mutex); - return index; -} - -SWITCH_DECLARE(const switch_state_handler_table_t *) switch_core_get_state_handler(int index) -{ - - if (index >= SWITCH_MAX_STATE_HANDLERS || index > runtime.state_handler_index) { - return NULL; - } - - return runtime.state_handlers[index]; -} - -SWITCH_DECLARE(void) switch_core_dump_variables(switch_stream_handle_t *stream) -{ - switch_event_header_t *hi; - - switch_mutex_lock(runtime.global_mutex); - for (hi = runtime.global_vars->headers; hi; hi = hi->next) { - stream->write_function(stream, "%s=%s\n", hi->name, hi->value); - } - switch_mutex_unlock(runtime.global_mutex); -} - -SWITCH_DECLARE(const char *) switch_core_get_hostname(void) -{ - return runtime.hostname; -} - -SWITCH_DECLARE(const char *) switch_core_get_switchname(void) -{ - if (!zstr(runtime.switchname)) return runtime.switchname; - return runtime.hostname; -} - - -SWITCH_DECLARE(char *) switch_core_get_variable(const char *varname) -{ - char *val; - switch_thread_rwlock_rdlock(runtime.global_var_rwlock); - val = (char *) switch_event_get_header(runtime.global_vars, varname); - switch_thread_rwlock_unlock(runtime.global_var_rwlock); - return val; -} - -SWITCH_DECLARE(char *) switch_core_get_variable_dup(const char *varname) -{ - char *val = NULL, *v; - - switch_thread_rwlock_rdlock(runtime.global_var_rwlock); - if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) { - val = strdup(v); - } - switch_thread_rwlock_unlock(runtime.global_var_rwlock); - - return val; -} - -SWITCH_DECLARE(char *) switch_core_get_variable_pdup(const char *varname, switch_memory_pool_t *pool) -{ - char *val = NULL, *v; - - switch_thread_rwlock_rdlock(runtime.global_var_rwlock); - if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) { - val = switch_core_strdup(pool, v); - } - switch_thread_rwlock_unlock(runtime.global_var_rwlock); - - return val; -} - -static void switch_core_unset_variables(void) -{ - switch_thread_rwlock_wrlock(runtime.global_var_rwlock); - switch_event_destroy(&runtime.global_vars); - switch_event_create_plain(&runtime.global_vars, SWITCH_EVENT_CHANNEL_DATA); - switch_thread_rwlock_unlock(runtime.global_var_rwlock); -} - -SWITCH_DECLARE(void) switch_core_set_variable(const char *varname, const char *value) -{ - char *val; - - if (varname) { - switch_thread_rwlock_wrlock(runtime.global_var_rwlock); - val = (char *) switch_event_get_header(runtime.global_vars, varname); - if (val) { - switch_event_del_header(runtime.global_vars, varname); - } - if (value) { - char *v = strdup(value); - switch_string_var_check(v, SWITCH_TRUE); - switch_event_add_header_string(runtime.global_vars, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, varname, v); - } else { - switch_event_del_header(runtime.global_vars, varname); - } - switch_thread_rwlock_unlock(runtime.global_var_rwlock); - } -} - -SWITCH_DECLARE(switch_bool_t) switch_core_set_var_conditional(const char *varname, const char *value, const char *val2) -{ - char *val; - - if (varname) { - switch_thread_rwlock_wrlock(runtime.global_var_rwlock); - val = (char *) switch_event_get_header(runtime.global_vars, varname); - - if (val) { - if (!val2 || strcmp(val, val2) != 0) { - switch_thread_rwlock_unlock(runtime.global_var_rwlock); - return SWITCH_FALSE; - } - switch_event_del_header(runtime.global_vars, varname); - } else if (!zstr(val2)) { - switch_thread_rwlock_unlock(runtime.global_var_rwlock); - return SWITCH_FALSE; - } - - if (value) { - char *v = strdup(value); - switch_string_var_check(v, SWITCH_TRUE); - switch_event_add_header_string(runtime.global_vars, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, varname, v); - } else { - switch_event_del_header(runtime.global_vars, varname); - } - switch_thread_rwlock_unlock(runtime.global_var_rwlock); - } - return SWITCH_TRUE; -} - -SWITCH_DECLARE(char *) switch_core_get_uuid(void) -{ - return runtime.uuid_str; -} - - -static void *SWITCH_THREAD_FUNC switch_core_service_thread(switch_thread_t *thread, void *obj) -{ - switch_core_session_t *session = obj; - switch_channel_t *channel; - switch_frame_t *read_frame; - -// switch_assert(thread != NULL); -// switch_assert(session != NULL); - - if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) { - return NULL; - } - - switch_mutex_lock(session->frame_read_mutex); - - channel = switch_core_session_get_channel(session); - - switch_channel_set_flag(channel, CF_SERVICE); - while (switch_channel_test_flag(channel, CF_SERVICE)) { - - if (switch_channel_test_flag(channel, CF_SERVICE_AUDIO)) { - switch (switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0)) { - case SWITCH_STATUS_SUCCESS: - case SWITCH_STATUS_TIMEOUT: - case SWITCH_STATUS_BREAK: - break; - default: - switch_channel_clear_flag(channel, CF_SERVICE); - break; - } - } - - if (switch_channel_test_flag(channel, CF_SERVICE_VIDEO) && switch_channel_test_flag(channel, CF_VIDEO)) { - switch (switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0)) { - case SWITCH_STATUS_SUCCESS: - case SWITCH_STATUS_TIMEOUT: - case SWITCH_STATUS_BREAK: - break; - default: - switch_channel_clear_flag(channel, CF_SERVICE); - break; - } - } - } - - switch_mutex_unlock(session->frame_read_mutex); - - switch_channel_clear_flag(channel, CF_SERVICE_AUDIO); - switch_channel_clear_flag(channel, CF_SERVICE_VIDEO); - - switch_core_session_rwunlock(session); - - return NULL; -} - -/* Either add a timeout here or make damn sure the thread cannot get hung somehow (my preference) */ -SWITCH_DECLARE(void) switch_core_thread_session_end(switch_core_session_t *session) -{ - switch_channel_t *channel; - switch_assert(session); - - channel = switch_core_session_get_channel(session); - switch_assert(channel); - - switch_channel_clear_flag(channel, CF_SERVICE); - switch_channel_clear_flag(channel, CF_SERVICE_AUDIO); - switch_channel_clear_flag(channel, CF_SERVICE_VIDEO); - - switch_core_session_kill_channel(session, SWITCH_SIG_BREAK); - -} - -SWITCH_DECLARE(void) switch_core_service_session_av(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video) -{ - switch_channel_t *channel; - switch_assert(session); - - channel = switch_core_session_get_channel(session); - switch_assert(channel); - - if (audio) switch_channel_set_flag(channel, CF_SERVICE_AUDIO); - if (video) switch_channel_set_flag(channel, CF_SERVICE_VIDEO); - - switch_core_session_launch_thread(session, (void *(*)(switch_thread_t *,void *))switch_core_service_thread, session); -} - -/* This function abstracts the thread creation for modules by allowing you to pass a function ptr and - a void object and trust that that the function will be run in a thread with arg This lets - you request and activate a thread without giving up any knowledge about what is in the thread - neither the core nor the calling module know anything about each other. - - This thread is expected to never exit until the application exits so the func is responsible - to make sure that is the case. - - The typical use for this is so switch_loadable_module.c can start up a thread for each module - passing the table of module methods as a session obj into the core without actually allowing - the core to have any clue and keeping switch_loadable_module.c from needing any thread code. - -*/ - -SWITCH_DECLARE(switch_thread_t *) switch_core_launch_thread(switch_thread_start_t func, void *obj, switch_memory_pool_t *pool) -{ - switch_thread_t *thread = NULL; - switch_threadattr_t *thd_attr = NULL; - switch_core_thread_session_t *ts; - int mypool; - - mypool = pool ? 0 : 1; - - if (!pool && switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory pool\n"); - return NULL; - } - - switch_threadattr_create(&thd_attr, pool); - - if ((ts = switch_core_alloc(pool, sizeof(*ts))) == 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory\n"); - } else { - if (mypool) { - ts->pool = pool; - } - ts->objs[0] = obj; - ts->objs[1] = thread; - switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); - switch_thread_create(&thread, thd_attr, func, ts, pool); - } - - return thread; -} - -SWITCH_DECLARE(void) switch_core_set_globals(void) -{ -#define BUFSIZE 1024 -#ifdef WIN32 - char lpPathBuffer[BUFSIZE]; - DWORD dwBufSize = BUFSIZE; - char base_dir[1024]; - char *lastbacklash; - char *tmp; - - GetModuleFileName(NULL, base_dir, BUFSIZE); - lastbacklash = strrchr(base_dir, '\\'); - base_dir[(lastbacklash - base_dir)] = '\0'; - /* set base_dir as cwd, to be able to use relative paths in scripting languages (e.g. mod_lua) when FS is running as a service or while debugging FS using visual studio */ - SetCurrentDirectory(base_dir); - tmp = switch_string_replace(base_dir, "\\", "/"); - strcpy(base_dir, tmp); - free(tmp); - -#else - char base_dir[1024] = SWITCH_PREFIX_DIR; -#endif - - if (!SWITCH_GLOBAL_dirs.base_dir && (SWITCH_GLOBAL_dirs.base_dir = (char *) malloc(BUFSIZE))) { - switch_snprintf(SWITCH_GLOBAL_dirs.base_dir, BUFSIZE, "%s", base_dir); - } - - if (!SWITCH_GLOBAL_dirs.mod_dir && (SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_MOD_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s", SWITCH_MOD_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s%smod", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.lib_dir && (SWITCH_GLOBAL_dirs.lib_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_LIB_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s", SWITCH_LIB_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s%slib", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.conf_dir && (SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_CONF_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s", SWITCH_CONF_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s%sconf", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.log_dir && (SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_LOG_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s", SWITCH_LOG_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s%slog", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.run_dir && (SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_RUN_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s", SWITCH_RUN_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s%srun", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.recordings_dir && (SWITCH_GLOBAL_dirs.recordings_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_RECORDINGS_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s", SWITCH_RECORDINGS_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s%srecordings", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.sounds_dir && (SWITCH_GLOBAL_dirs.sounds_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_SOUNDS_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s", SWITCH_SOUNDS_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s%ssounds", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.storage_dir && (SWITCH_GLOBAL_dirs.storage_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_STORAGE_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s", SWITCH_STORAGE_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s%sstorage", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.db_dir && (SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_DB_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s", SWITCH_DB_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s%sdb", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.script_dir && (SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_SCRIPT_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s", SWITCH_SCRIPT_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s%sscripts", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_HTDOCS_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s", SWITCH_HTDOCS_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s%shtdocs", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.grammar_dir && (SWITCH_GLOBAL_dirs.grammar_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_GRAMMAR_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s", SWITCH_GRAMMAR_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s%sgrammar", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.temp_dir && (SWITCH_GLOBAL_dirs.temp_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_TEMP_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", SWITCH_TEMP_DIR); -#else -#ifdef WIN32 - GetTempPath(dwBufSize, lpPathBuffer); - lpPathBuffer[strlen(lpPathBuffer)-1] = 0; - switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", lpPathBuffer); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", "/tmp"); -#endif -#endif - } - - switch_assert(SWITCH_GLOBAL_dirs.base_dir); - switch_assert(SWITCH_GLOBAL_dirs.mod_dir); - switch_assert(SWITCH_GLOBAL_dirs.lib_dir); - switch_assert(SWITCH_GLOBAL_dirs.conf_dir); - switch_assert(SWITCH_GLOBAL_dirs.log_dir); - switch_assert(SWITCH_GLOBAL_dirs.run_dir); - switch_assert(SWITCH_GLOBAL_dirs.db_dir); - switch_assert(SWITCH_GLOBAL_dirs.script_dir); - switch_assert(SWITCH_GLOBAL_dirs.htdocs_dir); - switch_assert(SWITCH_GLOBAL_dirs.grammar_dir); - switch_assert(SWITCH_GLOBAL_dirs.recordings_dir); - switch_assert(SWITCH_GLOBAL_dirs.sounds_dir); - switch_assert(SWITCH_GLOBAL_dirs.temp_dir); -} - - -SWITCH_DECLARE(int32_t) set_low_priority(void) -{ - - -#ifdef WIN32 - SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); -#else -#ifdef USE_SCHED_SETSCHEDULER - /* - * Try to use a normal scheduler - */ - struct sched_param sched = { 0 }; - sched.sched_priority = 0; - if (sched_setscheduler(0, SCHED_OTHER, &sched)) { - return -1; - } -#endif - -#ifdef HAVE_SETPRIORITY - /* - * setpriority() works on FreeBSD (6.2), nice() doesn't - */ - if (setpriority(PRIO_PROCESS, getpid(), 19) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); - return -1; - } -#else - if (nice(19) != 19) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); - return -1; - } -#endif -#endif - - return 0; -} - -SWITCH_DECLARE(int32_t) set_realtime_priority(void) -{ -#ifdef WIN32 - SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); -#else -#ifdef USE_SCHED_SETSCHEDULER - /* - * Try to use a round-robin scheduler - * with a fallback if that does not work - */ - struct sched_param sched = { 0 }; - sched.sched_priority = SWITCH_PRI_LOW; - if (sched_setscheduler(0, SCHED_FIFO, &sched)) { - sched.sched_priority = 0; - if (sched_setscheduler(0, SCHED_OTHER, &sched)) { - return -1; - } - } -#endif - - - -#ifdef HAVE_SETPRIORITY - /* - * setpriority() works on FreeBSD (6.2), nice() doesn't - */ - if (setpriority(PRIO_PROCESS, getpid(), -10) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); - return -1; - } -#else - if (nice(-10) != -10) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); - return -1; - } -#endif -#endif - return 0; -} - -SWITCH_DECLARE(uint32_t) switch_core_cpu_count(void) -{ - return runtime.cpu_count; -} - -SWITCH_DECLARE(int32_t) set_normal_priority(void) -{ - return 0; -} - -SWITCH_DECLARE(int32_t) set_auto_priority(void) -{ -#ifndef WIN32 - runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN); -#else - SYSTEM_INFO sysinfo; - GetSystemInfo( &sysinfo ); - runtime.cpu_count = sysinfo.dwNumberOfProcessors; -#endif - - if (!runtime.cpu_count) runtime.cpu_count = 1; - - /* If we have more than 1 cpu, we should use realtime priority so we can have priority threads */ - if (runtime.cpu_count > 1) { - return set_realtime_priority(); - } - - return 0; -} - -SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group) -{ -#ifndef WIN32 - uid_t runas_uid = 0; - gid_t runas_gid = 0; - struct passwd *runas_pw = NULL; - - if (user) { - /* - * Lookup user information in the system's db - */ - runas_pw = getpwnam(user); - if (!runas_pw) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unknown user \"%s\"\n", user); - return -1; - } - runas_uid = runas_pw->pw_uid; - } - - if (group) { - struct group *gr = NULL; - - /* - * Lookup group information in the system's db - */ - gr = getgrnam(group); - if (!gr) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unknown group \"%s\"\n", group); - return -1; - } - runas_gid = gr->gr_gid; - } - - if (runas_uid && getuid() == runas_uid && (!runas_gid || runas_gid == getgid())) { - /* already running as the right user and group, nothing to do! */ - return 0; - } - - if (runas_uid) { -#ifdef HAVE_SETGROUPS - /* - * Drop all group memberships prior to changing anything - * or else we're going to inherit the parent's list of groups - * (which is not what we want...) - */ - if (setgroups(0, NULL) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to drop group access list\n"); - return -1; - } -#endif - if (runas_gid) { - /* - * A group has been passed, switch to it - * (without loading the user's other groups) - */ - if (setgid(runas_gid) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change gid!\n"); - return -1; - } - } else { - /* - * No group has been passed, use the user's primary group in this case - */ - if (setgid(runas_pw->pw_gid) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change gid!\n"); - return -1; - } -#ifdef HAVE_INITGROUPS - /* - * Set all the other groups the user is a member of - * (This can be really useful for fine-grained access control) - */ - if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to set group access list for user\n"); - return -1; - } -#endif - } - - /* - * Finally drop all privileges by switching to the new userid - */ - if (setuid(runas_uid) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change uid!\n"); - return -1; - } - } -#endif - return 0; -} - -SWITCH_DECLARE(void) switch_core_runtime_loop(int bg) -{ -#ifdef WIN32 - HANDLE shutdown_event; - char path[256] = ""; -#endif - if (bg) { - bg = 0; -#ifdef WIN32 - switch_snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid()); - shutdown_event = CreateEvent(NULL, FALSE, FALSE, path); - if (shutdown_event) { - WaitForSingleObject(shutdown_event, INFINITE); - } -#else - runtime.running = 1; - while (runtime.running) { - switch_yield(1000000); - } -#endif - } else { - /* wait for console input */ - switch_console_loop(); - } -} - -SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext) -{ - if (!ext) { - return NULL; - } - return (const char *) switch_core_hash_find(runtime.mime_types, ext); -} - - -SWITCH_DECLARE(switch_hash_index_t *) switch_core_mime_index(void) -{ - return switch_hash_first(NULL, runtime.mime_types); -} - -SWITCH_DECLARE(switch_status_t) switch_core_mime_add_type(const char *type, const char *ext) -{ - const char *check; - switch_status_t status = SWITCH_STATUS_FALSE; - - switch_assert(type); - switch_assert(ext); - - check = (const char *) switch_core_hash_find(runtime.mime_types, ext); - - if (!check) { - char *ptype = switch_core_permanent_strdup(type); - char *ext_list = strdup(ext); - int argc = 0; - char *argv[20] = { 0 }; - int x; - - switch_assert(ext_list); - - if ((argc = switch_separate_string(ext_list, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { - - for (x = 0; x < argc; x++) { - if (argv[x] && ptype) { - switch_core_hash_insert(runtime.mime_types, argv[x], ptype); - } - } - - status = SWITCH_STATUS_SUCCESS; - } - - free(ext_list); - } - - return status; -} - -static void load_mime_types(void) -{ - char *cf = "mime.types"; - FILE *fd = NULL; - char *line_buf = NULL; - switch_size_t llen = 0; - char *mime_path = NULL; - - mime_path = switch_mprintf("%s/%s", SWITCH_GLOBAL_dirs.conf_dir, cf); - switch_assert(mime_path); - - fd = fopen(mime_path, "rb"); - - if (fd == NULL) { - goto end; - } - - while ((switch_fp_read_dline(fd, &line_buf, &llen))) { - char *p; - char *type = line_buf; - - if (*line_buf == '#') { - continue; - } - - if ((p = strchr(line_buf, '\r')) || (p = strchr(line_buf, '\n'))) { - *p = '\0'; - } - - if ((p = strchr(type, '\t')) || (p = strchr(type, ' '))) { - *p++ = '\0'; - - while (*p == ' ' || *p == '\t') { - p++; - } - - switch_core_mime_add_type(type, p); - } - - } - - switch_safe_free(line_buf); - - if (fd) { - fclose(fd); - fd = NULL; - } - - end: - - switch_safe_free(mime_path); - -} - -SWITCH_DECLARE(void) switch_core_setrlimits(void) -{ -#ifdef HAVE_SETRLIMIT - struct rlimit rlp; - - /* - Setting the stack size on FreeBSD results in an instant crash. - - If anyone knows how to fix this, - feel free to submit a patch to http://jira.freeswitch.org - */ - -#ifndef __FreeBSD__ - memset(&rlp, 0, sizeof(rlp)); - rlp.rlim_cur = SWITCH_THREAD_STACKSIZE; - rlp.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE; - setrlimit(RLIMIT_STACK, &rlp); -#endif - - memset(&rlp, 0, sizeof(rlp)); - rlp.rlim_cur = 999999; - rlp.rlim_max = 999999; - setrlimit(RLIMIT_NOFILE, &rlp); - - memset(&rlp, 0, sizeof(rlp)); - rlp.rlim_cur = RLIM_INFINITY; - rlp.rlim_max = RLIM_INFINITY; - - setrlimit(RLIMIT_CPU, &rlp); - setrlimit(RLIMIT_DATA, &rlp); - setrlimit(RLIMIT_FSIZE, &rlp); -#ifdef RLIMIT_NPROC - setrlimit(RLIMIT_NPROC, &rlp); -#endif -#ifdef RLIMIT_RTPRIO - setrlimit(RLIMIT_RTPRIO, &rlp); -#endif - -#if !defined(__OpenBSD__) && !defined(__NetBSD__) - setrlimit(RLIMIT_AS, &rlp); -#endif -#endif - return; -} - -typedef struct { - switch_memory_pool_t *pool; - switch_hash_t *hash; -} switch_ip_list_t; - -static switch_ip_list_t IP_LIST = { 0 }; - -SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token) -{ - switch_network_list_t *list; - ip_t ip, mask, net; - uint32_t bits; - char *ipv6 = strchr(ip_str,':'); - switch_bool_t ok = SWITCH_FALSE; - - switch_mutex_lock(runtime.global_mutex); - if (ipv6) { - switch_inet_pton(AF_INET6, ip_str, &ip); - } else { - switch_inet_pton(AF_INET, ip_str, &ip); - ip.v4 = htonl(ip.v4); - } - - if ((list = switch_core_hash_find(IP_LIST.hash, list_name))) { - if (ipv6) { - ok = switch_network_list_validate_ip6_token(list, ip, token); - } else { - ok = switch_network_list_validate_ip_token(list, ip.v4, token); - } - } else if (strchr(list_name, '/')) { - if (strchr(list_name, ',')) { - char *list_name_dup = strdup(list_name); - char *argv[32]; - int argc; - - switch_assert(list_name_dup); - - if ((argc = switch_separate_string(list_name_dup, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) { - int i; - for (i = 0; i < argc; i++) { - switch_parse_cidr(argv[i], &net, &mask, &bits); - if (ipv6) { - if ((ok = switch_testv6_subnet(ip, net, mask))){ - break; - } - } else { - if ((ok = switch_test_subnet(ip.v4, net.v4, mask.v4))) { - break; - } - } - } - } - free(list_name_dup); - } else { - switch_parse_cidr(list_name, &net, &mask, &bits); - ok = switch_test_subnet(ip.v4, net.v4, mask.v4); - } - } - switch_mutex_unlock(runtime.global_mutex); - - return ok; -} - - -SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload) -{ - switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, x_node = NULL, cfg = NULL; - switch_network_list_t *rfc_list, *list; - char guess_ip[16] = ""; - int mask = 0; - char guess_mask[16] = ""; - char *tmp_name; - struct in_addr in; - - switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET); - in.s_addr = mask; - switch_set_string(guess_mask, inet_ntoa(in)); - - switch_mutex_lock(runtime.global_mutex); - - if (IP_LIST.hash) { - switch_core_hash_destroy(&IP_LIST.hash); - } - - if (IP_LIST.pool) { - switch_core_destroy_memory_pool(&IP_LIST.pool); - } - - memset(&IP_LIST, 0, sizeof(IP_LIST)); - switch_core_new_memory_pool(&IP_LIST.pool); - switch_core_hash_init(&IP_LIST.hash, IP_LIST.pool); - - - tmp_name = "rfc1918.auto"; - switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); - switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE); - switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE); - switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE); - switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); - - tmp_name = "wan.auto"; - switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name); - switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_FALSE); - switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_FALSE); - switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_FALSE); - switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); - - tmp_name = "nat.auto"; - switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); - if (switch_network_list_add_host_mask(rfc_list, guess_ip, guess_mask, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s/%s (deny) to list %s\n", guess_ip, guess_mask, tmp_name); - } - switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE); - switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE); - switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE); - switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); - - tmp_name = "loopback.auto"; - switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); - switch_network_list_add_cidr(rfc_list, "127.0.0.0/8", SWITCH_TRUE); - switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); - - tmp_name = "localnet.auto"; - switch_network_list_create(&list, tmp_name, SWITCH_FALSE, IP_LIST.pool); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); - - if (switch_network_list_add_host_mask(list, guess_ip, guess_mask, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s/%s (allow) to list %s\n", guess_ip, guess_mask, tmp_name); - } - switch_core_hash_insert(IP_LIST.hash, tmp_name, list); - - - if ((xml = switch_xml_open_cfg("acl.conf", &cfg, NULL))) { - if ((x_lists = switch_xml_child(cfg, "network-lists"))) { - for (x_list = switch_xml_child(x_lists, "list"); x_list; x_list = x_list->next) { - const char *name = switch_xml_attr(x_list, "name"); - const char *dft = switch_xml_attr(x_list, "default"); - switch_bool_t default_type = SWITCH_TRUE; - - if (zstr(name)) { - continue; - } - - if (dft) { - default_type = switch_true(dft); - } - - if (switch_network_list_create(&list, name, default_type, IP_LIST.pool) != SWITCH_STATUS_SUCCESS) { - abort(); - } - - if (reload) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny"); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny"); - } - - - for (x_node = switch_xml_child(x_list, "node"); x_node; x_node = x_node->next) { - const char *cidr = NULL, *host = NULL, *mask = NULL, *domain = NULL; - switch_bool_t ok = default_type; - const char *type = switch_xml_attr(x_node, "type"); - - if (type) { - ok = switch_true(type); - } - - cidr = switch_xml_attr(x_node, "cidr"); - host = switch_xml_attr(x_node, "host"); - mask = switch_xml_attr(x_node, "mask"); - domain = switch_xml_attr(x_node, "domain"); - - if (domain) { - switch_event_t *my_params = NULL; - switch_xml_t x_domain, xml_root; - switch_xml_t gt, gts, ut, uts; - - switch_event_create(&my_params, SWITCH_EVENT_GENERAL); - switch_assert(my_params); - switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "domain", domain); - switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "purpose", "network-list"); - - if (switch_xml_locate_domain(domain, my_params, &xml_root, &x_domain) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate domain %s\n", domain); - switch_event_destroy(&my_params); - continue; - } - - switch_event_destroy(&my_params); - - for (ut = switch_xml_child(x_domain, "user"); ut; ut = ut->next) { - const char *user_cidr = switch_xml_attr(ut, "cidr"); - const char *id = switch_xml_attr(ut, "id"); - - if (id && user_cidr) { - char *token = switch_mprintf("%s@%s", id, domain); - switch_assert(token); - switch_network_list_add_cidr_token(list, user_cidr, ok, token); - free(token); - } - } - - for (gts = switch_xml_child(x_domain, "groups"); gts; gts = gts->next) { - for (gt = switch_xml_child(gts, "group"); gt; gt = gt->next) { - for (uts = switch_xml_child(gt, "users"); uts; uts = uts->next) { - for (ut = switch_xml_child(uts, "user"); ut; ut = ut->next) { - const char *user_cidr = switch_xml_attr(ut, "cidr"); - const char *id = switch_xml_attr(ut, "id"); - - if (id && user_cidr) { - char *token = switch_mprintf("%s@%s", id, domain); - switch_assert(token); - switch_network_list_add_cidr_token(list, user_cidr, ok, token); - free(token); - } - } - } - } - } - - switch_xml_free(xml_root); - } else if (cidr) { - if (switch_network_list_add_cidr(list, cidr, ok) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, - "Error Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name); - } - } else if (host && mask) { - if (switch_network_list_add_host_mask(list, host, mask, ok) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, - "Adding %s/%s (%s) to list %s\n", host, mask, ok ? "allow" : "deny", name); - } - } - - switch_core_hash_insert(IP_LIST.hash, name, list); - } - } - } - - switch_xml_free(xml); - } - - switch_mutex_unlock(runtime.global_mutex); -} - -SWITCH_DECLARE(uint32_t) switch_core_max_dtmf_duration(uint32_t duration) -{ - if (duration) { - if (duration > SWITCH_MAX_DTMF_DURATION) { - duration = SWITCH_MAX_DTMF_DURATION; - } - if (duration < SWITCH_MIN_DTMF_DURATION) { - duration = SWITCH_MIN_DTMF_DURATION; - } - runtime.max_dtmf_duration = duration; - if (duration < runtime.min_dtmf_duration) { - runtime.min_dtmf_duration = duration; - } - } - return runtime.max_dtmf_duration; -} - -SWITCH_DECLARE(uint32_t) switch_core_default_dtmf_duration(uint32_t duration) -{ - if (duration) { - if (duration < SWITCH_MIN_DTMF_DURATION) { - duration = SWITCH_MIN_DTMF_DURATION; - } - if (duration > SWITCH_MAX_DTMF_DURATION) { - duration = SWITCH_MAX_DTMF_DURATION; - } - runtime.default_dtmf_duration = duration; - - if (duration < runtime.min_dtmf_duration) { - runtime.min_dtmf_duration = duration; - } - - if (duration > runtime.max_dtmf_duration) { - runtime.max_dtmf_duration = duration; - } - - } - return runtime.default_dtmf_duration; -} - -SWITCH_DECLARE(uint32_t) switch_core_min_dtmf_duration(uint32_t duration) -{ - if (duration) { - if (duration < SWITCH_MIN_DTMF_DURATION) { - duration = SWITCH_MIN_DTMF_DURATION; - } - if (duration > SWITCH_MAX_DTMF_DURATION) { - duration = SWITCH_MAX_DTMF_DURATION; - } - - runtime.min_dtmf_duration = duration; - - if (duration > runtime.max_dtmf_duration) { - runtime.max_dtmf_duration = duration; - } - } - return runtime.min_dtmf_duration; -} - -SWITCH_DECLARE(switch_status_t) switch_core_thread_set_cpu_affinity(int cpu) -{ - switch_status_t status = SWITCH_STATUS_FALSE; - - if (cpu > -1) { - -#ifdef HAVE_CPU_SET_MACROS - cpu_set_t set; - - CPU_ZERO(&set); - CPU_SET(cpu, &set); - - if (!sched_setaffinity(0, sizeof(set), &set)) { - status = SWITCH_STATUS_SUCCESS; - } - -#else -#if WIN32 - if (SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR) cpu)) { - status = SWITCH_STATUS_SUCCESS; - } -#endif -#endif - } - - return status; -} - - -static void switch_core_set_serial(void) -{ - char buf[13] = ""; - char path[256]; - - int fd = -1, write_fd = -1; - switch_ssize_t bytes = 0; - - switch_snprintf(path, sizeof(path), "%s%sfreeswitch.serial", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR); - - - if ((fd = open(path, O_RDONLY, 0)) < 0) { - char *ip = switch_core_get_variable_dup("local_ip_v4"); - uint32_t ipi = 0; - switch_byte_t *byte; - int i = 0; - - if (ip) { - switch_inet_pton(AF_INET, ip, &ipi); - free(ip); - ip = NULL; - } - - - byte = (switch_byte_t *) & ipi; - - for (i = 0; i < 8; i += 2) { - switch_snprintf(buf + i, sizeof(buf) - i, "%0.2x", *byte); - byte++; - } - - switch_stun_random_string(buf + 8, 4, "0123456789abcdef"); - - if ((write_fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) >= 0) { - bytes = write(write_fd, buf, sizeof(buf)); - bytes++; - close(write_fd); - write_fd = -1; - } - } else { - bytes = read(fd, buf, sizeof(buf)); - close(fd); - fd = -1; - } - - switch_core_set_variable("switch_serial", buf); -} - - -SWITCH_DECLARE(int) switch_core_test_flag(int flag) -{ - return switch_test_flag((&runtime), flag); -} - - -SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switch_bool_t console, const char **err) -{ - switch_uuid_t uuid; - char guess_ip[256]; - int mask = 0; - struct in_addr in; - - - if (runtime.runlevel > 0) { - /* one per customer */ - return SWITCH_STATUS_SUCCESS; - } - - memset(&runtime, 0, sizeof(runtime)); - gethostname(runtime.hostname, sizeof(runtime.hostname)); - - runtime.max_db_handles = 50; - runtime.db_handle_timeout = 5000000; - - runtime.runlevel++; - runtime.dummy_cng_frame.data = runtime.dummy_data; - runtime.dummy_cng_frame.datalen = sizeof(runtime.dummy_data); - runtime.dummy_cng_frame.buflen = sizeof(runtime.dummy_data); - runtime.dbname = "core"; - switch_set_flag((&runtime.dummy_cng_frame), SFF_CNG); - switch_set_flag((&runtime), SCF_AUTO_SCHEMAS); - switch_set_flag((&runtime), SCF_CLEAR_SQL); - switch_set_flag((&runtime), SCF_API_EXPANSION); - switch_set_flag((&runtime), SCF_SESSION_THREAD_POOL); -#ifdef WIN32 - switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); -#endif - switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); - runtime.hard_log_level = SWITCH_LOG_DEBUG; - runtime.mailer_app = "sendmail"; - runtime.mailer_app_args = "-t"; - runtime.max_dtmf_duration = SWITCH_MAX_DTMF_DURATION; - runtime.default_dtmf_duration = SWITCH_DEFAULT_DTMF_DURATION; - runtime.min_dtmf_duration = SWITCH_MIN_DTMF_DURATION; - runtime.odbc_dbtype = DBTYPE_DEFAULT; - runtime.dbname = NULL; -#ifndef WIN32 - runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN); -#else - { - SYSTEM_INFO sysinfo; - GetSystemInfo( &sysinfo ); - runtime.cpu_count = sysinfo.dwNumberOfProcessors; - } -#endif - - if (!runtime.cpu_count) runtime.cpu_count = 1; - - - /* INIT APR and Create the pool context */ - if (apr_initialize() != SWITCH_STATUS_SUCCESS) { - *err = "FATAL ERROR! Could not initialize APR\n"; - return SWITCH_STATUS_MEMERR; - } - - if (!(runtime.memory_pool = switch_core_memory_init())) { - *err = "FATAL ERROR! Could not allocate memory pool\n"; - return SWITCH_STATUS_MEMERR; - } - switch_assert(runtime.memory_pool != NULL); - - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.base_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.mod_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.conf_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.log_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.run_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.db_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.script_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.htdocs_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.recordings_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.sounds_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.temp_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - - - switch_mutex_init(&runtime.uuid_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); - - switch_mutex_init(&runtime.throttle_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); - - switch_mutex_init(&runtime.session_hash_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); - switch_mutex_init(&runtime.global_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); - - switch_thread_rwlock_create(&runtime.global_var_rwlock, runtime.memory_pool); - switch_core_set_globals(); - switch_core_session_init(runtime.memory_pool); - switch_event_create_plain(&runtime.global_vars, SWITCH_EVENT_CHANNEL_DATA); - switch_core_hash_init(&runtime.mime_types, runtime.memory_pool); - switch_core_hash_init_case(&runtime.ptimes, runtime.memory_pool, SWITCH_FALSE); - load_mime_types(); - runtime.flags |= flags; - runtime.sps_total = 30; - - *err = NULL; - - if (console) { - runtime.console = stdout; - } - - switch_ssl_init_ssl_locks(); - switch_curl_init(); - - switch_core_set_variable("hostname", runtime.hostname); - switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET); - switch_core_set_variable("local_ip_v4", guess_ip); - in.s_addr = mask; - switch_core_set_variable("local_mask_v4", inet_ntoa(in)); - - - switch_find_local_ip(guess_ip, sizeof(guess_ip), NULL, AF_INET6); - switch_core_set_variable("local_ip_v6", guess_ip); - switch_core_set_variable("base_dir", SWITCH_GLOBAL_dirs.base_dir); - switch_core_set_variable("recordings_dir", SWITCH_GLOBAL_dirs.recordings_dir); - switch_core_set_variable("sound_prefix", SWITCH_GLOBAL_dirs.sounds_dir); - switch_core_set_variable("sounds_dir", SWITCH_GLOBAL_dirs.sounds_dir); - switch_core_set_serial(); - - switch_console_init(runtime.memory_pool); - switch_event_init(runtime.memory_pool); - - if (switch_xml_init(runtime.memory_pool, err) != SWITCH_STATUS_SUCCESS) { - apr_terminate(); - return SWITCH_STATUS_MEMERR; - } - - if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) { - switch_nat_init(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_NAT_MAPPING)); - } - - switch_log_init(runtime.memory_pool, runtime.colorize_console); - - if (flags & SCF_MINIMAL) return SWITCH_STATUS_SUCCESS; - - runtime.tipping_point = 0; - runtime.timer_affinity = -1; - runtime.microseconds_per_tick = 20000; - - switch_load_core_config("switch.conf"); - - switch_core_state_machine_init(runtime.memory_pool); - - if (switch_core_sqldb_start(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_SQL) ? SWITCH_TRUE : SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { - *err = "Error activating database"; - return SWITCH_STATUS_FALSE; - } - - switch_scheduler_task_thread_start(); - - switch_nat_late_init(); - - switch_rtp_init(runtime.memory_pool); - - runtime.running = 1; - runtime.initiated = switch_time_now(); - runtime.mono_initiated = switch_mono_micro_time_now(); - - switch_scheduler_add_task(switch_epoch_time_now(NULL), heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL); - - switch_scheduler_add_task(switch_epoch_time_now(NULL), check_ip_callback, "check_ip", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL | SSHF_OWN_THREAD); - - switch_uuid_get(&uuid); - switch_uuid_format(runtime.uuid_str, &uuid); - switch_core_set_variable("core_uuid", runtime.uuid_str); - - - return SWITCH_STATUS_SUCCESS; -} - - -#ifndef WIN32 -static void handle_SIGCHLD(int sig) -{ - int status = 0; - - wait(&status); - return; -} -#endif - -#ifdef TRAP_BUS -static void handle_SIGBUS(int sig) -{ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Sig BUS!\n"); - return; -} -#endif - -static void handle_SIGHUP(int sig) -{ - if (sig) { - switch_event_t *event; - - if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Trapped-Signal", "HUP"); - switch_event_fire(&event); - } - } - return; -} - - -SWITCH_DECLARE(uint32_t) switch_default_ptime(const char *name, uint32_t number) -{ - uint32_t *p; - - if ((p = switch_core_hash_find(runtime.ptimes, name))) { - return *p; - } - - return 20; -} - -static uint32_t d_30 = 30; - -static void switch_load_core_config(const char *file) -{ - switch_xml_t xml = NULL, cfg = NULL; - - switch_core_hash_insert(runtime.ptimes, "ilbc", &d_30); - switch_core_hash_insert(runtime.ptimes, "G723", &d_30); - - if ((xml = switch_xml_open_cfg(file, &cfg, NULL))) { - switch_xml_t settings, param; - - if ((settings = switch_xml_child(cfg, "default-ptimes"))) { - for (param = switch_xml_child(settings, "codec"); param; param = param->next) { - const char *var = switch_xml_attr_soft(param, "name"); - const char *val = switch_xml_attr_soft(param, "ptime"); - - if (!zstr(var) && !zstr(val)) { - uint32_t *p; - uint32_t v = switch_atoul(val); - - if (!strcasecmp(var, "G723") || !strcasecmp(var, "iLBC")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding %s, defaults cannot be changed\n", var); - continue; - } - - if (v == 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding %s, invalid ptime\n", var); - continue; - } - - p = switch_core_alloc(runtime.memory_pool, sizeof(*p)); - *p = v; - switch_core_hash_insert(runtime.ptimes, var, p); - } - - } - } - - if ((settings = switch_xml_child(cfg, "settings"))) { - for (param = switch_xml_child(settings, "param"); param; param = param->next) { - const char *var = switch_xml_attr_soft(param, "name"); - const char *val = switch_xml_attr_soft(param, "value"); - - if (!strcasecmp(var, "loglevel")) { - int level; - if (*val > 47 && *val < 58) { - level = atoi(val); - } else { - level = switch_log_str2level(val); - } - - if (level != SWITCH_LOG_INVALID) { - switch_core_session_ctl(SCSC_LOGLEVEL, &level); - } -#ifdef HAVE_SETRLIMIT - } else if (!strcasecmp(var, "dump-cores") && switch_true(val)) { - struct rlimit rlp; - memset(&rlp, 0, sizeof(rlp)); - rlp.rlim_cur = RLIM_INFINITY; - rlp.rlim_max = RLIM_INFINITY; - setrlimit(RLIMIT_CORE, &rlp); -#endif - } else if (!strcasecmp(var, "debug-level")) { - int tmp = atoi(val); - if (tmp > -1 && tmp < 11) { - switch_core_session_ctl(SCSC_DEBUG_LEVEL, &tmp); - } - } else if (!strcasecmp(var, "max-db-handles")) { - long tmp = atol(val); - - if (tmp > 4 && tmp < 5001) { - runtime.max_db_handles = (uint32_t) tmp; - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "max-db-handles must be between 5 and 5000\n"); - } - } else if (!strcasecmp(var, "db-handle-timeout")) { - long tmp = atol(val); - - if (tmp > 0 && tmp < 5001) { - runtime.db_handle_timeout = (uint32_t) tmp * 1000000; - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "db-handle-timeout must be between 1 and 5000\n"); - } - - } else if (!strcasecmp(var, "multiple-registrations")) { - runtime.multiple_registrations = switch_true(val); - } else if (!strcasecmp(var, "auto-create-schemas")) { - if (switch_true(val)) { - switch_set_flag((&runtime), SCF_AUTO_SCHEMAS); - } else { - switch_clear_flag((&runtime), SCF_AUTO_SCHEMAS); - } - } else if (!strcasecmp(var, "session-thread-pool")) { - if (switch_true(val)) { - switch_set_flag((&runtime), SCF_SESSION_THREAD_POOL); - } else { - switch_clear_flag((&runtime), SCF_SESSION_THREAD_POOL); - } - } else if (!strcasecmp(var, "auto-clear-sql")) { - if (switch_true(val)) { - switch_set_flag((&runtime), SCF_CLEAR_SQL); - } else { - switch_clear_flag((&runtime), SCF_CLEAR_SQL); - } - } else if (!strcasecmp(var, "api-expansion")) { - if (switch_true(val)) { - switch_set_flag((&runtime), SCF_API_EXPANSION); - } else { - switch_clear_flag((&runtime), SCF_API_EXPANSION); - } - } else if (!strcasecmp(var, "enable-early-hangup") && switch_true(val)) { - switch_set_flag((&runtime), SCF_EARLY_HANGUP); - } else if (!strcasecmp(var, "colorize-console") && switch_true(val)) { - runtime.colorize_console = SWITCH_TRUE; - } else if (!strcasecmp(var, "core-db-pre-trans-execute") && !zstr(val)) { - runtime.core_db_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val); - } else if (!strcasecmp(var, "core-db-post-trans-execute") && !zstr(val)) { - runtime.core_db_post_trans_execute = switch_core_strdup(runtime.memory_pool, val); - } else if (!strcasecmp(var, "core-db-inner-pre-trans-execute") && !zstr(val)) { - runtime.core_db_inner_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val); - } else if (!strcasecmp(var, "core-db-inner-post-trans-execute") && !zstr(val)) { - runtime.core_db_inner_post_trans_execute = switch_core_strdup(runtime.memory_pool, val); - } else if (!strcasecmp(var, "mailer-app") && !zstr(val)) { - runtime.mailer_app = switch_core_strdup(runtime.memory_pool, val); - } else if (!strcasecmp(var, "mailer-app-args") && val) { - runtime.mailer_app_args = switch_core_strdup(runtime.memory_pool, val); - } else if (!strcasecmp(var, "sessions-per-second") && !zstr(val)) { - switch_core_sessions_per_second(atoi(val)); - } else if (!strcasecmp(var, "max-dtmf-duration") && !zstr(val)) { - int tmp = atoi(val); - if (tmp > 0) { - switch_core_max_dtmf_duration((uint32_t) tmp); - } - } else if (!strcasecmp(var, "min-dtmf-duration") && !zstr(val)) { - int tmp = atoi(val); - if (tmp > 0) { - switch_core_min_dtmf_duration((uint32_t) tmp); - } - } else if (!strcasecmp(var, "default-dtmf-duration") && !zstr(val)) { - int tmp = atoi(val); - if (tmp > 0) { - switch_core_default_dtmf_duration((uint32_t) tmp); - } - } else if (!strcasecmp(var, "enable-use-system-time")) { - switch_time_set_use_system_time(switch_true(val)); - } else if (!strcasecmp(var, "enable-monotonic-timing")) { - switch_time_set_monotonic(switch_true(val)); - } else if (!strcasecmp(var, "enable-softtimer-timerfd")) { - switch_time_set_timerfd(switch_true(val)); - } else if (!strcasecmp(var, "enable-clock-nanosleep")) { - switch_time_set_nanosleep(switch_true(val)); - } else if (!strcasecmp(var, "enable-cond-yield")) { - switch_time_set_cond_yield(switch_true(val)); - } else if (!strcasecmp(var, "enable-timer-matrix")) { - switch_time_set_matrix(switch_true(val)); - } else if (!strcasecmp(var, "max-sessions") && !zstr(val)) { - switch_core_session_limit(atoi(val)); - } else if (!strcasecmp(var, "verbose-channel-events") && !zstr(val)) { - int v = switch_true(val); - if (v) { - switch_set_flag((&runtime), SCF_VERBOSE_EVENTS); - } else { - switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS); - } - } else if (!strcasecmp(var, "threaded-system-exec") && !zstr(val)) { -#ifdef WIN32 - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "threaded-system-exec is not implemented on this platform\n"); -#else - int v = switch_true(val); - if (v) { - switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); - } else { - switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); - } -#endif - } else if (!strcasecmp(var, "min-idle-cpu") && !zstr(val)) { - switch_core_min_idle_cpu(atof(val)); - } else if (!strcasecmp(var, "tipping-point") && !zstr(val)) { - runtime.tipping_point = atoi(val); - } else if (!strcasecmp(var, "initial-event-threads") && !zstr(val)) { - int tmp = atoi(val); - - - if (tmp > runtime.cpu_count / 2) { - tmp = runtime.cpu_count / 2; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "This value cannot be higher than %d so setting it to that value\n", - runtime.cpu_count / 2); - } - - if (tmp < 1) { - tmp = 1; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "This value cannot be lower than 1 so setting it to that level\n"); - } - - switch_event_launch_dispatch_threads(tmp); - - } else if (!strcasecmp(var, "1ms-timer") && switch_true(val)) { - runtime.microseconds_per_tick = 1000; - } else if (!strcasecmp(var, "timer-affinity") && !zstr(val)) { - if (!strcasecmp(val, "disabled")) { - runtime.timer_affinity = -1; - } else { - runtime.timer_affinity = atoi(val); - } - } else if (!strcasecmp(var, "rtp-start-port") && !zstr(val)) { - switch_rtp_set_start_port((switch_port_t) atoi(val)); - } else if (!strcasecmp(var, "rtp-end-port") && !zstr(val)) { - switch_rtp_set_end_port((switch_port_t) atoi(val)); - } else if (!strcasecmp(var, "core-db-name") && !zstr(val)) { - runtime.dbname = switch_core_strdup(runtime.memory_pool, val); - } else if (!strcasecmp(var, "core-db-dsn") && !zstr(val)) { - if (switch_odbc_available() || switch_pgsql_available()) { - runtime.odbc_dsn = switch_core_strdup(runtime.memory_pool, val); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC AND PGSQL ARE NOT AVAILABLE!\n"); - } - } else if (!strcasecmp(var, "core-non-sqlite-db-required") && !zstr(val)) { - switch_set_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ); - } else if (!strcasecmp(var, "core-dbtype") && !zstr(val)) { - if (!strcasecmp(val, "MSSQL")) { - runtime.odbc_dbtype = DBTYPE_MSSQL; - } else { - runtime.odbc_dbtype = DBTYPE_DEFAULT; - } -#ifdef ENABLE_ZRTP - } else if (!strcasecmp(var, "rtp-enable-zrtp")) { - switch_core_set_variable("zrtp_enabled", val); -#endif - } else if (!strcasecmp(var, "switchname") && !zstr(val)) { - runtime.switchname = switch_core_strdup(runtime.memory_pool, val); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Set switchname to %s\n", runtime.switchname); - } - } - } - - if ((settings = switch_xml_child(cfg, "variables"))) { - for (param = switch_xml_child(settings, "variable"); param; param = param->next) { - const char *var = switch_xml_attr_soft(param, "name"); - const char *val = switch_xml_attr_soft(param, "value"); - if (var && val) { - switch_core_set_variable(var, val); - } - } - } - - switch_xml_free(xml); - } - - -} - -SWITCH_DECLARE(const char *) switch_core_banner(void) -{ - - return ("\n" - ".=============================================================.\n" - "| _____ ______ _____ _____ ____ _ _ |\n" - "| | ___| __ ___ ___/ ___\\ \\ / /_ _|_ _/ ___| | | | |\n" - "| | |_ | '__/ _ \\/ _ \\___ \\\\ \\ /\\ / / | | | || | | |_| | |\n" - "| | _|| | | __/ __/___) |\\ V V / | | | || |___| _ | |\n" - "| |_| |_| \\___|\\___|____/ \\_/\\_/ |___| |_| \\____|_| |_| |\n" - "| |\n" - ".=============================================================." - "\n" - - "| Anthony Minessale II, Michael Jerris, Brian West, Others |\n" - "| FreeSWITCH (http://www.freeswitch.org) |\n" - "| Paypal Donations Appreciated: paypal@freeswitch.org |\n" - "| Brought to you by ClueCon http://www.cluecon.com/ |\n" - ".=============================================================.\n" - "\n"); -} - - -SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t flags, switch_bool_t console, const char **err) -{ - switch_event_t *event; - char *cmd; - int x = 0; - const char *use = NULL; -#include "cc.h" - - - if (switch_core_init(flags, console, err) != SWITCH_STATUS_SUCCESS) { - return SWITCH_STATUS_GENERR; - } - - if (runtime.runlevel > 1) { - /* one per customer */ - return SWITCH_STATUS_SUCCESS; - } - - runtime.runlevel++; - - switch_core_set_signal_handlers(); - switch_load_network_lists(SWITCH_FALSE); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Bringing up environment.\n"); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Loading Modules.\n"); - if (switch_loadable_module_init(SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) { - *err = "Cannot load modules"; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error: %s\n", *err); - return SWITCH_STATUS_GENERR; - } - - switch_load_network_lists(SWITCH_FALSE); - - switch_load_core_config("post_load_switch.conf"); - - switch_core_set_signal_handlers(); - - if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready"); - switch_event_fire(&event); - } - - switch_core_screen_size(&x, NULL); - - use = (x > 100) ? cc : cc_s; - -#ifdef WIN32 - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s\n\n", switch_core_banner(), use); -#else - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s%s%s%s%s\n\n", - SWITCH_SEQ_DEFAULT_COLOR, - SWITCH_SEQ_FYELLOW, SWITCH_SEQ_BBLUE, - switch_core_banner(), - use, SWITCH_SEQ_DEFAULT_COLOR); - -#endif - - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, - "\nFreeSWITCH Version %s (%s)\n\nFreeSWITCH Started\nMax Sessions [%u]\nSession Rate [%d]\nSQL [%s]\n", - SWITCH_VERSION_FULL, SWITCH_VERSION_REVISION_HUMAN, - switch_core_session_limit(0), - switch_core_sessions_per_second(0), switch_test_flag((&runtime), SCF_USE_SQL) ? "Enabled" : "Disabled"); - - - if (x < 160) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\n[This app Best viewed at 160x60 or more..]\n"); - } - - switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS); - - if ((cmd = switch_core_get_variable_dup("api_on_startup"))) { - switch_stream_handle_t stream = { 0 }; - SWITCH_STANDARD_STREAM(stream); - switch_console_execute(cmd, 0, &stream); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Startup command [%s] executed. Output:\n%s\n", cmd, (char *)stream.data); - free(stream.data); - free(cmd); - } - - return SWITCH_STATUS_SUCCESS; - -} - -SWITCH_DECLARE(void) switch_core_measure_time(switch_time_t total_ms, switch_core_time_duration_t *duration) -{ - switch_time_t temp = total_ms / 1000; - memset(duration, 0, sizeof(*duration)); - duration->mms = (uint32_t) (total_ms % 1000); - duration->ms = (uint32_t) (temp % 1000); - temp = temp / 1000; - duration->sec = (uint32_t) (temp % 60); - temp = temp / 60; - duration->min = (uint32_t) (temp % 60); - temp = temp / 60; - duration->hr = (uint32_t) (temp % 24); - temp = temp / 24; - duration->day = (uint32_t) (temp % 365); - duration->yr = (uint32_t) (temp / 365); -} - -SWITCH_DECLARE(switch_time_t) switch_core_uptime(void) -{ - return switch_mono_micro_time_now() - runtime.mono_initiated; -} - - -#ifdef _MSC_VER -static void win_shutdown(void) -{ - - HANDLE shutdown_event; - char path[512]; - /* for windows we need the event to signal for shutting down a background FreeSWITCH */ - snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid()); - - /* open the event so we can signal it */ - shutdown_event = OpenEvent(EVENT_MODIFY_STATE, FALSE, path); - - if (shutdown_event) { - /* signal the event to shutdown */ - SetEvent(shutdown_event); - /* cleanup */ - CloseHandle(shutdown_event); - } -} -#endif - -SWITCH_DECLARE(void) switch_core_set_signal_handlers(void) -{ - /* set signal handlers */ - signal(SIGINT, SIG_IGN); -#ifndef WIN32 - if (switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC)) { - signal(SIGCHLD, SIG_DFL); - } else { - signal(SIGCHLD, handle_SIGCHLD); - } -#endif -#ifdef SIGPIPE - signal(SIGPIPE, SIG_IGN); -#endif -#ifdef SIGQUIT - signal(SIGQUIT, SIG_IGN); -#endif -#ifdef SIGPOLL - signal(SIGPOLL, SIG_IGN); -#endif -#ifdef SIGIO - signal(SIGIO, SIG_IGN); -#endif -#ifdef TRAP_BUS - signal(SIGBUS, handle_SIGBUS); -#endif -#ifdef SIGUSR1 - signal(SIGUSR1, handle_SIGHUP); -#endif - signal(SIGHUP, handle_SIGHUP); -} - -SWITCH_DECLARE(uint32_t) switch_core_debug_level(void) -{ - return runtime.debug_level; -} - - -SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, void *val) -{ - int *intval = (int *) val; - int oldintval = 0, newintval = 0; - - if (intval) { - oldintval = *intval; - } - - if (switch_test_flag((&runtime), SCF_SHUTTING_DOWN)) { - return -1; - } - - switch (cmd) { - case SCSC_RECOVER: - { - char *arg = (char *) val; - char *tech = NULL, *prof = NULL; - int r, flush = 0; - - if (!zstr(arg)) { - tech = strdup(arg); - - if ((prof = strchr(tech, ':'))) { - *prof++ = '\0'; - } - - if (!strcasecmp(tech, "flush")) { - flush++; - - if (prof) { - tech = prof; - if ((prof = strchr(tech, ':'))) { - *prof++ = '\0'; - } - } - } - - } - - if (flush) { - switch_core_recovery_flush(tech, prof); - r = -1; - } else { - r = switch_core_recovery_recover(tech, prof); - } - - switch_safe_free(tech); - return r; - - } - break; - case SCSC_DEBUG_SQL: - { - if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) { - switch_clear_flag((&runtime), SCF_DEBUG_SQL); - newintval = 0; - } else { - switch_set_flag((&runtime), SCF_DEBUG_SQL); - newintval = 1; - } - } - break; - case SCSC_VERBOSE_EVENTS: - if (intval) { - if (oldintval > -1) { - if (oldintval) { - switch_set_flag((&runtime), SCF_VERBOSE_EVENTS); - } else { - switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS); - } - } - newintval = switch_test_flag((&runtime), SCF_VERBOSE_EVENTS); - } - break; - case SCSC_API_EXPANSION: - if (intval) { - if (oldintval > -1) { - if (oldintval) { - switch_set_flag((&runtime), SCF_API_EXPANSION); - } else { - switch_clear_flag((&runtime), SCF_API_EXPANSION); - } - } - newintval = switch_test_flag((&runtime), SCF_API_EXPANSION); - } - break; - case SCSC_THREADED_SYSTEM_EXEC: - if (intval) { - if (oldintval > -1) { - if (oldintval) { - switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); - } else { - switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); - } - } - newintval = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); - } - break; - case SCSC_CALIBRATE_CLOCK: - switch_time_calibrate_clock(); - break; - case SCSC_FLUSH_DB_HANDLES: - switch_cache_db_flush_handles(); - break; - case SCSC_SEND_SIGHUP: - handle_SIGHUP(1); - break; - case SCSC_SYNC_CLOCK: - switch_time_sync(); - newintval = 0; - break; - case SCSC_SYNC_CLOCK_WHEN_IDLE: - newintval = switch_core_session_sync_clock(); - break; - case SCSC_SQL: - if (oldintval) { - switch_core_sqldb_resume(); - } else { - switch_core_sqldb_pause(); - } - break; - case SCSC_PAUSE_ALL: - if (oldintval) { - switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); - } else { - switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS); - } - break; - case SCSC_PAUSE_INBOUND: - if (oldintval) { - switch_set_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS); - } else { - switch_clear_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS); - } - break; - case SCSC_PAUSE_OUTBOUND: - if (oldintval) { - switch_set_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS); - } else { - switch_clear_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS); - } - break; - case SCSC_HUPALL: - switch_core_session_hupall(SWITCH_CAUSE_MANAGER_REQUEST); - break; - case SCSC_CANCEL_SHUTDOWN: - switch_clear_flag((&runtime), SCF_SHUTDOWN_REQUESTED); - break; - case SCSC_SAVE_HISTORY: - switch_console_save_history(); - break; - case SCSC_CRASH: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Declinatio Mortuus Obfirmo!\n"); - switch_console_save_history(); - abort(); - break; - case SCSC_SHUTDOWN_NOW: - switch_console_save_history(); - exit(0); - break; - case SCSC_SHUTDOWN_ELEGANT: - case SCSC_SHUTDOWN_ASAP: - { - int x = 19; - uint32_t count; - - switch_set_flag((&runtime), SCF_SHUTDOWN_REQUESTED); - if (cmd == SCSC_SHUTDOWN_ASAP) { - switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); - } - - while (runtime.running && switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED) && (count = switch_core_session_count())) { - switch_yield(500000); - if (++x == 20) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, - "Shutdown in progress, %u session(s) remain.\nShutting down %s\n", - count, cmd == SCSC_SHUTDOWN_ASAP ? "ASAP" : "once there are no active calls."); - x = 0; - } - } - - if (switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED)) { - switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); -#ifdef _MSC_VER - win_shutdown(); -#endif - - if (oldintval) { - switch_set_flag((&runtime), SCF_RESTART); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Restarting\n"); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutting down\n"); -#ifdef _MSC_VER - fclose(stdin); -#endif - } - runtime.running = 0; - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutdown Cancelled\n"); - switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS); - } - } - break; - case SCSC_PAUSE_CHECK: - newintval = !!(switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS) == SCF_NO_NEW_SESSIONS); - break; - case SCSC_PAUSE_INBOUND_CHECK: - newintval = !!switch_test_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS); - break; - case SCSC_PAUSE_OUTBOUND_CHECK: - newintval = !!switch_test_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS); - break; - case SCSC_READY_CHECK: - newintval = switch_core_ready(); - break; - case SCSC_SHUTDOWN_CHECK: - newintval = !!switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED); - break; - case SCSC_SHUTDOWN: - -#ifdef _MSC_VER - win_shutdown(); -#endif - - if (oldintval) { - switch_set_flag((&runtime), SCF_RESTART); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Restarting\n"); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutting down\n"); -#ifdef _MSC_VER - fclose(stdin); -#endif - } - runtime.running = 0; - break; - case SCSC_CHECK_RUNNING: - newintval = runtime.running; - break; - case SCSC_LOGLEVEL: - if (oldintval > -1) { - runtime.hard_log_level = oldintval; - } - - if (runtime.hard_log_level > SWITCH_LOG_DEBUG) { - runtime.hard_log_level = SWITCH_LOG_DEBUG; - } - newintval = runtime.hard_log_level; - break; - case SCSC_DEBUG_LEVEL: - if (oldintval > -1) { - if (oldintval > 10) - newintval = 10; - runtime.debug_level = oldintval; - } - newintval = runtime.debug_level; - break; - case SCSC_MIN_IDLE_CPU: - { - double *dval = (double *) val; - if (dval) { - *dval = switch_core_min_idle_cpu(*dval); - } - intval = NULL; - } - break; - case SCSC_MAX_SESSIONS: - newintval = switch_core_session_limit(oldintval); - break; - case SCSC_LAST_SPS: - newintval = runtime.sps_last; - break; - case SCSC_MAX_DTMF_DURATION: - newintval = switch_core_max_dtmf_duration(oldintval); - break; - case SCSC_MIN_DTMF_DURATION: - newintval = switch_core_min_dtmf_duration(oldintval); - break; - case SCSC_DEFAULT_DTMF_DURATION: - newintval = switch_core_default_dtmf_duration(oldintval); - break; - case SCSC_SPS: - switch_mutex_lock(runtime.throttle_mutex); - if (oldintval > 0) { - runtime.sps_total = oldintval; - } - newintval = runtime.sps_total; - switch_mutex_unlock(runtime.throttle_mutex); - break; - - case SCSC_RECLAIM: - switch_core_memory_reclaim_all(); - newintval = 0; - break; - } - - if (intval) { - *intval = newintval; - } - - - return 0; -} - -SWITCH_DECLARE(switch_core_flag_t) switch_core_flags(void) -{ - return runtime.flags; -} - -SWITCH_DECLARE(switch_bool_t) switch_core_ready(void) -{ - return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS) == SCF_NO_NEW_SESSIONS) ? SWITCH_FALSE : SWITCH_TRUE; -} - -SWITCH_DECLARE(switch_bool_t) switch_core_ready_inbound(void) -{ - return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE; -} - -SWITCH_DECLARE(switch_bool_t) switch_core_ready_outbound(void) -{ - return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE; -} - -SWITCH_DECLARE(switch_status_t) switch_core_destroy(void) -{ - switch_event_t *event; - - if (switch_event_create(&event, SWITCH_EVENT_SHUTDOWN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Shutting Down"); - switch_event_fire(&event); - } - - switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); - switch_set_flag((&runtime), SCF_SHUTTING_DOWN); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "End existing sessions\n"); - switch_core_session_hupall(SWITCH_CAUSE_SYSTEM_SHUTDOWN); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Clean up modules.\n"); - - switch_loadable_module_shutdown(); - - switch_ssl_destroy_ssl_locks(); - - if (switch_test_flag((&runtime), SCF_USE_SQL)) { - switch_core_sqldb_stop(); - } - switch_scheduler_task_thread_stop(); - - switch_rtp_shutdown(); - - if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) { - switch_nat_shutdown(); - } - switch_xml_destroy(); - switch_core_session_uninit(); - switch_console_shutdown(); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Closing Event Engine.\n"); - switch_event_shutdown(); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n"); - switch_log_shutdown(); - - switch_core_unset_variables(); - switch_core_memory_stop(); - - if (runtime.console && runtime.console != stdout && runtime.console != stderr) { - fclose(runtime.console); - runtime.console = NULL; - } - - switch_safe_free(SWITCH_GLOBAL_dirs.base_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.mod_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.conf_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.log_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.db_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.script_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.htdocs_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.grammar_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.storage_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.recordings_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.sounds_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.run_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.temp_dir); - - switch_event_destroy(&runtime.global_vars); - switch_core_hash_destroy(&runtime.ptimes); - switch_core_hash_destroy(&runtime.mime_types); - - if (IP_LIST.hash) { - switch_core_hash_destroy(&IP_LIST.hash); - } - - if (IP_LIST.pool) { - switch_core_destroy_memory_pool(&IP_LIST.pool); - } - - if (runtime.memory_pool) { - apr_pool_destroy(runtime.memory_pool); - apr_terminate(); - } - - return switch_test_flag((&runtime), SCF_RESTART) ? SWITCH_STATUS_RESTART : SWITCH_STATUS_SUCCESS; -} - -SWITCH_DECLARE(switch_status_t) switch_core_management_exec(char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen) -{ - const switch_management_interface_t *ptr; - switch_status_t status = SWITCH_STATUS_FALSE; - - if ((ptr = switch_loadable_module_get_management_interface(relative_oid))) { - status = ptr->management_function(relative_oid, action, data, datalen); - } - - return status; -} - -SWITCH_DECLARE(void) switch_core_memory_reclaim_all(void) -{ - switch_core_memory_reclaim_logger(); - switch_core_memory_reclaim_events(); - switch_core_memory_reclaim(); -} - - -struct system_thread_handle { - const char *cmd; - switch_thread_cond_t *cond; - switch_mutex_t *mutex; - switch_memory_pool_t *pool; - int ret; - int *fds; -}; - -static void *SWITCH_THREAD_FUNC system_thread(switch_thread_t *thread, void *obj) -{ - struct system_thread_handle *sth = (struct system_thread_handle *) obj; - -#if 0 // if we are a luser we can never turn this back down, didn't we already set the stack size? -#if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__) - struct rlimit rlim; - - rlim.rlim_cur = SWITCH_SYSTEM_THREAD_STACKSIZE; - rlim.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE; - if (setrlimit(RLIMIT_STACK, &rlim) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno)); - } -#endif -#endif - - if (sth->fds) { - dup2(sth->fds[1], STDOUT_FILENO); - } - - sth->ret = system(sth->cmd); - -#if 0 -#if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__) - rlim.rlim_cur = SWITCH_THREAD_STACKSIZE; - rlim.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE; - if (setrlimit(RLIMIT_STACK, &rlim) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno)); - } -#endif -#endif - - switch_mutex_lock(sth->mutex); - switch_thread_cond_signal(sth->cond); - switch_mutex_unlock(sth->mutex); - - switch_core_destroy_memory_pool(&sth->pool); - - return NULL; -} - - -static int switch_system_thread(const char *cmd, switch_bool_t wait) -{ - switch_thread_t *thread; - switch_threadattr_t *thd_attr; - int ret = 0; - struct system_thread_handle *sth; - switch_memory_pool_t *pool; - - if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Pool Failure\n"); - return 1; - } - - if (!(sth = switch_core_alloc(pool, sizeof(struct system_thread_handle)))) { - switch_core_destroy_memory_pool(&pool); - return 1; - } - - sth->pool = pool; - sth->cmd = switch_core_strdup(pool, cmd); - - switch_thread_cond_create(&sth->cond, sth->pool); - switch_mutex_init(&sth->mutex, SWITCH_MUTEX_NESTED, sth->pool); - switch_mutex_lock(sth->mutex); - - switch_threadattr_create(&thd_attr, sth->pool); - switch_threadattr_stacksize_set(thd_attr, SWITCH_SYSTEM_THREAD_STACKSIZE); - switch_threadattr_detach_set(thd_attr, 1); - switch_thread_create(&thread, thd_attr, system_thread, sth, sth->pool); - - if (wait) { - switch_thread_cond_wait(sth->cond, sth->mutex); - ret = sth->ret; - } - switch_mutex_unlock(sth->mutex); - - return ret; -} - -SWITCH_DECLARE(int) switch_max_file_desc(void) -{ - int max = 0; - -#ifndef WIN32 -#if defined(HAVE_GETDTABLESIZE) - max = getdtablesize(); -#else - max = sysconf(_SC_OPEN_MAX); -#endif -#endif - - return max; - -} - -SWITCH_DECLARE(void) switch_close_extra_files(int *keep, int keep_ttl) -{ - int open_max = switch_max_file_desc(); - int i, j; - - for (i = 3; i < open_max; i++) { - if (keep) { - for (j = 0; j < keep_ttl; j++) { - if (i == keep[j]) { - goto skip; - } - } - } - - close(i); - - skip: - - continue; - - } -} - - -#ifdef WIN32 -static int switch_system_fork(const char *cmd, switch_bool_t wait) -{ - return switch_system_thread(cmd, wait); -} - -SWITCH_DECLARE(pid_t) switch_fork(void) -{ - return -1; -} - - -#else - -SWITCH_DECLARE(pid_t) switch_fork(void) -{ - int i = fork(); - - if (!i) { - set_low_priority(); - } - - return i; -} - - - -static int switch_system_fork(const char *cmd, switch_bool_t wait) -{ - int pid; - char *dcmd = strdup(cmd); - - switch_core_set_signal_handlers(); - - pid = switch_fork(); - - if (pid) { - if (wait) { - waitpid(pid, NULL, 0); - } - free(dcmd); - } else { - switch_close_extra_files(NULL, 0); - - if (system(dcmd) == -1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute because of a command error : %s\n", dcmd); - } - free(dcmd); - exit(0); - } - - return 0; -} -#endif - - - -SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait) -{ - int (*sys_p)(const char *cmd, switch_bool_t wait); - - sys_p = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC) ? switch_system_thread : switch_system_fork; - - return sys_p(cmd, wait); - -} - - - -SWITCH_DECLARE(int) switch_stream_system_fork(const char *cmd, switch_stream_handle_t *stream) -{ -#ifdef WIN32 - return switch_system(cmd, SWITCH_TRUE); -#else - int fds[2], pid = 0; - - if (pipe(fds)) { - goto end; - } else { /* good to go */ - pid = switch_fork(); - - if (pid < 0) { /* ok maybe not */ - close(fds[0]); - close(fds[1]); - goto end; - } else if (pid) { /* parent */ - char buf[1024] = ""; - int bytes; - close(fds[1]); - while ((bytes = read(fds[0], buf, sizeof(buf))) > 0) { - stream->raw_write_function(stream, (unsigned char *)buf, bytes); - } - close(fds[0]); - waitpid(pid, NULL, 0); - } else { /* child */ - switch_close_extra_files(fds, 2); - close(fds[0]); - dup2(fds[1], STDOUT_FILENO); - switch_system(cmd, SWITCH_TRUE); - close(fds[1]); - exit(0); - } - } - - end: - - return 0; - -#endif - -} - -SWITCH_DECLARE(switch_status_t) switch_core_get_stacksizes(switch_size_t *cur, switch_size_t *max) -{ -#ifdef HAVE_SETRLIMIT - struct rlimit rlp; - - memset(&rlp, 0, sizeof(rlp)); - getrlimit(RLIMIT_STACK, &rlp); - - *cur = rlp.rlim_cur; - *max = rlp.rlim_max; - - return SWITCH_STATUS_SUCCESS; - -#else - - return SWITCH_STATUS_FALSE; - -#endif - - - -} - - -SWITCH_DECLARE(int) switch_stream_system(const char *cmd, switch_stream_handle_t *stream) -{ -#ifdef WIN32 - stream->write_function(stream, "Capturing output not supported.\n"); - return switch_system(cmd, SWITCH_TRUE); -#else - return switch_stream_system_fork(cmd, stream); -#endif - -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4: - */ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2012, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * Michael Jerris + * Paul D. Tinsley + * Marcel Barbulescu + * Joseph Sullivan + * + * + * switch_core.c -- Main Core Library + * + */ + + + +#include +#include +#include +#include +#include +#include "private/switch_core_pvt.h" +#include +#ifndef WIN32 +#include +#ifdef HAVE_SETRLIMIT +#include +#endif +#endif +#include + + +SWITCH_DECLARE_DATA switch_directories SWITCH_GLOBAL_dirs = { 0 }; + +/* The main runtime obj we keep this hidden for ourselves */ +struct switch_runtime runtime = { 0 }; +static void switch_load_core_config(const char *file); + +static void send_heartbeat(void) +{ + switch_event_t *event; + switch_core_time_duration_t duration; + + switch_core_measure_time(switch_core_uptime(), &duration); + + if (switch_event_create(&event, SWITCH_EVENT_HEARTBEAT) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Up-Time", + "%u year%s, " + "%u day%s, " + "%u hour%s, " + "%u minute%s, " + "%u second%s, " + "%u millisecond%s, " + "%u microsecond%s", + duration.yr, duration.yr == 1 ? "" : "s", + duration.day, duration.day == 1 ? "" : "s", + duration.hr, duration.hr == 1 ? "" : "s", + duration.min, duration.min == 1 ? "" : "s", + duration.sec, duration.sec == 1 ? "" : "s", + duration.ms, duration.ms == 1 ? "" : "s", duration.mms, duration.mms == 1 ? "" : "s"); + + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Version", SWITCH_VERSION_FULL); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Uptime-msec", "%"SWITCH_TIME_T_FMT, switch_core_uptime() / 1000); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Count", "%u", switch_core_session_count()); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Max-Sessions", "%u", switch_core_session_limit(0)); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec", "%u", runtime.sps); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Since-Startup", "%" SWITCH_SIZE_T_FMT, switch_core_session_id() - 1); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Idle-CPU", "%f", switch_core_idle_cpu()); + switch_event_fire(&event); + } +} + +static char main_ip4[256] = ""; +static char main_ip6[256] = ""; + +static void check_ip(void) +{ + char guess_ip4[256] = ""; + char guess_ip6[256] = ""; + char old_ip4[256] = ""; + char old_ip6[256] = ""; + int ok4 = 1, ok6 = 1; + int mask = 0; + + gethostname(runtime.hostname, sizeof(runtime.hostname)); + switch_core_set_variable("hostname", runtime.hostname); + + switch_find_local_ip(guess_ip4, sizeof(guess_ip4), &mask, AF_INET); + switch_find_local_ip(guess_ip6, sizeof(guess_ip6), NULL, AF_INET6); + + if (!*main_ip4) { + switch_set_string(main_ip4, guess_ip4); + } else { + if (!(ok4 = !strcmp(main_ip4, guess_ip4))) { + struct in_addr in; + + in.s_addr = mask; + switch_set_string(old_ip4, main_ip4); + switch_set_string(main_ip4, guess_ip4); + switch_core_set_variable("local_ip_v4", guess_ip4); + switch_core_set_variable("local_mask_v4", inet_ntoa(in)); + } + } + + if (!*main_ip6) { + switch_set_string(main_ip6, guess_ip6); + } else { + if (!(ok6 = !strcmp(main_ip6, guess_ip6))) { + switch_set_string(old_ip6, main_ip6); + switch_set_string(main_ip6, guess_ip6); + switch_core_set_variable("local_ip_v6", guess_ip6); + } + } + + if (!ok4 || !ok6) { + switch_event_t *event; + + if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "condition", "network-address-change"); + if (!ok4) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v4", old_ip4); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v4", main_ip4); + } + if (!ok6) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v6", old_ip6); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v6", main_ip6); + } + switch_event_fire(&event); + } + } +} + +SWITCH_STANDARD_SCHED_FUNC(heartbeat_callback) +{ + send_heartbeat(); + + /* reschedule this task */ + task->runtime = switch_epoch_time_now(NULL) + 20; +} + + +SWITCH_STANDARD_SCHED_FUNC(check_ip_callback) +{ + check_ip(); + + /* reschedule this task */ + task->runtime = switch_epoch_time_now(NULL) + 60; +} + + +SWITCH_DECLARE(switch_status_t) switch_core_set_console(const char *console) +{ + if ((runtime.console = fopen(console, "a")) == 0) { + fprintf(stderr, "Cannot open output file %s.\n", console); + return SWITCH_STATUS_FALSE; + } + + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_DECLARE(FILE *) switch_core_get_console(void) +{ + return runtime.console; +} + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +SWITCH_DECLARE(void) switch_core_screen_size(int *x, int *y) +{ + +#ifdef WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbi; + int ret; + + if ((ret = GetConsoleScreenBufferInfo(GetStdHandle( STD_OUTPUT_HANDLE ), &csbi))) { + if (x) *x = csbi.dwSize.X; + if (y) *y = csbi.dwSize.Y; + } + +#elif defined(TIOCGWINSZ) + struct winsize w; + ioctl(0, TIOCGWINSZ, &w); + + if (x) *x = w.ws_col; + if (y) *y = w.ws_row; +#else + if (x) *x = 80; + if (y) *y = 24; +#endif + +} + +SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel_t channel) +{ + FILE *handle = stdout; + + switch (channel) { + case SWITCH_CHANNEL_ID_LOG: + case SWITCH_CHANNEL_ID_LOG_CLEAN: + handle = runtime.console; + break; + default: + handle = runtime.console; + break; + } + + return handle; +} + + +SWITCH_DECLARE(void) switch_core_remove_state_handler(const switch_state_handler_table_t *state_handler) +{ + int index, tmp_index = 0; + const switch_state_handler_table_t *tmp[SWITCH_MAX_STATE_HANDLERS + 1] = { 0 }; + + switch_mutex_lock(runtime.global_mutex); + + for (index = 0; index < runtime.state_handler_index; index++) { + const switch_state_handler_table_t *cur = runtime.state_handlers[index]; + runtime.state_handlers[index] = NULL; + if (cur == state_handler) { + continue; + } + tmp[tmp_index++] = cur; + } + + runtime.state_handler_index = 0; + + for (index = 0; index < tmp_index; index++) { + runtime.state_handlers[runtime.state_handler_index++] = tmp[index]; + } + switch_mutex_unlock(runtime.global_mutex); +} + + +SWITCH_DECLARE(int) switch_core_add_state_handler(const switch_state_handler_table_t *state_handler) +{ + int index; + + switch_mutex_lock(runtime.global_mutex); + index = runtime.state_handler_index++; + + if (runtime.state_handler_index >= SWITCH_MAX_STATE_HANDLERS) { + index = -1; + } else { + runtime.state_handlers[index] = state_handler; + } + + switch_mutex_unlock(runtime.global_mutex); + return index; +} + +SWITCH_DECLARE(const switch_state_handler_table_t *) switch_core_get_state_handler(int index) +{ + + if (index >= SWITCH_MAX_STATE_HANDLERS || index > runtime.state_handler_index) { + return NULL; + } + + return runtime.state_handlers[index]; +} + +SWITCH_DECLARE(void) switch_core_dump_variables(switch_stream_handle_t *stream) +{ + switch_event_header_t *hi; + + switch_mutex_lock(runtime.global_mutex); + for (hi = runtime.global_vars->headers; hi; hi = hi->next) { + stream->write_function(stream, "%s=%s\n", hi->name, hi->value); + } + switch_mutex_unlock(runtime.global_mutex); +} + +SWITCH_DECLARE(const char *) switch_core_get_hostname(void) +{ + return runtime.hostname; +} + +SWITCH_DECLARE(const char *) switch_core_get_switchname(void) +{ + if (!zstr(runtime.switchname)) return runtime.switchname; + return runtime.hostname; +} + + +SWITCH_DECLARE(char *) switch_core_get_variable(const char *varname) +{ + char *val; + switch_thread_rwlock_rdlock(runtime.global_var_rwlock); + val = (char *) switch_event_get_header(runtime.global_vars, varname); + switch_thread_rwlock_unlock(runtime.global_var_rwlock); + return val; +} + +SWITCH_DECLARE(char *) switch_core_get_variable_dup(const char *varname) +{ + char *val = NULL, *v; + + switch_thread_rwlock_rdlock(runtime.global_var_rwlock); + if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) { + val = strdup(v); + } + switch_thread_rwlock_unlock(runtime.global_var_rwlock); + + return val; +} + +SWITCH_DECLARE(char *) switch_core_get_variable_pdup(const char *varname, switch_memory_pool_t *pool) +{ + char *val = NULL, *v; + + switch_thread_rwlock_rdlock(runtime.global_var_rwlock); + if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) { + val = switch_core_strdup(pool, v); + } + switch_thread_rwlock_unlock(runtime.global_var_rwlock); + + return val; +} + +static void switch_core_unset_variables(void) +{ + switch_thread_rwlock_wrlock(runtime.global_var_rwlock); + switch_event_destroy(&runtime.global_vars); + switch_event_create_plain(&runtime.global_vars, SWITCH_EVENT_CHANNEL_DATA); + switch_thread_rwlock_unlock(runtime.global_var_rwlock); +} + +SWITCH_DECLARE(void) switch_core_set_variable(const char *varname, const char *value) +{ + char *val; + + if (varname) { + switch_thread_rwlock_wrlock(runtime.global_var_rwlock); + val = (char *) switch_event_get_header(runtime.global_vars, varname); + if (val) { + switch_event_del_header(runtime.global_vars, varname); + } + if (value) { + char *v = strdup(value); + switch_string_var_check(v, SWITCH_TRUE); + switch_event_add_header_string(runtime.global_vars, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, varname, v); + } else { + switch_event_del_header(runtime.global_vars, varname); + } + switch_thread_rwlock_unlock(runtime.global_var_rwlock); + } +} + +SWITCH_DECLARE(switch_bool_t) switch_core_set_var_conditional(const char *varname, const char *value, const char *val2) +{ + char *val; + + if (varname) { + switch_thread_rwlock_wrlock(runtime.global_var_rwlock); + val = (char *) switch_event_get_header(runtime.global_vars, varname); + + if (val) { + if (!val2 || strcmp(val, val2) != 0) { + switch_thread_rwlock_unlock(runtime.global_var_rwlock); + return SWITCH_FALSE; + } + switch_event_del_header(runtime.global_vars, varname); + } else if (!zstr(val2)) { + switch_thread_rwlock_unlock(runtime.global_var_rwlock); + return SWITCH_FALSE; + } + + if (value) { + char *v = strdup(value); + switch_string_var_check(v, SWITCH_TRUE); + switch_event_add_header_string(runtime.global_vars, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, varname, v); + } else { + switch_event_del_header(runtime.global_vars, varname); + } + switch_thread_rwlock_unlock(runtime.global_var_rwlock); + } + return SWITCH_TRUE; +} + +SWITCH_DECLARE(char *) switch_core_get_uuid(void) +{ + return runtime.uuid_str; +} + + +static void *SWITCH_THREAD_FUNC switch_core_service_thread(switch_thread_t *thread, void *obj) +{ + switch_core_session_t *session = obj; + switch_channel_t *channel; + switch_frame_t *read_frame; + +// switch_assert(thread != NULL); +// switch_assert(session != NULL); + + if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) { + return NULL; + } + + switch_mutex_lock(session->frame_read_mutex); + + channel = switch_core_session_get_channel(session); + + switch_channel_set_flag(channel, CF_SERVICE); + while (switch_channel_test_flag(channel, CF_SERVICE)) { + + if (switch_channel_test_flag(channel, CF_SERVICE_AUDIO)) { + switch (switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0)) { + case SWITCH_STATUS_SUCCESS: + case SWITCH_STATUS_TIMEOUT: + case SWITCH_STATUS_BREAK: + break; + default: + switch_channel_clear_flag(channel, CF_SERVICE); + break; + } + } + + if (switch_channel_test_flag(channel, CF_SERVICE_VIDEO) && switch_channel_test_flag(channel, CF_VIDEO)) { + switch (switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0)) { + case SWITCH_STATUS_SUCCESS: + case SWITCH_STATUS_TIMEOUT: + case SWITCH_STATUS_BREAK: + break; + default: + switch_channel_clear_flag(channel, CF_SERVICE); + break; + } + } + } + + switch_mutex_unlock(session->frame_read_mutex); + + switch_channel_clear_flag(channel, CF_SERVICE_AUDIO); + switch_channel_clear_flag(channel, CF_SERVICE_VIDEO); + + switch_core_session_rwunlock(session); + + return NULL; +} + +/* Either add a timeout here or make damn sure the thread cannot get hung somehow (my preference) */ +SWITCH_DECLARE(void) switch_core_thread_session_end(switch_core_session_t *session) +{ + switch_channel_t *channel; + switch_assert(session); + + channel = switch_core_session_get_channel(session); + switch_assert(channel); + + switch_channel_clear_flag(channel, CF_SERVICE); + switch_channel_clear_flag(channel, CF_SERVICE_AUDIO); + switch_channel_clear_flag(channel, CF_SERVICE_VIDEO); + + switch_core_session_kill_channel(session, SWITCH_SIG_BREAK); + +} + +SWITCH_DECLARE(void) switch_core_service_session_av(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video) +{ + switch_channel_t *channel; + switch_assert(session); + + channel = switch_core_session_get_channel(session); + switch_assert(channel); + + if (audio) switch_channel_set_flag(channel, CF_SERVICE_AUDIO); + if (video) switch_channel_set_flag(channel, CF_SERVICE_VIDEO); + + switch_core_session_launch_thread(session, (void *(*)(switch_thread_t *,void *))switch_core_service_thread, session); +} + +/* This function abstracts the thread creation for modules by allowing you to pass a function ptr and + a void object and trust that that the function will be run in a thread with arg This lets + you request and activate a thread without giving up any knowledge about what is in the thread + neither the core nor the calling module know anything about each other. + + This thread is expected to never exit until the application exits so the func is responsible + to make sure that is the case. + + The typical use for this is so switch_loadable_module.c can start up a thread for each module + passing the table of module methods as a session obj into the core without actually allowing + the core to have any clue and keeping switch_loadable_module.c from needing any thread code. + +*/ + +SWITCH_DECLARE(switch_thread_t *) switch_core_launch_thread(switch_thread_start_t func, void *obj, switch_memory_pool_t *pool) +{ + switch_thread_t *thread = NULL; + switch_threadattr_t *thd_attr = NULL; + switch_core_thread_session_t *ts; + int mypool; + + mypool = pool ? 0 : 1; + + if (!pool && switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory pool\n"); + return NULL; + } + + switch_threadattr_create(&thd_attr, pool); + + if ((ts = switch_core_alloc(pool, sizeof(*ts))) == 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory\n"); + } else { + if (mypool) { + ts->pool = pool; + } + ts->objs[0] = obj; + ts->objs[1] = thread; + switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); + switch_thread_create(&thread, thd_attr, func, ts, pool); + } + + return thread; +} + +SWITCH_DECLARE(void) switch_core_set_globals(void) +{ +#define BUFSIZE 1024 +#ifdef WIN32 + char lpPathBuffer[BUFSIZE]; + DWORD dwBufSize = BUFSIZE; + char base_dir[1024]; + char *lastbacklash; + char *tmp; + + GetModuleFileName(NULL, base_dir, BUFSIZE); + lastbacklash = strrchr(base_dir, '\\'); + base_dir[(lastbacklash - base_dir)] = '\0'; + /* set base_dir as cwd, to be able to use relative paths in scripting languages (e.g. mod_lua) when FS is running as a service or while debugging FS using visual studio */ + SetCurrentDirectory(base_dir); + tmp = switch_string_replace(base_dir, "\\", "/"); + strcpy(base_dir, tmp); + free(tmp); + +#else + char base_dir[1024] = SWITCH_PREFIX_DIR; +#endif + + if (!SWITCH_GLOBAL_dirs.base_dir && (SWITCH_GLOBAL_dirs.base_dir = (char *) malloc(BUFSIZE))) { + switch_snprintf(SWITCH_GLOBAL_dirs.base_dir, BUFSIZE, "%s", base_dir); + } + + if (!SWITCH_GLOBAL_dirs.mod_dir && (SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_MOD_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s", SWITCH_MOD_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s%smod", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.lib_dir && (SWITCH_GLOBAL_dirs.lib_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_LIB_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s", SWITCH_LIB_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s%slib", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.conf_dir && (SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_CONF_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s", SWITCH_CONF_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s%sconf", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.log_dir && (SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_LOG_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s", SWITCH_LOG_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s%slog", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.run_dir && (SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_RUN_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s", SWITCH_RUN_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s%srun", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.recordings_dir && (SWITCH_GLOBAL_dirs.recordings_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_RECORDINGS_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s", SWITCH_RECORDINGS_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s%srecordings", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.sounds_dir && (SWITCH_GLOBAL_dirs.sounds_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_SOUNDS_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s", SWITCH_SOUNDS_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s%ssounds", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.storage_dir && (SWITCH_GLOBAL_dirs.storage_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_STORAGE_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s", SWITCH_STORAGE_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s%sstorage", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.db_dir && (SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_DB_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s", SWITCH_DB_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s%sdb", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.script_dir && (SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_SCRIPT_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s", SWITCH_SCRIPT_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s%sscripts", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_HTDOCS_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s", SWITCH_HTDOCS_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s%shtdocs", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.grammar_dir && (SWITCH_GLOBAL_dirs.grammar_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_GRAMMAR_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s", SWITCH_GRAMMAR_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s%sgrammar", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.temp_dir && (SWITCH_GLOBAL_dirs.temp_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_TEMP_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", SWITCH_TEMP_DIR); +#else +#ifdef WIN32 + GetTempPath(dwBufSize, lpPathBuffer); + lpPathBuffer[strlen(lpPathBuffer)-1] = 0; + tmp = switch_string_replace(lpPathBuffer, "\\", "/"); + strcpy(lpPathBuffer, tmp); + free(tmp); + switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", lpPathBuffer); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", "/tmp"); +#endif +#endif + } + + switch_assert(SWITCH_GLOBAL_dirs.base_dir); + switch_assert(SWITCH_GLOBAL_dirs.mod_dir); + switch_assert(SWITCH_GLOBAL_dirs.lib_dir); + switch_assert(SWITCH_GLOBAL_dirs.conf_dir); + switch_assert(SWITCH_GLOBAL_dirs.log_dir); + switch_assert(SWITCH_GLOBAL_dirs.run_dir); + switch_assert(SWITCH_GLOBAL_dirs.db_dir); + switch_assert(SWITCH_GLOBAL_dirs.script_dir); + switch_assert(SWITCH_GLOBAL_dirs.htdocs_dir); + switch_assert(SWITCH_GLOBAL_dirs.grammar_dir); + switch_assert(SWITCH_GLOBAL_dirs.recordings_dir); + switch_assert(SWITCH_GLOBAL_dirs.sounds_dir); + switch_assert(SWITCH_GLOBAL_dirs.temp_dir); +} + + +SWITCH_DECLARE(int32_t) set_low_priority(void) +{ + + +#ifdef WIN32 + SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); +#else +#ifdef USE_SCHED_SETSCHEDULER + /* + * Try to use a normal scheduler + */ + struct sched_param sched = { 0 }; + sched.sched_priority = 0; + if (sched_setscheduler(0, SCHED_OTHER, &sched)) { + return -1; + } +#endif + +#ifdef HAVE_SETPRIORITY + /* + * setpriority() works on FreeBSD (6.2), nice() doesn't + */ + if (setpriority(PRIO_PROCESS, getpid(), 19) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); + return -1; + } +#else + if (nice(19) != 19) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); + return -1; + } +#endif +#endif + + return 0; +} + +SWITCH_DECLARE(int32_t) set_realtime_priority(void) +{ +#ifdef WIN32 + SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); +#else +#ifdef USE_SCHED_SETSCHEDULER + /* + * Try to use a round-robin scheduler + * with a fallback if that does not work + */ + struct sched_param sched = { 0 }; + sched.sched_priority = SWITCH_PRI_LOW; + if (sched_setscheduler(0, SCHED_FIFO, &sched)) { + sched.sched_priority = 0; + if (sched_setscheduler(0, SCHED_OTHER, &sched)) { + return -1; + } + } +#endif + + + +#ifdef HAVE_SETPRIORITY + /* + * setpriority() works on FreeBSD (6.2), nice() doesn't + */ + if (setpriority(PRIO_PROCESS, getpid(), -10) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); + return -1; + } +#else + if (nice(-10) != -10) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); + return -1; + } +#endif +#endif + return 0; +} + +SWITCH_DECLARE(uint32_t) switch_core_cpu_count(void) +{ + return runtime.cpu_count; +} + +SWITCH_DECLARE(int32_t) set_normal_priority(void) +{ + return 0; +} + +SWITCH_DECLARE(int32_t) set_auto_priority(void) +{ +#ifndef WIN32 + runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN); +#else + SYSTEM_INFO sysinfo; + GetSystemInfo( &sysinfo ); + runtime.cpu_count = sysinfo.dwNumberOfProcessors; +#endif + + if (!runtime.cpu_count) runtime.cpu_count = 1; + + /* If we have more than 1 cpu, we should use realtime priority so we can have priority threads */ + if (runtime.cpu_count > 1) { + return set_realtime_priority(); + } + + return 0; +} + +SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group) +{ +#ifndef WIN32 + uid_t runas_uid = 0; + gid_t runas_gid = 0; + struct passwd *runas_pw = NULL; + + if (user) { + /* + * Lookup user information in the system's db + */ + runas_pw = getpwnam(user); + if (!runas_pw) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unknown user \"%s\"\n", user); + return -1; + } + runas_uid = runas_pw->pw_uid; + } + + if (group) { + struct group *gr = NULL; + + /* + * Lookup group information in the system's db + */ + gr = getgrnam(group); + if (!gr) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unknown group \"%s\"\n", group); + return -1; + } + runas_gid = gr->gr_gid; + } + + if (runas_uid && getuid() == runas_uid && (!runas_gid || runas_gid == getgid())) { + /* already running as the right user and group, nothing to do! */ + return 0; + } + + if (runas_uid) { +#ifdef HAVE_SETGROUPS + /* + * Drop all group memberships prior to changing anything + * or else we're going to inherit the parent's list of groups + * (which is not what we want...) + */ + if (setgroups(0, NULL) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to drop group access list\n"); + return -1; + } +#endif + if (runas_gid) { + /* + * A group has been passed, switch to it + * (without loading the user's other groups) + */ + if (setgid(runas_gid) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change gid!\n"); + return -1; + } + } else { + /* + * No group has been passed, use the user's primary group in this case + */ + if (setgid(runas_pw->pw_gid) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change gid!\n"); + return -1; + } +#ifdef HAVE_INITGROUPS + /* + * Set all the other groups the user is a member of + * (This can be really useful for fine-grained access control) + */ + if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to set group access list for user\n"); + return -1; + } +#endif + } + + /* + * Finally drop all privileges by switching to the new userid + */ + if (setuid(runas_uid) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change uid!\n"); + return -1; + } + } +#endif + return 0; +} + +SWITCH_DECLARE(void) switch_core_runtime_loop(int bg) +{ +#ifdef WIN32 + HANDLE shutdown_event; + char path[256] = ""; +#endif + if (bg) { + bg = 0; +#ifdef WIN32 + switch_snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid()); + shutdown_event = CreateEvent(NULL, FALSE, FALSE, path); + if (shutdown_event) { + WaitForSingleObject(shutdown_event, INFINITE); + } +#else + runtime.running = 1; + while (runtime.running) { + switch_yield(1000000); + } +#endif + } else { + /* wait for console input */ + switch_console_loop(); + } +} + +SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext) +{ + if (!ext) { + return NULL; + } + return (const char *) switch_core_hash_find(runtime.mime_types, ext); +} + + +SWITCH_DECLARE(switch_hash_index_t *) switch_core_mime_index(void) +{ + return switch_hash_first(NULL, runtime.mime_types); +} + +SWITCH_DECLARE(switch_status_t) switch_core_mime_add_type(const char *type, const char *ext) +{ + const char *check; + switch_status_t status = SWITCH_STATUS_FALSE; + + switch_assert(type); + switch_assert(ext); + + check = (const char *) switch_core_hash_find(runtime.mime_types, ext); + + if (!check) { + char *ptype = switch_core_permanent_strdup(type); + char *ext_list = strdup(ext); + int argc = 0; + char *argv[20] = { 0 }; + int x; + + switch_assert(ext_list); + + if ((argc = switch_separate_string(ext_list, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { + + for (x = 0; x < argc; x++) { + if (argv[x] && ptype) { + switch_core_hash_insert(runtime.mime_types, argv[x], ptype); + } + } + + status = SWITCH_STATUS_SUCCESS; + } + + free(ext_list); + } + + return status; +} + +static void load_mime_types(void) +{ + char *cf = "mime.types"; + FILE *fd = NULL; + char *line_buf = NULL; + switch_size_t llen = 0; + char *mime_path = NULL; + + mime_path = switch_mprintf("%s/%s", SWITCH_GLOBAL_dirs.conf_dir, cf); + switch_assert(mime_path); + + fd = fopen(mime_path, "rb"); + + if (fd == NULL) { + goto end; + } + + while ((switch_fp_read_dline(fd, &line_buf, &llen))) { + char *p; + char *type = line_buf; + + if (*line_buf == '#') { + continue; + } + + if ((p = strchr(line_buf, '\r')) || (p = strchr(line_buf, '\n'))) { + *p = '\0'; + } + + if ((p = strchr(type, '\t')) || (p = strchr(type, ' '))) { + *p++ = '\0'; + + while (*p == ' ' || *p == '\t') { + p++; + } + + switch_core_mime_add_type(type, p); + } + + } + + switch_safe_free(line_buf); + + if (fd) { + fclose(fd); + fd = NULL; + } + + end: + + switch_safe_free(mime_path); + +} + +SWITCH_DECLARE(void) switch_core_setrlimits(void) +{ +#ifdef HAVE_SETRLIMIT + struct rlimit rlp; + + /* + Setting the stack size on FreeBSD results in an instant crash. + + If anyone knows how to fix this, + feel free to submit a patch to http://jira.freeswitch.org + */ + +#ifndef __FreeBSD__ + memset(&rlp, 0, sizeof(rlp)); + rlp.rlim_cur = SWITCH_THREAD_STACKSIZE; + rlp.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE; + setrlimit(RLIMIT_STACK, &rlp); +#endif + + memset(&rlp, 0, sizeof(rlp)); + rlp.rlim_cur = 999999; + rlp.rlim_max = 999999; + setrlimit(RLIMIT_NOFILE, &rlp); + + memset(&rlp, 0, sizeof(rlp)); + rlp.rlim_cur = RLIM_INFINITY; + rlp.rlim_max = RLIM_INFINITY; + + setrlimit(RLIMIT_CPU, &rlp); + setrlimit(RLIMIT_DATA, &rlp); + setrlimit(RLIMIT_FSIZE, &rlp); +#ifdef RLIMIT_NPROC + setrlimit(RLIMIT_NPROC, &rlp); +#endif +#ifdef RLIMIT_RTPRIO + setrlimit(RLIMIT_RTPRIO, &rlp); +#endif + +#if !defined(__OpenBSD__) && !defined(__NetBSD__) + setrlimit(RLIMIT_AS, &rlp); +#endif +#endif + return; +} + +typedef struct { + switch_memory_pool_t *pool; + switch_hash_t *hash; +} switch_ip_list_t; + +static switch_ip_list_t IP_LIST = { 0 }; + +SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token) +{ + switch_network_list_t *list; + ip_t ip, mask, net; + uint32_t bits; + char *ipv6 = strchr(ip_str,':'); + switch_bool_t ok = SWITCH_FALSE; + + switch_mutex_lock(runtime.global_mutex); + if (ipv6) { + switch_inet_pton(AF_INET6, ip_str, &ip); + } else { + switch_inet_pton(AF_INET, ip_str, &ip); + ip.v4 = htonl(ip.v4); + } + + if ((list = switch_core_hash_find(IP_LIST.hash, list_name))) { + if (ipv6) { + ok = switch_network_list_validate_ip6_token(list, ip, token); + } else { + ok = switch_network_list_validate_ip_token(list, ip.v4, token); + } + } else if (strchr(list_name, '/')) { + if (strchr(list_name, ',')) { + char *list_name_dup = strdup(list_name); + char *argv[32]; + int argc; + + switch_assert(list_name_dup); + + if ((argc = switch_separate_string(list_name_dup, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) { + int i; + for (i = 0; i < argc; i++) { + switch_parse_cidr(argv[i], &net, &mask, &bits); + if (ipv6) { + if ((ok = switch_testv6_subnet(ip, net, mask))){ + break; + } + } else { + if ((ok = switch_test_subnet(ip.v4, net.v4, mask.v4))) { + break; + } + } + } + } + free(list_name_dup); + } else { + switch_parse_cidr(list_name, &net, &mask, &bits); + ok = switch_test_subnet(ip.v4, net.v4, mask.v4); + } + } + switch_mutex_unlock(runtime.global_mutex); + + return ok; +} + + +SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload) +{ + switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, x_node = NULL, cfg = NULL; + switch_network_list_t *rfc_list, *list; + char guess_ip[16] = ""; + int mask = 0; + char guess_mask[16] = ""; + char *tmp_name; + struct in_addr in; + + switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET); + in.s_addr = mask; + switch_set_string(guess_mask, inet_ntoa(in)); + + switch_mutex_lock(runtime.global_mutex); + + if (IP_LIST.hash) { + switch_core_hash_destroy(&IP_LIST.hash); + } + + if (IP_LIST.pool) { + switch_core_destroy_memory_pool(&IP_LIST.pool); + } + + memset(&IP_LIST, 0, sizeof(IP_LIST)); + switch_core_new_memory_pool(&IP_LIST.pool); + switch_core_hash_init(&IP_LIST.hash, IP_LIST.pool); + + + tmp_name = "rfc1918.auto"; + switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); + switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE); + switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE); + switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE); + switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); + + tmp_name = "wan.auto"; + switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name); + switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_FALSE); + switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_FALSE); + switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_FALSE); + switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); + + tmp_name = "nat.auto"; + switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); + if (switch_network_list_add_host_mask(rfc_list, guess_ip, guess_mask, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s/%s (deny) to list %s\n", guess_ip, guess_mask, tmp_name); + } + switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE); + switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE); + switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE); + switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); + + tmp_name = "loopback.auto"; + switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); + switch_network_list_add_cidr(rfc_list, "127.0.0.0/8", SWITCH_TRUE); + switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); + + tmp_name = "localnet.auto"; + switch_network_list_create(&list, tmp_name, SWITCH_FALSE, IP_LIST.pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); + + if (switch_network_list_add_host_mask(list, guess_ip, guess_mask, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s/%s (allow) to list %s\n", guess_ip, guess_mask, tmp_name); + } + switch_core_hash_insert(IP_LIST.hash, tmp_name, list); + + + if ((xml = switch_xml_open_cfg("acl.conf", &cfg, NULL))) { + if ((x_lists = switch_xml_child(cfg, "network-lists"))) { + for (x_list = switch_xml_child(x_lists, "list"); x_list; x_list = x_list->next) { + const char *name = switch_xml_attr(x_list, "name"); + const char *dft = switch_xml_attr(x_list, "default"); + switch_bool_t default_type = SWITCH_TRUE; + + if (zstr(name)) { + continue; + } + + if (dft) { + default_type = switch_true(dft); + } + + if (switch_network_list_create(&list, name, default_type, IP_LIST.pool) != SWITCH_STATUS_SUCCESS) { + abort(); + } + + if (reload) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny"); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny"); + } + + + for (x_node = switch_xml_child(x_list, "node"); x_node; x_node = x_node->next) { + const char *cidr = NULL, *host = NULL, *mask = NULL, *domain = NULL; + switch_bool_t ok = default_type; + const char *type = switch_xml_attr(x_node, "type"); + + if (type) { + ok = switch_true(type); + } + + cidr = switch_xml_attr(x_node, "cidr"); + host = switch_xml_attr(x_node, "host"); + mask = switch_xml_attr(x_node, "mask"); + domain = switch_xml_attr(x_node, "domain"); + + if (domain) { + switch_event_t *my_params = NULL; + switch_xml_t x_domain, xml_root; + switch_xml_t gt, gts, ut, uts; + + switch_event_create(&my_params, SWITCH_EVENT_GENERAL); + switch_assert(my_params); + switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "domain", domain); + switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "purpose", "network-list"); + + if (switch_xml_locate_domain(domain, my_params, &xml_root, &x_domain) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate domain %s\n", domain); + switch_event_destroy(&my_params); + continue; + } + + switch_event_destroy(&my_params); + + for (ut = switch_xml_child(x_domain, "user"); ut; ut = ut->next) { + const char *user_cidr = switch_xml_attr(ut, "cidr"); + const char *id = switch_xml_attr(ut, "id"); + + if (id && user_cidr) { + char *token = switch_mprintf("%s@%s", id, domain); + switch_assert(token); + switch_network_list_add_cidr_token(list, user_cidr, ok, token); + free(token); + } + } + + for (gts = switch_xml_child(x_domain, "groups"); gts; gts = gts->next) { + for (gt = switch_xml_child(gts, "group"); gt; gt = gt->next) { + for (uts = switch_xml_child(gt, "users"); uts; uts = uts->next) { + for (ut = switch_xml_child(uts, "user"); ut; ut = ut->next) { + const char *user_cidr = switch_xml_attr(ut, "cidr"); + const char *id = switch_xml_attr(ut, "id"); + + if (id && user_cidr) { + char *token = switch_mprintf("%s@%s", id, domain); + switch_assert(token); + switch_network_list_add_cidr_token(list, user_cidr, ok, token); + free(token); + } + } + } + } + } + + switch_xml_free(xml_root); + } else if (cidr) { + if (switch_network_list_add_cidr(list, cidr, ok) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "Error Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name); + } + } else if (host && mask) { + if (switch_network_list_add_host_mask(list, host, mask, ok) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, + "Adding %s/%s (%s) to list %s\n", host, mask, ok ? "allow" : "deny", name); + } + } + + switch_core_hash_insert(IP_LIST.hash, name, list); + } + } + } + + switch_xml_free(xml); + } + + switch_mutex_unlock(runtime.global_mutex); +} + +SWITCH_DECLARE(uint32_t) switch_core_max_dtmf_duration(uint32_t duration) +{ + if (duration) { + if (duration > SWITCH_MAX_DTMF_DURATION) { + duration = SWITCH_MAX_DTMF_DURATION; + } + if (duration < SWITCH_MIN_DTMF_DURATION) { + duration = SWITCH_MIN_DTMF_DURATION; + } + runtime.max_dtmf_duration = duration; + if (duration < runtime.min_dtmf_duration) { + runtime.min_dtmf_duration = duration; + } + } + return runtime.max_dtmf_duration; +} + +SWITCH_DECLARE(uint32_t) switch_core_default_dtmf_duration(uint32_t duration) +{ + if (duration) { + if (duration < SWITCH_MIN_DTMF_DURATION) { + duration = SWITCH_MIN_DTMF_DURATION; + } + if (duration > SWITCH_MAX_DTMF_DURATION) { + duration = SWITCH_MAX_DTMF_DURATION; + } + runtime.default_dtmf_duration = duration; + + if (duration < runtime.min_dtmf_duration) { + runtime.min_dtmf_duration = duration; + } + + if (duration > runtime.max_dtmf_duration) { + runtime.max_dtmf_duration = duration; + } + + } + return runtime.default_dtmf_duration; +} + +SWITCH_DECLARE(uint32_t) switch_core_min_dtmf_duration(uint32_t duration) +{ + if (duration) { + if (duration < SWITCH_MIN_DTMF_DURATION) { + duration = SWITCH_MIN_DTMF_DURATION; + } + if (duration > SWITCH_MAX_DTMF_DURATION) { + duration = SWITCH_MAX_DTMF_DURATION; + } + + runtime.min_dtmf_duration = duration; + + if (duration > runtime.max_dtmf_duration) { + runtime.max_dtmf_duration = duration; + } + } + return runtime.min_dtmf_duration; +} + +SWITCH_DECLARE(switch_status_t) switch_core_thread_set_cpu_affinity(int cpu) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + + if (cpu > -1) { + +#ifdef HAVE_CPU_SET_MACROS + cpu_set_t set; + + CPU_ZERO(&set); + CPU_SET(cpu, &set); + + if (!sched_setaffinity(0, sizeof(set), &set)) { + status = SWITCH_STATUS_SUCCESS; + } + +#else +#if WIN32 + if (SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR) cpu)) { + status = SWITCH_STATUS_SUCCESS; + } +#endif +#endif + } + + return status; +} + + +static void switch_core_set_serial(void) +{ + char buf[13] = ""; + char path[256]; + + int fd = -1, write_fd = -1; + switch_ssize_t bytes = 0; + + switch_snprintf(path, sizeof(path), "%s%sfreeswitch.serial", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR); + + + if ((fd = open(path, O_RDONLY, 0)) < 0) { + char *ip = switch_core_get_variable_dup("local_ip_v4"); + uint32_t ipi = 0; + switch_byte_t *byte; + int i = 0; + + if (ip) { + switch_inet_pton(AF_INET, ip, &ipi); + free(ip); + ip = NULL; + } + + + byte = (switch_byte_t *) & ipi; + + for (i = 0; i < 8; i += 2) { + switch_snprintf(buf + i, sizeof(buf) - i, "%0.2x", *byte); + byte++; + } + + switch_stun_random_string(buf + 8, 4, "0123456789abcdef"); + + if ((write_fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) >= 0) { + bytes = write(write_fd, buf, sizeof(buf)); + bytes++; + close(write_fd); + write_fd = -1; + } + } else { + bytes = read(fd, buf, sizeof(buf)); + close(fd); + fd = -1; + } + + switch_core_set_variable("switch_serial", buf); +} + + +SWITCH_DECLARE(int) switch_core_test_flag(int flag) +{ + return switch_test_flag((&runtime), flag); +} + + +SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switch_bool_t console, const char **err) +{ + switch_uuid_t uuid; + char guess_ip[256]; + int mask = 0; + struct in_addr in; + + + if (runtime.runlevel > 0) { + /* one per customer */ + return SWITCH_STATUS_SUCCESS; + } + + memset(&runtime, 0, sizeof(runtime)); + gethostname(runtime.hostname, sizeof(runtime.hostname)); + + runtime.max_db_handles = 50; + runtime.db_handle_timeout = 5000000; + + runtime.runlevel++; + runtime.dummy_cng_frame.data = runtime.dummy_data; + runtime.dummy_cng_frame.datalen = sizeof(runtime.dummy_data); + runtime.dummy_cng_frame.buflen = sizeof(runtime.dummy_data); + runtime.dbname = "core"; + switch_set_flag((&runtime.dummy_cng_frame), SFF_CNG); + switch_set_flag((&runtime), SCF_AUTO_SCHEMAS); + switch_set_flag((&runtime), SCF_CLEAR_SQL); + switch_set_flag((&runtime), SCF_API_EXPANSION); + switch_set_flag((&runtime), SCF_SESSION_THREAD_POOL); +#ifdef WIN32 + switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); +#endif + switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); + runtime.hard_log_level = SWITCH_LOG_DEBUG; + runtime.mailer_app = "sendmail"; + runtime.mailer_app_args = "-t"; + runtime.max_dtmf_duration = SWITCH_MAX_DTMF_DURATION; + runtime.default_dtmf_duration = SWITCH_DEFAULT_DTMF_DURATION; + runtime.min_dtmf_duration = SWITCH_MIN_DTMF_DURATION; + runtime.odbc_dbtype = DBTYPE_DEFAULT; + runtime.dbname = NULL; +#ifndef WIN32 + runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN); +#else + { + SYSTEM_INFO sysinfo; + GetSystemInfo( &sysinfo ); + runtime.cpu_count = sysinfo.dwNumberOfProcessors; + } +#endif + + if (!runtime.cpu_count) runtime.cpu_count = 1; + + + /* INIT APR and Create the pool context */ + if (apr_initialize() != SWITCH_STATUS_SUCCESS) { + *err = "FATAL ERROR! Could not initialize APR\n"; + return SWITCH_STATUS_MEMERR; + } + + if (!(runtime.memory_pool = switch_core_memory_init())) { + *err = "FATAL ERROR! Could not allocate memory pool\n"; + return SWITCH_STATUS_MEMERR; + } + switch_assert(runtime.memory_pool != NULL); + + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.base_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.mod_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.conf_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.log_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.run_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.db_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.script_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.htdocs_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.recordings_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.sounds_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.temp_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + + + switch_mutex_init(&runtime.uuid_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); + + switch_mutex_init(&runtime.throttle_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); + + switch_mutex_init(&runtime.session_hash_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); + switch_mutex_init(&runtime.global_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); + + switch_thread_rwlock_create(&runtime.global_var_rwlock, runtime.memory_pool); + switch_core_set_globals(); + switch_core_session_init(runtime.memory_pool); + switch_event_create_plain(&runtime.global_vars, SWITCH_EVENT_CHANNEL_DATA); + switch_core_hash_init(&runtime.mime_types, runtime.memory_pool); + switch_core_hash_init_case(&runtime.ptimes, runtime.memory_pool, SWITCH_FALSE); + load_mime_types(); + runtime.flags |= flags; + runtime.sps_total = 30; + + *err = NULL; + + if (console) { + runtime.console = stdout; + } + + switch_ssl_init_ssl_locks(); + switch_curl_init(); + + switch_core_set_variable("hostname", runtime.hostname); + switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET); + switch_core_set_variable("local_ip_v4", guess_ip); + in.s_addr = mask; + switch_core_set_variable("local_mask_v4", inet_ntoa(in)); + + + switch_find_local_ip(guess_ip, sizeof(guess_ip), NULL, AF_INET6); + switch_core_set_variable("local_ip_v6", guess_ip); + switch_core_set_variable("base_dir", SWITCH_GLOBAL_dirs.base_dir); + switch_core_set_variable("recordings_dir", SWITCH_GLOBAL_dirs.recordings_dir); + switch_core_set_variable("sound_prefix", SWITCH_GLOBAL_dirs.sounds_dir); + switch_core_set_variable("sounds_dir", SWITCH_GLOBAL_dirs.sounds_dir); + switch_core_set_serial(); + + switch_console_init(runtime.memory_pool); + switch_event_init(runtime.memory_pool); + + if (switch_xml_init(runtime.memory_pool, err) != SWITCH_STATUS_SUCCESS) { + apr_terminate(); + return SWITCH_STATUS_MEMERR; + } + + if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) { + switch_nat_init(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_NAT_MAPPING)); + } + + switch_log_init(runtime.memory_pool, runtime.colorize_console); + + if (flags & SCF_MINIMAL) return SWITCH_STATUS_SUCCESS; + + runtime.tipping_point = 0; + runtime.timer_affinity = -1; + runtime.microseconds_per_tick = 20000; + + switch_load_core_config("switch.conf"); + + switch_core_state_machine_init(runtime.memory_pool); + + if (switch_core_sqldb_start(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_SQL) ? SWITCH_TRUE : SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { + *err = "Error activating database"; + return SWITCH_STATUS_FALSE; + } + + switch_scheduler_task_thread_start(); + + switch_nat_late_init(); + + switch_rtp_init(runtime.memory_pool); + + runtime.running = 1; + runtime.initiated = switch_time_now(); + runtime.mono_initiated = switch_mono_micro_time_now(); + + switch_scheduler_add_task(switch_epoch_time_now(NULL), heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL); + + switch_scheduler_add_task(switch_epoch_time_now(NULL), check_ip_callback, "check_ip", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL | SSHF_OWN_THREAD); + + switch_uuid_get(&uuid); + switch_uuid_format(runtime.uuid_str, &uuid); + switch_core_set_variable("core_uuid", runtime.uuid_str); + + + return SWITCH_STATUS_SUCCESS; +} + + +#ifndef WIN32 +static void handle_SIGCHLD(int sig) +{ + int status = 0; + + wait(&status); + return; +} +#endif + +#ifdef TRAP_BUS +static void handle_SIGBUS(int sig) +{ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Sig BUS!\n"); + return; +} +#endif + +static void handle_SIGHUP(int sig) +{ + if (sig) { + switch_event_t *event; + + if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Trapped-Signal", "HUP"); + switch_event_fire(&event); + } + } + return; +} + + +SWITCH_DECLARE(uint32_t) switch_default_ptime(const char *name, uint32_t number) +{ + uint32_t *p; + + if ((p = switch_core_hash_find(runtime.ptimes, name))) { + return *p; + } + + return 20; +} + +static uint32_t d_30 = 30; + +static void switch_load_core_config(const char *file) +{ + switch_xml_t xml = NULL, cfg = NULL; + + switch_core_hash_insert(runtime.ptimes, "ilbc", &d_30); + switch_core_hash_insert(runtime.ptimes, "G723", &d_30); + + if ((xml = switch_xml_open_cfg(file, &cfg, NULL))) { + switch_xml_t settings, param; + + if ((settings = switch_xml_child(cfg, "default-ptimes"))) { + for (param = switch_xml_child(settings, "codec"); param; param = param->next) { + const char *var = switch_xml_attr_soft(param, "name"); + const char *val = switch_xml_attr_soft(param, "ptime"); + + if (!zstr(var) && !zstr(val)) { + uint32_t *p; + uint32_t v = switch_atoul(val); + + if (!strcasecmp(var, "G723") || !strcasecmp(var, "iLBC")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding %s, defaults cannot be changed\n", var); + continue; + } + + if (v == 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding %s, invalid ptime\n", var); + continue; + } + + p = switch_core_alloc(runtime.memory_pool, sizeof(*p)); + *p = v; + switch_core_hash_insert(runtime.ptimes, var, p); + } + + } + } + + if ((settings = switch_xml_child(cfg, "settings"))) { + for (param = switch_xml_child(settings, "param"); param; param = param->next) { + const char *var = switch_xml_attr_soft(param, "name"); + const char *val = switch_xml_attr_soft(param, "value"); + + if (!strcasecmp(var, "loglevel")) { + int level; + if (*val > 47 && *val < 58) { + level = atoi(val); + } else { + level = switch_log_str2level(val); + } + + if (level != SWITCH_LOG_INVALID) { + switch_core_session_ctl(SCSC_LOGLEVEL, &level); + } +#ifdef HAVE_SETRLIMIT + } else if (!strcasecmp(var, "dump-cores") && switch_true(val)) { + struct rlimit rlp; + memset(&rlp, 0, sizeof(rlp)); + rlp.rlim_cur = RLIM_INFINITY; + rlp.rlim_max = RLIM_INFINITY; + setrlimit(RLIMIT_CORE, &rlp); +#endif + } else if (!strcasecmp(var, "debug-level")) { + int tmp = atoi(val); + if (tmp > -1 && tmp < 11) { + switch_core_session_ctl(SCSC_DEBUG_LEVEL, &tmp); + } + } else if (!strcasecmp(var, "max-db-handles")) { + long tmp = atol(val); + + if (tmp > 4 && tmp < 5001) { + runtime.max_db_handles = (uint32_t) tmp; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "max-db-handles must be between 5 and 5000\n"); + } + } else if (!strcasecmp(var, "db-handle-timeout")) { + long tmp = atol(val); + + if (tmp > 0 && tmp < 5001) { + runtime.db_handle_timeout = (uint32_t) tmp * 1000000; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "db-handle-timeout must be between 1 and 5000\n"); + } + + } else if (!strcasecmp(var, "multiple-registrations")) { + runtime.multiple_registrations = switch_true(val); + } else if (!strcasecmp(var, "auto-create-schemas")) { + if (switch_true(val)) { + switch_set_flag((&runtime), SCF_AUTO_SCHEMAS); + } else { + switch_clear_flag((&runtime), SCF_AUTO_SCHEMAS); + } + } else if (!strcasecmp(var, "session-thread-pool")) { + if (switch_true(val)) { + switch_set_flag((&runtime), SCF_SESSION_THREAD_POOL); + } else { + switch_clear_flag((&runtime), SCF_SESSION_THREAD_POOL); + } + } else if (!strcasecmp(var, "auto-clear-sql")) { + if (switch_true(val)) { + switch_set_flag((&runtime), SCF_CLEAR_SQL); + } else { + switch_clear_flag((&runtime), SCF_CLEAR_SQL); + } + } else if (!strcasecmp(var, "api-expansion")) { + if (switch_true(val)) { + switch_set_flag((&runtime), SCF_API_EXPANSION); + } else { + switch_clear_flag((&runtime), SCF_API_EXPANSION); + } + } else if (!strcasecmp(var, "enable-early-hangup") && switch_true(val)) { + switch_set_flag((&runtime), SCF_EARLY_HANGUP); + } else if (!strcasecmp(var, "colorize-console") && switch_true(val)) { + runtime.colorize_console = SWITCH_TRUE; + } else if (!strcasecmp(var, "core-db-pre-trans-execute") && !zstr(val)) { + runtime.core_db_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "core-db-post-trans-execute") && !zstr(val)) { + runtime.core_db_post_trans_execute = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "core-db-inner-pre-trans-execute") && !zstr(val)) { + runtime.core_db_inner_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "core-db-inner-post-trans-execute") && !zstr(val)) { + runtime.core_db_inner_post_trans_execute = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "mailer-app") && !zstr(val)) { + runtime.mailer_app = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "mailer-app-args") && val) { + runtime.mailer_app_args = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "sessions-per-second") && !zstr(val)) { + switch_core_sessions_per_second(atoi(val)); + } else if (!strcasecmp(var, "max-dtmf-duration") && !zstr(val)) { + int tmp = atoi(val); + if (tmp > 0) { + switch_core_max_dtmf_duration((uint32_t) tmp); + } + } else if (!strcasecmp(var, "min-dtmf-duration") && !zstr(val)) { + int tmp = atoi(val); + if (tmp > 0) { + switch_core_min_dtmf_duration((uint32_t) tmp); + } + } else if (!strcasecmp(var, "default-dtmf-duration") && !zstr(val)) { + int tmp = atoi(val); + if (tmp > 0) { + switch_core_default_dtmf_duration((uint32_t) tmp); + } + } else if (!strcasecmp(var, "enable-use-system-time")) { + switch_time_set_use_system_time(switch_true(val)); + } else if (!strcasecmp(var, "enable-monotonic-timing")) { + switch_time_set_monotonic(switch_true(val)); + } else if (!strcasecmp(var, "enable-softtimer-timerfd")) { + switch_time_set_timerfd(switch_true(val)); + } else if (!strcasecmp(var, "enable-clock-nanosleep")) { + switch_time_set_nanosleep(switch_true(val)); + } else if (!strcasecmp(var, "enable-cond-yield")) { + switch_time_set_cond_yield(switch_true(val)); + } else if (!strcasecmp(var, "enable-timer-matrix")) { + switch_time_set_matrix(switch_true(val)); + } else if (!strcasecmp(var, "max-sessions") && !zstr(val)) { + switch_core_session_limit(atoi(val)); + } else if (!strcasecmp(var, "verbose-channel-events") && !zstr(val)) { + int v = switch_true(val); + if (v) { + switch_set_flag((&runtime), SCF_VERBOSE_EVENTS); + } else { + switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS); + } + } else if (!strcasecmp(var, "threaded-system-exec") && !zstr(val)) { +#ifdef WIN32 + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "threaded-system-exec is not implemented on this platform\n"); +#else + int v = switch_true(val); + if (v) { + switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } else { + switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } +#endif + } else if (!strcasecmp(var, "min-idle-cpu") && !zstr(val)) { + switch_core_min_idle_cpu(atof(val)); + } else if (!strcasecmp(var, "tipping-point") && !zstr(val)) { + runtime.tipping_point = atoi(val); + } else if (!strcasecmp(var, "initial-event-threads") && !zstr(val)) { + int tmp = atoi(val); + + + if (tmp > runtime.cpu_count / 2) { + tmp = runtime.cpu_count / 2; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "This value cannot be higher than %d so setting it to that value\n", + runtime.cpu_count / 2); + } + + if (tmp < 1) { + tmp = 1; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "This value cannot be lower than 1 so setting it to that level\n"); + } + + switch_event_launch_dispatch_threads(tmp); + + } else if (!strcasecmp(var, "1ms-timer") && switch_true(val)) { + runtime.microseconds_per_tick = 1000; + } else if (!strcasecmp(var, "timer-affinity") && !zstr(val)) { + if (!strcasecmp(val, "disabled")) { + runtime.timer_affinity = -1; + } else { + runtime.timer_affinity = atoi(val); + } + } else if (!strcasecmp(var, "rtp-start-port") && !zstr(val)) { + switch_rtp_set_start_port((switch_port_t) atoi(val)); + } else if (!strcasecmp(var, "rtp-end-port") && !zstr(val)) { + switch_rtp_set_end_port((switch_port_t) atoi(val)); + } else if (!strcasecmp(var, "core-db-name") && !zstr(val)) { + runtime.dbname = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "core-db-dsn") && !zstr(val)) { + if (switch_odbc_available() || switch_pgsql_available()) { + runtime.odbc_dsn = switch_core_strdup(runtime.memory_pool, val); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC AND PGSQL ARE NOT AVAILABLE!\n"); + } + } else if (!strcasecmp(var, "core-non-sqlite-db-required") && !zstr(val)) { + switch_set_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ); + } else if (!strcasecmp(var, "core-dbtype") && !zstr(val)) { + if (!strcasecmp(val, "MSSQL")) { + runtime.odbc_dbtype = DBTYPE_MSSQL; + } else { + runtime.odbc_dbtype = DBTYPE_DEFAULT; + } +#ifdef ENABLE_ZRTP + } else if (!strcasecmp(var, "rtp-enable-zrtp")) { + switch_core_set_variable("zrtp_enabled", val); +#endif + } else if (!strcasecmp(var, "switchname") && !zstr(val)) { + runtime.switchname = switch_core_strdup(runtime.memory_pool, val); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Set switchname to %s\n", runtime.switchname); + } + } + } + + if ((settings = switch_xml_child(cfg, "variables"))) { + for (param = switch_xml_child(settings, "variable"); param; param = param->next) { + const char *var = switch_xml_attr_soft(param, "name"); + const char *val = switch_xml_attr_soft(param, "value"); + if (var && val) { + switch_core_set_variable(var, val); + } + } + } + + switch_xml_free(xml); + } + + +} + +SWITCH_DECLARE(const char *) switch_core_banner(void) +{ + + return ("\n" + ".=============================================================.\n" + "| _____ ______ _____ _____ ____ _ _ |\n" + "| | ___| __ ___ ___/ ___\\ \\ / /_ _|_ _/ ___| | | | |\n" + "| | |_ | '__/ _ \\/ _ \\___ \\\\ \\ /\\ / / | | | || | | |_| | |\n" + "| | _|| | | __/ __/___) |\\ V V / | | | || |___| _ | |\n" + "| |_| |_| \\___|\\___|____/ \\_/\\_/ |___| |_| \\____|_| |_| |\n" + "| |\n" + ".=============================================================." + "\n" + + "| Anthony Minessale II, Michael Jerris, Brian West, Others |\n" + "| FreeSWITCH (http://www.freeswitch.org) |\n" + "| Paypal Donations Appreciated: paypal@freeswitch.org |\n" + "| Brought to you by ClueCon http://www.cluecon.com/ |\n" + ".=============================================================.\n" + "\n"); +} + + +SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t flags, switch_bool_t console, const char **err) +{ + switch_event_t *event; + char *cmd; + int x = 0; + const char *use = NULL; +#include "cc.h" + + + if (switch_core_init(flags, console, err) != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_GENERR; + } + + if (runtime.runlevel > 1) { + /* one per customer */ + return SWITCH_STATUS_SUCCESS; + } + + runtime.runlevel++; + + switch_core_set_signal_handlers(); + switch_load_network_lists(SWITCH_FALSE); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Bringing up environment.\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Loading Modules.\n"); + if (switch_loadable_module_init(SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) { + *err = "Cannot load modules"; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error: %s\n", *err); + return SWITCH_STATUS_GENERR; + } + + switch_load_network_lists(SWITCH_FALSE); + + switch_load_core_config("post_load_switch.conf"); + + switch_core_set_signal_handlers(); + + if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready"); + switch_event_fire(&event); + } + + switch_core_screen_size(&x, NULL); + + use = (x > 100) ? cc : cc_s; + +#ifdef WIN32 + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s\n\n", switch_core_banner(), use); +#else + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s%s%s%s%s\n\n", + SWITCH_SEQ_DEFAULT_COLOR, + SWITCH_SEQ_FYELLOW, SWITCH_SEQ_BBLUE, + switch_core_banner(), + use, SWITCH_SEQ_DEFAULT_COLOR); + +#endif + + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, + "\nFreeSWITCH Version %s (%s)\n\nFreeSWITCH Started\nMax Sessions [%u]\nSession Rate [%d]\nSQL [%s]\n", + SWITCH_VERSION_FULL, SWITCH_VERSION_REVISION_HUMAN, + switch_core_session_limit(0), + switch_core_sessions_per_second(0), switch_test_flag((&runtime), SCF_USE_SQL) ? "Enabled" : "Disabled"); + + + if (x < 160) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\n[This app Best viewed at 160x60 or more..]\n"); + } + + switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS); + + if ((cmd = switch_core_get_variable_dup("api_on_startup"))) { + switch_stream_handle_t stream = { 0 }; + SWITCH_STANDARD_STREAM(stream); + switch_console_execute(cmd, 0, &stream); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Startup command [%s] executed. Output:\n%s\n", cmd, (char *)stream.data); + free(stream.data); + free(cmd); + } + + return SWITCH_STATUS_SUCCESS; + +} + +SWITCH_DECLARE(void) switch_core_measure_time(switch_time_t total_ms, switch_core_time_duration_t *duration) +{ + switch_time_t temp = total_ms / 1000; + memset(duration, 0, sizeof(*duration)); + duration->mms = (uint32_t) (total_ms % 1000); + duration->ms = (uint32_t) (temp % 1000); + temp = temp / 1000; + duration->sec = (uint32_t) (temp % 60); + temp = temp / 60; + duration->min = (uint32_t) (temp % 60); + temp = temp / 60; + duration->hr = (uint32_t) (temp % 24); + temp = temp / 24; + duration->day = (uint32_t) (temp % 365); + duration->yr = (uint32_t) (temp / 365); +} + +SWITCH_DECLARE(switch_time_t) switch_core_uptime(void) +{ + return switch_mono_micro_time_now() - runtime.mono_initiated; +} + + +#ifdef _MSC_VER +static void win_shutdown(void) +{ + + HANDLE shutdown_event; + char path[512]; + /* for windows we need the event to signal for shutting down a background FreeSWITCH */ + snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid()); + + /* open the event so we can signal it */ + shutdown_event = OpenEvent(EVENT_MODIFY_STATE, FALSE, path); + + if (shutdown_event) { + /* signal the event to shutdown */ + SetEvent(shutdown_event); + /* cleanup */ + CloseHandle(shutdown_event); + } +} +#endif + +SWITCH_DECLARE(void) switch_core_set_signal_handlers(void) +{ + /* set signal handlers */ + signal(SIGINT, SIG_IGN); +#ifndef WIN32 + if (switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC)) { + signal(SIGCHLD, SIG_DFL); + } else { + signal(SIGCHLD, handle_SIGCHLD); + } +#endif +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif +#ifdef SIGQUIT + signal(SIGQUIT, SIG_IGN); +#endif +#ifdef SIGPOLL + signal(SIGPOLL, SIG_IGN); +#endif +#ifdef SIGIO + signal(SIGIO, SIG_IGN); +#endif +#ifdef TRAP_BUS + signal(SIGBUS, handle_SIGBUS); +#endif +#ifdef SIGUSR1 + signal(SIGUSR1, handle_SIGHUP); +#endif + signal(SIGHUP, handle_SIGHUP); +} + +SWITCH_DECLARE(uint32_t) switch_core_debug_level(void) +{ + return runtime.debug_level; +} + + +SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, void *val) +{ + int *intval = (int *) val; + int oldintval = 0, newintval = 0; + + if (intval) { + oldintval = *intval; + } + + if (switch_test_flag((&runtime), SCF_SHUTTING_DOWN)) { + return -1; + } + + switch (cmd) { + case SCSC_RECOVER: + { + char *arg = (char *) val; + char *tech = NULL, *prof = NULL; + int r, flush = 0; + + if (!zstr(arg)) { + tech = strdup(arg); + + if ((prof = strchr(tech, ':'))) { + *prof++ = '\0'; + } + + if (!strcasecmp(tech, "flush")) { + flush++; + + if (prof) { + tech = prof; + if ((prof = strchr(tech, ':'))) { + *prof++ = '\0'; + } + } + } + + } + + if (flush) { + switch_core_recovery_flush(tech, prof); + r = -1; + } else { + r = switch_core_recovery_recover(tech, prof); + } + + switch_safe_free(tech); + return r; + + } + break; + case SCSC_DEBUG_SQL: + { + if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) { + switch_clear_flag((&runtime), SCF_DEBUG_SQL); + newintval = 0; + } else { + switch_set_flag((&runtime), SCF_DEBUG_SQL); + newintval = 1; + } + } + break; + case SCSC_VERBOSE_EVENTS: + if (intval) { + if (oldintval > -1) { + if (oldintval) { + switch_set_flag((&runtime), SCF_VERBOSE_EVENTS); + } else { + switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS); + } + } + newintval = switch_test_flag((&runtime), SCF_VERBOSE_EVENTS); + } + break; + case SCSC_API_EXPANSION: + if (intval) { + if (oldintval > -1) { + if (oldintval) { + switch_set_flag((&runtime), SCF_API_EXPANSION); + } else { + switch_clear_flag((&runtime), SCF_API_EXPANSION); + } + } + newintval = switch_test_flag((&runtime), SCF_API_EXPANSION); + } + break; + case SCSC_THREADED_SYSTEM_EXEC: + if (intval) { + if (oldintval > -1) { + if (oldintval) { + switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } else { + switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } + } + newintval = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } + break; + case SCSC_CALIBRATE_CLOCK: + switch_time_calibrate_clock(); + break; + case SCSC_FLUSH_DB_HANDLES: + switch_cache_db_flush_handles(); + break; + case SCSC_SEND_SIGHUP: + handle_SIGHUP(1); + break; + case SCSC_SYNC_CLOCK: + switch_time_sync(); + newintval = 0; + break; + case SCSC_SYNC_CLOCK_WHEN_IDLE: + newintval = switch_core_session_sync_clock(); + break; + case SCSC_SQL: + if (oldintval) { + switch_core_sqldb_resume(); + } else { + switch_core_sqldb_pause(); + } + break; + case SCSC_PAUSE_ALL: + if (oldintval) { + switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); + } else { + switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS); + } + break; + case SCSC_PAUSE_INBOUND: + if (oldintval) { + switch_set_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS); + } else { + switch_clear_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS); + } + break; + case SCSC_PAUSE_OUTBOUND: + if (oldintval) { + switch_set_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS); + } else { + switch_clear_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS); + } + break; + case SCSC_HUPALL: + switch_core_session_hupall(SWITCH_CAUSE_MANAGER_REQUEST); + break; + case SCSC_CANCEL_SHUTDOWN: + switch_clear_flag((&runtime), SCF_SHUTDOWN_REQUESTED); + break; + case SCSC_SAVE_HISTORY: + switch_console_save_history(); + break; + case SCSC_CRASH: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Declinatio Mortuus Obfirmo!\n"); + switch_console_save_history(); + abort(); + break; + case SCSC_SHUTDOWN_NOW: + switch_console_save_history(); + exit(0); + break; + case SCSC_SHUTDOWN_ELEGANT: + case SCSC_SHUTDOWN_ASAP: + { + int x = 19; + uint32_t count; + + switch_set_flag((&runtime), SCF_SHUTDOWN_REQUESTED); + if (cmd == SCSC_SHUTDOWN_ASAP) { + switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); + } + + while (runtime.running && switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED) && (count = switch_core_session_count())) { + switch_yield(500000); + if (++x == 20) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Shutdown in progress, %u session(s) remain.\nShutting down %s\n", + count, cmd == SCSC_SHUTDOWN_ASAP ? "ASAP" : "once there are no active calls."); + x = 0; + } + } + + if (switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED)) { + switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); +#ifdef _MSC_VER + win_shutdown(); +#endif + + if (oldintval) { + switch_set_flag((&runtime), SCF_RESTART); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Restarting\n"); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutting down\n"); +#ifdef _MSC_VER + fclose(stdin); +#endif + } + runtime.running = 0; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutdown Cancelled\n"); + switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS); + } + } + break; + case SCSC_PAUSE_CHECK: + newintval = !!(switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS) == SCF_NO_NEW_SESSIONS); + break; + case SCSC_PAUSE_INBOUND_CHECK: + newintval = !!switch_test_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS); + break; + case SCSC_PAUSE_OUTBOUND_CHECK: + newintval = !!switch_test_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS); + break; + case SCSC_READY_CHECK: + newintval = switch_core_ready(); + break; + case SCSC_SHUTDOWN_CHECK: + newintval = !!switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED); + break; + case SCSC_SHUTDOWN: + +#ifdef _MSC_VER + win_shutdown(); +#endif + + if (oldintval) { + switch_set_flag((&runtime), SCF_RESTART); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Restarting\n"); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutting down\n"); +#ifdef _MSC_VER + fclose(stdin); +#endif + } + runtime.running = 0; + break; + case SCSC_CHECK_RUNNING: + newintval = runtime.running; + break; + case SCSC_LOGLEVEL: + if (oldintval > -1) { + runtime.hard_log_level = oldintval; + } + + if (runtime.hard_log_level > SWITCH_LOG_DEBUG) { + runtime.hard_log_level = SWITCH_LOG_DEBUG; + } + newintval = runtime.hard_log_level; + break; + case SCSC_DEBUG_LEVEL: + if (oldintval > -1) { + if (oldintval > 10) + newintval = 10; + runtime.debug_level = oldintval; + } + newintval = runtime.debug_level; + break; + case SCSC_MIN_IDLE_CPU: + { + double *dval = (double *) val; + if (dval) { + *dval = switch_core_min_idle_cpu(*dval); + } + intval = NULL; + } + break; + case SCSC_MAX_SESSIONS: + newintval = switch_core_session_limit(oldintval); + break; + case SCSC_LAST_SPS: + newintval = runtime.sps_last; + break; + case SCSC_MAX_DTMF_DURATION: + newintval = switch_core_max_dtmf_duration(oldintval); + break; + case SCSC_MIN_DTMF_DURATION: + newintval = switch_core_min_dtmf_duration(oldintval); + break; + case SCSC_DEFAULT_DTMF_DURATION: + newintval = switch_core_default_dtmf_duration(oldintval); + break; + case SCSC_SPS: + switch_mutex_lock(runtime.throttle_mutex); + if (oldintval > 0) { + runtime.sps_total = oldintval; + } + newintval = runtime.sps_total; + switch_mutex_unlock(runtime.throttle_mutex); + break; + + case SCSC_RECLAIM: + switch_core_memory_reclaim_all(); + newintval = 0; + break; + } + + if (intval) { + *intval = newintval; + } + + + return 0; +} + +SWITCH_DECLARE(switch_core_flag_t) switch_core_flags(void) +{ + return runtime.flags; +} + +SWITCH_DECLARE(switch_bool_t) switch_core_ready(void) +{ + return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS) == SCF_NO_NEW_SESSIONS) ? SWITCH_FALSE : SWITCH_TRUE; +} + +SWITCH_DECLARE(switch_bool_t) switch_core_ready_inbound(void) +{ + return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE; +} + +SWITCH_DECLARE(switch_bool_t) switch_core_ready_outbound(void) +{ + return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE; +} + +SWITCH_DECLARE(switch_status_t) switch_core_destroy(void) +{ + switch_event_t *event; + + if (switch_event_create(&event, SWITCH_EVENT_SHUTDOWN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Shutting Down"); + switch_event_fire(&event); + } + + switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); + switch_set_flag((&runtime), SCF_SHUTTING_DOWN); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "End existing sessions\n"); + switch_core_session_hupall(SWITCH_CAUSE_SYSTEM_SHUTDOWN); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Clean up modules.\n"); + + switch_loadable_module_shutdown(); + + switch_ssl_destroy_ssl_locks(); + + if (switch_test_flag((&runtime), SCF_USE_SQL)) { + switch_core_sqldb_stop(); + } + switch_scheduler_task_thread_stop(); + + switch_rtp_shutdown(); + + if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) { + switch_nat_shutdown(); + } + switch_xml_destroy(); + switch_core_session_uninit(); + switch_console_shutdown(); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Closing Event Engine.\n"); + switch_event_shutdown(); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n"); + switch_log_shutdown(); + + switch_core_unset_variables(); + switch_core_memory_stop(); + + if (runtime.console && runtime.console != stdout && runtime.console != stderr) { + fclose(runtime.console); + runtime.console = NULL; + } + + switch_safe_free(SWITCH_GLOBAL_dirs.base_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.mod_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.conf_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.log_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.db_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.script_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.htdocs_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.grammar_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.storage_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.recordings_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.sounds_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.run_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.temp_dir); + + switch_event_destroy(&runtime.global_vars); + switch_core_hash_destroy(&runtime.ptimes); + switch_core_hash_destroy(&runtime.mime_types); + + if (IP_LIST.hash) { + switch_core_hash_destroy(&IP_LIST.hash); + } + + if (IP_LIST.pool) { + switch_core_destroy_memory_pool(&IP_LIST.pool); + } + + if (runtime.memory_pool) { + apr_pool_destroy(runtime.memory_pool); + apr_terminate(); + } + + return switch_test_flag((&runtime), SCF_RESTART) ? SWITCH_STATUS_RESTART : SWITCH_STATUS_SUCCESS; +} + +SWITCH_DECLARE(switch_status_t) switch_core_management_exec(char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen) +{ + const switch_management_interface_t *ptr; + switch_status_t status = SWITCH_STATUS_FALSE; + + if ((ptr = switch_loadable_module_get_management_interface(relative_oid))) { + status = ptr->management_function(relative_oid, action, data, datalen); + } + + return status; +} + +SWITCH_DECLARE(void) switch_core_memory_reclaim_all(void) +{ + switch_core_memory_reclaim_logger(); + switch_core_memory_reclaim_events(); + switch_core_memory_reclaim(); +} + + +struct system_thread_handle { + const char *cmd; + switch_thread_cond_t *cond; + switch_mutex_t *mutex; + switch_memory_pool_t *pool; + int ret; + int *fds; +}; + +static void *SWITCH_THREAD_FUNC system_thread(switch_thread_t *thread, void *obj) +{ + struct system_thread_handle *sth = (struct system_thread_handle *) obj; + +#if 0 // if we are a luser we can never turn this back down, didn't we already set the stack size? +#if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__) + struct rlimit rlim; + + rlim.rlim_cur = SWITCH_SYSTEM_THREAD_STACKSIZE; + rlim.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE; + if (setrlimit(RLIMIT_STACK, &rlim) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno)); + } +#endif +#endif + + if (sth->fds) { + dup2(sth->fds[1], STDOUT_FILENO); + } + + sth->ret = system(sth->cmd); + +#if 0 +#if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__) + rlim.rlim_cur = SWITCH_THREAD_STACKSIZE; + rlim.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE; + if (setrlimit(RLIMIT_STACK, &rlim) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno)); + } +#endif +#endif + + switch_mutex_lock(sth->mutex); + switch_thread_cond_signal(sth->cond); + switch_mutex_unlock(sth->mutex); + + switch_core_destroy_memory_pool(&sth->pool); + + return NULL; +} + + +static int switch_system_thread(const char *cmd, switch_bool_t wait) +{ + switch_thread_t *thread; + switch_threadattr_t *thd_attr; + int ret = 0; + struct system_thread_handle *sth; + switch_memory_pool_t *pool; + + if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Pool Failure\n"); + return 1; + } + + if (!(sth = switch_core_alloc(pool, sizeof(struct system_thread_handle)))) { + switch_core_destroy_memory_pool(&pool); + return 1; + } + + sth->pool = pool; + sth->cmd = switch_core_strdup(pool, cmd); + + switch_thread_cond_create(&sth->cond, sth->pool); + switch_mutex_init(&sth->mutex, SWITCH_MUTEX_NESTED, sth->pool); + switch_mutex_lock(sth->mutex); + + switch_threadattr_create(&thd_attr, sth->pool); + switch_threadattr_stacksize_set(thd_attr, SWITCH_SYSTEM_THREAD_STACKSIZE); + switch_threadattr_detach_set(thd_attr, 1); + switch_thread_create(&thread, thd_attr, system_thread, sth, sth->pool); + + if (wait) { + switch_thread_cond_wait(sth->cond, sth->mutex); + ret = sth->ret; + } + switch_mutex_unlock(sth->mutex); + + return ret; +} + +SWITCH_DECLARE(int) switch_max_file_desc(void) +{ + int max = 0; + +#ifndef WIN32 +#if defined(HAVE_GETDTABLESIZE) + max = getdtablesize(); +#else + max = sysconf(_SC_OPEN_MAX); +#endif +#endif + + return max; + +} + +SWITCH_DECLARE(void) switch_close_extra_files(int *keep, int keep_ttl) +{ + int open_max = switch_max_file_desc(); + int i, j; + + for (i = 3; i < open_max; i++) { + if (keep) { + for (j = 0; j < keep_ttl; j++) { + if (i == keep[j]) { + goto skip; + } + } + } + + close(i); + + skip: + + continue; + + } +} + + +#ifdef WIN32 +static int switch_system_fork(const char *cmd, switch_bool_t wait) +{ + return switch_system_thread(cmd, wait); +} + +SWITCH_DECLARE(pid_t) switch_fork(void) +{ + return -1; +} + + +#else + +SWITCH_DECLARE(pid_t) switch_fork(void) +{ + int i = fork(); + + if (!i) { + set_low_priority(); + } + + return i; +} + + + +static int switch_system_fork(const char *cmd, switch_bool_t wait) +{ + int pid; + char *dcmd = strdup(cmd); + + switch_core_set_signal_handlers(); + + pid = switch_fork(); + + if (pid) { + if (wait) { + waitpid(pid, NULL, 0); + } + free(dcmd); + } else { + switch_close_extra_files(NULL, 0); + + if (system(dcmd) == -1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute because of a command error : %s\n", dcmd); + } + free(dcmd); + exit(0); + } + + return 0; +} +#endif + + + +SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait) +{ + int (*sys_p)(const char *cmd, switch_bool_t wait); + + sys_p = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC) ? switch_system_thread : switch_system_fork; + + return sys_p(cmd, wait); + +} + + + +SWITCH_DECLARE(int) switch_stream_system_fork(const char *cmd, switch_stream_handle_t *stream) +{ +#ifdef WIN32 + return switch_system(cmd, SWITCH_TRUE); +#else + int fds[2], pid = 0; + + if (pipe(fds)) { + goto end; + } else { /* good to go */ + pid = switch_fork(); + + if (pid < 0) { /* ok maybe not */ + close(fds[0]); + close(fds[1]); + goto end; + } else if (pid) { /* parent */ + char buf[1024] = ""; + int bytes; + close(fds[1]); + while ((bytes = read(fds[0], buf, sizeof(buf))) > 0) { + stream->raw_write_function(stream, (unsigned char *)buf, bytes); + } + close(fds[0]); + waitpid(pid, NULL, 0); + } else { /* child */ + switch_close_extra_files(fds, 2); + close(fds[0]); + dup2(fds[1], STDOUT_FILENO); + switch_system(cmd, SWITCH_TRUE); + close(fds[1]); + exit(0); + } + } + + end: + + return 0; + +#endif + +} + +SWITCH_DECLARE(switch_status_t) switch_core_get_stacksizes(switch_size_t *cur, switch_size_t *max) +{ +#ifdef HAVE_SETRLIMIT + struct rlimit rlp; + + memset(&rlp, 0, sizeof(rlp)); + getrlimit(RLIMIT_STACK, &rlp); + + *cur = rlp.rlim_cur; + *max = rlp.rlim_max; + + return SWITCH_STATUS_SUCCESS; + +#else + + return SWITCH_STATUS_FALSE; + +#endif + + + +} + + +SWITCH_DECLARE(int) switch_stream_system(const char *cmd, switch_stream_handle_t *stream) +{ +#ifdef WIN32 + stream->write_function(stream, "Capturing output not supported.\n"); + return switch_system(cmd, SWITCH_TRUE); +#else + return switch_stream_system_fork(cmd, stream); +#endif + +} + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */ From 3ea579ccc32a56d60fd2989594d094c22d516c48 Mon Sep 17 00:00:00 2001 From: Eliot Gable Date: Tue, 20 Nov 2012 14:09:02 +0000 Subject: [PATCH 03/30] FS-4850: Make cache db get_handle call not return handles which are already in use. --- src/switch_core_sqldb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index b776a14a87..5df382efab 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -144,7 +144,7 @@ static switch_cache_db_handle_t *get_handle(const char *db_str, const char *user switch_mutex_lock(sql_manager.dbh_mutex); for (dbh_ptr = sql_manager.handle_pool; dbh_ptr; dbh_ptr = dbh_ptr->next) { - if (dbh_ptr->thread_hash == thread_hash && dbh_ptr->hash == hash && + if (dbh_ptr->thread_hash == thread_hash && dbh_ptr->hash == hash && !dbh_ptr->use_count && !switch_test_flag(dbh_ptr, CDF_PRUNE) && switch_mutex_trylock(dbh_ptr->mutex) == SWITCH_STATUS_SUCCESS) { r = dbh_ptr; } From bfae89267e68ec94551b5c892fe32459219f61e0 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 20 Nov 2012 10:13:05 -0600 Subject: [PATCH 04/30] revert --- src/switch_core.c | 5665 ++++++++++++++++++++++----------------------- 1 file changed, 2831 insertions(+), 2834 deletions(-) diff --git a/src/switch_core.c b/src/switch_core.c index 9bbb11956d..4682d3c002 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1,2834 +1,2831 @@ -/* - * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2005-2012, Anthony Minessale II - * - * Version: MPL 1.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * - * The Initial Developer of the Original Code is - * Anthony Minessale II - * Portions created by the Initial Developer are Copyright (C) - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Anthony Minessale II - * Michael Jerris - * Paul D. Tinsley - * Marcel Barbulescu - * Joseph Sullivan - * - * - * switch_core.c -- Main Core Library - * - */ - - - -#include -#include -#include -#include -#include -#include "private/switch_core_pvt.h" -#include -#ifndef WIN32 -#include -#ifdef HAVE_SETRLIMIT -#include -#endif -#endif -#include - - -SWITCH_DECLARE_DATA switch_directories SWITCH_GLOBAL_dirs = { 0 }; - -/* The main runtime obj we keep this hidden for ourselves */ -struct switch_runtime runtime = { 0 }; -static void switch_load_core_config(const char *file); - -static void send_heartbeat(void) -{ - switch_event_t *event; - switch_core_time_duration_t duration; - - switch_core_measure_time(switch_core_uptime(), &duration); - - if (switch_event_create(&event, SWITCH_EVENT_HEARTBEAT) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready"); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Up-Time", - "%u year%s, " - "%u day%s, " - "%u hour%s, " - "%u minute%s, " - "%u second%s, " - "%u millisecond%s, " - "%u microsecond%s", - duration.yr, duration.yr == 1 ? "" : "s", - duration.day, duration.day == 1 ? "" : "s", - duration.hr, duration.hr == 1 ? "" : "s", - duration.min, duration.min == 1 ? "" : "s", - duration.sec, duration.sec == 1 ? "" : "s", - duration.ms, duration.ms == 1 ? "" : "s", duration.mms, duration.mms == 1 ? "" : "s"); - - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Version", SWITCH_VERSION_FULL); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Uptime-msec", "%"SWITCH_TIME_T_FMT, switch_core_uptime() / 1000); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Count", "%u", switch_core_session_count()); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Max-Sessions", "%u", switch_core_session_limit(0)); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec", "%u", runtime.sps); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Since-Startup", "%" SWITCH_SIZE_T_FMT, switch_core_session_id() - 1); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Idle-CPU", "%f", switch_core_idle_cpu()); - switch_event_fire(&event); - } -} - -static char main_ip4[256] = ""; -static char main_ip6[256] = ""; - -static void check_ip(void) -{ - char guess_ip4[256] = ""; - char guess_ip6[256] = ""; - char old_ip4[256] = ""; - char old_ip6[256] = ""; - int ok4 = 1, ok6 = 1; - int mask = 0; - - gethostname(runtime.hostname, sizeof(runtime.hostname)); - switch_core_set_variable("hostname", runtime.hostname); - - switch_find_local_ip(guess_ip4, sizeof(guess_ip4), &mask, AF_INET); - switch_find_local_ip(guess_ip6, sizeof(guess_ip6), NULL, AF_INET6); - - if (!*main_ip4) { - switch_set_string(main_ip4, guess_ip4); - } else { - if (!(ok4 = !strcmp(main_ip4, guess_ip4))) { - struct in_addr in; - - in.s_addr = mask; - switch_set_string(old_ip4, main_ip4); - switch_set_string(main_ip4, guess_ip4); - switch_core_set_variable("local_ip_v4", guess_ip4); - switch_core_set_variable("local_mask_v4", inet_ntoa(in)); - } - } - - if (!*main_ip6) { - switch_set_string(main_ip6, guess_ip6); - } else { - if (!(ok6 = !strcmp(main_ip6, guess_ip6))) { - switch_set_string(old_ip6, main_ip6); - switch_set_string(main_ip6, guess_ip6); - switch_core_set_variable("local_ip_v6", guess_ip6); - } - } - - if (!ok4 || !ok6) { - switch_event_t *event; - - if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "condition", "network-address-change"); - if (!ok4) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v4", old_ip4); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v4", main_ip4); - } - if (!ok6) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v6", old_ip6); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v6", main_ip6); - } - switch_event_fire(&event); - } - } -} - -SWITCH_STANDARD_SCHED_FUNC(heartbeat_callback) -{ - send_heartbeat(); - - /* reschedule this task */ - task->runtime = switch_epoch_time_now(NULL) + 20; -} - - -SWITCH_STANDARD_SCHED_FUNC(check_ip_callback) -{ - check_ip(); - - /* reschedule this task */ - task->runtime = switch_epoch_time_now(NULL) + 60; -} - - -SWITCH_DECLARE(switch_status_t) switch_core_set_console(const char *console) -{ - if ((runtime.console = fopen(console, "a")) == 0) { - fprintf(stderr, "Cannot open output file %s.\n", console); - return SWITCH_STATUS_FALSE; - } - - return SWITCH_STATUS_SUCCESS; -} - -SWITCH_DECLARE(FILE *) switch_core_get_console(void) -{ - return runtime.console; -} - -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -SWITCH_DECLARE(void) switch_core_screen_size(int *x, int *y) -{ - -#ifdef WIN32 - CONSOLE_SCREEN_BUFFER_INFO csbi; - int ret; - - if ((ret = GetConsoleScreenBufferInfo(GetStdHandle( STD_OUTPUT_HANDLE ), &csbi))) { - if (x) *x = csbi.dwSize.X; - if (y) *y = csbi.dwSize.Y; - } - -#elif defined(TIOCGWINSZ) - struct winsize w; - ioctl(0, TIOCGWINSZ, &w); - - if (x) *x = w.ws_col; - if (y) *y = w.ws_row; -#else - if (x) *x = 80; - if (y) *y = 24; -#endif - -} - -SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel_t channel) -{ - FILE *handle = stdout; - - switch (channel) { - case SWITCH_CHANNEL_ID_LOG: - case SWITCH_CHANNEL_ID_LOG_CLEAN: - handle = runtime.console; - break; - default: - handle = runtime.console; - break; - } - - return handle; -} - - -SWITCH_DECLARE(void) switch_core_remove_state_handler(const switch_state_handler_table_t *state_handler) -{ - int index, tmp_index = 0; - const switch_state_handler_table_t *tmp[SWITCH_MAX_STATE_HANDLERS + 1] = { 0 }; - - switch_mutex_lock(runtime.global_mutex); - - for (index = 0; index < runtime.state_handler_index; index++) { - const switch_state_handler_table_t *cur = runtime.state_handlers[index]; - runtime.state_handlers[index] = NULL; - if (cur == state_handler) { - continue; - } - tmp[tmp_index++] = cur; - } - - runtime.state_handler_index = 0; - - for (index = 0; index < tmp_index; index++) { - runtime.state_handlers[runtime.state_handler_index++] = tmp[index]; - } - switch_mutex_unlock(runtime.global_mutex); -} - - -SWITCH_DECLARE(int) switch_core_add_state_handler(const switch_state_handler_table_t *state_handler) -{ - int index; - - switch_mutex_lock(runtime.global_mutex); - index = runtime.state_handler_index++; - - if (runtime.state_handler_index >= SWITCH_MAX_STATE_HANDLERS) { - index = -1; - } else { - runtime.state_handlers[index] = state_handler; - } - - switch_mutex_unlock(runtime.global_mutex); - return index; -} - -SWITCH_DECLARE(const switch_state_handler_table_t *) switch_core_get_state_handler(int index) -{ - - if (index >= SWITCH_MAX_STATE_HANDLERS || index > runtime.state_handler_index) { - return NULL; - } - - return runtime.state_handlers[index]; -} - -SWITCH_DECLARE(void) switch_core_dump_variables(switch_stream_handle_t *stream) -{ - switch_event_header_t *hi; - - switch_mutex_lock(runtime.global_mutex); - for (hi = runtime.global_vars->headers; hi; hi = hi->next) { - stream->write_function(stream, "%s=%s\n", hi->name, hi->value); - } - switch_mutex_unlock(runtime.global_mutex); -} - -SWITCH_DECLARE(const char *) switch_core_get_hostname(void) -{ - return runtime.hostname; -} - -SWITCH_DECLARE(const char *) switch_core_get_switchname(void) -{ - if (!zstr(runtime.switchname)) return runtime.switchname; - return runtime.hostname; -} - - -SWITCH_DECLARE(char *) switch_core_get_variable(const char *varname) -{ - char *val; - switch_thread_rwlock_rdlock(runtime.global_var_rwlock); - val = (char *) switch_event_get_header(runtime.global_vars, varname); - switch_thread_rwlock_unlock(runtime.global_var_rwlock); - return val; -} - -SWITCH_DECLARE(char *) switch_core_get_variable_dup(const char *varname) -{ - char *val = NULL, *v; - - switch_thread_rwlock_rdlock(runtime.global_var_rwlock); - if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) { - val = strdup(v); - } - switch_thread_rwlock_unlock(runtime.global_var_rwlock); - - return val; -} - -SWITCH_DECLARE(char *) switch_core_get_variable_pdup(const char *varname, switch_memory_pool_t *pool) -{ - char *val = NULL, *v; - - switch_thread_rwlock_rdlock(runtime.global_var_rwlock); - if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) { - val = switch_core_strdup(pool, v); - } - switch_thread_rwlock_unlock(runtime.global_var_rwlock); - - return val; -} - -static void switch_core_unset_variables(void) -{ - switch_thread_rwlock_wrlock(runtime.global_var_rwlock); - switch_event_destroy(&runtime.global_vars); - switch_event_create_plain(&runtime.global_vars, SWITCH_EVENT_CHANNEL_DATA); - switch_thread_rwlock_unlock(runtime.global_var_rwlock); -} - -SWITCH_DECLARE(void) switch_core_set_variable(const char *varname, const char *value) -{ - char *val; - - if (varname) { - switch_thread_rwlock_wrlock(runtime.global_var_rwlock); - val = (char *) switch_event_get_header(runtime.global_vars, varname); - if (val) { - switch_event_del_header(runtime.global_vars, varname); - } - if (value) { - char *v = strdup(value); - switch_string_var_check(v, SWITCH_TRUE); - switch_event_add_header_string(runtime.global_vars, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, varname, v); - } else { - switch_event_del_header(runtime.global_vars, varname); - } - switch_thread_rwlock_unlock(runtime.global_var_rwlock); - } -} - -SWITCH_DECLARE(switch_bool_t) switch_core_set_var_conditional(const char *varname, const char *value, const char *val2) -{ - char *val; - - if (varname) { - switch_thread_rwlock_wrlock(runtime.global_var_rwlock); - val = (char *) switch_event_get_header(runtime.global_vars, varname); - - if (val) { - if (!val2 || strcmp(val, val2) != 0) { - switch_thread_rwlock_unlock(runtime.global_var_rwlock); - return SWITCH_FALSE; - } - switch_event_del_header(runtime.global_vars, varname); - } else if (!zstr(val2)) { - switch_thread_rwlock_unlock(runtime.global_var_rwlock); - return SWITCH_FALSE; - } - - if (value) { - char *v = strdup(value); - switch_string_var_check(v, SWITCH_TRUE); - switch_event_add_header_string(runtime.global_vars, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, varname, v); - } else { - switch_event_del_header(runtime.global_vars, varname); - } - switch_thread_rwlock_unlock(runtime.global_var_rwlock); - } - return SWITCH_TRUE; -} - -SWITCH_DECLARE(char *) switch_core_get_uuid(void) -{ - return runtime.uuid_str; -} - - -static void *SWITCH_THREAD_FUNC switch_core_service_thread(switch_thread_t *thread, void *obj) -{ - switch_core_session_t *session = obj; - switch_channel_t *channel; - switch_frame_t *read_frame; - -// switch_assert(thread != NULL); -// switch_assert(session != NULL); - - if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) { - return NULL; - } - - switch_mutex_lock(session->frame_read_mutex); - - channel = switch_core_session_get_channel(session); - - switch_channel_set_flag(channel, CF_SERVICE); - while (switch_channel_test_flag(channel, CF_SERVICE)) { - - if (switch_channel_test_flag(channel, CF_SERVICE_AUDIO)) { - switch (switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0)) { - case SWITCH_STATUS_SUCCESS: - case SWITCH_STATUS_TIMEOUT: - case SWITCH_STATUS_BREAK: - break; - default: - switch_channel_clear_flag(channel, CF_SERVICE); - break; - } - } - - if (switch_channel_test_flag(channel, CF_SERVICE_VIDEO) && switch_channel_test_flag(channel, CF_VIDEO)) { - switch (switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0)) { - case SWITCH_STATUS_SUCCESS: - case SWITCH_STATUS_TIMEOUT: - case SWITCH_STATUS_BREAK: - break; - default: - switch_channel_clear_flag(channel, CF_SERVICE); - break; - } - } - } - - switch_mutex_unlock(session->frame_read_mutex); - - switch_channel_clear_flag(channel, CF_SERVICE_AUDIO); - switch_channel_clear_flag(channel, CF_SERVICE_VIDEO); - - switch_core_session_rwunlock(session); - - return NULL; -} - -/* Either add a timeout here or make damn sure the thread cannot get hung somehow (my preference) */ -SWITCH_DECLARE(void) switch_core_thread_session_end(switch_core_session_t *session) -{ - switch_channel_t *channel; - switch_assert(session); - - channel = switch_core_session_get_channel(session); - switch_assert(channel); - - switch_channel_clear_flag(channel, CF_SERVICE); - switch_channel_clear_flag(channel, CF_SERVICE_AUDIO); - switch_channel_clear_flag(channel, CF_SERVICE_VIDEO); - - switch_core_session_kill_channel(session, SWITCH_SIG_BREAK); - -} - -SWITCH_DECLARE(void) switch_core_service_session_av(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video) -{ - switch_channel_t *channel; - switch_assert(session); - - channel = switch_core_session_get_channel(session); - switch_assert(channel); - - if (audio) switch_channel_set_flag(channel, CF_SERVICE_AUDIO); - if (video) switch_channel_set_flag(channel, CF_SERVICE_VIDEO); - - switch_core_session_launch_thread(session, (void *(*)(switch_thread_t *,void *))switch_core_service_thread, session); -} - -/* This function abstracts the thread creation for modules by allowing you to pass a function ptr and - a void object and trust that that the function will be run in a thread with arg This lets - you request and activate a thread without giving up any knowledge about what is in the thread - neither the core nor the calling module know anything about each other. - - This thread is expected to never exit until the application exits so the func is responsible - to make sure that is the case. - - The typical use for this is so switch_loadable_module.c can start up a thread for each module - passing the table of module methods as a session obj into the core without actually allowing - the core to have any clue and keeping switch_loadable_module.c from needing any thread code. - -*/ - -SWITCH_DECLARE(switch_thread_t *) switch_core_launch_thread(switch_thread_start_t func, void *obj, switch_memory_pool_t *pool) -{ - switch_thread_t *thread = NULL; - switch_threadattr_t *thd_attr = NULL; - switch_core_thread_session_t *ts; - int mypool; - - mypool = pool ? 0 : 1; - - if (!pool && switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory pool\n"); - return NULL; - } - - switch_threadattr_create(&thd_attr, pool); - - if ((ts = switch_core_alloc(pool, sizeof(*ts))) == 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory\n"); - } else { - if (mypool) { - ts->pool = pool; - } - ts->objs[0] = obj; - ts->objs[1] = thread; - switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); - switch_thread_create(&thread, thd_attr, func, ts, pool); - } - - return thread; -} - -SWITCH_DECLARE(void) switch_core_set_globals(void) -{ -#define BUFSIZE 1024 -#ifdef WIN32 - char lpPathBuffer[BUFSIZE]; - DWORD dwBufSize = BUFSIZE; - char base_dir[1024]; - char *lastbacklash; - char *tmp; - - GetModuleFileName(NULL, base_dir, BUFSIZE); - lastbacklash = strrchr(base_dir, '\\'); - base_dir[(lastbacklash - base_dir)] = '\0'; - /* set base_dir as cwd, to be able to use relative paths in scripting languages (e.g. mod_lua) when FS is running as a service or while debugging FS using visual studio */ - SetCurrentDirectory(base_dir); - tmp = switch_string_replace(base_dir, "\\", "/"); - strcpy(base_dir, tmp); - free(tmp); - -#else - char base_dir[1024] = SWITCH_PREFIX_DIR; -#endif - - if (!SWITCH_GLOBAL_dirs.base_dir && (SWITCH_GLOBAL_dirs.base_dir = (char *) malloc(BUFSIZE))) { - switch_snprintf(SWITCH_GLOBAL_dirs.base_dir, BUFSIZE, "%s", base_dir); - } - - if (!SWITCH_GLOBAL_dirs.mod_dir && (SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_MOD_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s", SWITCH_MOD_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s%smod", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.lib_dir && (SWITCH_GLOBAL_dirs.lib_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_LIB_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s", SWITCH_LIB_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s%slib", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.conf_dir && (SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_CONF_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s", SWITCH_CONF_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s%sconf", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.log_dir && (SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_LOG_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s", SWITCH_LOG_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s%slog", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.run_dir && (SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_RUN_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s", SWITCH_RUN_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s%srun", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.recordings_dir && (SWITCH_GLOBAL_dirs.recordings_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_RECORDINGS_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s", SWITCH_RECORDINGS_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s%srecordings", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.sounds_dir && (SWITCH_GLOBAL_dirs.sounds_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_SOUNDS_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s", SWITCH_SOUNDS_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s%ssounds", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.storage_dir && (SWITCH_GLOBAL_dirs.storage_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_STORAGE_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s", SWITCH_STORAGE_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s%sstorage", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.db_dir && (SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_DB_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s", SWITCH_DB_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s%sdb", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.script_dir && (SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_SCRIPT_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s", SWITCH_SCRIPT_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s%sscripts", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_HTDOCS_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s", SWITCH_HTDOCS_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s%shtdocs", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.grammar_dir && (SWITCH_GLOBAL_dirs.grammar_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_GRAMMAR_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s", SWITCH_GRAMMAR_DIR); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s%sgrammar", base_dir, SWITCH_PATH_SEPARATOR); -#endif - } - - if (!SWITCH_GLOBAL_dirs.temp_dir && (SWITCH_GLOBAL_dirs.temp_dir = (char *) malloc(BUFSIZE))) { -#ifdef SWITCH_TEMP_DIR - switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", SWITCH_TEMP_DIR); -#else -#ifdef WIN32 - GetTempPath(dwBufSize, lpPathBuffer); - lpPathBuffer[strlen(lpPathBuffer)-1] = 0; - tmp = switch_string_replace(lpPathBuffer, "\\", "/"); - strcpy(lpPathBuffer, tmp); - free(tmp); - switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", lpPathBuffer); -#else - switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", "/tmp"); -#endif -#endif - } - - switch_assert(SWITCH_GLOBAL_dirs.base_dir); - switch_assert(SWITCH_GLOBAL_dirs.mod_dir); - switch_assert(SWITCH_GLOBAL_dirs.lib_dir); - switch_assert(SWITCH_GLOBAL_dirs.conf_dir); - switch_assert(SWITCH_GLOBAL_dirs.log_dir); - switch_assert(SWITCH_GLOBAL_dirs.run_dir); - switch_assert(SWITCH_GLOBAL_dirs.db_dir); - switch_assert(SWITCH_GLOBAL_dirs.script_dir); - switch_assert(SWITCH_GLOBAL_dirs.htdocs_dir); - switch_assert(SWITCH_GLOBAL_dirs.grammar_dir); - switch_assert(SWITCH_GLOBAL_dirs.recordings_dir); - switch_assert(SWITCH_GLOBAL_dirs.sounds_dir); - switch_assert(SWITCH_GLOBAL_dirs.temp_dir); -} - - -SWITCH_DECLARE(int32_t) set_low_priority(void) -{ - - -#ifdef WIN32 - SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); -#else -#ifdef USE_SCHED_SETSCHEDULER - /* - * Try to use a normal scheduler - */ - struct sched_param sched = { 0 }; - sched.sched_priority = 0; - if (sched_setscheduler(0, SCHED_OTHER, &sched)) { - return -1; - } -#endif - -#ifdef HAVE_SETPRIORITY - /* - * setpriority() works on FreeBSD (6.2), nice() doesn't - */ - if (setpriority(PRIO_PROCESS, getpid(), 19) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); - return -1; - } -#else - if (nice(19) != 19) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); - return -1; - } -#endif -#endif - - return 0; -} - -SWITCH_DECLARE(int32_t) set_realtime_priority(void) -{ -#ifdef WIN32 - SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); -#else -#ifdef USE_SCHED_SETSCHEDULER - /* - * Try to use a round-robin scheduler - * with a fallback if that does not work - */ - struct sched_param sched = { 0 }; - sched.sched_priority = SWITCH_PRI_LOW; - if (sched_setscheduler(0, SCHED_FIFO, &sched)) { - sched.sched_priority = 0; - if (sched_setscheduler(0, SCHED_OTHER, &sched)) { - return -1; - } - } -#endif - - - -#ifdef HAVE_SETPRIORITY - /* - * setpriority() works on FreeBSD (6.2), nice() doesn't - */ - if (setpriority(PRIO_PROCESS, getpid(), -10) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); - return -1; - } -#else - if (nice(-10) != -10) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); - return -1; - } -#endif -#endif - return 0; -} - -SWITCH_DECLARE(uint32_t) switch_core_cpu_count(void) -{ - return runtime.cpu_count; -} - -SWITCH_DECLARE(int32_t) set_normal_priority(void) -{ - return 0; -} - -SWITCH_DECLARE(int32_t) set_auto_priority(void) -{ -#ifndef WIN32 - runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN); -#else - SYSTEM_INFO sysinfo; - GetSystemInfo( &sysinfo ); - runtime.cpu_count = sysinfo.dwNumberOfProcessors; -#endif - - if (!runtime.cpu_count) runtime.cpu_count = 1; - - /* If we have more than 1 cpu, we should use realtime priority so we can have priority threads */ - if (runtime.cpu_count > 1) { - return set_realtime_priority(); - } - - return 0; -} - -SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group) -{ -#ifndef WIN32 - uid_t runas_uid = 0; - gid_t runas_gid = 0; - struct passwd *runas_pw = NULL; - - if (user) { - /* - * Lookup user information in the system's db - */ - runas_pw = getpwnam(user); - if (!runas_pw) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unknown user \"%s\"\n", user); - return -1; - } - runas_uid = runas_pw->pw_uid; - } - - if (group) { - struct group *gr = NULL; - - /* - * Lookup group information in the system's db - */ - gr = getgrnam(group); - if (!gr) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unknown group \"%s\"\n", group); - return -1; - } - runas_gid = gr->gr_gid; - } - - if (runas_uid && getuid() == runas_uid && (!runas_gid || runas_gid == getgid())) { - /* already running as the right user and group, nothing to do! */ - return 0; - } - - if (runas_uid) { -#ifdef HAVE_SETGROUPS - /* - * Drop all group memberships prior to changing anything - * or else we're going to inherit the parent's list of groups - * (which is not what we want...) - */ - if (setgroups(0, NULL) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to drop group access list\n"); - return -1; - } -#endif - if (runas_gid) { - /* - * A group has been passed, switch to it - * (without loading the user's other groups) - */ - if (setgid(runas_gid) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change gid!\n"); - return -1; - } - } else { - /* - * No group has been passed, use the user's primary group in this case - */ - if (setgid(runas_pw->pw_gid) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change gid!\n"); - return -1; - } -#ifdef HAVE_INITGROUPS - /* - * Set all the other groups the user is a member of - * (This can be really useful for fine-grained access control) - */ - if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to set group access list for user\n"); - return -1; - } -#endif - } - - /* - * Finally drop all privileges by switching to the new userid - */ - if (setuid(runas_uid) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change uid!\n"); - return -1; - } - } -#endif - return 0; -} - -SWITCH_DECLARE(void) switch_core_runtime_loop(int bg) -{ -#ifdef WIN32 - HANDLE shutdown_event; - char path[256] = ""; -#endif - if (bg) { - bg = 0; -#ifdef WIN32 - switch_snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid()); - shutdown_event = CreateEvent(NULL, FALSE, FALSE, path); - if (shutdown_event) { - WaitForSingleObject(shutdown_event, INFINITE); - } -#else - runtime.running = 1; - while (runtime.running) { - switch_yield(1000000); - } -#endif - } else { - /* wait for console input */ - switch_console_loop(); - } -} - -SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext) -{ - if (!ext) { - return NULL; - } - return (const char *) switch_core_hash_find(runtime.mime_types, ext); -} - - -SWITCH_DECLARE(switch_hash_index_t *) switch_core_mime_index(void) -{ - return switch_hash_first(NULL, runtime.mime_types); -} - -SWITCH_DECLARE(switch_status_t) switch_core_mime_add_type(const char *type, const char *ext) -{ - const char *check; - switch_status_t status = SWITCH_STATUS_FALSE; - - switch_assert(type); - switch_assert(ext); - - check = (const char *) switch_core_hash_find(runtime.mime_types, ext); - - if (!check) { - char *ptype = switch_core_permanent_strdup(type); - char *ext_list = strdup(ext); - int argc = 0; - char *argv[20] = { 0 }; - int x; - - switch_assert(ext_list); - - if ((argc = switch_separate_string(ext_list, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { - - for (x = 0; x < argc; x++) { - if (argv[x] && ptype) { - switch_core_hash_insert(runtime.mime_types, argv[x], ptype); - } - } - - status = SWITCH_STATUS_SUCCESS; - } - - free(ext_list); - } - - return status; -} - -static void load_mime_types(void) -{ - char *cf = "mime.types"; - FILE *fd = NULL; - char *line_buf = NULL; - switch_size_t llen = 0; - char *mime_path = NULL; - - mime_path = switch_mprintf("%s/%s", SWITCH_GLOBAL_dirs.conf_dir, cf); - switch_assert(mime_path); - - fd = fopen(mime_path, "rb"); - - if (fd == NULL) { - goto end; - } - - while ((switch_fp_read_dline(fd, &line_buf, &llen))) { - char *p; - char *type = line_buf; - - if (*line_buf == '#') { - continue; - } - - if ((p = strchr(line_buf, '\r')) || (p = strchr(line_buf, '\n'))) { - *p = '\0'; - } - - if ((p = strchr(type, '\t')) || (p = strchr(type, ' '))) { - *p++ = '\0'; - - while (*p == ' ' || *p == '\t') { - p++; - } - - switch_core_mime_add_type(type, p); - } - - } - - switch_safe_free(line_buf); - - if (fd) { - fclose(fd); - fd = NULL; - } - - end: - - switch_safe_free(mime_path); - -} - -SWITCH_DECLARE(void) switch_core_setrlimits(void) -{ -#ifdef HAVE_SETRLIMIT - struct rlimit rlp; - - /* - Setting the stack size on FreeBSD results in an instant crash. - - If anyone knows how to fix this, - feel free to submit a patch to http://jira.freeswitch.org - */ - -#ifndef __FreeBSD__ - memset(&rlp, 0, sizeof(rlp)); - rlp.rlim_cur = SWITCH_THREAD_STACKSIZE; - rlp.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE; - setrlimit(RLIMIT_STACK, &rlp); -#endif - - memset(&rlp, 0, sizeof(rlp)); - rlp.rlim_cur = 999999; - rlp.rlim_max = 999999; - setrlimit(RLIMIT_NOFILE, &rlp); - - memset(&rlp, 0, sizeof(rlp)); - rlp.rlim_cur = RLIM_INFINITY; - rlp.rlim_max = RLIM_INFINITY; - - setrlimit(RLIMIT_CPU, &rlp); - setrlimit(RLIMIT_DATA, &rlp); - setrlimit(RLIMIT_FSIZE, &rlp); -#ifdef RLIMIT_NPROC - setrlimit(RLIMIT_NPROC, &rlp); -#endif -#ifdef RLIMIT_RTPRIO - setrlimit(RLIMIT_RTPRIO, &rlp); -#endif - -#if !defined(__OpenBSD__) && !defined(__NetBSD__) - setrlimit(RLIMIT_AS, &rlp); -#endif -#endif - return; -} - -typedef struct { - switch_memory_pool_t *pool; - switch_hash_t *hash; -} switch_ip_list_t; - -static switch_ip_list_t IP_LIST = { 0 }; - -SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token) -{ - switch_network_list_t *list; - ip_t ip, mask, net; - uint32_t bits; - char *ipv6 = strchr(ip_str,':'); - switch_bool_t ok = SWITCH_FALSE; - - switch_mutex_lock(runtime.global_mutex); - if (ipv6) { - switch_inet_pton(AF_INET6, ip_str, &ip); - } else { - switch_inet_pton(AF_INET, ip_str, &ip); - ip.v4 = htonl(ip.v4); - } - - if ((list = switch_core_hash_find(IP_LIST.hash, list_name))) { - if (ipv6) { - ok = switch_network_list_validate_ip6_token(list, ip, token); - } else { - ok = switch_network_list_validate_ip_token(list, ip.v4, token); - } - } else if (strchr(list_name, '/')) { - if (strchr(list_name, ',')) { - char *list_name_dup = strdup(list_name); - char *argv[32]; - int argc; - - switch_assert(list_name_dup); - - if ((argc = switch_separate_string(list_name_dup, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) { - int i; - for (i = 0; i < argc; i++) { - switch_parse_cidr(argv[i], &net, &mask, &bits); - if (ipv6) { - if ((ok = switch_testv6_subnet(ip, net, mask))){ - break; - } - } else { - if ((ok = switch_test_subnet(ip.v4, net.v4, mask.v4))) { - break; - } - } - } - } - free(list_name_dup); - } else { - switch_parse_cidr(list_name, &net, &mask, &bits); - ok = switch_test_subnet(ip.v4, net.v4, mask.v4); - } - } - switch_mutex_unlock(runtime.global_mutex); - - return ok; -} - - -SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload) -{ - switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, x_node = NULL, cfg = NULL; - switch_network_list_t *rfc_list, *list; - char guess_ip[16] = ""; - int mask = 0; - char guess_mask[16] = ""; - char *tmp_name; - struct in_addr in; - - switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET); - in.s_addr = mask; - switch_set_string(guess_mask, inet_ntoa(in)); - - switch_mutex_lock(runtime.global_mutex); - - if (IP_LIST.hash) { - switch_core_hash_destroy(&IP_LIST.hash); - } - - if (IP_LIST.pool) { - switch_core_destroy_memory_pool(&IP_LIST.pool); - } - - memset(&IP_LIST, 0, sizeof(IP_LIST)); - switch_core_new_memory_pool(&IP_LIST.pool); - switch_core_hash_init(&IP_LIST.hash, IP_LIST.pool); - - - tmp_name = "rfc1918.auto"; - switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); - switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE); - switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE); - switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE); - switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); - - tmp_name = "wan.auto"; - switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name); - switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_FALSE); - switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_FALSE); - switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_FALSE); - switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); - - tmp_name = "nat.auto"; - switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); - if (switch_network_list_add_host_mask(rfc_list, guess_ip, guess_mask, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s/%s (deny) to list %s\n", guess_ip, guess_mask, tmp_name); - } - switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE); - switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE); - switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE); - switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); - - tmp_name = "loopback.auto"; - switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); - switch_network_list_add_cidr(rfc_list, "127.0.0.0/8", SWITCH_TRUE); - switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); - - tmp_name = "localnet.auto"; - switch_network_list_create(&list, tmp_name, SWITCH_FALSE, IP_LIST.pool); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); - - if (switch_network_list_add_host_mask(list, guess_ip, guess_mask, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s/%s (allow) to list %s\n", guess_ip, guess_mask, tmp_name); - } - switch_core_hash_insert(IP_LIST.hash, tmp_name, list); - - - if ((xml = switch_xml_open_cfg("acl.conf", &cfg, NULL))) { - if ((x_lists = switch_xml_child(cfg, "network-lists"))) { - for (x_list = switch_xml_child(x_lists, "list"); x_list; x_list = x_list->next) { - const char *name = switch_xml_attr(x_list, "name"); - const char *dft = switch_xml_attr(x_list, "default"); - switch_bool_t default_type = SWITCH_TRUE; - - if (zstr(name)) { - continue; - } - - if (dft) { - default_type = switch_true(dft); - } - - if (switch_network_list_create(&list, name, default_type, IP_LIST.pool) != SWITCH_STATUS_SUCCESS) { - abort(); - } - - if (reload) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny"); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny"); - } - - - for (x_node = switch_xml_child(x_list, "node"); x_node; x_node = x_node->next) { - const char *cidr = NULL, *host = NULL, *mask = NULL, *domain = NULL; - switch_bool_t ok = default_type; - const char *type = switch_xml_attr(x_node, "type"); - - if (type) { - ok = switch_true(type); - } - - cidr = switch_xml_attr(x_node, "cidr"); - host = switch_xml_attr(x_node, "host"); - mask = switch_xml_attr(x_node, "mask"); - domain = switch_xml_attr(x_node, "domain"); - - if (domain) { - switch_event_t *my_params = NULL; - switch_xml_t x_domain, xml_root; - switch_xml_t gt, gts, ut, uts; - - switch_event_create(&my_params, SWITCH_EVENT_GENERAL); - switch_assert(my_params); - switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "domain", domain); - switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "purpose", "network-list"); - - if (switch_xml_locate_domain(domain, my_params, &xml_root, &x_domain) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate domain %s\n", domain); - switch_event_destroy(&my_params); - continue; - } - - switch_event_destroy(&my_params); - - for (ut = switch_xml_child(x_domain, "user"); ut; ut = ut->next) { - const char *user_cidr = switch_xml_attr(ut, "cidr"); - const char *id = switch_xml_attr(ut, "id"); - - if (id && user_cidr) { - char *token = switch_mprintf("%s@%s", id, domain); - switch_assert(token); - switch_network_list_add_cidr_token(list, user_cidr, ok, token); - free(token); - } - } - - for (gts = switch_xml_child(x_domain, "groups"); gts; gts = gts->next) { - for (gt = switch_xml_child(gts, "group"); gt; gt = gt->next) { - for (uts = switch_xml_child(gt, "users"); uts; uts = uts->next) { - for (ut = switch_xml_child(uts, "user"); ut; ut = ut->next) { - const char *user_cidr = switch_xml_attr(ut, "cidr"); - const char *id = switch_xml_attr(ut, "id"); - - if (id && user_cidr) { - char *token = switch_mprintf("%s@%s", id, domain); - switch_assert(token); - switch_network_list_add_cidr_token(list, user_cidr, ok, token); - free(token); - } - } - } - } - } - - switch_xml_free(xml_root); - } else if (cidr) { - if (switch_network_list_add_cidr(list, cidr, ok) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, - "Error Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name); - } - } else if (host && mask) { - if (switch_network_list_add_host_mask(list, host, mask, ok) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, - "Adding %s/%s (%s) to list %s\n", host, mask, ok ? "allow" : "deny", name); - } - } - - switch_core_hash_insert(IP_LIST.hash, name, list); - } - } - } - - switch_xml_free(xml); - } - - switch_mutex_unlock(runtime.global_mutex); -} - -SWITCH_DECLARE(uint32_t) switch_core_max_dtmf_duration(uint32_t duration) -{ - if (duration) { - if (duration > SWITCH_MAX_DTMF_DURATION) { - duration = SWITCH_MAX_DTMF_DURATION; - } - if (duration < SWITCH_MIN_DTMF_DURATION) { - duration = SWITCH_MIN_DTMF_DURATION; - } - runtime.max_dtmf_duration = duration; - if (duration < runtime.min_dtmf_duration) { - runtime.min_dtmf_duration = duration; - } - } - return runtime.max_dtmf_duration; -} - -SWITCH_DECLARE(uint32_t) switch_core_default_dtmf_duration(uint32_t duration) -{ - if (duration) { - if (duration < SWITCH_MIN_DTMF_DURATION) { - duration = SWITCH_MIN_DTMF_DURATION; - } - if (duration > SWITCH_MAX_DTMF_DURATION) { - duration = SWITCH_MAX_DTMF_DURATION; - } - runtime.default_dtmf_duration = duration; - - if (duration < runtime.min_dtmf_duration) { - runtime.min_dtmf_duration = duration; - } - - if (duration > runtime.max_dtmf_duration) { - runtime.max_dtmf_duration = duration; - } - - } - return runtime.default_dtmf_duration; -} - -SWITCH_DECLARE(uint32_t) switch_core_min_dtmf_duration(uint32_t duration) -{ - if (duration) { - if (duration < SWITCH_MIN_DTMF_DURATION) { - duration = SWITCH_MIN_DTMF_DURATION; - } - if (duration > SWITCH_MAX_DTMF_DURATION) { - duration = SWITCH_MAX_DTMF_DURATION; - } - - runtime.min_dtmf_duration = duration; - - if (duration > runtime.max_dtmf_duration) { - runtime.max_dtmf_duration = duration; - } - } - return runtime.min_dtmf_duration; -} - -SWITCH_DECLARE(switch_status_t) switch_core_thread_set_cpu_affinity(int cpu) -{ - switch_status_t status = SWITCH_STATUS_FALSE; - - if (cpu > -1) { - -#ifdef HAVE_CPU_SET_MACROS - cpu_set_t set; - - CPU_ZERO(&set); - CPU_SET(cpu, &set); - - if (!sched_setaffinity(0, sizeof(set), &set)) { - status = SWITCH_STATUS_SUCCESS; - } - -#else -#if WIN32 - if (SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR) cpu)) { - status = SWITCH_STATUS_SUCCESS; - } -#endif -#endif - } - - return status; -} - - -static void switch_core_set_serial(void) -{ - char buf[13] = ""; - char path[256]; - - int fd = -1, write_fd = -1; - switch_ssize_t bytes = 0; - - switch_snprintf(path, sizeof(path), "%s%sfreeswitch.serial", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR); - - - if ((fd = open(path, O_RDONLY, 0)) < 0) { - char *ip = switch_core_get_variable_dup("local_ip_v4"); - uint32_t ipi = 0; - switch_byte_t *byte; - int i = 0; - - if (ip) { - switch_inet_pton(AF_INET, ip, &ipi); - free(ip); - ip = NULL; - } - - - byte = (switch_byte_t *) & ipi; - - for (i = 0; i < 8; i += 2) { - switch_snprintf(buf + i, sizeof(buf) - i, "%0.2x", *byte); - byte++; - } - - switch_stun_random_string(buf + 8, 4, "0123456789abcdef"); - - if ((write_fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) >= 0) { - bytes = write(write_fd, buf, sizeof(buf)); - bytes++; - close(write_fd); - write_fd = -1; - } - } else { - bytes = read(fd, buf, sizeof(buf)); - close(fd); - fd = -1; - } - - switch_core_set_variable("switch_serial", buf); -} - - -SWITCH_DECLARE(int) switch_core_test_flag(int flag) -{ - return switch_test_flag((&runtime), flag); -} - - -SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switch_bool_t console, const char **err) -{ - switch_uuid_t uuid; - char guess_ip[256]; - int mask = 0; - struct in_addr in; - - - if (runtime.runlevel > 0) { - /* one per customer */ - return SWITCH_STATUS_SUCCESS; - } - - memset(&runtime, 0, sizeof(runtime)); - gethostname(runtime.hostname, sizeof(runtime.hostname)); - - runtime.max_db_handles = 50; - runtime.db_handle_timeout = 5000000; - - runtime.runlevel++; - runtime.dummy_cng_frame.data = runtime.dummy_data; - runtime.dummy_cng_frame.datalen = sizeof(runtime.dummy_data); - runtime.dummy_cng_frame.buflen = sizeof(runtime.dummy_data); - runtime.dbname = "core"; - switch_set_flag((&runtime.dummy_cng_frame), SFF_CNG); - switch_set_flag((&runtime), SCF_AUTO_SCHEMAS); - switch_set_flag((&runtime), SCF_CLEAR_SQL); - switch_set_flag((&runtime), SCF_API_EXPANSION); - switch_set_flag((&runtime), SCF_SESSION_THREAD_POOL); -#ifdef WIN32 - switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); -#endif - switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); - runtime.hard_log_level = SWITCH_LOG_DEBUG; - runtime.mailer_app = "sendmail"; - runtime.mailer_app_args = "-t"; - runtime.max_dtmf_duration = SWITCH_MAX_DTMF_DURATION; - runtime.default_dtmf_duration = SWITCH_DEFAULT_DTMF_DURATION; - runtime.min_dtmf_duration = SWITCH_MIN_DTMF_DURATION; - runtime.odbc_dbtype = DBTYPE_DEFAULT; - runtime.dbname = NULL; -#ifndef WIN32 - runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN); -#else - { - SYSTEM_INFO sysinfo; - GetSystemInfo( &sysinfo ); - runtime.cpu_count = sysinfo.dwNumberOfProcessors; - } -#endif - - if (!runtime.cpu_count) runtime.cpu_count = 1; - - - /* INIT APR and Create the pool context */ - if (apr_initialize() != SWITCH_STATUS_SUCCESS) { - *err = "FATAL ERROR! Could not initialize APR\n"; - return SWITCH_STATUS_MEMERR; - } - - if (!(runtime.memory_pool = switch_core_memory_init())) { - *err = "FATAL ERROR! Could not allocate memory pool\n"; - return SWITCH_STATUS_MEMERR; - } - switch_assert(runtime.memory_pool != NULL); - - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.base_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.mod_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.conf_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.log_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.run_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.db_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.script_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.htdocs_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.recordings_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.sounds_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - switch_dir_make_recursive(SWITCH_GLOBAL_dirs.temp_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); - - - switch_mutex_init(&runtime.uuid_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); - - switch_mutex_init(&runtime.throttle_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); - - switch_mutex_init(&runtime.session_hash_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); - switch_mutex_init(&runtime.global_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); - - switch_thread_rwlock_create(&runtime.global_var_rwlock, runtime.memory_pool); - switch_core_set_globals(); - switch_core_session_init(runtime.memory_pool); - switch_event_create_plain(&runtime.global_vars, SWITCH_EVENT_CHANNEL_DATA); - switch_core_hash_init(&runtime.mime_types, runtime.memory_pool); - switch_core_hash_init_case(&runtime.ptimes, runtime.memory_pool, SWITCH_FALSE); - load_mime_types(); - runtime.flags |= flags; - runtime.sps_total = 30; - - *err = NULL; - - if (console) { - runtime.console = stdout; - } - - switch_ssl_init_ssl_locks(); - switch_curl_init(); - - switch_core_set_variable("hostname", runtime.hostname); - switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET); - switch_core_set_variable("local_ip_v4", guess_ip); - in.s_addr = mask; - switch_core_set_variable("local_mask_v4", inet_ntoa(in)); - - - switch_find_local_ip(guess_ip, sizeof(guess_ip), NULL, AF_INET6); - switch_core_set_variable("local_ip_v6", guess_ip); - switch_core_set_variable("base_dir", SWITCH_GLOBAL_dirs.base_dir); - switch_core_set_variable("recordings_dir", SWITCH_GLOBAL_dirs.recordings_dir); - switch_core_set_variable("sound_prefix", SWITCH_GLOBAL_dirs.sounds_dir); - switch_core_set_variable("sounds_dir", SWITCH_GLOBAL_dirs.sounds_dir); - switch_core_set_serial(); - - switch_console_init(runtime.memory_pool); - switch_event_init(runtime.memory_pool); - - if (switch_xml_init(runtime.memory_pool, err) != SWITCH_STATUS_SUCCESS) { - apr_terminate(); - return SWITCH_STATUS_MEMERR; - } - - if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) { - switch_nat_init(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_NAT_MAPPING)); - } - - switch_log_init(runtime.memory_pool, runtime.colorize_console); - - if (flags & SCF_MINIMAL) return SWITCH_STATUS_SUCCESS; - - runtime.tipping_point = 0; - runtime.timer_affinity = -1; - runtime.microseconds_per_tick = 20000; - - switch_load_core_config("switch.conf"); - - switch_core_state_machine_init(runtime.memory_pool); - - if (switch_core_sqldb_start(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_SQL) ? SWITCH_TRUE : SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { - *err = "Error activating database"; - return SWITCH_STATUS_FALSE; - } - - switch_scheduler_task_thread_start(); - - switch_nat_late_init(); - - switch_rtp_init(runtime.memory_pool); - - runtime.running = 1; - runtime.initiated = switch_time_now(); - runtime.mono_initiated = switch_mono_micro_time_now(); - - switch_scheduler_add_task(switch_epoch_time_now(NULL), heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL); - - switch_scheduler_add_task(switch_epoch_time_now(NULL), check_ip_callback, "check_ip", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL | SSHF_OWN_THREAD); - - switch_uuid_get(&uuid); - switch_uuid_format(runtime.uuid_str, &uuid); - switch_core_set_variable("core_uuid", runtime.uuid_str); - - - return SWITCH_STATUS_SUCCESS; -} - - -#ifndef WIN32 -static void handle_SIGCHLD(int sig) -{ - int status = 0; - - wait(&status); - return; -} -#endif - -#ifdef TRAP_BUS -static void handle_SIGBUS(int sig) -{ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Sig BUS!\n"); - return; -} -#endif - -static void handle_SIGHUP(int sig) -{ - if (sig) { - switch_event_t *event; - - if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Trapped-Signal", "HUP"); - switch_event_fire(&event); - } - } - return; -} - - -SWITCH_DECLARE(uint32_t) switch_default_ptime(const char *name, uint32_t number) -{ - uint32_t *p; - - if ((p = switch_core_hash_find(runtime.ptimes, name))) { - return *p; - } - - return 20; -} - -static uint32_t d_30 = 30; - -static void switch_load_core_config(const char *file) -{ - switch_xml_t xml = NULL, cfg = NULL; - - switch_core_hash_insert(runtime.ptimes, "ilbc", &d_30); - switch_core_hash_insert(runtime.ptimes, "G723", &d_30); - - if ((xml = switch_xml_open_cfg(file, &cfg, NULL))) { - switch_xml_t settings, param; - - if ((settings = switch_xml_child(cfg, "default-ptimes"))) { - for (param = switch_xml_child(settings, "codec"); param; param = param->next) { - const char *var = switch_xml_attr_soft(param, "name"); - const char *val = switch_xml_attr_soft(param, "ptime"); - - if (!zstr(var) && !zstr(val)) { - uint32_t *p; - uint32_t v = switch_atoul(val); - - if (!strcasecmp(var, "G723") || !strcasecmp(var, "iLBC")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding %s, defaults cannot be changed\n", var); - continue; - } - - if (v == 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding %s, invalid ptime\n", var); - continue; - } - - p = switch_core_alloc(runtime.memory_pool, sizeof(*p)); - *p = v; - switch_core_hash_insert(runtime.ptimes, var, p); - } - - } - } - - if ((settings = switch_xml_child(cfg, "settings"))) { - for (param = switch_xml_child(settings, "param"); param; param = param->next) { - const char *var = switch_xml_attr_soft(param, "name"); - const char *val = switch_xml_attr_soft(param, "value"); - - if (!strcasecmp(var, "loglevel")) { - int level; - if (*val > 47 && *val < 58) { - level = atoi(val); - } else { - level = switch_log_str2level(val); - } - - if (level != SWITCH_LOG_INVALID) { - switch_core_session_ctl(SCSC_LOGLEVEL, &level); - } -#ifdef HAVE_SETRLIMIT - } else if (!strcasecmp(var, "dump-cores") && switch_true(val)) { - struct rlimit rlp; - memset(&rlp, 0, sizeof(rlp)); - rlp.rlim_cur = RLIM_INFINITY; - rlp.rlim_max = RLIM_INFINITY; - setrlimit(RLIMIT_CORE, &rlp); -#endif - } else if (!strcasecmp(var, "debug-level")) { - int tmp = atoi(val); - if (tmp > -1 && tmp < 11) { - switch_core_session_ctl(SCSC_DEBUG_LEVEL, &tmp); - } - } else if (!strcasecmp(var, "max-db-handles")) { - long tmp = atol(val); - - if (tmp > 4 && tmp < 5001) { - runtime.max_db_handles = (uint32_t) tmp; - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "max-db-handles must be between 5 and 5000\n"); - } - } else if (!strcasecmp(var, "db-handle-timeout")) { - long tmp = atol(val); - - if (tmp > 0 && tmp < 5001) { - runtime.db_handle_timeout = (uint32_t) tmp * 1000000; - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "db-handle-timeout must be between 1 and 5000\n"); - } - - } else if (!strcasecmp(var, "multiple-registrations")) { - runtime.multiple_registrations = switch_true(val); - } else if (!strcasecmp(var, "auto-create-schemas")) { - if (switch_true(val)) { - switch_set_flag((&runtime), SCF_AUTO_SCHEMAS); - } else { - switch_clear_flag((&runtime), SCF_AUTO_SCHEMAS); - } - } else if (!strcasecmp(var, "session-thread-pool")) { - if (switch_true(val)) { - switch_set_flag((&runtime), SCF_SESSION_THREAD_POOL); - } else { - switch_clear_flag((&runtime), SCF_SESSION_THREAD_POOL); - } - } else if (!strcasecmp(var, "auto-clear-sql")) { - if (switch_true(val)) { - switch_set_flag((&runtime), SCF_CLEAR_SQL); - } else { - switch_clear_flag((&runtime), SCF_CLEAR_SQL); - } - } else if (!strcasecmp(var, "api-expansion")) { - if (switch_true(val)) { - switch_set_flag((&runtime), SCF_API_EXPANSION); - } else { - switch_clear_flag((&runtime), SCF_API_EXPANSION); - } - } else if (!strcasecmp(var, "enable-early-hangup") && switch_true(val)) { - switch_set_flag((&runtime), SCF_EARLY_HANGUP); - } else if (!strcasecmp(var, "colorize-console") && switch_true(val)) { - runtime.colorize_console = SWITCH_TRUE; - } else if (!strcasecmp(var, "core-db-pre-trans-execute") && !zstr(val)) { - runtime.core_db_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val); - } else if (!strcasecmp(var, "core-db-post-trans-execute") && !zstr(val)) { - runtime.core_db_post_trans_execute = switch_core_strdup(runtime.memory_pool, val); - } else if (!strcasecmp(var, "core-db-inner-pre-trans-execute") && !zstr(val)) { - runtime.core_db_inner_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val); - } else if (!strcasecmp(var, "core-db-inner-post-trans-execute") && !zstr(val)) { - runtime.core_db_inner_post_trans_execute = switch_core_strdup(runtime.memory_pool, val); - } else if (!strcasecmp(var, "mailer-app") && !zstr(val)) { - runtime.mailer_app = switch_core_strdup(runtime.memory_pool, val); - } else if (!strcasecmp(var, "mailer-app-args") && val) { - runtime.mailer_app_args = switch_core_strdup(runtime.memory_pool, val); - } else if (!strcasecmp(var, "sessions-per-second") && !zstr(val)) { - switch_core_sessions_per_second(atoi(val)); - } else if (!strcasecmp(var, "max-dtmf-duration") && !zstr(val)) { - int tmp = atoi(val); - if (tmp > 0) { - switch_core_max_dtmf_duration((uint32_t) tmp); - } - } else if (!strcasecmp(var, "min-dtmf-duration") && !zstr(val)) { - int tmp = atoi(val); - if (tmp > 0) { - switch_core_min_dtmf_duration((uint32_t) tmp); - } - } else if (!strcasecmp(var, "default-dtmf-duration") && !zstr(val)) { - int tmp = atoi(val); - if (tmp > 0) { - switch_core_default_dtmf_duration((uint32_t) tmp); - } - } else if (!strcasecmp(var, "enable-use-system-time")) { - switch_time_set_use_system_time(switch_true(val)); - } else if (!strcasecmp(var, "enable-monotonic-timing")) { - switch_time_set_monotonic(switch_true(val)); - } else if (!strcasecmp(var, "enable-softtimer-timerfd")) { - switch_time_set_timerfd(switch_true(val)); - } else if (!strcasecmp(var, "enable-clock-nanosleep")) { - switch_time_set_nanosleep(switch_true(val)); - } else if (!strcasecmp(var, "enable-cond-yield")) { - switch_time_set_cond_yield(switch_true(val)); - } else if (!strcasecmp(var, "enable-timer-matrix")) { - switch_time_set_matrix(switch_true(val)); - } else if (!strcasecmp(var, "max-sessions") && !zstr(val)) { - switch_core_session_limit(atoi(val)); - } else if (!strcasecmp(var, "verbose-channel-events") && !zstr(val)) { - int v = switch_true(val); - if (v) { - switch_set_flag((&runtime), SCF_VERBOSE_EVENTS); - } else { - switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS); - } - } else if (!strcasecmp(var, "threaded-system-exec") && !zstr(val)) { -#ifdef WIN32 - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "threaded-system-exec is not implemented on this platform\n"); -#else - int v = switch_true(val); - if (v) { - switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); - } else { - switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); - } -#endif - } else if (!strcasecmp(var, "min-idle-cpu") && !zstr(val)) { - switch_core_min_idle_cpu(atof(val)); - } else if (!strcasecmp(var, "tipping-point") && !zstr(val)) { - runtime.tipping_point = atoi(val); - } else if (!strcasecmp(var, "initial-event-threads") && !zstr(val)) { - int tmp = atoi(val); - - - if (tmp > runtime.cpu_count / 2) { - tmp = runtime.cpu_count / 2; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "This value cannot be higher than %d so setting it to that value\n", - runtime.cpu_count / 2); - } - - if (tmp < 1) { - tmp = 1; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "This value cannot be lower than 1 so setting it to that level\n"); - } - - switch_event_launch_dispatch_threads(tmp); - - } else if (!strcasecmp(var, "1ms-timer") && switch_true(val)) { - runtime.microseconds_per_tick = 1000; - } else if (!strcasecmp(var, "timer-affinity") && !zstr(val)) { - if (!strcasecmp(val, "disabled")) { - runtime.timer_affinity = -1; - } else { - runtime.timer_affinity = atoi(val); - } - } else if (!strcasecmp(var, "rtp-start-port") && !zstr(val)) { - switch_rtp_set_start_port((switch_port_t) atoi(val)); - } else if (!strcasecmp(var, "rtp-end-port") && !zstr(val)) { - switch_rtp_set_end_port((switch_port_t) atoi(val)); - } else if (!strcasecmp(var, "core-db-name") && !zstr(val)) { - runtime.dbname = switch_core_strdup(runtime.memory_pool, val); - } else if (!strcasecmp(var, "core-db-dsn") && !zstr(val)) { - if (switch_odbc_available() || switch_pgsql_available()) { - runtime.odbc_dsn = switch_core_strdup(runtime.memory_pool, val); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC AND PGSQL ARE NOT AVAILABLE!\n"); - } - } else if (!strcasecmp(var, "core-non-sqlite-db-required") && !zstr(val)) { - switch_set_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ); - } else if (!strcasecmp(var, "core-dbtype") && !zstr(val)) { - if (!strcasecmp(val, "MSSQL")) { - runtime.odbc_dbtype = DBTYPE_MSSQL; - } else { - runtime.odbc_dbtype = DBTYPE_DEFAULT; - } -#ifdef ENABLE_ZRTP - } else if (!strcasecmp(var, "rtp-enable-zrtp")) { - switch_core_set_variable("zrtp_enabled", val); -#endif - } else if (!strcasecmp(var, "switchname") && !zstr(val)) { - runtime.switchname = switch_core_strdup(runtime.memory_pool, val); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Set switchname to %s\n", runtime.switchname); - } - } - } - - if ((settings = switch_xml_child(cfg, "variables"))) { - for (param = switch_xml_child(settings, "variable"); param; param = param->next) { - const char *var = switch_xml_attr_soft(param, "name"); - const char *val = switch_xml_attr_soft(param, "value"); - if (var && val) { - switch_core_set_variable(var, val); - } - } - } - - switch_xml_free(xml); - } - - -} - -SWITCH_DECLARE(const char *) switch_core_banner(void) -{ - - return ("\n" - ".=============================================================.\n" - "| _____ ______ _____ _____ ____ _ _ |\n" - "| | ___| __ ___ ___/ ___\\ \\ / /_ _|_ _/ ___| | | | |\n" - "| | |_ | '__/ _ \\/ _ \\___ \\\\ \\ /\\ / / | | | || | | |_| | |\n" - "| | _|| | | __/ __/___) |\\ V V / | | | || |___| _ | |\n" - "| |_| |_| \\___|\\___|____/ \\_/\\_/ |___| |_| \\____|_| |_| |\n" - "| |\n" - ".=============================================================." - "\n" - - "| Anthony Minessale II, Michael Jerris, Brian West, Others |\n" - "| FreeSWITCH (http://www.freeswitch.org) |\n" - "| Paypal Donations Appreciated: paypal@freeswitch.org |\n" - "| Brought to you by ClueCon http://www.cluecon.com/ |\n" - ".=============================================================.\n" - "\n"); -} - - -SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t flags, switch_bool_t console, const char **err) -{ - switch_event_t *event; - char *cmd; - int x = 0; - const char *use = NULL; -#include "cc.h" - - - if (switch_core_init(flags, console, err) != SWITCH_STATUS_SUCCESS) { - return SWITCH_STATUS_GENERR; - } - - if (runtime.runlevel > 1) { - /* one per customer */ - return SWITCH_STATUS_SUCCESS; - } - - runtime.runlevel++; - - switch_core_set_signal_handlers(); - switch_load_network_lists(SWITCH_FALSE); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Bringing up environment.\n"); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Loading Modules.\n"); - if (switch_loadable_module_init(SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) { - *err = "Cannot load modules"; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error: %s\n", *err); - return SWITCH_STATUS_GENERR; - } - - switch_load_network_lists(SWITCH_FALSE); - - switch_load_core_config("post_load_switch.conf"); - - switch_core_set_signal_handlers(); - - if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready"); - switch_event_fire(&event); - } - - switch_core_screen_size(&x, NULL); - - use = (x > 100) ? cc : cc_s; - -#ifdef WIN32 - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s\n\n", switch_core_banner(), use); -#else - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s%s%s%s%s\n\n", - SWITCH_SEQ_DEFAULT_COLOR, - SWITCH_SEQ_FYELLOW, SWITCH_SEQ_BBLUE, - switch_core_banner(), - use, SWITCH_SEQ_DEFAULT_COLOR); - -#endif - - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, - "\nFreeSWITCH Version %s (%s)\n\nFreeSWITCH Started\nMax Sessions [%u]\nSession Rate [%d]\nSQL [%s]\n", - SWITCH_VERSION_FULL, SWITCH_VERSION_REVISION_HUMAN, - switch_core_session_limit(0), - switch_core_sessions_per_second(0), switch_test_flag((&runtime), SCF_USE_SQL) ? "Enabled" : "Disabled"); - - - if (x < 160) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\n[This app Best viewed at 160x60 or more..]\n"); - } - - switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS); - - if ((cmd = switch_core_get_variable_dup("api_on_startup"))) { - switch_stream_handle_t stream = { 0 }; - SWITCH_STANDARD_STREAM(stream); - switch_console_execute(cmd, 0, &stream); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Startup command [%s] executed. Output:\n%s\n", cmd, (char *)stream.data); - free(stream.data); - free(cmd); - } - - return SWITCH_STATUS_SUCCESS; - -} - -SWITCH_DECLARE(void) switch_core_measure_time(switch_time_t total_ms, switch_core_time_duration_t *duration) -{ - switch_time_t temp = total_ms / 1000; - memset(duration, 0, sizeof(*duration)); - duration->mms = (uint32_t) (total_ms % 1000); - duration->ms = (uint32_t) (temp % 1000); - temp = temp / 1000; - duration->sec = (uint32_t) (temp % 60); - temp = temp / 60; - duration->min = (uint32_t) (temp % 60); - temp = temp / 60; - duration->hr = (uint32_t) (temp % 24); - temp = temp / 24; - duration->day = (uint32_t) (temp % 365); - duration->yr = (uint32_t) (temp / 365); -} - -SWITCH_DECLARE(switch_time_t) switch_core_uptime(void) -{ - return switch_mono_micro_time_now() - runtime.mono_initiated; -} - - -#ifdef _MSC_VER -static void win_shutdown(void) -{ - - HANDLE shutdown_event; - char path[512]; - /* for windows we need the event to signal for shutting down a background FreeSWITCH */ - snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid()); - - /* open the event so we can signal it */ - shutdown_event = OpenEvent(EVENT_MODIFY_STATE, FALSE, path); - - if (shutdown_event) { - /* signal the event to shutdown */ - SetEvent(shutdown_event); - /* cleanup */ - CloseHandle(shutdown_event); - } -} -#endif - -SWITCH_DECLARE(void) switch_core_set_signal_handlers(void) -{ - /* set signal handlers */ - signal(SIGINT, SIG_IGN); -#ifndef WIN32 - if (switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC)) { - signal(SIGCHLD, SIG_DFL); - } else { - signal(SIGCHLD, handle_SIGCHLD); - } -#endif -#ifdef SIGPIPE - signal(SIGPIPE, SIG_IGN); -#endif -#ifdef SIGQUIT - signal(SIGQUIT, SIG_IGN); -#endif -#ifdef SIGPOLL - signal(SIGPOLL, SIG_IGN); -#endif -#ifdef SIGIO - signal(SIGIO, SIG_IGN); -#endif -#ifdef TRAP_BUS - signal(SIGBUS, handle_SIGBUS); -#endif -#ifdef SIGUSR1 - signal(SIGUSR1, handle_SIGHUP); -#endif - signal(SIGHUP, handle_SIGHUP); -} - -SWITCH_DECLARE(uint32_t) switch_core_debug_level(void) -{ - return runtime.debug_level; -} - - -SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, void *val) -{ - int *intval = (int *) val; - int oldintval = 0, newintval = 0; - - if (intval) { - oldintval = *intval; - } - - if (switch_test_flag((&runtime), SCF_SHUTTING_DOWN)) { - return -1; - } - - switch (cmd) { - case SCSC_RECOVER: - { - char *arg = (char *) val; - char *tech = NULL, *prof = NULL; - int r, flush = 0; - - if (!zstr(arg)) { - tech = strdup(arg); - - if ((prof = strchr(tech, ':'))) { - *prof++ = '\0'; - } - - if (!strcasecmp(tech, "flush")) { - flush++; - - if (prof) { - tech = prof; - if ((prof = strchr(tech, ':'))) { - *prof++ = '\0'; - } - } - } - - } - - if (flush) { - switch_core_recovery_flush(tech, prof); - r = -1; - } else { - r = switch_core_recovery_recover(tech, prof); - } - - switch_safe_free(tech); - return r; - - } - break; - case SCSC_DEBUG_SQL: - { - if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) { - switch_clear_flag((&runtime), SCF_DEBUG_SQL); - newintval = 0; - } else { - switch_set_flag((&runtime), SCF_DEBUG_SQL); - newintval = 1; - } - } - break; - case SCSC_VERBOSE_EVENTS: - if (intval) { - if (oldintval > -1) { - if (oldintval) { - switch_set_flag((&runtime), SCF_VERBOSE_EVENTS); - } else { - switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS); - } - } - newintval = switch_test_flag((&runtime), SCF_VERBOSE_EVENTS); - } - break; - case SCSC_API_EXPANSION: - if (intval) { - if (oldintval > -1) { - if (oldintval) { - switch_set_flag((&runtime), SCF_API_EXPANSION); - } else { - switch_clear_flag((&runtime), SCF_API_EXPANSION); - } - } - newintval = switch_test_flag((&runtime), SCF_API_EXPANSION); - } - break; - case SCSC_THREADED_SYSTEM_EXEC: - if (intval) { - if (oldintval > -1) { - if (oldintval) { - switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); - } else { - switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); - } - } - newintval = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); - } - break; - case SCSC_CALIBRATE_CLOCK: - switch_time_calibrate_clock(); - break; - case SCSC_FLUSH_DB_HANDLES: - switch_cache_db_flush_handles(); - break; - case SCSC_SEND_SIGHUP: - handle_SIGHUP(1); - break; - case SCSC_SYNC_CLOCK: - switch_time_sync(); - newintval = 0; - break; - case SCSC_SYNC_CLOCK_WHEN_IDLE: - newintval = switch_core_session_sync_clock(); - break; - case SCSC_SQL: - if (oldintval) { - switch_core_sqldb_resume(); - } else { - switch_core_sqldb_pause(); - } - break; - case SCSC_PAUSE_ALL: - if (oldintval) { - switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); - } else { - switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS); - } - break; - case SCSC_PAUSE_INBOUND: - if (oldintval) { - switch_set_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS); - } else { - switch_clear_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS); - } - break; - case SCSC_PAUSE_OUTBOUND: - if (oldintval) { - switch_set_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS); - } else { - switch_clear_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS); - } - break; - case SCSC_HUPALL: - switch_core_session_hupall(SWITCH_CAUSE_MANAGER_REQUEST); - break; - case SCSC_CANCEL_SHUTDOWN: - switch_clear_flag((&runtime), SCF_SHUTDOWN_REQUESTED); - break; - case SCSC_SAVE_HISTORY: - switch_console_save_history(); - break; - case SCSC_CRASH: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Declinatio Mortuus Obfirmo!\n"); - switch_console_save_history(); - abort(); - break; - case SCSC_SHUTDOWN_NOW: - switch_console_save_history(); - exit(0); - break; - case SCSC_SHUTDOWN_ELEGANT: - case SCSC_SHUTDOWN_ASAP: - { - int x = 19; - uint32_t count; - - switch_set_flag((&runtime), SCF_SHUTDOWN_REQUESTED); - if (cmd == SCSC_SHUTDOWN_ASAP) { - switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); - } - - while (runtime.running && switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED) && (count = switch_core_session_count())) { - switch_yield(500000); - if (++x == 20) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, - "Shutdown in progress, %u session(s) remain.\nShutting down %s\n", - count, cmd == SCSC_SHUTDOWN_ASAP ? "ASAP" : "once there are no active calls."); - x = 0; - } - } - - if (switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED)) { - switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); -#ifdef _MSC_VER - win_shutdown(); -#endif - - if (oldintval) { - switch_set_flag((&runtime), SCF_RESTART); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Restarting\n"); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutting down\n"); -#ifdef _MSC_VER - fclose(stdin); -#endif - } - runtime.running = 0; - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutdown Cancelled\n"); - switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS); - } - } - break; - case SCSC_PAUSE_CHECK: - newintval = !!(switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS) == SCF_NO_NEW_SESSIONS); - break; - case SCSC_PAUSE_INBOUND_CHECK: - newintval = !!switch_test_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS); - break; - case SCSC_PAUSE_OUTBOUND_CHECK: - newintval = !!switch_test_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS); - break; - case SCSC_READY_CHECK: - newintval = switch_core_ready(); - break; - case SCSC_SHUTDOWN_CHECK: - newintval = !!switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED); - break; - case SCSC_SHUTDOWN: - -#ifdef _MSC_VER - win_shutdown(); -#endif - - if (oldintval) { - switch_set_flag((&runtime), SCF_RESTART); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Restarting\n"); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutting down\n"); -#ifdef _MSC_VER - fclose(stdin); -#endif - } - runtime.running = 0; - break; - case SCSC_CHECK_RUNNING: - newintval = runtime.running; - break; - case SCSC_LOGLEVEL: - if (oldintval > -1) { - runtime.hard_log_level = oldintval; - } - - if (runtime.hard_log_level > SWITCH_LOG_DEBUG) { - runtime.hard_log_level = SWITCH_LOG_DEBUG; - } - newintval = runtime.hard_log_level; - break; - case SCSC_DEBUG_LEVEL: - if (oldintval > -1) { - if (oldintval > 10) - newintval = 10; - runtime.debug_level = oldintval; - } - newintval = runtime.debug_level; - break; - case SCSC_MIN_IDLE_CPU: - { - double *dval = (double *) val; - if (dval) { - *dval = switch_core_min_idle_cpu(*dval); - } - intval = NULL; - } - break; - case SCSC_MAX_SESSIONS: - newintval = switch_core_session_limit(oldintval); - break; - case SCSC_LAST_SPS: - newintval = runtime.sps_last; - break; - case SCSC_MAX_DTMF_DURATION: - newintval = switch_core_max_dtmf_duration(oldintval); - break; - case SCSC_MIN_DTMF_DURATION: - newintval = switch_core_min_dtmf_duration(oldintval); - break; - case SCSC_DEFAULT_DTMF_DURATION: - newintval = switch_core_default_dtmf_duration(oldintval); - break; - case SCSC_SPS: - switch_mutex_lock(runtime.throttle_mutex); - if (oldintval > 0) { - runtime.sps_total = oldintval; - } - newintval = runtime.sps_total; - switch_mutex_unlock(runtime.throttle_mutex); - break; - - case SCSC_RECLAIM: - switch_core_memory_reclaim_all(); - newintval = 0; - break; - } - - if (intval) { - *intval = newintval; - } - - - return 0; -} - -SWITCH_DECLARE(switch_core_flag_t) switch_core_flags(void) -{ - return runtime.flags; -} - -SWITCH_DECLARE(switch_bool_t) switch_core_ready(void) -{ - return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS) == SCF_NO_NEW_SESSIONS) ? SWITCH_FALSE : SWITCH_TRUE; -} - -SWITCH_DECLARE(switch_bool_t) switch_core_ready_inbound(void) -{ - return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE; -} - -SWITCH_DECLARE(switch_bool_t) switch_core_ready_outbound(void) -{ - return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE; -} - -SWITCH_DECLARE(switch_status_t) switch_core_destroy(void) -{ - switch_event_t *event; - - if (switch_event_create(&event, SWITCH_EVENT_SHUTDOWN) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Shutting Down"); - switch_event_fire(&event); - } - - switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); - switch_set_flag((&runtime), SCF_SHUTTING_DOWN); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "End existing sessions\n"); - switch_core_session_hupall(SWITCH_CAUSE_SYSTEM_SHUTDOWN); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Clean up modules.\n"); - - switch_loadable_module_shutdown(); - - switch_ssl_destroy_ssl_locks(); - - if (switch_test_flag((&runtime), SCF_USE_SQL)) { - switch_core_sqldb_stop(); - } - switch_scheduler_task_thread_stop(); - - switch_rtp_shutdown(); - - if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) { - switch_nat_shutdown(); - } - switch_xml_destroy(); - switch_core_session_uninit(); - switch_console_shutdown(); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Closing Event Engine.\n"); - switch_event_shutdown(); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n"); - switch_log_shutdown(); - - switch_core_unset_variables(); - switch_core_memory_stop(); - - if (runtime.console && runtime.console != stdout && runtime.console != stderr) { - fclose(runtime.console); - runtime.console = NULL; - } - - switch_safe_free(SWITCH_GLOBAL_dirs.base_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.mod_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.conf_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.log_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.db_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.script_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.htdocs_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.grammar_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.storage_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.recordings_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.sounds_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.run_dir); - switch_safe_free(SWITCH_GLOBAL_dirs.temp_dir); - - switch_event_destroy(&runtime.global_vars); - switch_core_hash_destroy(&runtime.ptimes); - switch_core_hash_destroy(&runtime.mime_types); - - if (IP_LIST.hash) { - switch_core_hash_destroy(&IP_LIST.hash); - } - - if (IP_LIST.pool) { - switch_core_destroy_memory_pool(&IP_LIST.pool); - } - - if (runtime.memory_pool) { - apr_pool_destroy(runtime.memory_pool); - apr_terminate(); - } - - return switch_test_flag((&runtime), SCF_RESTART) ? SWITCH_STATUS_RESTART : SWITCH_STATUS_SUCCESS; -} - -SWITCH_DECLARE(switch_status_t) switch_core_management_exec(char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen) -{ - const switch_management_interface_t *ptr; - switch_status_t status = SWITCH_STATUS_FALSE; - - if ((ptr = switch_loadable_module_get_management_interface(relative_oid))) { - status = ptr->management_function(relative_oid, action, data, datalen); - } - - return status; -} - -SWITCH_DECLARE(void) switch_core_memory_reclaim_all(void) -{ - switch_core_memory_reclaim_logger(); - switch_core_memory_reclaim_events(); - switch_core_memory_reclaim(); -} - - -struct system_thread_handle { - const char *cmd; - switch_thread_cond_t *cond; - switch_mutex_t *mutex; - switch_memory_pool_t *pool; - int ret; - int *fds; -}; - -static void *SWITCH_THREAD_FUNC system_thread(switch_thread_t *thread, void *obj) -{ - struct system_thread_handle *sth = (struct system_thread_handle *) obj; - -#if 0 // if we are a luser we can never turn this back down, didn't we already set the stack size? -#if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__) - struct rlimit rlim; - - rlim.rlim_cur = SWITCH_SYSTEM_THREAD_STACKSIZE; - rlim.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE; - if (setrlimit(RLIMIT_STACK, &rlim) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno)); - } -#endif -#endif - - if (sth->fds) { - dup2(sth->fds[1], STDOUT_FILENO); - } - - sth->ret = system(sth->cmd); - -#if 0 -#if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__) - rlim.rlim_cur = SWITCH_THREAD_STACKSIZE; - rlim.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE; - if (setrlimit(RLIMIT_STACK, &rlim) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno)); - } -#endif -#endif - - switch_mutex_lock(sth->mutex); - switch_thread_cond_signal(sth->cond); - switch_mutex_unlock(sth->mutex); - - switch_core_destroy_memory_pool(&sth->pool); - - return NULL; -} - - -static int switch_system_thread(const char *cmd, switch_bool_t wait) -{ - switch_thread_t *thread; - switch_threadattr_t *thd_attr; - int ret = 0; - struct system_thread_handle *sth; - switch_memory_pool_t *pool; - - if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Pool Failure\n"); - return 1; - } - - if (!(sth = switch_core_alloc(pool, sizeof(struct system_thread_handle)))) { - switch_core_destroy_memory_pool(&pool); - return 1; - } - - sth->pool = pool; - sth->cmd = switch_core_strdup(pool, cmd); - - switch_thread_cond_create(&sth->cond, sth->pool); - switch_mutex_init(&sth->mutex, SWITCH_MUTEX_NESTED, sth->pool); - switch_mutex_lock(sth->mutex); - - switch_threadattr_create(&thd_attr, sth->pool); - switch_threadattr_stacksize_set(thd_attr, SWITCH_SYSTEM_THREAD_STACKSIZE); - switch_threadattr_detach_set(thd_attr, 1); - switch_thread_create(&thread, thd_attr, system_thread, sth, sth->pool); - - if (wait) { - switch_thread_cond_wait(sth->cond, sth->mutex); - ret = sth->ret; - } - switch_mutex_unlock(sth->mutex); - - return ret; -} - -SWITCH_DECLARE(int) switch_max_file_desc(void) -{ - int max = 0; - -#ifndef WIN32 -#if defined(HAVE_GETDTABLESIZE) - max = getdtablesize(); -#else - max = sysconf(_SC_OPEN_MAX); -#endif -#endif - - return max; - -} - -SWITCH_DECLARE(void) switch_close_extra_files(int *keep, int keep_ttl) -{ - int open_max = switch_max_file_desc(); - int i, j; - - for (i = 3; i < open_max; i++) { - if (keep) { - for (j = 0; j < keep_ttl; j++) { - if (i == keep[j]) { - goto skip; - } - } - } - - close(i); - - skip: - - continue; - - } -} - - -#ifdef WIN32 -static int switch_system_fork(const char *cmd, switch_bool_t wait) -{ - return switch_system_thread(cmd, wait); -} - -SWITCH_DECLARE(pid_t) switch_fork(void) -{ - return -1; -} - - -#else - -SWITCH_DECLARE(pid_t) switch_fork(void) -{ - int i = fork(); - - if (!i) { - set_low_priority(); - } - - return i; -} - - - -static int switch_system_fork(const char *cmd, switch_bool_t wait) -{ - int pid; - char *dcmd = strdup(cmd); - - switch_core_set_signal_handlers(); - - pid = switch_fork(); - - if (pid) { - if (wait) { - waitpid(pid, NULL, 0); - } - free(dcmd); - } else { - switch_close_extra_files(NULL, 0); - - if (system(dcmd) == -1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute because of a command error : %s\n", dcmd); - } - free(dcmd); - exit(0); - } - - return 0; -} -#endif - - - -SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait) -{ - int (*sys_p)(const char *cmd, switch_bool_t wait); - - sys_p = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC) ? switch_system_thread : switch_system_fork; - - return sys_p(cmd, wait); - -} - - - -SWITCH_DECLARE(int) switch_stream_system_fork(const char *cmd, switch_stream_handle_t *stream) -{ -#ifdef WIN32 - return switch_system(cmd, SWITCH_TRUE); -#else - int fds[2], pid = 0; - - if (pipe(fds)) { - goto end; - } else { /* good to go */ - pid = switch_fork(); - - if (pid < 0) { /* ok maybe not */ - close(fds[0]); - close(fds[1]); - goto end; - } else if (pid) { /* parent */ - char buf[1024] = ""; - int bytes; - close(fds[1]); - while ((bytes = read(fds[0], buf, sizeof(buf))) > 0) { - stream->raw_write_function(stream, (unsigned char *)buf, bytes); - } - close(fds[0]); - waitpid(pid, NULL, 0); - } else { /* child */ - switch_close_extra_files(fds, 2); - close(fds[0]); - dup2(fds[1], STDOUT_FILENO); - switch_system(cmd, SWITCH_TRUE); - close(fds[1]); - exit(0); - } - } - - end: - - return 0; - -#endif - -} - -SWITCH_DECLARE(switch_status_t) switch_core_get_stacksizes(switch_size_t *cur, switch_size_t *max) -{ -#ifdef HAVE_SETRLIMIT - struct rlimit rlp; - - memset(&rlp, 0, sizeof(rlp)); - getrlimit(RLIMIT_STACK, &rlp); - - *cur = rlp.rlim_cur; - *max = rlp.rlim_max; - - return SWITCH_STATUS_SUCCESS; - -#else - - return SWITCH_STATUS_FALSE; - -#endif - - - -} - - -SWITCH_DECLARE(int) switch_stream_system(const char *cmd, switch_stream_handle_t *stream) -{ -#ifdef WIN32 - stream->write_function(stream, "Capturing output not supported.\n"); - return switch_system(cmd, SWITCH_TRUE); -#else - return switch_stream_system_fork(cmd, stream); -#endif - -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4: - */ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2012, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * Michael Jerris + * Paul D. Tinsley + * Marcel Barbulescu + * Joseph Sullivan + * + * + * switch_core.c -- Main Core Library + * + */ + + + +#include +#include +#include +#include +#include +#include "private/switch_core_pvt.h" +#include +#ifndef WIN32 +#include +#ifdef HAVE_SETRLIMIT +#include +#endif +#endif +#include + + +SWITCH_DECLARE_DATA switch_directories SWITCH_GLOBAL_dirs = { 0 }; + +/* The main runtime obj we keep this hidden for ourselves */ +struct switch_runtime runtime = { 0 }; +static void switch_load_core_config(const char *file); + +static void send_heartbeat(void) +{ + switch_event_t *event; + switch_core_time_duration_t duration; + + switch_core_measure_time(switch_core_uptime(), &duration); + + if (switch_event_create(&event, SWITCH_EVENT_HEARTBEAT) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Up-Time", + "%u year%s, " + "%u day%s, " + "%u hour%s, " + "%u minute%s, " + "%u second%s, " + "%u millisecond%s, " + "%u microsecond%s", + duration.yr, duration.yr == 1 ? "" : "s", + duration.day, duration.day == 1 ? "" : "s", + duration.hr, duration.hr == 1 ? "" : "s", + duration.min, duration.min == 1 ? "" : "s", + duration.sec, duration.sec == 1 ? "" : "s", + duration.ms, duration.ms == 1 ? "" : "s", duration.mms, duration.mms == 1 ? "" : "s"); + + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Version", SWITCH_VERSION_FULL); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Uptime-msec", "%"SWITCH_TIME_T_FMT, switch_core_uptime() / 1000); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Count", "%u", switch_core_session_count()); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Max-Sessions", "%u", switch_core_session_limit(0)); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec", "%u", runtime.sps); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Since-Startup", "%" SWITCH_SIZE_T_FMT, switch_core_session_id() - 1); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Idle-CPU", "%f", switch_core_idle_cpu()); + switch_event_fire(&event); + } +} + +static char main_ip4[256] = ""; +static char main_ip6[256] = ""; + +static void check_ip(void) +{ + char guess_ip4[256] = ""; + char guess_ip6[256] = ""; + char old_ip4[256] = ""; + char old_ip6[256] = ""; + int ok4 = 1, ok6 = 1; + int mask = 0; + + gethostname(runtime.hostname, sizeof(runtime.hostname)); + switch_core_set_variable("hostname", runtime.hostname); + + switch_find_local_ip(guess_ip4, sizeof(guess_ip4), &mask, AF_INET); + switch_find_local_ip(guess_ip6, sizeof(guess_ip6), NULL, AF_INET6); + + if (!*main_ip4) { + switch_set_string(main_ip4, guess_ip4); + } else { + if (!(ok4 = !strcmp(main_ip4, guess_ip4))) { + struct in_addr in; + + in.s_addr = mask; + switch_set_string(old_ip4, main_ip4); + switch_set_string(main_ip4, guess_ip4); + switch_core_set_variable("local_ip_v4", guess_ip4); + switch_core_set_variable("local_mask_v4", inet_ntoa(in)); + } + } + + if (!*main_ip6) { + switch_set_string(main_ip6, guess_ip6); + } else { + if (!(ok6 = !strcmp(main_ip6, guess_ip6))) { + switch_set_string(old_ip6, main_ip6); + switch_set_string(main_ip6, guess_ip6); + switch_core_set_variable("local_ip_v6", guess_ip6); + } + } + + if (!ok4 || !ok6) { + switch_event_t *event; + + if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "condition", "network-address-change"); + if (!ok4) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v4", old_ip4); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v4", main_ip4); + } + if (!ok6) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v6", old_ip6); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v6", main_ip6); + } + switch_event_fire(&event); + } + } +} + +SWITCH_STANDARD_SCHED_FUNC(heartbeat_callback) +{ + send_heartbeat(); + + /* reschedule this task */ + task->runtime = switch_epoch_time_now(NULL) + 20; +} + + +SWITCH_STANDARD_SCHED_FUNC(check_ip_callback) +{ + check_ip(); + + /* reschedule this task */ + task->runtime = switch_epoch_time_now(NULL) + 60; +} + + +SWITCH_DECLARE(switch_status_t) switch_core_set_console(const char *console) +{ + if ((runtime.console = fopen(console, "a")) == 0) { + fprintf(stderr, "Cannot open output file %s.\n", console); + return SWITCH_STATUS_FALSE; + } + + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_DECLARE(FILE *) switch_core_get_console(void) +{ + return runtime.console; +} + +#ifdef HAVE_SYS_IOCTL_H +#include +#endif +SWITCH_DECLARE(void) switch_core_screen_size(int *x, int *y) +{ + +#ifdef WIN32 + CONSOLE_SCREEN_BUFFER_INFO csbi; + int ret; + + if ((ret = GetConsoleScreenBufferInfo(GetStdHandle( STD_OUTPUT_HANDLE ), &csbi))) { + if (x) *x = csbi.dwSize.X; + if (y) *y = csbi.dwSize.Y; + } + +#elif defined(TIOCGWINSZ) + struct winsize w; + ioctl(0, TIOCGWINSZ, &w); + + if (x) *x = w.ws_col; + if (y) *y = w.ws_row; +#else + if (x) *x = 80; + if (y) *y = 24; +#endif + +} + +SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel_t channel) +{ + FILE *handle = stdout; + + switch (channel) { + case SWITCH_CHANNEL_ID_LOG: + case SWITCH_CHANNEL_ID_LOG_CLEAN: + handle = runtime.console; + break; + default: + handle = runtime.console; + break; + } + + return handle; +} + + +SWITCH_DECLARE(void) switch_core_remove_state_handler(const switch_state_handler_table_t *state_handler) +{ + int index, tmp_index = 0; + const switch_state_handler_table_t *tmp[SWITCH_MAX_STATE_HANDLERS + 1] = { 0 }; + + switch_mutex_lock(runtime.global_mutex); + + for (index = 0; index < runtime.state_handler_index; index++) { + const switch_state_handler_table_t *cur = runtime.state_handlers[index]; + runtime.state_handlers[index] = NULL; + if (cur == state_handler) { + continue; + } + tmp[tmp_index++] = cur; + } + + runtime.state_handler_index = 0; + + for (index = 0; index < tmp_index; index++) { + runtime.state_handlers[runtime.state_handler_index++] = tmp[index]; + } + switch_mutex_unlock(runtime.global_mutex); +} + + +SWITCH_DECLARE(int) switch_core_add_state_handler(const switch_state_handler_table_t *state_handler) +{ + int index; + + switch_mutex_lock(runtime.global_mutex); + index = runtime.state_handler_index++; + + if (runtime.state_handler_index >= SWITCH_MAX_STATE_HANDLERS) { + index = -1; + } else { + runtime.state_handlers[index] = state_handler; + } + + switch_mutex_unlock(runtime.global_mutex); + return index; +} + +SWITCH_DECLARE(const switch_state_handler_table_t *) switch_core_get_state_handler(int index) +{ + + if (index >= SWITCH_MAX_STATE_HANDLERS || index > runtime.state_handler_index) { + return NULL; + } + + return runtime.state_handlers[index]; +} + +SWITCH_DECLARE(void) switch_core_dump_variables(switch_stream_handle_t *stream) +{ + switch_event_header_t *hi; + + switch_mutex_lock(runtime.global_mutex); + for (hi = runtime.global_vars->headers; hi; hi = hi->next) { + stream->write_function(stream, "%s=%s\n", hi->name, hi->value); + } + switch_mutex_unlock(runtime.global_mutex); +} + +SWITCH_DECLARE(const char *) switch_core_get_hostname(void) +{ + return runtime.hostname; +} + +SWITCH_DECLARE(const char *) switch_core_get_switchname(void) +{ + if (!zstr(runtime.switchname)) return runtime.switchname; + return runtime.hostname; +} + + +SWITCH_DECLARE(char *) switch_core_get_variable(const char *varname) +{ + char *val; + switch_thread_rwlock_rdlock(runtime.global_var_rwlock); + val = (char *) switch_event_get_header(runtime.global_vars, varname); + switch_thread_rwlock_unlock(runtime.global_var_rwlock); + return val; +} + +SWITCH_DECLARE(char *) switch_core_get_variable_dup(const char *varname) +{ + char *val = NULL, *v; + + switch_thread_rwlock_rdlock(runtime.global_var_rwlock); + if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) { + val = strdup(v); + } + switch_thread_rwlock_unlock(runtime.global_var_rwlock); + + return val; +} + +SWITCH_DECLARE(char *) switch_core_get_variable_pdup(const char *varname, switch_memory_pool_t *pool) +{ + char *val = NULL, *v; + + switch_thread_rwlock_rdlock(runtime.global_var_rwlock); + if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) { + val = switch_core_strdup(pool, v); + } + switch_thread_rwlock_unlock(runtime.global_var_rwlock); + + return val; +} + +static void switch_core_unset_variables(void) +{ + switch_thread_rwlock_wrlock(runtime.global_var_rwlock); + switch_event_destroy(&runtime.global_vars); + switch_event_create_plain(&runtime.global_vars, SWITCH_EVENT_CHANNEL_DATA); + switch_thread_rwlock_unlock(runtime.global_var_rwlock); +} + +SWITCH_DECLARE(void) switch_core_set_variable(const char *varname, const char *value) +{ + char *val; + + if (varname) { + switch_thread_rwlock_wrlock(runtime.global_var_rwlock); + val = (char *) switch_event_get_header(runtime.global_vars, varname); + if (val) { + switch_event_del_header(runtime.global_vars, varname); + } + if (value) { + char *v = strdup(value); + switch_string_var_check(v, SWITCH_TRUE); + switch_event_add_header_string(runtime.global_vars, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, varname, v); + } else { + switch_event_del_header(runtime.global_vars, varname); + } + switch_thread_rwlock_unlock(runtime.global_var_rwlock); + } +} + +SWITCH_DECLARE(switch_bool_t) switch_core_set_var_conditional(const char *varname, const char *value, const char *val2) +{ + char *val; + + if (varname) { + switch_thread_rwlock_wrlock(runtime.global_var_rwlock); + val = (char *) switch_event_get_header(runtime.global_vars, varname); + + if (val) { + if (!val2 || strcmp(val, val2) != 0) { + switch_thread_rwlock_unlock(runtime.global_var_rwlock); + return SWITCH_FALSE; + } + switch_event_del_header(runtime.global_vars, varname); + } else if (!zstr(val2)) { + switch_thread_rwlock_unlock(runtime.global_var_rwlock); + return SWITCH_FALSE; + } + + if (value) { + char *v = strdup(value); + switch_string_var_check(v, SWITCH_TRUE); + switch_event_add_header_string(runtime.global_vars, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, varname, v); + } else { + switch_event_del_header(runtime.global_vars, varname); + } + switch_thread_rwlock_unlock(runtime.global_var_rwlock); + } + return SWITCH_TRUE; +} + +SWITCH_DECLARE(char *) switch_core_get_uuid(void) +{ + return runtime.uuid_str; +} + + +static void *SWITCH_THREAD_FUNC switch_core_service_thread(switch_thread_t *thread, void *obj) +{ + switch_core_session_t *session = obj; + switch_channel_t *channel; + switch_frame_t *read_frame; + +// switch_assert(thread != NULL); +// switch_assert(session != NULL); + + if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) { + return NULL; + } + + switch_mutex_lock(session->frame_read_mutex); + + channel = switch_core_session_get_channel(session); + + switch_channel_set_flag(channel, CF_SERVICE); + while (switch_channel_test_flag(channel, CF_SERVICE)) { + + if (switch_channel_test_flag(channel, CF_SERVICE_AUDIO)) { + switch (switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0)) { + case SWITCH_STATUS_SUCCESS: + case SWITCH_STATUS_TIMEOUT: + case SWITCH_STATUS_BREAK: + break; + default: + switch_channel_clear_flag(channel, CF_SERVICE); + break; + } + } + + if (switch_channel_test_flag(channel, CF_SERVICE_VIDEO) && switch_channel_test_flag(channel, CF_VIDEO)) { + switch (switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0)) { + case SWITCH_STATUS_SUCCESS: + case SWITCH_STATUS_TIMEOUT: + case SWITCH_STATUS_BREAK: + break; + default: + switch_channel_clear_flag(channel, CF_SERVICE); + break; + } + } + } + + switch_mutex_unlock(session->frame_read_mutex); + + switch_channel_clear_flag(channel, CF_SERVICE_AUDIO); + switch_channel_clear_flag(channel, CF_SERVICE_VIDEO); + + switch_core_session_rwunlock(session); + + return NULL; +} + +/* Either add a timeout here or make damn sure the thread cannot get hung somehow (my preference) */ +SWITCH_DECLARE(void) switch_core_thread_session_end(switch_core_session_t *session) +{ + switch_channel_t *channel; + switch_assert(session); + + channel = switch_core_session_get_channel(session); + switch_assert(channel); + + switch_channel_clear_flag(channel, CF_SERVICE); + switch_channel_clear_flag(channel, CF_SERVICE_AUDIO); + switch_channel_clear_flag(channel, CF_SERVICE_VIDEO); + + switch_core_session_kill_channel(session, SWITCH_SIG_BREAK); + +} + +SWITCH_DECLARE(void) switch_core_service_session_av(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video) +{ + switch_channel_t *channel; + switch_assert(session); + + channel = switch_core_session_get_channel(session); + switch_assert(channel); + + if (audio) switch_channel_set_flag(channel, CF_SERVICE_AUDIO); + if (video) switch_channel_set_flag(channel, CF_SERVICE_VIDEO); + + switch_core_session_launch_thread(session, (void *(*)(switch_thread_t *,void *))switch_core_service_thread, session); +} + +/* This function abstracts the thread creation for modules by allowing you to pass a function ptr and + a void object and trust that that the function will be run in a thread with arg This lets + you request and activate a thread without giving up any knowledge about what is in the thread + neither the core nor the calling module know anything about each other. + + This thread is expected to never exit until the application exits so the func is responsible + to make sure that is the case. + + The typical use for this is so switch_loadable_module.c can start up a thread for each module + passing the table of module methods as a session obj into the core without actually allowing + the core to have any clue and keeping switch_loadable_module.c from needing any thread code. + +*/ + +SWITCH_DECLARE(switch_thread_t *) switch_core_launch_thread(switch_thread_start_t func, void *obj, switch_memory_pool_t *pool) +{ + switch_thread_t *thread = NULL; + switch_threadattr_t *thd_attr = NULL; + switch_core_thread_session_t *ts; + int mypool; + + mypool = pool ? 0 : 1; + + if (!pool && switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory pool\n"); + return NULL; + } + + switch_threadattr_create(&thd_attr, pool); + + if ((ts = switch_core_alloc(pool, sizeof(*ts))) == 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory\n"); + } else { + if (mypool) { + ts->pool = pool; + } + ts->objs[0] = obj; + ts->objs[1] = thread; + switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); + switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME); + switch_thread_create(&thread, thd_attr, func, ts, pool); + } + + return thread; +} + +SWITCH_DECLARE(void) switch_core_set_globals(void) +{ +#define BUFSIZE 1024 +#ifdef WIN32 + char lpPathBuffer[BUFSIZE]; + DWORD dwBufSize = BUFSIZE; + char base_dir[1024]; + char *lastbacklash; + char *tmp; + + GetModuleFileName(NULL, base_dir, BUFSIZE); + lastbacklash = strrchr(base_dir, '\\'); + base_dir[(lastbacklash - base_dir)] = '\0'; + /* set base_dir as cwd, to be able to use relative paths in scripting languages (e.g. mod_lua) when FS is running as a service or while debugging FS using visual studio */ + SetCurrentDirectory(base_dir); + tmp = switch_string_replace(base_dir, "\\", "/"); + strcpy(base_dir, tmp); + free(tmp); + +#else + char base_dir[1024] = SWITCH_PREFIX_DIR; +#endif + + if (!SWITCH_GLOBAL_dirs.base_dir && (SWITCH_GLOBAL_dirs.base_dir = (char *) malloc(BUFSIZE))) { + switch_snprintf(SWITCH_GLOBAL_dirs.base_dir, BUFSIZE, "%s", base_dir); + } + + if (!SWITCH_GLOBAL_dirs.mod_dir && (SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_MOD_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s", SWITCH_MOD_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s%smod", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.lib_dir && (SWITCH_GLOBAL_dirs.lib_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_LIB_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s", SWITCH_LIB_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s%slib", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.conf_dir && (SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_CONF_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s", SWITCH_CONF_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s%sconf", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.log_dir && (SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_LOG_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s", SWITCH_LOG_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s%slog", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.run_dir && (SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_RUN_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s", SWITCH_RUN_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s%srun", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.recordings_dir && (SWITCH_GLOBAL_dirs.recordings_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_RECORDINGS_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s", SWITCH_RECORDINGS_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s%srecordings", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.sounds_dir && (SWITCH_GLOBAL_dirs.sounds_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_SOUNDS_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s", SWITCH_SOUNDS_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s%ssounds", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.storage_dir && (SWITCH_GLOBAL_dirs.storage_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_STORAGE_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s", SWITCH_STORAGE_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s%sstorage", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.db_dir && (SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_DB_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s", SWITCH_DB_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s%sdb", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.script_dir && (SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_SCRIPT_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s", SWITCH_SCRIPT_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s%sscripts", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_HTDOCS_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s", SWITCH_HTDOCS_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s%shtdocs", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.grammar_dir && (SWITCH_GLOBAL_dirs.grammar_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_GRAMMAR_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s", SWITCH_GRAMMAR_DIR); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s%sgrammar", base_dir, SWITCH_PATH_SEPARATOR); +#endif + } + + if (!SWITCH_GLOBAL_dirs.temp_dir && (SWITCH_GLOBAL_dirs.temp_dir = (char *) malloc(BUFSIZE))) { +#ifdef SWITCH_TEMP_DIR + switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", SWITCH_TEMP_DIR); +#else +#ifdef WIN32 + GetTempPath(dwBufSize, lpPathBuffer); + lpPathBuffer[strlen(lpPathBuffer)-1] = 0; + switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", lpPathBuffer); +#else + switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", "/tmp"); +#endif +#endif + } + + switch_assert(SWITCH_GLOBAL_dirs.base_dir); + switch_assert(SWITCH_GLOBAL_dirs.mod_dir); + switch_assert(SWITCH_GLOBAL_dirs.lib_dir); + switch_assert(SWITCH_GLOBAL_dirs.conf_dir); + switch_assert(SWITCH_GLOBAL_dirs.log_dir); + switch_assert(SWITCH_GLOBAL_dirs.run_dir); + switch_assert(SWITCH_GLOBAL_dirs.db_dir); + switch_assert(SWITCH_GLOBAL_dirs.script_dir); + switch_assert(SWITCH_GLOBAL_dirs.htdocs_dir); + switch_assert(SWITCH_GLOBAL_dirs.grammar_dir); + switch_assert(SWITCH_GLOBAL_dirs.recordings_dir); + switch_assert(SWITCH_GLOBAL_dirs.sounds_dir); + switch_assert(SWITCH_GLOBAL_dirs.temp_dir); +} + + +SWITCH_DECLARE(int32_t) set_low_priority(void) +{ + + +#ifdef WIN32 + SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); +#else +#ifdef USE_SCHED_SETSCHEDULER + /* + * Try to use a normal scheduler + */ + struct sched_param sched = { 0 }; + sched.sched_priority = 0; + if (sched_setscheduler(0, SCHED_OTHER, &sched)) { + return -1; + } +#endif + +#ifdef HAVE_SETPRIORITY + /* + * setpriority() works on FreeBSD (6.2), nice() doesn't + */ + if (setpriority(PRIO_PROCESS, getpid(), 19) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); + return -1; + } +#else + if (nice(19) != 19) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); + return -1; + } +#endif +#endif + + return 0; +} + +SWITCH_DECLARE(int32_t) set_realtime_priority(void) +{ +#ifdef WIN32 + SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); +#else +#ifdef USE_SCHED_SETSCHEDULER + /* + * Try to use a round-robin scheduler + * with a fallback if that does not work + */ + struct sched_param sched = { 0 }; + sched.sched_priority = SWITCH_PRI_LOW; + if (sched_setscheduler(0, SCHED_FIFO, &sched)) { + sched.sched_priority = 0; + if (sched_setscheduler(0, SCHED_OTHER, &sched)) { + return -1; + } + } +#endif + + + +#ifdef HAVE_SETPRIORITY + /* + * setpriority() works on FreeBSD (6.2), nice() doesn't + */ + if (setpriority(PRIO_PROCESS, getpid(), -10) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); + return -1; + } +#else + if (nice(-10) != -10) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); + return -1; + } +#endif +#endif + return 0; +} + +SWITCH_DECLARE(uint32_t) switch_core_cpu_count(void) +{ + return runtime.cpu_count; +} + +SWITCH_DECLARE(int32_t) set_normal_priority(void) +{ + return 0; +} + +SWITCH_DECLARE(int32_t) set_auto_priority(void) +{ +#ifndef WIN32 + runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN); +#else + SYSTEM_INFO sysinfo; + GetSystemInfo( &sysinfo ); + runtime.cpu_count = sysinfo.dwNumberOfProcessors; +#endif + + if (!runtime.cpu_count) runtime.cpu_count = 1; + + /* If we have more than 1 cpu, we should use realtime priority so we can have priority threads */ + if (runtime.cpu_count > 1) { + return set_realtime_priority(); + } + + return 0; +} + +SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group) +{ +#ifndef WIN32 + uid_t runas_uid = 0; + gid_t runas_gid = 0; + struct passwd *runas_pw = NULL; + + if (user) { + /* + * Lookup user information in the system's db + */ + runas_pw = getpwnam(user); + if (!runas_pw) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unknown user \"%s\"\n", user); + return -1; + } + runas_uid = runas_pw->pw_uid; + } + + if (group) { + struct group *gr = NULL; + + /* + * Lookup group information in the system's db + */ + gr = getgrnam(group); + if (!gr) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unknown group \"%s\"\n", group); + return -1; + } + runas_gid = gr->gr_gid; + } + + if (runas_uid && getuid() == runas_uid && (!runas_gid || runas_gid == getgid())) { + /* already running as the right user and group, nothing to do! */ + return 0; + } + + if (runas_uid) { +#ifdef HAVE_SETGROUPS + /* + * Drop all group memberships prior to changing anything + * or else we're going to inherit the parent's list of groups + * (which is not what we want...) + */ + if (setgroups(0, NULL) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to drop group access list\n"); + return -1; + } +#endif + if (runas_gid) { + /* + * A group has been passed, switch to it + * (without loading the user's other groups) + */ + if (setgid(runas_gid) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change gid!\n"); + return -1; + } + } else { + /* + * No group has been passed, use the user's primary group in this case + */ + if (setgid(runas_pw->pw_gid) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change gid!\n"); + return -1; + } +#ifdef HAVE_INITGROUPS + /* + * Set all the other groups the user is a member of + * (This can be really useful for fine-grained access control) + */ + if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to set group access list for user\n"); + return -1; + } +#endif + } + + /* + * Finally drop all privileges by switching to the new userid + */ + if (setuid(runas_uid) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change uid!\n"); + return -1; + } + } +#endif + return 0; +} + +SWITCH_DECLARE(void) switch_core_runtime_loop(int bg) +{ +#ifdef WIN32 + HANDLE shutdown_event; + char path[256] = ""; +#endif + if (bg) { + bg = 0; +#ifdef WIN32 + switch_snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid()); + shutdown_event = CreateEvent(NULL, FALSE, FALSE, path); + if (shutdown_event) { + WaitForSingleObject(shutdown_event, INFINITE); + } +#else + runtime.running = 1; + while (runtime.running) { + switch_yield(1000000); + } +#endif + } else { + /* wait for console input */ + switch_console_loop(); + } +} + +SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext) +{ + if (!ext) { + return NULL; + } + return (const char *) switch_core_hash_find(runtime.mime_types, ext); +} + + +SWITCH_DECLARE(switch_hash_index_t *) switch_core_mime_index(void) +{ + return switch_hash_first(NULL, runtime.mime_types); +} + +SWITCH_DECLARE(switch_status_t) switch_core_mime_add_type(const char *type, const char *ext) +{ + const char *check; + switch_status_t status = SWITCH_STATUS_FALSE; + + switch_assert(type); + switch_assert(ext); + + check = (const char *) switch_core_hash_find(runtime.mime_types, ext); + + if (!check) { + char *ptype = switch_core_permanent_strdup(type); + char *ext_list = strdup(ext); + int argc = 0; + char *argv[20] = { 0 }; + int x; + + switch_assert(ext_list); + + if ((argc = switch_separate_string(ext_list, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { + + for (x = 0; x < argc; x++) { + if (argv[x] && ptype) { + switch_core_hash_insert(runtime.mime_types, argv[x], ptype); + } + } + + status = SWITCH_STATUS_SUCCESS; + } + + free(ext_list); + } + + return status; +} + +static void load_mime_types(void) +{ + char *cf = "mime.types"; + FILE *fd = NULL; + char *line_buf = NULL; + switch_size_t llen = 0; + char *mime_path = NULL; + + mime_path = switch_mprintf("%s/%s", SWITCH_GLOBAL_dirs.conf_dir, cf); + switch_assert(mime_path); + + fd = fopen(mime_path, "rb"); + + if (fd == NULL) { + goto end; + } + + while ((switch_fp_read_dline(fd, &line_buf, &llen))) { + char *p; + char *type = line_buf; + + if (*line_buf == '#') { + continue; + } + + if ((p = strchr(line_buf, '\r')) || (p = strchr(line_buf, '\n'))) { + *p = '\0'; + } + + if ((p = strchr(type, '\t')) || (p = strchr(type, ' '))) { + *p++ = '\0'; + + while (*p == ' ' || *p == '\t') { + p++; + } + + switch_core_mime_add_type(type, p); + } + + } + + switch_safe_free(line_buf); + + if (fd) { + fclose(fd); + fd = NULL; + } + + end: + + switch_safe_free(mime_path); + +} + +SWITCH_DECLARE(void) switch_core_setrlimits(void) +{ +#ifdef HAVE_SETRLIMIT + struct rlimit rlp; + + /* + Setting the stack size on FreeBSD results in an instant crash. + + If anyone knows how to fix this, + feel free to submit a patch to http://jira.freeswitch.org + */ + +#ifndef __FreeBSD__ + memset(&rlp, 0, sizeof(rlp)); + rlp.rlim_cur = SWITCH_THREAD_STACKSIZE; + rlp.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE; + setrlimit(RLIMIT_STACK, &rlp); +#endif + + memset(&rlp, 0, sizeof(rlp)); + rlp.rlim_cur = 999999; + rlp.rlim_max = 999999; + setrlimit(RLIMIT_NOFILE, &rlp); + + memset(&rlp, 0, sizeof(rlp)); + rlp.rlim_cur = RLIM_INFINITY; + rlp.rlim_max = RLIM_INFINITY; + + setrlimit(RLIMIT_CPU, &rlp); + setrlimit(RLIMIT_DATA, &rlp); + setrlimit(RLIMIT_FSIZE, &rlp); +#ifdef RLIMIT_NPROC + setrlimit(RLIMIT_NPROC, &rlp); +#endif +#ifdef RLIMIT_RTPRIO + setrlimit(RLIMIT_RTPRIO, &rlp); +#endif + +#if !defined(__OpenBSD__) && !defined(__NetBSD__) + setrlimit(RLIMIT_AS, &rlp); +#endif +#endif + return; +} + +typedef struct { + switch_memory_pool_t *pool; + switch_hash_t *hash; +} switch_ip_list_t; + +static switch_ip_list_t IP_LIST = { 0 }; + +SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token) +{ + switch_network_list_t *list; + ip_t ip, mask, net; + uint32_t bits; + char *ipv6 = strchr(ip_str,':'); + switch_bool_t ok = SWITCH_FALSE; + + switch_mutex_lock(runtime.global_mutex); + if (ipv6) { + switch_inet_pton(AF_INET6, ip_str, &ip); + } else { + switch_inet_pton(AF_INET, ip_str, &ip); + ip.v4 = htonl(ip.v4); + } + + if ((list = switch_core_hash_find(IP_LIST.hash, list_name))) { + if (ipv6) { + ok = switch_network_list_validate_ip6_token(list, ip, token); + } else { + ok = switch_network_list_validate_ip_token(list, ip.v4, token); + } + } else if (strchr(list_name, '/')) { + if (strchr(list_name, ',')) { + char *list_name_dup = strdup(list_name); + char *argv[32]; + int argc; + + switch_assert(list_name_dup); + + if ((argc = switch_separate_string(list_name_dup, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) { + int i; + for (i = 0; i < argc; i++) { + switch_parse_cidr(argv[i], &net, &mask, &bits); + if (ipv6) { + if ((ok = switch_testv6_subnet(ip, net, mask))){ + break; + } + } else { + if ((ok = switch_test_subnet(ip.v4, net.v4, mask.v4))) { + break; + } + } + } + } + free(list_name_dup); + } else { + switch_parse_cidr(list_name, &net, &mask, &bits); + ok = switch_test_subnet(ip.v4, net.v4, mask.v4); + } + } + switch_mutex_unlock(runtime.global_mutex); + + return ok; +} + + +SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload) +{ + switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, x_node = NULL, cfg = NULL; + switch_network_list_t *rfc_list, *list; + char guess_ip[16] = ""; + int mask = 0; + char guess_mask[16] = ""; + char *tmp_name; + struct in_addr in; + + switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET); + in.s_addr = mask; + switch_set_string(guess_mask, inet_ntoa(in)); + + switch_mutex_lock(runtime.global_mutex); + + if (IP_LIST.hash) { + switch_core_hash_destroy(&IP_LIST.hash); + } + + if (IP_LIST.pool) { + switch_core_destroy_memory_pool(&IP_LIST.pool); + } + + memset(&IP_LIST, 0, sizeof(IP_LIST)); + switch_core_new_memory_pool(&IP_LIST.pool); + switch_core_hash_init(&IP_LIST.hash, IP_LIST.pool); + + + tmp_name = "rfc1918.auto"; + switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); + switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE); + switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE); + switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE); + switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); + + tmp_name = "wan.auto"; + switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name); + switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_FALSE); + switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_FALSE); + switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_FALSE); + switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); + + tmp_name = "nat.auto"; + switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); + if (switch_network_list_add_host_mask(rfc_list, guess_ip, guess_mask, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s/%s (deny) to list %s\n", guess_ip, guess_mask, tmp_name); + } + switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE); + switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE); + switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE); + switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); + + tmp_name = "loopback.auto"; + switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); + switch_network_list_add_cidr(rfc_list, "127.0.0.0/8", SWITCH_TRUE); + switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); + + tmp_name = "localnet.auto"; + switch_network_list_create(&list, tmp_name, SWITCH_FALSE, IP_LIST.pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); + + if (switch_network_list_add_host_mask(list, guess_ip, guess_mask, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s/%s (allow) to list %s\n", guess_ip, guess_mask, tmp_name); + } + switch_core_hash_insert(IP_LIST.hash, tmp_name, list); + + + if ((xml = switch_xml_open_cfg("acl.conf", &cfg, NULL))) { + if ((x_lists = switch_xml_child(cfg, "network-lists"))) { + for (x_list = switch_xml_child(x_lists, "list"); x_list; x_list = x_list->next) { + const char *name = switch_xml_attr(x_list, "name"); + const char *dft = switch_xml_attr(x_list, "default"); + switch_bool_t default_type = SWITCH_TRUE; + + if (zstr(name)) { + continue; + } + + if (dft) { + default_type = switch_true(dft); + } + + if (switch_network_list_create(&list, name, default_type, IP_LIST.pool) != SWITCH_STATUS_SUCCESS) { + abort(); + } + + if (reload) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny"); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny"); + } + + + for (x_node = switch_xml_child(x_list, "node"); x_node; x_node = x_node->next) { + const char *cidr = NULL, *host = NULL, *mask = NULL, *domain = NULL; + switch_bool_t ok = default_type; + const char *type = switch_xml_attr(x_node, "type"); + + if (type) { + ok = switch_true(type); + } + + cidr = switch_xml_attr(x_node, "cidr"); + host = switch_xml_attr(x_node, "host"); + mask = switch_xml_attr(x_node, "mask"); + domain = switch_xml_attr(x_node, "domain"); + + if (domain) { + switch_event_t *my_params = NULL; + switch_xml_t x_domain, xml_root; + switch_xml_t gt, gts, ut, uts; + + switch_event_create(&my_params, SWITCH_EVENT_GENERAL); + switch_assert(my_params); + switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "domain", domain); + switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "purpose", "network-list"); + + if (switch_xml_locate_domain(domain, my_params, &xml_root, &x_domain) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate domain %s\n", domain); + switch_event_destroy(&my_params); + continue; + } + + switch_event_destroy(&my_params); + + for (ut = switch_xml_child(x_domain, "user"); ut; ut = ut->next) { + const char *user_cidr = switch_xml_attr(ut, "cidr"); + const char *id = switch_xml_attr(ut, "id"); + + if (id && user_cidr) { + char *token = switch_mprintf("%s@%s", id, domain); + switch_assert(token); + switch_network_list_add_cidr_token(list, user_cidr, ok, token); + free(token); + } + } + + for (gts = switch_xml_child(x_domain, "groups"); gts; gts = gts->next) { + for (gt = switch_xml_child(gts, "group"); gt; gt = gt->next) { + for (uts = switch_xml_child(gt, "users"); uts; uts = uts->next) { + for (ut = switch_xml_child(uts, "user"); ut; ut = ut->next) { + const char *user_cidr = switch_xml_attr(ut, "cidr"); + const char *id = switch_xml_attr(ut, "id"); + + if (id && user_cidr) { + char *token = switch_mprintf("%s@%s", id, domain); + switch_assert(token); + switch_network_list_add_cidr_token(list, user_cidr, ok, token); + free(token); + } + } + } + } + } + + switch_xml_free(xml_root); + } else if (cidr) { + if (switch_network_list_add_cidr(list, cidr, ok) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "Error Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name); + } + } else if (host && mask) { + if (switch_network_list_add_host_mask(list, host, mask, ok) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, + "Adding %s/%s (%s) to list %s\n", host, mask, ok ? "allow" : "deny", name); + } + } + + switch_core_hash_insert(IP_LIST.hash, name, list); + } + } + } + + switch_xml_free(xml); + } + + switch_mutex_unlock(runtime.global_mutex); +} + +SWITCH_DECLARE(uint32_t) switch_core_max_dtmf_duration(uint32_t duration) +{ + if (duration) { + if (duration > SWITCH_MAX_DTMF_DURATION) { + duration = SWITCH_MAX_DTMF_DURATION; + } + if (duration < SWITCH_MIN_DTMF_DURATION) { + duration = SWITCH_MIN_DTMF_DURATION; + } + runtime.max_dtmf_duration = duration; + if (duration < runtime.min_dtmf_duration) { + runtime.min_dtmf_duration = duration; + } + } + return runtime.max_dtmf_duration; +} + +SWITCH_DECLARE(uint32_t) switch_core_default_dtmf_duration(uint32_t duration) +{ + if (duration) { + if (duration < SWITCH_MIN_DTMF_DURATION) { + duration = SWITCH_MIN_DTMF_DURATION; + } + if (duration > SWITCH_MAX_DTMF_DURATION) { + duration = SWITCH_MAX_DTMF_DURATION; + } + runtime.default_dtmf_duration = duration; + + if (duration < runtime.min_dtmf_duration) { + runtime.min_dtmf_duration = duration; + } + + if (duration > runtime.max_dtmf_duration) { + runtime.max_dtmf_duration = duration; + } + + } + return runtime.default_dtmf_duration; +} + +SWITCH_DECLARE(uint32_t) switch_core_min_dtmf_duration(uint32_t duration) +{ + if (duration) { + if (duration < SWITCH_MIN_DTMF_DURATION) { + duration = SWITCH_MIN_DTMF_DURATION; + } + if (duration > SWITCH_MAX_DTMF_DURATION) { + duration = SWITCH_MAX_DTMF_DURATION; + } + + runtime.min_dtmf_duration = duration; + + if (duration > runtime.max_dtmf_duration) { + runtime.max_dtmf_duration = duration; + } + } + return runtime.min_dtmf_duration; +} + +SWITCH_DECLARE(switch_status_t) switch_core_thread_set_cpu_affinity(int cpu) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + + if (cpu > -1) { + +#ifdef HAVE_CPU_SET_MACROS + cpu_set_t set; + + CPU_ZERO(&set); + CPU_SET(cpu, &set); + + if (!sched_setaffinity(0, sizeof(set), &set)) { + status = SWITCH_STATUS_SUCCESS; + } + +#else +#if WIN32 + if (SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR) cpu)) { + status = SWITCH_STATUS_SUCCESS; + } +#endif +#endif + } + + return status; +} + + +static void switch_core_set_serial(void) +{ + char buf[13] = ""; + char path[256]; + + int fd = -1, write_fd = -1; + switch_ssize_t bytes = 0; + + switch_snprintf(path, sizeof(path), "%s%sfreeswitch.serial", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR); + + + if ((fd = open(path, O_RDONLY, 0)) < 0) { + char *ip = switch_core_get_variable_dup("local_ip_v4"); + uint32_t ipi = 0; + switch_byte_t *byte; + int i = 0; + + if (ip) { + switch_inet_pton(AF_INET, ip, &ipi); + free(ip); + ip = NULL; + } + + + byte = (switch_byte_t *) & ipi; + + for (i = 0; i < 8; i += 2) { + switch_snprintf(buf + i, sizeof(buf) - i, "%0.2x", *byte); + byte++; + } + + switch_stun_random_string(buf + 8, 4, "0123456789abcdef"); + + if ((write_fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) >= 0) { + bytes = write(write_fd, buf, sizeof(buf)); + bytes++; + close(write_fd); + write_fd = -1; + } + } else { + bytes = read(fd, buf, sizeof(buf)); + close(fd); + fd = -1; + } + + switch_core_set_variable("switch_serial", buf); +} + + +SWITCH_DECLARE(int) switch_core_test_flag(int flag) +{ + return switch_test_flag((&runtime), flag); +} + + +SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switch_bool_t console, const char **err) +{ + switch_uuid_t uuid; + char guess_ip[256]; + int mask = 0; + struct in_addr in; + + + if (runtime.runlevel > 0) { + /* one per customer */ + return SWITCH_STATUS_SUCCESS; + } + + memset(&runtime, 0, sizeof(runtime)); + gethostname(runtime.hostname, sizeof(runtime.hostname)); + + runtime.max_db_handles = 50; + runtime.db_handle_timeout = 5000000; + + runtime.runlevel++; + runtime.dummy_cng_frame.data = runtime.dummy_data; + runtime.dummy_cng_frame.datalen = sizeof(runtime.dummy_data); + runtime.dummy_cng_frame.buflen = sizeof(runtime.dummy_data); + runtime.dbname = "core"; + switch_set_flag((&runtime.dummy_cng_frame), SFF_CNG); + switch_set_flag((&runtime), SCF_AUTO_SCHEMAS); + switch_set_flag((&runtime), SCF_CLEAR_SQL); + switch_set_flag((&runtime), SCF_API_EXPANSION); + switch_set_flag((&runtime), SCF_SESSION_THREAD_POOL); +#ifdef WIN32 + switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); +#endif + switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); + runtime.hard_log_level = SWITCH_LOG_DEBUG; + runtime.mailer_app = "sendmail"; + runtime.mailer_app_args = "-t"; + runtime.max_dtmf_duration = SWITCH_MAX_DTMF_DURATION; + runtime.default_dtmf_duration = SWITCH_DEFAULT_DTMF_DURATION; + runtime.min_dtmf_duration = SWITCH_MIN_DTMF_DURATION; + runtime.odbc_dbtype = DBTYPE_DEFAULT; + runtime.dbname = NULL; +#ifndef WIN32 + runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN); +#else + { + SYSTEM_INFO sysinfo; + GetSystemInfo( &sysinfo ); + runtime.cpu_count = sysinfo.dwNumberOfProcessors; + } +#endif + + if (!runtime.cpu_count) runtime.cpu_count = 1; + + + /* INIT APR and Create the pool context */ + if (apr_initialize() != SWITCH_STATUS_SUCCESS) { + *err = "FATAL ERROR! Could not initialize APR\n"; + return SWITCH_STATUS_MEMERR; + } + + if (!(runtime.memory_pool = switch_core_memory_init())) { + *err = "FATAL ERROR! Could not allocate memory pool\n"; + return SWITCH_STATUS_MEMERR; + } + switch_assert(runtime.memory_pool != NULL); + + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.base_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.mod_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.conf_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.log_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.run_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.db_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.script_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.htdocs_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.recordings_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.sounds_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + switch_dir_make_recursive(SWITCH_GLOBAL_dirs.temp_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool); + + + switch_mutex_init(&runtime.uuid_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); + + switch_mutex_init(&runtime.throttle_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); + + switch_mutex_init(&runtime.session_hash_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); + switch_mutex_init(&runtime.global_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); + + switch_thread_rwlock_create(&runtime.global_var_rwlock, runtime.memory_pool); + switch_core_set_globals(); + switch_core_session_init(runtime.memory_pool); + switch_event_create_plain(&runtime.global_vars, SWITCH_EVENT_CHANNEL_DATA); + switch_core_hash_init(&runtime.mime_types, runtime.memory_pool); + switch_core_hash_init_case(&runtime.ptimes, runtime.memory_pool, SWITCH_FALSE); + load_mime_types(); + runtime.flags |= flags; + runtime.sps_total = 30; + + *err = NULL; + + if (console) { + runtime.console = stdout; + } + + switch_ssl_init_ssl_locks(); + switch_curl_init(); + + switch_core_set_variable("hostname", runtime.hostname); + switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET); + switch_core_set_variable("local_ip_v4", guess_ip); + in.s_addr = mask; + switch_core_set_variable("local_mask_v4", inet_ntoa(in)); + + + switch_find_local_ip(guess_ip, sizeof(guess_ip), NULL, AF_INET6); + switch_core_set_variable("local_ip_v6", guess_ip); + switch_core_set_variable("base_dir", SWITCH_GLOBAL_dirs.base_dir); + switch_core_set_variable("recordings_dir", SWITCH_GLOBAL_dirs.recordings_dir); + switch_core_set_variable("sound_prefix", SWITCH_GLOBAL_dirs.sounds_dir); + switch_core_set_variable("sounds_dir", SWITCH_GLOBAL_dirs.sounds_dir); + switch_core_set_serial(); + + switch_console_init(runtime.memory_pool); + switch_event_init(runtime.memory_pool); + + if (switch_xml_init(runtime.memory_pool, err) != SWITCH_STATUS_SUCCESS) { + apr_terminate(); + return SWITCH_STATUS_MEMERR; + } + + if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) { + switch_nat_init(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_NAT_MAPPING)); + } + + switch_log_init(runtime.memory_pool, runtime.colorize_console); + + if (flags & SCF_MINIMAL) return SWITCH_STATUS_SUCCESS; + + runtime.tipping_point = 0; + runtime.timer_affinity = -1; + runtime.microseconds_per_tick = 20000; + + switch_load_core_config("switch.conf"); + + switch_core_state_machine_init(runtime.memory_pool); + + if (switch_core_sqldb_start(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_SQL) ? SWITCH_TRUE : SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { + *err = "Error activating database"; + return SWITCH_STATUS_FALSE; + } + + switch_scheduler_task_thread_start(); + + switch_nat_late_init(); + + switch_rtp_init(runtime.memory_pool); + + runtime.running = 1; + runtime.initiated = switch_time_now(); + runtime.mono_initiated = switch_mono_micro_time_now(); + + switch_scheduler_add_task(switch_epoch_time_now(NULL), heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL); + + switch_scheduler_add_task(switch_epoch_time_now(NULL), check_ip_callback, "check_ip", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL | SSHF_OWN_THREAD); + + switch_uuid_get(&uuid); + switch_uuid_format(runtime.uuid_str, &uuid); + switch_core_set_variable("core_uuid", runtime.uuid_str); + + + return SWITCH_STATUS_SUCCESS; +} + + +#ifndef WIN32 +static void handle_SIGCHLD(int sig) +{ + int status = 0; + + wait(&status); + return; +} +#endif + +#ifdef TRAP_BUS +static void handle_SIGBUS(int sig) +{ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Sig BUS!\n"); + return; +} +#endif + +static void handle_SIGHUP(int sig) +{ + if (sig) { + switch_event_t *event; + + if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Trapped-Signal", "HUP"); + switch_event_fire(&event); + } + } + return; +} + + +SWITCH_DECLARE(uint32_t) switch_default_ptime(const char *name, uint32_t number) +{ + uint32_t *p; + + if ((p = switch_core_hash_find(runtime.ptimes, name))) { + return *p; + } + + return 20; +} + +static uint32_t d_30 = 30; + +static void switch_load_core_config(const char *file) +{ + switch_xml_t xml = NULL, cfg = NULL; + + switch_core_hash_insert(runtime.ptimes, "ilbc", &d_30); + switch_core_hash_insert(runtime.ptimes, "G723", &d_30); + + if ((xml = switch_xml_open_cfg(file, &cfg, NULL))) { + switch_xml_t settings, param; + + if ((settings = switch_xml_child(cfg, "default-ptimes"))) { + for (param = switch_xml_child(settings, "codec"); param; param = param->next) { + const char *var = switch_xml_attr_soft(param, "name"); + const char *val = switch_xml_attr_soft(param, "ptime"); + + if (!zstr(var) && !zstr(val)) { + uint32_t *p; + uint32_t v = switch_atoul(val); + + if (!strcasecmp(var, "G723") || !strcasecmp(var, "iLBC")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding %s, defaults cannot be changed\n", var); + continue; + } + + if (v == 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding %s, invalid ptime\n", var); + continue; + } + + p = switch_core_alloc(runtime.memory_pool, sizeof(*p)); + *p = v; + switch_core_hash_insert(runtime.ptimes, var, p); + } + + } + } + + if ((settings = switch_xml_child(cfg, "settings"))) { + for (param = switch_xml_child(settings, "param"); param; param = param->next) { + const char *var = switch_xml_attr_soft(param, "name"); + const char *val = switch_xml_attr_soft(param, "value"); + + if (!strcasecmp(var, "loglevel")) { + int level; + if (*val > 47 && *val < 58) { + level = atoi(val); + } else { + level = switch_log_str2level(val); + } + + if (level != SWITCH_LOG_INVALID) { + switch_core_session_ctl(SCSC_LOGLEVEL, &level); + } +#ifdef HAVE_SETRLIMIT + } else if (!strcasecmp(var, "dump-cores") && switch_true(val)) { + struct rlimit rlp; + memset(&rlp, 0, sizeof(rlp)); + rlp.rlim_cur = RLIM_INFINITY; + rlp.rlim_max = RLIM_INFINITY; + setrlimit(RLIMIT_CORE, &rlp); +#endif + } else if (!strcasecmp(var, "debug-level")) { + int tmp = atoi(val); + if (tmp > -1 && tmp < 11) { + switch_core_session_ctl(SCSC_DEBUG_LEVEL, &tmp); + } + } else if (!strcasecmp(var, "max-db-handles")) { + long tmp = atol(val); + + if (tmp > 4 && tmp < 5001) { + runtime.max_db_handles = (uint32_t) tmp; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "max-db-handles must be between 5 and 5000\n"); + } + } else if (!strcasecmp(var, "db-handle-timeout")) { + long tmp = atol(val); + + if (tmp > 0 && tmp < 5001) { + runtime.db_handle_timeout = (uint32_t) tmp * 1000000; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "db-handle-timeout must be between 1 and 5000\n"); + } + + } else if (!strcasecmp(var, "multiple-registrations")) { + runtime.multiple_registrations = switch_true(val); + } else if (!strcasecmp(var, "auto-create-schemas")) { + if (switch_true(val)) { + switch_set_flag((&runtime), SCF_AUTO_SCHEMAS); + } else { + switch_clear_flag((&runtime), SCF_AUTO_SCHEMAS); + } + } else if (!strcasecmp(var, "session-thread-pool")) { + if (switch_true(val)) { + switch_set_flag((&runtime), SCF_SESSION_THREAD_POOL); + } else { + switch_clear_flag((&runtime), SCF_SESSION_THREAD_POOL); + } + } else if (!strcasecmp(var, "auto-clear-sql")) { + if (switch_true(val)) { + switch_set_flag((&runtime), SCF_CLEAR_SQL); + } else { + switch_clear_flag((&runtime), SCF_CLEAR_SQL); + } + } else if (!strcasecmp(var, "api-expansion")) { + if (switch_true(val)) { + switch_set_flag((&runtime), SCF_API_EXPANSION); + } else { + switch_clear_flag((&runtime), SCF_API_EXPANSION); + } + } else if (!strcasecmp(var, "enable-early-hangup") && switch_true(val)) { + switch_set_flag((&runtime), SCF_EARLY_HANGUP); + } else if (!strcasecmp(var, "colorize-console") && switch_true(val)) { + runtime.colorize_console = SWITCH_TRUE; + } else if (!strcasecmp(var, "core-db-pre-trans-execute") && !zstr(val)) { + runtime.core_db_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "core-db-post-trans-execute") && !zstr(val)) { + runtime.core_db_post_trans_execute = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "core-db-inner-pre-trans-execute") && !zstr(val)) { + runtime.core_db_inner_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "core-db-inner-post-trans-execute") && !zstr(val)) { + runtime.core_db_inner_post_trans_execute = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "mailer-app") && !zstr(val)) { + runtime.mailer_app = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "mailer-app-args") && val) { + runtime.mailer_app_args = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "sessions-per-second") && !zstr(val)) { + switch_core_sessions_per_second(atoi(val)); + } else if (!strcasecmp(var, "max-dtmf-duration") && !zstr(val)) { + int tmp = atoi(val); + if (tmp > 0) { + switch_core_max_dtmf_duration((uint32_t) tmp); + } + } else if (!strcasecmp(var, "min-dtmf-duration") && !zstr(val)) { + int tmp = atoi(val); + if (tmp > 0) { + switch_core_min_dtmf_duration((uint32_t) tmp); + } + } else if (!strcasecmp(var, "default-dtmf-duration") && !zstr(val)) { + int tmp = atoi(val); + if (tmp > 0) { + switch_core_default_dtmf_duration((uint32_t) tmp); + } + } else if (!strcasecmp(var, "enable-use-system-time")) { + switch_time_set_use_system_time(switch_true(val)); + } else if (!strcasecmp(var, "enable-monotonic-timing")) { + switch_time_set_monotonic(switch_true(val)); + } else if (!strcasecmp(var, "enable-softtimer-timerfd")) { + switch_time_set_timerfd(switch_true(val)); + } else if (!strcasecmp(var, "enable-clock-nanosleep")) { + switch_time_set_nanosleep(switch_true(val)); + } else if (!strcasecmp(var, "enable-cond-yield")) { + switch_time_set_cond_yield(switch_true(val)); + } else if (!strcasecmp(var, "enable-timer-matrix")) { + switch_time_set_matrix(switch_true(val)); + } else if (!strcasecmp(var, "max-sessions") && !zstr(val)) { + switch_core_session_limit(atoi(val)); + } else if (!strcasecmp(var, "verbose-channel-events") && !zstr(val)) { + int v = switch_true(val); + if (v) { + switch_set_flag((&runtime), SCF_VERBOSE_EVENTS); + } else { + switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS); + } + } else if (!strcasecmp(var, "threaded-system-exec") && !zstr(val)) { +#ifdef WIN32 + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "threaded-system-exec is not implemented on this platform\n"); +#else + int v = switch_true(val); + if (v) { + switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } else { + switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } +#endif + } else if (!strcasecmp(var, "min-idle-cpu") && !zstr(val)) { + switch_core_min_idle_cpu(atof(val)); + } else if (!strcasecmp(var, "tipping-point") && !zstr(val)) { + runtime.tipping_point = atoi(val); + } else if (!strcasecmp(var, "initial-event-threads") && !zstr(val)) { + int tmp = atoi(val); + + + if (tmp > runtime.cpu_count / 2) { + tmp = runtime.cpu_count / 2; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "This value cannot be higher than %d so setting it to that value\n", + runtime.cpu_count / 2); + } + + if (tmp < 1) { + tmp = 1; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "This value cannot be lower than 1 so setting it to that level\n"); + } + + switch_event_launch_dispatch_threads(tmp); + + } else if (!strcasecmp(var, "1ms-timer") && switch_true(val)) { + runtime.microseconds_per_tick = 1000; + } else if (!strcasecmp(var, "timer-affinity") && !zstr(val)) { + if (!strcasecmp(val, "disabled")) { + runtime.timer_affinity = -1; + } else { + runtime.timer_affinity = atoi(val); + } + } else if (!strcasecmp(var, "rtp-start-port") && !zstr(val)) { + switch_rtp_set_start_port((switch_port_t) atoi(val)); + } else if (!strcasecmp(var, "rtp-end-port") && !zstr(val)) { + switch_rtp_set_end_port((switch_port_t) atoi(val)); + } else if (!strcasecmp(var, "core-db-name") && !zstr(val)) { + runtime.dbname = switch_core_strdup(runtime.memory_pool, val); + } else if (!strcasecmp(var, "core-db-dsn") && !zstr(val)) { + if (switch_odbc_available() || switch_pgsql_available()) { + runtime.odbc_dsn = switch_core_strdup(runtime.memory_pool, val); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC AND PGSQL ARE NOT AVAILABLE!\n"); + } + } else if (!strcasecmp(var, "core-non-sqlite-db-required") && !zstr(val)) { + switch_set_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ); + } else if (!strcasecmp(var, "core-dbtype") && !zstr(val)) { + if (!strcasecmp(val, "MSSQL")) { + runtime.odbc_dbtype = DBTYPE_MSSQL; + } else { + runtime.odbc_dbtype = DBTYPE_DEFAULT; + } +#ifdef ENABLE_ZRTP + } else if (!strcasecmp(var, "rtp-enable-zrtp")) { + switch_core_set_variable("zrtp_enabled", val); +#endif + } else if (!strcasecmp(var, "switchname") && !zstr(val)) { + runtime.switchname = switch_core_strdup(runtime.memory_pool, val); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Set switchname to %s\n", runtime.switchname); + } + } + } + + if ((settings = switch_xml_child(cfg, "variables"))) { + for (param = switch_xml_child(settings, "variable"); param; param = param->next) { + const char *var = switch_xml_attr_soft(param, "name"); + const char *val = switch_xml_attr_soft(param, "value"); + if (var && val) { + switch_core_set_variable(var, val); + } + } + } + + switch_xml_free(xml); + } + + +} + +SWITCH_DECLARE(const char *) switch_core_banner(void) +{ + + return ("\n" + ".=============================================================.\n" + "| _____ ______ _____ _____ ____ _ _ |\n" + "| | ___| __ ___ ___/ ___\\ \\ / /_ _|_ _/ ___| | | | |\n" + "| | |_ | '__/ _ \\/ _ \\___ \\\\ \\ /\\ / / | | | || | | |_| | |\n" + "| | _|| | | __/ __/___) |\\ V V / | | | || |___| _ | |\n" + "| |_| |_| \\___|\\___|____/ \\_/\\_/ |___| |_| \\____|_| |_| |\n" + "| |\n" + ".=============================================================." + "\n" + + "| Anthony Minessale II, Michael Jerris, Brian West, Others |\n" + "| FreeSWITCH (http://www.freeswitch.org) |\n" + "| Paypal Donations Appreciated: paypal@freeswitch.org |\n" + "| Brought to you by ClueCon http://www.cluecon.com/ |\n" + ".=============================================================.\n" + "\n"); +} + + +SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t flags, switch_bool_t console, const char **err) +{ + switch_event_t *event; + char *cmd; + int x = 0; + const char *use = NULL; +#include "cc.h" + + + if (switch_core_init(flags, console, err) != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_GENERR; + } + + if (runtime.runlevel > 1) { + /* one per customer */ + return SWITCH_STATUS_SUCCESS; + } + + runtime.runlevel++; + + switch_core_set_signal_handlers(); + switch_load_network_lists(SWITCH_FALSE); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Bringing up environment.\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Loading Modules.\n"); + if (switch_loadable_module_init(SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) { + *err = "Cannot load modules"; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error: %s\n", *err); + return SWITCH_STATUS_GENERR; + } + + switch_load_network_lists(SWITCH_FALSE); + + switch_load_core_config("post_load_switch.conf"); + + switch_core_set_signal_handlers(); + + if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready"); + switch_event_fire(&event); + } + + switch_core_screen_size(&x, NULL); + + use = (x > 100) ? cc : cc_s; + +#ifdef WIN32 + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s\n\n", switch_core_banner(), use); +#else + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s%s%s%s%s\n\n", + SWITCH_SEQ_DEFAULT_COLOR, + SWITCH_SEQ_FYELLOW, SWITCH_SEQ_BBLUE, + switch_core_banner(), + use, SWITCH_SEQ_DEFAULT_COLOR); + +#endif + + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, + "\nFreeSWITCH Version %s (%s)\n\nFreeSWITCH Started\nMax Sessions [%u]\nSession Rate [%d]\nSQL [%s]\n", + SWITCH_VERSION_FULL, SWITCH_VERSION_REVISION_HUMAN, + switch_core_session_limit(0), + switch_core_sessions_per_second(0), switch_test_flag((&runtime), SCF_USE_SQL) ? "Enabled" : "Disabled"); + + + if (x < 160) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\n[This app Best viewed at 160x60 or more..]\n"); + } + + switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS); + + if ((cmd = switch_core_get_variable_dup("api_on_startup"))) { + switch_stream_handle_t stream = { 0 }; + SWITCH_STANDARD_STREAM(stream); + switch_console_execute(cmd, 0, &stream); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Startup command [%s] executed. Output:\n%s\n", cmd, (char *)stream.data); + free(stream.data); + free(cmd); + } + + return SWITCH_STATUS_SUCCESS; + +} + +SWITCH_DECLARE(void) switch_core_measure_time(switch_time_t total_ms, switch_core_time_duration_t *duration) +{ + switch_time_t temp = total_ms / 1000; + memset(duration, 0, sizeof(*duration)); + duration->mms = (uint32_t) (total_ms % 1000); + duration->ms = (uint32_t) (temp % 1000); + temp = temp / 1000; + duration->sec = (uint32_t) (temp % 60); + temp = temp / 60; + duration->min = (uint32_t) (temp % 60); + temp = temp / 60; + duration->hr = (uint32_t) (temp % 24); + temp = temp / 24; + duration->day = (uint32_t) (temp % 365); + duration->yr = (uint32_t) (temp / 365); +} + +SWITCH_DECLARE(switch_time_t) switch_core_uptime(void) +{ + return switch_mono_micro_time_now() - runtime.mono_initiated; +} + + +#ifdef _MSC_VER +static void win_shutdown(void) +{ + + HANDLE shutdown_event; + char path[512]; + /* for windows we need the event to signal for shutting down a background FreeSWITCH */ + snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid()); + + /* open the event so we can signal it */ + shutdown_event = OpenEvent(EVENT_MODIFY_STATE, FALSE, path); + + if (shutdown_event) { + /* signal the event to shutdown */ + SetEvent(shutdown_event); + /* cleanup */ + CloseHandle(shutdown_event); + } +} +#endif + +SWITCH_DECLARE(void) switch_core_set_signal_handlers(void) +{ + /* set signal handlers */ + signal(SIGINT, SIG_IGN); +#ifndef WIN32 + if (switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC)) { + signal(SIGCHLD, SIG_DFL); + } else { + signal(SIGCHLD, handle_SIGCHLD); + } +#endif +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif +#ifdef SIGQUIT + signal(SIGQUIT, SIG_IGN); +#endif +#ifdef SIGPOLL + signal(SIGPOLL, SIG_IGN); +#endif +#ifdef SIGIO + signal(SIGIO, SIG_IGN); +#endif +#ifdef TRAP_BUS + signal(SIGBUS, handle_SIGBUS); +#endif +#ifdef SIGUSR1 + signal(SIGUSR1, handle_SIGHUP); +#endif + signal(SIGHUP, handle_SIGHUP); +} + +SWITCH_DECLARE(uint32_t) switch_core_debug_level(void) +{ + return runtime.debug_level; +} + + +SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, void *val) +{ + int *intval = (int *) val; + int oldintval = 0, newintval = 0; + + if (intval) { + oldintval = *intval; + } + + if (switch_test_flag((&runtime), SCF_SHUTTING_DOWN)) { + return -1; + } + + switch (cmd) { + case SCSC_RECOVER: + { + char *arg = (char *) val; + char *tech = NULL, *prof = NULL; + int r, flush = 0; + + if (!zstr(arg)) { + tech = strdup(arg); + + if ((prof = strchr(tech, ':'))) { + *prof++ = '\0'; + } + + if (!strcasecmp(tech, "flush")) { + flush++; + + if (prof) { + tech = prof; + if ((prof = strchr(tech, ':'))) { + *prof++ = '\0'; + } + } + } + + } + + if (flush) { + switch_core_recovery_flush(tech, prof); + r = -1; + } else { + r = switch_core_recovery_recover(tech, prof); + } + + switch_safe_free(tech); + return r; + + } + break; + case SCSC_DEBUG_SQL: + { + if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) { + switch_clear_flag((&runtime), SCF_DEBUG_SQL); + newintval = 0; + } else { + switch_set_flag((&runtime), SCF_DEBUG_SQL); + newintval = 1; + } + } + break; + case SCSC_VERBOSE_EVENTS: + if (intval) { + if (oldintval > -1) { + if (oldintval) { + switch_set_flag((&runtime), SCF_VERBOSE_EVENTS); + } else { + switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS); + } + } + newintval = switch_test_flag((&runtime), SCF_VERBOSE_EVENTS); + } + break; + case SCSC_API_EXPANSION: + if (intval) { + if (oldintval > -1) { + if (oldintval) { + switch_set_flag((&runtime), SCF_API_EXPANSION); + } else { + switch_clear_flag((&runtime), SCF_API_EXPANSION); + } + } + newintval = switch_test_flag((&runtime), SCF_API_EXPANSION); + } + break; + case SCSC_THREADED_SYSTEM_EXEC: + if (intval) { + if (oldintval > -1) { + if (oldintval) { + switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } else { + switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } + } + newintval = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } + break; + case SCSC_CALIBRATE_CLOCK: + switch_time_calibrate_clock(); + break; + case SCSC_FLUSH_DB_HANDLES: + switch_cache_db_flush_handles(); + break; + case SCSC_SEND_SIGHUP: + handle_SIGHUP(1); + break; + case SCSC_SYNC_CLOCK: + switch_time_sync(); + newintval = 0; + break; + case SCSC_SYNC_CLOCK_WHEN_IDLE: + newintval = switch_core_session_sync_clock(); + break; + case SCSC_SQL: + if (oldintval) { + switch_core_sqldb_resume(); + } else { + switch_core_sqldb_pause(); + } + break; + case SCSC_PAUSE_ALL: + if (oldintval) { + switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); + } else { + switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS); + } + break; + case SCSC_PAUSE_INBOUND: + if (oldintval) { + switch_set_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS); + } else { + switch_clear_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS); + } + break; + case SCSC_PAUSE_OUTBOUND: + if (oldintval) { + switch_set_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS); + } else { + switch_clear_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS); + } + break; + case SCSC_HUPALL: + switch_core_session_hupall(SWITCH_CAUSE_MANAGER_REQUEST); + break; + case SCSC_CANCEL_SHUTDOWN: + switch_clear_flag((&runtime), SCF_SHUTDOWN_REQUESTED); + break; + case SCSC_SAVE_HISTORY: + switch_console_save_history(); + break; + case SCSC_CRASH: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Declinatio Mortuus Obfirmo!\n"); + switch_console_save_history(); + abort(); + break; + case SCSC_SHUTDOWN_NOW: + switch_console_save_history(); + exit(0); + break; + case SCSC_SHUTDOWN_ELEGANT: + case SCSC_SHUTDOWN_ASAP: + { + int x = 19; + uint32_t count; + + switch_set_flag((&runtime), SCF_SHUTDOWN_REQUESTED); + if (cmd == SCSC_SHUTDOWN_ASAP) { + switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); + } + + while (runtime.running && switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED) && (count = switch_core_session_count())) { + switch_yield(500000); + if (++x == 20) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Shutdown in progress, %u session(s) remain.\nShutting down %s\n", + count, cmd == SCSC_SHUTDOWN_ASAP ? "ASAP" : "once there are no active calls."); + x = 0; + } + } + + if (switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED)) { + switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); +#ifdef _MSC_VER + win_shutdown(); +#endif + + if (oldintval) { + switch_set_flag((&runtime), SCF_RESTART); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Restarting\n"); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutting down\n"); +#ifdef _MSC_VER + fclose(stdin); +#endif + } + runtime.running = 0; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutdown Cancelled\n"); + switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS); + } + } + break; + case SCSC_PAUSE_CHECK: + newintval = !!(switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS) == SCF_NO_NEW_SESSIONS); + break; + case SCSC_PAUSE_INBOUND_CHECK: + newintval = !!switch_test_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS); + break; + case SCSC_PAUSE_OUTBOUND_CHECK: + newintval = !!switch_test_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS); + break; + case SCSC_READY_CHECK: + newintval = switch_core_ready(); + break; + case SCSC_SHUTDOWN_CHECK: + newintval = !!switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED); + break; + case SCSC_SHUTDOWN: + +#ifdef _MSC_VER + win_shutdown(); +#endif + + if (oldintval) { + switch_set_flag((&runtime), SCF_RESTART); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Restarting\n"); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutting down\n"); +#ifdef _MSC_VER + fclose(stdin); +#endif + } + runtime.running = 0; + break; + case SCSC_CHECK_RUNNING: + newintval = runtime.running; + break; + case SCSC_LOGLEVEL: + if (oldintval > -1) { + runtime.hard_log_level = oldintval; + } + + if (runtime.hard_log_level > SWITCH_LOG_DEBUG) { + runtime.hard_log_level = SWITCH_LOG_DEBUG; + } + newintval = runtime.hard_log_level; + break; + case SCSC_DEBUG_LEVEL: + if (oldintval > -1) { + if (oldintval > 10) + newintval = 10; + runtime.debug_level = oldintval; + } + newintval = runtime.debug_level; + break; + case SCSC_MIN_IDLE_CPU: + { + double *dval = (double *) val; + if (dval) { + *dval = switch_core_min_idle_cpu(*dval); + } + intval = NULL; + } + break; + case SCSC_MAX_SESSIONS: + newintval = switch_core_session_limit(oldintval); + break; + case SCSC_LAST_SPS: + newintval = runtime.sps_last; + break; + case SCSC_MAX_DTMF_DURATION: + newintval = switch_core_max_dtmf_duration(oldintval); + break; + case SCSC_MIN_DTMF_DURATION: + newintval = switch_core_min_dtmf_duration(oldintval); + break; + case SCSC_DEFAULT_DTMF_DURATION: + newintval = switch_core_default_dtmf_duration(oldintval); + break; + case SCSC_SPS: + switch_mutex_lock(runtime.throttle_mutex); + if (oldintval > 0) { + runtime.sps_total = oldintval; + } + newintval = runtime.sps_total; + switch_mutex_unlock(runtime.throttle_mutex); + break; + + case SCSC_RECLAIM: + switch_core_memory_reclaim_all(); + newintval = 0; + break; + } + + if (intval) { + *intval = newintval; + } + + + return 0; +} + +SWITCH_DECLARE(switch_core_flag_t) switch_core_flags(void) +{ + return runtime.flags; +} + +SWITCH_DECLARE(switch_bool_t) switch_core_ready(void) +{ + return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS) == SCF_NO_NEW_SESSIONS) ? SWITCH_FALSE : SWITCH_TRUE; +} + +SWITCH_DECLARE(switch_bool_t) switch_core_ready_inbound(void) +{ + return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE; +} + +SWITCH_DECLARE(switch_bool_t) switch_core_ready_outbound(void) +{ + return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE; +} + +SWITCH_DECLARE(switch_status_t) switch_core_destroy(void) +{ + switch_event_t *event; + + if (switch_event_create(&event, SWITCH_EVENT_SHUTDOWN) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Shutting Down"); + switch_event_fire(&event); + } + + switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); + switch_set_flag((&runtime), SCF_SHUTTING_DOWN); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "End existing sessions\n"); + switch_core_session_hupall(SWITCH_CAUSE_SYSTEM_SHUTDOWN); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Clean up modules.\n"); + + switch_loadable_module_shutdown(); + + switch_ssl_destroy_ssl_locks(); + + if (switch_test_flag((&runtime), SCF_USE_SQL)) { + switch_core_sqldb_stop(); + } + switch_scheduler_task_thread_stop(); + + switch_rtp_shutdown(); + + if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) { + switch_nat_shutdown(); + } + switch_xml_destroy(); + switch_core_session_uninit(); + switch_console_shutdown(); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Closing Event Engine.\n"); + switch_event_shutdown(); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n"); + switch_log_shutdown(); + + switch_core_unset_variables(); + switch_core_memory_stop(); + + if (runtime.console && runtime.console != stdout && runtime.console != stderr) { + fclose(runtime.console); + runtime.console = NULL; + } + + switch_safe_free(SWITCH_GLOBAL_dirs.base_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.mod_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.conf_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.log_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.db_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.script_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.htdocs_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.grammar_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.storage_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.recordings_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.sounds_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.run_dir); + switch_safe_free(SWITCH_GLOBAL_dirs.temp_dir); + + switch_event_destroy(&runtime.global_vars); + switch_core_hash_destroy(&runtime.ptimes); + switch_core_hash_destroy(&runtime.mime_types); + + if (IP_LIST.hash) { + switch_core_hash_destroy(&IP_LIST.hash); + } + + if (IP_LIST.pool) { + switch_core_destroy_memory_pool(&IP_LIST.pool); + } + + if (runtime.memory_pool) { + apr_pool_destroy(runtime.memory_pool); + apr_terminate(); + } + + return switch_test_flag((&runtime), SCF_RESTART) ? SWITCH_STATUS_RESTART : SWITCH_STATUS_SUCCESS; +} + +SWITCH_DECLARE(switch_status_t) switch_core_management_exec(char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen) +{ + const switch_management_interface_t *ptr; + switch_status_t status = SWITCH_STATUS_FALSE; + + if ((ptr = switch_loadable_module_get_management_interface(relative_oid))) { + status = ptr->management_function(relative_oid, action, data, datalen); + } + + return status; +} + +SWITCH_DECLARE(void) switch_core_memory_reclaim_all(void) +{ + switch_core_memory_reclaim_logger(); + switch_core_memory_reclaim_events(); + switch_core_memory_reclaim(); +} + + +struct system_thread_handle { + const char *cmd; + switch_thread_cond_t *cond; + switch_mutex_t *mutex; + switch_memory_pool_t *pool; + int ret; + int *fds; +}; + +static void *SWITCH_THREAD_FUNC system_thread(switch_thread_t *thread, void *obj) +{ + struct system_thread_handle *sth = (struct system_thread_handle *) obj; + +#if 0 // if we are a luser we can never turn this back down, didn't we already set the stack size? +#if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__) + struct rlimit rlim; + + rlim.rlim_cur = SWITCH_SYSTEM_THREAD_STACKSIZE; + rlim.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE; + if (setrlimit(RLIMIT_STACK, &rlim) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno)); + } +#endif +#endif + + if (sth->fds) { + dup2(sth->fds[1], STDOUT_FILENO); + } + + sth->ret = system(sth->cmd); + +#if 0 +#if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__) + rlim.rlim_cur = SWITCH_THREAD_STACKSIZE; + rlim.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE; + if (setrlimit(RLIMIT_STACK, &rlim) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno)); + } +#endif +#endif + + switch_mutex_lock(sth->mutex); + switch_thread_cond_signal(sth->cond); + switch_mutex_unlock(sth->mutex); + + switch_core_destroy_memory_pool(&sth->pool); + + return NULL; +} + + +static int switch_system_thread(const char *cmd, switch_bool_t wait) +{ + switch_thread_t *thread; + switch_threadattr_t *thd_attr; + int ret = 0; + struct system_thread_handle *sth; + switch_memory_pool_t *pool; + + if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Pool Failure\n"); + return 1; + } + + if (!(sth = switch_core_alloc(pool, sizeof(struct system_thread_handle)))) { + switch_core_destroy_memory_pool(&pool); + return 1; + } + + sth->pool = pool; + sth->cmd = switch_core_strdup(pool, cmd); + + switch_thread_cond_create(&sth->cond, sth->pool); + switch_mutex_init(&sth->mutex, SWITCH_MUTEX_NESTED, sth->pool); + switch_mutex_lock(sth->mutex); + + switch_threadattr_create(&thd_attr, sth->pool); + switch_threadattr_stacksize_set(thd_attr, SWITCH_SYSTEM_THREAD_STACKSIZE); + switch_threadattr_detach_set(thd_attr, 1); + switch_thread_create(&thread, thd_attr, system_thread, sth, sth->pool); + + if (wait) { + switch_thread_cond_wait(sth->cond, sth->mutex); + ret = sth->ret; + } + switch_mutex_unlock(sth->mutex); + + return ret; +} + +SWITCH_DECLARE(int) switch_max_file_desc(void) +{ + int max = 0; + +#ifndef WIN32 +#if defined(HAVE_GETDTABLESIZE) + max = getdtablesize(); +#else + max = sysconf(_SC_OPEN_MAX); +#endif +#endif + + return max; + +} + +SWITCH_DECLARE(void) switch_close_extra_files(int *keep, int keep_ttl) +{ + int open_max = switch_max_file_desc(); + int i, j; + + for (i = 3; i < open_max; i++) { + if (keep) { + for (j = 0; j < keep_ttl; j++) { + if (i == keep[j]) { + goto skip; + } + } + } + + close(i); + + skip: + + continue; + + } +} + + +#ifdef WIN32 +static int switch_system_fork(const char *cmd, switch_bool_t wait) +{ + return switch_system_thread(cmd, wait); +} + +SWITCH_DECLARE(pid_t) switch_fork(void) +{ + return -1; +} + + +#else + +SWITCH_DECLARE(pid_t) switch_fork(void) +{ + int i = fork(); + + if (!i) { + set_low_priority(); + } + + return i; +} + + + +static int switch_system_fork(const char *cmd, switch_bool_t wait) +{ + int pid; + char *dcmd = strdup(cmd); + + switch_core_set_signal_handlers(); + + pid = switch_fork(); + + if (pid) { + if (wait) { + waitpid(pid, NULL, 0); + } + free(dcmd); + } else { + switch_close_extra_files(NULL, 0); + + if (system(dcmd) == -1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute because of a command error : %s\n", dcmd); + } + free(dcmd); + exit(0); + } + + return 0; +} +#endif + + + +SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait) +{ + int (*sys_p)(const char *cmd, switch_bool_t wait); + + sys_p = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC) ? switch_system_thread : switch_system_fork; + + return sys_p(cmd, wait); + +} + + + +SWITCH_DECLARE(int) switch_stream_system_fork(const char *cmd, switch_stream_handle_t *stream) +{ +#ifdef WIN32 + return switch_system(cmd, SWITCH_TRUE); +#else + int fds[2], pid = 0; + + if (pipe(fds)) { + goto end; + } else { /* good to go */ + pid = switch_fork(); + + if (pid < 0) { /* ok maybe not */ + close(fds[0]); + close(fds[1]); + goto end; + } else if (pid) { /* parent */ + char buf[1024] = ""; + int bytes; + close(fds[1]); + while ((bytes = read(fds[0], buf, sizeof(buf))) > 0) { + stream->raw_write_function(stream, (unsigned char *)buf, bytes); + } + close(fds[0]); + waitpid(pid, NULL, 0); + } else { /* child */ + switch_close_extra_files(fds, 2); + close(fds[0]); + dup2(fds[1], STDOUT_FILENO); + switch_system(cmd, SWITCH_TRUE); + close(fds[1]); + exit(0); + } + } + + end: + + return 0; + +#endif + +} + +SWITCH_DECLARE(switch_status_t) switch_core_get_stacksizes(switch_size_t *cur, switch_size_t *max) +{ +#ifdef HAVE_SETRLIMIT + struct rlimit rlp; + + memset(&rlp, 0, sizeof(rlp)); + getrlimit(RLIMIT_STACK, &rlp); + + *cur = rlp.rlim_cur; + *max = rlp.rlim_max; + + return SWITCH_STATUS_SUCCESS; + +#else + + return SWITCH_STATUS_FALSE; + +#endif + + + +} + + +SWITCH_DECLARE(int) switch_stream_system(const char *cmd, switch_stream_handle_t *stream) +{ +#ifdef WIN32 + stream->write_function(stream, "Capturing output not supported.\n"); + return switch_system(cmd, SWITCH_TRUE); +#else + return switch_stream_system_fork(cmd, stream); +#endif + +} + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */ From 55ac6d22adb0d6383b916f4e8b11d182ed7ca9ea Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 20 Nov 2012 10:19:08 -0600 Subject: [PATCH 05/30] restore significant part of last patch --- src/switch_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/switch_core.c b/src/switch_core.c index 4682d3c002..1cc0dd0569 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -670,6 +670,9 @@ SWITCH_DECLARE(void) switch_core_set_globals(void) #ifdef WIN32 GetTempPath(dwBufSize, lpPathBuffer); lpPathBuffer[strlen(lpPathBuffer)-1] = 0; + tmp = switch_string_replace(lpPathBuffer, "\\", "/"); + strcpy(lpPathBuffer, tmp); + free(tmp); switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", lpPathBuffer); #else switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", "/tmp"); From ce885f1c31a60eafe61969513280ad587fde6eca Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 20 Nov 2012 13:45:32 -0600 Subject: [PATCH 06/30] fix occasional empty transaction --- src/switch_core_sqldb.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 5df382efab..f396d18f2b 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -1670,7 +1670,7 @@ static void *SWITCH_THREAD_FUNC switch_user_sql_thread(switch_thread_t *thread, while (qm->thread_running == 1) { uint32_t i, lc; - uint32_t written, iterations = 0; + uint32_t written = 0, iterations = 0; if (sql_manager.paused) { for (i = 0; i < qm->numq; i++) { @@ -1680,7 +1680,10 @@ static void *SWITCH_THREAD_FUNC switch_user_sql_thread(switch_thread_t *thread, } do { - written = do_trans(qm); + if (!qm_ttl(qm)) { + goto check; + } + written = do_trans(qm); iterations += written; } while(written == qm->max_trans); From 2ee80584886809dead128626264f75a05fbd36c0 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Tue, 20 Nov 2012 16:54:35 -0600 Subject: [PATCH 07/30] FS-4847 try this --- src/switch_utils.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/switch_utils.c b/src/switch_utils.c index fad8530245..56a7ab06d1 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -876,12 +876,16 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, } } + if (fd > -1) { + close(fd); + fd = -1; + } if (zstr(from)) { from = "freeswitch"; } #ifdef WIN32 - switch_snprintf(buf, B64BUFFLEN, "type \"%s\" | \"%s\" -f %s %s %s", filename, runtime.mailer_app, from, runtime.mailer_app_args, to); + switch_snprintf(buf, B64BUFFLEN, "\"%s\" -f %s %s %s < \"%s\"", runtime.mailer_app, from, runtime.mailer_app_args, to, filename); #else switch_snprintf(buf, B64BUFFLEN, "/bin/cat %s | %s -f %s %s %s", filename, runtime.mailer_app, from, runtime.mailer_app_args, to); #endif From 27c236a03ab2715d09283924b2a5d6eef9866fd5 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 21 Nov 2012 09:41:14 -0600 Subject: [PATCH 08/30] FS-4847 test again --- src/switch_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_utils.c b/src/switch_utils.c index 56a7ab06d1..4335b4dcd3 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -885,7 +885,7 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, from = "freeswitch"; } #ifdef WIN32 - switch_snprintf(buf, B64BUFFLEN, "\"%s\" -f %s %s %s < \"%s\"", runtime.mailer_app, from, runtime.mailer_app_args, to, filename); + switch_snprintf(buf, B64BUFFLEN, "\"\"%s\" -f %s %s %s < \"%s\"\"", runtime.mailer_app, from, runtime.mailer_app_args, to, filename); #else switch_snprintf(buf, B64BUFFLEN, "/bin/cat %s | %s -f %s %s %s", filename, runtime.mailer_app, from, runtime.mailer_app_args, to); #endif From ffa64d6f82d8fdaad4510e88d247938b0dcf1070 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 08:54:06 -0600 Subject: [PATCH 09/30] add new lib_dir to bottom of the struct --- src/include/switch_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 15993c7993..20c83cd898 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -466,7 +466,6 @@ typedef struct { struct switch_directories { char *base_dir; char *mod_dir; - char *lib_dir; char *conf_dir; char *log_dir; char *run_dir; @@ -478,6 +477,7 @@ struct switch_directories { char *storage_dir; char *recordings_dir; char *sounds_dir; + char *lib_dir; }; typedef struct switch_directories switch_directories; From ed11a3c9501cacb9c872537725780f5775465f38 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 09:08:24 -0600 Subject: [PATCH 10/30] FS-4854 try this, it should auto detect this situation and work w/o configuration --- src/mod/endpoints/mod_dingaling/mod_dingaling.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index 24a0e497a9..2878968ddf 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -1264,6 +1264,9 @@ static int activate_audio_rtp(struct private_object *tech_pvt) switch_rtp_set_ssrc(tech_pvt->transports[LDL_TPORT_RTP].rtp_session, tech_pvt->transports[LDL_TPORT_RTP].ssrc); + switch_rtp_intentional_bugs(tech_pvt->transports[LDL_TPORT_RTP].rtp_session, RTP_BUG_GEN_ONE_GEN_ALL); + + if (tech_pvt->transports[LDL_TPORT_RTCP].remote_port) { switch_rtp_activate_rtcp(tech_pvt->transports[LDL_TPORT_RTP].rtp_session, MDL_RTCP_DUR, tech_pvt->transports[LDL_TPORT_RTCP].remote_port); From 812d87641414ec7f2ffe6284fd376396daad28b6 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 09:11:04 -0600 Subject: [PATCH 11/30] FS-4856 --resolve --- src/mod/endpoints/mod_sofia/sofia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index b4d3e894a3..e1aa82a37e 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2212,7 +2212,7 @@ void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread if (!sofia_test_pflag(profile, PFLAG_STANDBY)) { - if (++ireg_loops >= IREG_SECONDS) { + if (++ireg_loops >= profile->ireg_seconds) { time_t now = switch_epoch_time_now(NULL); sofia_reg_check_expire(profile, now, 0); ireg_loops = 0; From 624b49f2a3921082d45d643f3579a5d8f1d01dd6 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 09:39:32 -0600 Subject: [PATCH 12/30] FS-4793 --resolve --- src/switch_core_media_bug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_core_media_bug.c b/src/switch_core_media_bug.c index b8b83da6bd..b0d9e8d4f9 100644 --- a/src/switch_core_media_bug.c +++ b/src/switch_core_media_bug.c @@ -247,7 +247,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_bug_read(switch_media_bug_t *b if (read_impl.actual_samples_per_second == other_read_impl.actual_samples_per_second) { if (read_impl.decoded_bytes_per_packet < other_read_impl.decoded_bytes_per_packet) { - frame_size = other_read_impl.decoded_bytes_per_packet; + frame_size = read_impl.decoded_bytes_per_packet; } } else { if (read_impl.decoded_bytes_per_packet > other_read_impl.decoded_bytes_per_packet) { From b7e6f4ab8203f6fed897d9cb8bac62feff46e651 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 09:57:13 -0600 Subject: [PATCH 13/30] FS-4853 --- src/switch_ivr.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 18329714aa..dd5055351c 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -1390,6 +1390,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_hold(switch_core_session_t *session, switch_channel_t *channel = switch_core_session_get_channel(session); const char *stream; const char *other_uuid; + switch_event_t *event; msg.message_id = SWITCH_MESSAGE_INDICATE_HOLD; msg.string_arg = message; @@ -1406,6 +1407,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_hold(switch_core_session_t *session, } } + if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HOLD) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel, event); + switch_event_fire(&event); + } + return SWITCH_STATUS_SUCCESS; } @@ -1428,6 +1434,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_unhold(switch_core_session_t *session switch_channel_t *channel = switch_core_session_get_channel(session); const char *other_uuid; switch_core_session_t *b_session; + switch_event_t *event; msg.message_id = SWITCH_MESSAGE_INDICATE_UNHOLD; msg.from = __FILE__; @@ -1446,6 +1453,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_unhold(switch_core_session_t *session } + if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_UNHOLD) == SWITCH_STATUS_SUCCESS) { + switch_channel_event_set_data(channel, event); + switch_event_fire(&event); + } + return SWITCH_STATUS_SUCCESS; } From af786291eff1ee1b5531d155ce39ef06f5d23891 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 10:00:44 -0600 Subject: [PATCH 14/30] FS-4852 --resolve --- src/mod/endpoints/mod_sofia/sofia_reg.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 79b49c1b6b..e64dab7415 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1595,8 +1595,12 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } else { sql = switch_mprintf("update sip_registrations set " "sub_host='%q', network_ip='%q',network_port='%q'," + "presence_hosts='%q', server_host='%q', orig_server_host='%q'," + "hostname='%q', orig_hostname='%q'," "expires = %ld where sip_user='%q' and sip_username='%q' and sip_host='%q' and contact='%q'", sub_host, network_ip, network_port_c, + profile->presence_hosts ? profile->presence_hosts : "", guess_ip4, guess_ip4, + mod_sofia_globals.hostname, mod_sofia_globals.hostname, (long) switch_epoch_time_now(NULL) + (long) exptime + 60, to_user, username, reg_host, contact_str); } From 294a6016b8cff9289c1eea25990fdc7d1fe3112f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 10:32:41 -0600 Subject: [PATCH 15/30] FS-4859 --- src/mod/endpoints/mod_sofia/mod_sofia.h | 1 + src/mod/endpoints/mod_sofia/sofia.c | 14 ++++++++++++-- src/mod/endpoints/mod_sofia/sofia_glue.c | 2 +- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 5240553caa..45f73c5866 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -600,6 +600,7 @@ struct sofia_profile { sofia_dtmf_t dtmf_type; int auto_restart; switch_port_t sip_port; + switch_port_t extsipport; switch_port_t tls_sip_port; int tls_version; unsigned int tls_timeout; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index e1aa82a37e..ab45ed78b3 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -3988,6 +3988,9 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) ip = strcasecmp(val, "auto") ? val : mod_sofia_globals.guess_ip; } profile->sipip = switch_core_strdup(profile->pool, ip); + } else if (!strcasecmp(var, "ext-sip-port") && val) { + int tmp = atoi(val); + if (tmp > 0) profile->extsipport = tmp; } else if (!strcasecmp(var, "ext-sip-ip")) { if (!zstr(val)) { char *ip = mod_sofia_globals.guess_ip; @@ -4002,8 +4005,11 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) } else if (!strcasecmp(val, "auto-nat")) { ip = NULL; } else if (strcasecmp(val, "auto")) { - switch_port_t port = 0; - if (sofia_glue_ext_address_lookup(profile, NULL, &myip, &port, val, profile->pool) == SWITCH_STATUS_SUCCESS) { + if (!profile->extsipport) { + profile->extsipport = profile->sip_port; + } + + if (sofia_glue_ext_address_lookup(profile, NULL, &myip, &profile->extsipport, val, profile->pool) == SWITCH_STATUS_SUCCESS) { ip = myip; sofia_clear_pflag(profile, PFLAG_AUTO_NAT); } else { @@ -4687,6 +4693,10 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) } done: + if (!profile->extsipport) { + profile->extsipport = profile->sip_port; + } + if (profile_already_started) { sofia_glue_release_profile(profile_already_started); } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 37caeba651..31ea2bb66b 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -1373,7 +1373,7 @@ const char *sofia_glue_transport2str(const sofia_transport_t tp) char *sofia_glue_create_external_via(switch_core_session_t *session, sofia_profile_t *profile, sofia_transport_t transport) { return sofia_glue_create_via(session, profile->extsipip, (sofia_glue_transport_has_tls(transport)) - ? profile->tls_sip_port : profile->sip_port, transport); + ? profile->tls_sip_port : profile->extsipport, transport); } char *sofia_glue_create_via(switch_core_session_t *session, const char *ip, switch_port_t port, sofia_transport_t transport) From 4f9de4364f77fde81953864edc07ca4d37b14c8a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 10:46:18 -0600 Subject: [PATCH 16/30] add strerror to some file failures --- src/mod/loggers/mod_logfile/mod_logfile.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mod/loggers/mod_logfile/mod_logfile.c b/src/mod/loggers/mod_logfile/mod_logfile.c index db78909134..ee41c021a8 100644 --- a/src/mod/loggers/mod_logfile/mod_logfile.c +++ b/src/mod/loggers/mod_logfile/mod_logfile.c @@ -161,7 +161,8 @@ static switch_status_t mod_logfile_rotate(logfile_profile_t *profile) } if ((status = switch_file_rename(from_filename, to_filename, pool)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error renaming log from %s to %s\n",from_filename, to_filename); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error renaming log from %s to %s [%s]\n", + from_filename, to_filename, strerror(errno)); goto end; } } @@ -170,19 +171,19 @@ static switch_status_t mod_logfile_rotate(logfile_profile_t *profile) if (switch_file_exists(to_filename, pool) == SWITCH_STATUS_SUCCESS) { if ((status = switch_file_remove(to_filename, pool)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error removing log %s\n",to_filename); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error removing log %s [%s]\n", to_filename, strerror(errno)); goto end; } } switch_file_close(profile->log_afd); if ((status = switch_file_rename(profile->logfile, to_filename, pool)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error renaming log from %s to %s\n", profile->logfile, to_filename); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error renaming log from %s to %s [%s]\n", profile->logfile, to_filename, strerror(errno)); goto end; } if ((status = mod_logfile_openlogfile(profile, SWITCH_FALSE)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error reopening log %s\n",profile->logfile); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error reopening log %s\n", profile->logfile); } if (profile->suffix < profile->max_rot) { profile->suffix++; From 89f4cd75f071d8330273cbb94d56188ce6ae0843 Mon Sep 17 00:00:00 2001 From: Brian West Date: Wed, 21 Nov 2012 13:59:23 -0600 Subject: [PATCH 17/30] Fix 2833 Debuging --- src/switch_rtp.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 73c1db88b0..e469066fce 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -341,9 +341,10 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session); static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_size_t bytes, int *do_cng) { + #ifdef DEBUG_2833 if (rtp_session->dtmf_data.in_digit_sanity && !(rtp_session->dtmf_data.in_digit_sanity % 100)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "sanity %d\n", rtp_session->dtmf_data.in_digit_sanity); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sanity %d\n", rtp_session->dtmf_data.in_digit_sanity); } #endif @@ -396,8 +397,7 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_ } } #ifdef DEBUG_2833 - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned) - packet[1], (unsigned) packet[2], (unsigned) packet[3]); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "packet[%d]: %02x %02x %02x %02x\n", (int) len, (unsigned) packet[0], (unsigned) packet[1], (unsigned) packet[2], (unsigned) packet[3]); #endif if (in_digit_seq > rtp_session->dtmf_data.in_digit_seq) { @@ -405,7 +405,7 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_ rtp_session->dtmf_data.in_digit_seq = in_digit_seq; #ifdef DEBUG_2833 - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "read: %c %u %u %u %u %d %d %s\n", + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "read: %c %u %u %u %u %d %d %s\n", key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, ts, duration, rtp_session->recv_msg.header.m, end, end && !rtp_session->dtmf_data.in_digit_ts ? "ignored" : ""); #endif @@ -414,7 +414,7 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_ rtp_session->dtmf_data.in_digit_ts) { switch_dtmf_t dtmf = { key, switch_core_min_dtmf_duration(0), 0, SWITCH_DTMF_RTP }; #ifdef DEBUG_2833 - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Early Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Early Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8); #endif switch_rtp_queue_rfc2833_in(rtp_session, &dtmf); rtp_session->dtmf_data.in_digit_queued = 1; @@ -433,7 +433,7 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_ if (end) { if (!rtp_session->dtmf_data.in_digit_ts && rtp_session->dtmf_data.last_in_digit_ts != ts) { #ifdef DEBUG_2833 - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "start with end packet %d\n", ts); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "start with end packet %d\n", ts); #endif rtp_session->dtmf_data.last_in_digit_ts = ts; rtp_session->dtmf_data.in_digit_ts = ts; @@ -450,17 +450,17 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_ dtmf.duration += rtp_session->dtmf_data.flip * 0xFFFF; rtp_session->dtmf_data.flip = 0; #ifdef DEBUG_2833 - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "you're welcome!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "you're welcome!\n"); #endif } #ifdef DEBUG_2833 - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n", + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "done digit=%c ts=%u start_ts=%u dur=%u ddur=%u\n", dtmf.digit, ts, rtp_session->dtmf_data.in_digit_ts, duration, dtmf.duration); #endif if (!(rtp_session->rtp_bugs & RTP_BUG_IGNORE_DTMF_DURATION) && !rtp_session->dtmf_data.in_digit_queued) { #ifdef DEBUG_2833 - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Queuing digit %c:%d\n", dtmf.digit, dtmf.duration / 8); #endif switch_rtp_queue_rfc2833_in(rtp_session, &dtmf); } @@ -481,7 +481,7 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_ } else if (!rtp_session->dtmf_data.in_digit_ts) { #ifdef DEBUG_2833 - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "start %d\n", ts); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "start %d\n", ts); #endif rtp_session->dtmf_data.in_digit_ts = ts; rtp_session->dtmf_data.last_in_digit_ts = ts; @@ -492,7 +492,7 @@ static handle_rfc2833_result_t handle_rfc2833(switch_rtp_t *rtp_session, switch_ rtp_session->dtmf_data.last_duration = duration; } else { #ifdef DEBUG_2833 - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "drop: %c %u %u %u %u %d %d\n", + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "drop: %c %u %u %u %u %d %d\n", key, in_digit_seq, rtp_session->dtmf_data.in_digit_seq, ts, duration, rtp_session->recv_msg.header.m, end); #endif switch_cond_next(); @@ -2822,7 +2822,7 @@ static void do_flush(switch_rtp_t *rtp_session) if (bytes > rtp_header_len && rtp_session->recv_te && rtp_session->recv_msg.header.pt == rtp_session->recv_te) { handle_rfc2833(rtp_session, bytes, &do_cng); #ifdef DEBUG_2833 - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "*** RTP packet handled in flush loop %d ***\n", do_cng); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "*** RTP packet handled in flush loop %d ***\n", do_cng); #endif } From 1f06fe909cec21a9aa90e556c17210be302408e2 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 11:49:35 -0600 Subject: [PATCH 18/30] FS-4859 correction --- src/mod/endpoints/mod_sofia/sofia.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index ab45ed78b3..092b1dca27 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4672,6 +4672,11 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) } if (profile->sipip) { + + if (!profile->extsipport) { + profile->extsipport = profile->sip_port; + } + launch_sofia_profile_thread(profile); if (profile->odbc_dsn) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Connecting ODBC Profile %s [%s]\n", profile->name, url); @@ -4693,10 +4698,6 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) } done: - if (!profile->extsipport) { - profile->extsipport = profile->sip_port; - } - if (profile_already_started) { sofia_glue_release_profile(profile_already_started); } From cf32d24b5df7aefaa4818427f7adb9a42bb0c841 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 13:06:28 -0600 Subject: [PATCH 19/30] FS-4860 --resolve This seems to have come from a malformed file_string in the ringback var --- src/mod/applications/mod_dptools/mod_dptools.c | 7 ++++++- src/switch_core_file.c | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index eefd4aad4b..d672e2a3db 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -4476,8 +4476,13 @@ static switch_status_t next_file(switch_file_handle_t *handle) } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error finding the folder path section in '%s'\n", path); } - } + + if (switch_file_exists(file, handle->memory_pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File [%s] does not exist.\n", file); + goto top; + } + if (switch_core_file_open(&context->fh, file, handle->channels, handle->samplerate, handle->flags, NULL) != SWITCH_STATUS_SUCCESS) { goto top; } diff --git a/src/switch_core_file.c b/src/switch_core_file.c index b1a1effc85..baec6f5184 100644 --- a/src/switch_core_file.c +++ b/src/switch_core_file.c @@ -76,6 +76,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, switch_set_flag(fh, SWITCH_FILE_FLAG_FREE_POOL); } + if (switch_directory_exists(file_path, fh->memory_pool) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File [%s] is a directory not a file.\n", file_path); + goto fail; + } if ((rhs = strstr(file_path, SWITCH_URL_SEPARATOR))) { switch_copy_string(stream_name, file_path, (rhs + 1) - file_path); @@ -198,6 +202,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, fail: + switch_clear_flag(fh, SWITCH_FILE_OPEN); + if (switch_test_flag(fh, SWITCH_FILE_FLAG_FREE_POOL)) { switch_core_destroy_memory_pool(&fh->memory_pool); } From e2e9938d1a478a8085a8cdc0e5c5981e68dbc1eb Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 18:14:15 -0600 Subject: [PATCH 20/30] only drop re-reg once instead of permenantly --- src/mod/endpoints/mod_sofia/sofia_reg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index e64dab7415..2dbdeaf5a8 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -2018,9 +2018,9 @@ void sofia_reg_handle_sip_r_register(int status, expi = (uint32_t) atoi(new_expires); if (expi > 0 && expi != sofia_private->gateway->freq) { - sofia_private->gateway->freq = expi; - sofia_private->gateway->expires_str = switch_core_sprintf(sofia_private->gateway->pool, "%d", expi); - + //sofia_private->gateway->freq = expi; + //sofia_private->gateway->expires_str = switch_core_sprintf(sofia_private->gateway->pool, "%d", expi); + if (expi > 60) { sofia_private->gateway->expires = switch_epoch_time_now(NULL) + (expi - 15); } else { From 2b2a4fb256105236df92ee18c64ae3361cd7ebf0 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 21 Nov 2012 22:04:55 -0600 Subject: [PATCH 21/30] fix compiler warning --- src/switch_core_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_core_file.c b/src/switch_core_file.c index baec6f5184..ae040b31be 100644 --- a/src/switch_core_file.c +++ b/src/switch_core_file.c @@ -42,7 +42,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, uint8_t channels, uint32_t rate, unsigned int flags, switch_memory_pool_t *pool) { char *ext; - switch_status_t status; + switch_status_t status = SWITCH_STATUS_FALSE; char stream_name[128] = ""; char *rhs = NULL; const char *spool_path = NULL; From 5dccbe4818ecdf5b93d6e073f8e14cfa5e638011 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 21:15:31 -0600 Subject: [PATCH 22/30] fix sql queue manager issues --- src/mod/endpoints/mod_sofia/sofia_presence.c | 6 ++-- src/switch_core_sqldb.c | 33 +++++++++++--------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index e11d96ff76..53b524a236 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -873,13 +873,13 @@ static void do_dialog_probe(switch_event_t *event) if (mod_sofia_globals.debug_presence > 1) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s DUMP DIALOG_PROBE set version sql:\n%s\n", profile->name, sql); } - sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + sofia_glue_execute_sql_soon(profile, &sql, SWITCH_TRUE); switch_safe_free(sql); // The dialog_probe_callback has built up the dialogs to be included in the NOTIFY. // Now send the "full" dialog event to the triggering subscription. - sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,version, " + sql = switch_mprintf("select call_id,expires,sub_to_user,sub_to_host,event,version+1, " "'full',full_to,full_from,contact,network_ip,network_port " "from sip_subscriptions " "where hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and call_id='%q'", @@ -4543,7 +4543,7 @@ void sofia_presence_check_subscriptions(sofia_profile_t *profile, time_t now) "((expires > 0 and expires <= %ld)) and profile_name='%q' and hostname='%q'", (long) now, profile->name, mod_sofia_globals.hostname); - sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + sofia_glue_execute_sql_soon(profile, &sql, SWITCH_TRUE); switch_safe_free(sql); sql = switch_mprintf("select full_to, full_from, contact, -1, call_id, event, network_ip, network_port, " diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index f396d18f2b..556306ec97 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -1314,10 +1314,12 @@ SWITCH_DECLARE(switch_status_t) switch_sql_queue_manager_start(switch_sql_queue_ } -static void do_flush(switch_queue_t *q, switch_cache_db_handle_t *dbh) +static void do_flush(switch_sql_queue_manager_t *qm, int i, switch_cache_db_handle_t *dbh) { void *pop = NULL; - + switch_queue_t *q = qm->sql_queue[i]; + + switch_mutex_lock(qm->mutex); while (switch_queue_trypop(q, &pop) == SWITCH_STATUS_SUCCESS) { if (pop) { if (dbh) { @@ -1326,6 +1328,7 @@ static void do_flush(switch_queue_t *q, switch_cache_db_handle_t *dbh) free(pop); } } + switch_mutex_unlock(qm->mutex); } @@ -1347,7 +1350,7 @@ SWITCH_DECLARE(switch_status_t) switch_sql_queue_manager_destroy(switch_sql_queu for(i = 0; i < qm->numq; i++) { - do_flush(qm->sql_queue[i], NULL); + do_flush(qm, i, NULL); } pool = qm->pool; @@ -1408,7 +1411,7 @@ SWITCH_DECLARE(switch_status_t) switch_sql_queue_manager_push_confirm(switch_sql switch_queue_push(qm->sql_queue[pos], dup ? strdup(sql) : (char *)sql); written = qm->written[pos]; size = switch_sql_queue_manager_size(qm, pos); - want = written + size; + want = written + qm->pre_written[pos] + size; switch_mutex_unlock(qm->mutex); qm_wake(qm); @@ -1563,7 +1566,9 @@ static uint32_t do_trans(switch_sql_queue_manager_t *qm) if (pop) { if ((status = switch_cache_db_execute_sql(qm->event_db, (char *) pop, NULL)) == SWITCH_STATUS_SUCCESS) { + switch_mutex_lock(qm->mutex); qm->pre_written[i]++; + switch_mutex_unlock(qm->mutex); ttl++; } free(pop); @@ -1633,7 +1638,7 @@ static void *SWITCH_THREAD_FUNC switch_user_sql_thread(switch_thread_t *thread, uint32_t sanity = 120; switch_sql_queue_manager_t *qm = (switch_sql_queue_manager_t *) obj; - uint32_t i, countdown = 0; + uint32_t i; while (!qm->event_db) { if (switch_cache_db_get_db_handle_dsn(&qm->event_db, qm->dsn) == SWITCH_STATUS_SUCCESS && qm->event_db) @@ -1674,7 +1679,7 @@ static void *SWITCH_THREAD_FUNC switch_user_sql_thread(switch_thread_t *thread, if (sql_manager.paused) { for (i = 0; i < qm->numq; i++) { - do_flush(qm->sql_queue[i], NULL); + do_flush(qm, i, NULL); } goto check; } @@ -1707,21 +1712,19 @@ static void *SWITCH_THREAD_FUNC switch_user_sql_thread(switch_thread_t *thread, check: - countdown = 40; - - while (--countdown && (lc = qm_ttl(qm)) < qm->max_trans / 4) { - if (lc == 0) { - switch_thread_cond_wait(qm->cond, qm->cond_mutex); - break; - } - switch_yield(5000); + if ((lc = qm_ttl(qm)) < qm->max_trans / 4) { + switch_yield(500000); + } else if (lc == 0) { + switch_thread_cond_wait(qm->cond, qm->cond_mutex); + } else { + switch_cond_next(); } } switch_mutex_unlock(qm->cond_mutex); for(i = 0; i < qm->numq; i++) { - do_flush(qm->sql_queue[i], qm->event_db); + do_flush(qm, i, qm->event_db); } qm->thread_running = 0; From e4c7eac4c31c9dd64599dea476a368d13faf3468 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 21:16:18 -0600 Subject: [PATCH 23/30] bump --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 15c91a976a..367ab86350 100644 --- a/configure.in +++ b/configure.in @@ -3,10 +3,10 @@ # Must change all of the below together # For a release, set revision for that tagged release as well and uncomment -AC_INIT([freeswitch], [1.3.6b], bugs@freeswitch.org) +AC_INIT([freeswitch], [1.3.6], bugs@freeswitch.org) AC_SUBST(SWITCH_VERSION_MAJOR, [1]) AC_SUBST(SWITCH_VERSION_MINOR, [3]) -AC_SUBST(SWITCH_VERSION_MICRO, [6b]) +AC_SUBST(SWITCH_VERSION_MICRO, [6]) AC_SUBST(SWITCH_VERSION_REVISION, []) AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, []) From d659f8ced401e59f1e97e62cd2dcf406c8308890 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 21:19:29 -0600 Subject: [PATCH 24/30] bump --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 367ab86350..c96f9f8dd9 100644 --- a/configure.in +++ b/configure.in @@ -3,10 +3,10 @@ # Must change all of the below together # For a release, set revision for that tagged release as well and uncomment -AC_INIT([freeswitch], [1.3.6], bugs@freeswitch.org) +AC_INIT([freeswitch], [1.3.7b], bugs@freeswitch.org) AC_SUBST(SWITCH_VERSION_MAJOR, [1]) AC_SUBST(SWITCH_VERSION_MINOR, [3]) -AC_SUBST(SWITCH_VERSION_MICRO, [6]) +AC_SUBST(SWITCH_VERSION_MICRO, [7b]) AC_SUBST(SWITCH_VERSION_REVISION, []) AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, []) From 377e093a319c6ce59fabca97740938f1cbc3fb49 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 22:22:37 -0600 Subject: [PATCH 25/30] mistake on last commit --- src/switch_core_sqldb.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 556306ec97..caee1ee1f6 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -1714,10 +1714,9 @@ static void *SWITCH_THREAD_FUNC switch_user_sql_thread(switch_thread_t *thread, if ((lc = qm_ttl(qm)) < qm->max_trans / 4) { switch_yield(500000); - } else if (lc == 0) { - switch_thread_cond_wait(qm->cond, qm->cond_mutex); - } else { - switch_cond_next(); + if ((lc = qm_ttl(qm)) == 0) { + switch_thread_cond_wait(qm->cond, qm->cond_mutex); + } } } From c9a72c676720b93a34744792935bcbfbd03e2ccd Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 22:25:19 -0600 Subject: [PATCH 26/30] debump --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index c96f9f8dd9..367ab86350 100644 --- a/configure.in +++ b/configure.in @@ -3,10 +3,10 @@ # Must change all of the below together # For a release, set revision for that tagged release as well and uncomment -AC_INIT([freeswitch], [1.3.7b], bugs@freeswitch.org) +AC_INIT([freeswitch], [1.3.6], bugs@freeswitch.org) AC_SUBST(SWITCH_VERSION_MAJOR, [1]) AC_SUBST(SWITCH_VERSION_MINOR, [3]) -AC_SUBST(SWITCH_VERSION_MICRO, [7b]) +AC_SUBST(SWITCH_VERSION_MICRO, [6]) AC_SUBST(SWITCH_VERSION_REVISION, []) AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, []) From c1572392945cc7982fd0ee0f4a19c72bfd7437f8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Nov 2012 22:28:18 -0600 Subject: [PATCH 27/30] bump --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 367ab86350..c96f9f8dd9 100644 --- a/configure.in +++ b/configure.in @@ -3,10 +3,10 @@ # Must change all of the below together # For a release, set revision for that tagged release as well and uncomment -AC_INIT([freeswitch], [1.3.6], bugs@freeswitch.org) +AC_INIT([freeswitch], [1.3.7b], bugs@freeswitch.org) AC_SUBST(SWITCH_VERSION_MAJOR, [1]) AC_SUBST(SWITCH_VERSION_MINOR, [3]) -AC_SUBST(SWITCH_VERSION_MICRO, [6]) +AC_SUBST(SWITCH_VERSION_MICRO, [7b]) AC_SUBST(SWITCH_VERSION_REVISION, []) AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, []) From 66e85c8d7152132e44a13545e21d406f840edf94 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 22 Nov 2012 15:19:38 -0600 Subject: [PATCH 28/30] wrong turn in albakoykee --- src/switch_core_sqldb.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index caee1ee1f6..c8cdfe049e 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -1409,9 +1409,9 @@ SWITCH_DECLARE(switch_status_t) switch_sql_queue_manager_push_confirm(switch_sql switch_mutex_lock(qm->mutex); switch_queue_push(qm->sql_queue[pos], dup ? strdup(sql) : (char *)sql); - written = qm->written[pos]; + written = qm->pre_written[pos]; size = switch_sql_queue_manager_size(qm, pos); - want = written + qm->pre_written[pos] + size; + want = written + size; switch_mutex_unlock(qm->mutex); qm_wake(qm); @@ -1494,12 +1494,6 @@ static uint32_t do_trans(switch_sql_queue_manager_t *qm) if (io_mutex) switch_mutex_lock(io_mutex); - switch_mutex_lock(qm->mutex); - for (i = 0; i < qm->numq; i++) { - qm->pre_written[i] = 0; - } - switch_mutex_unlock(qm->mutex); - if (!zstr(qm->pre_trans_execute)) { switch_cache_db_execute_sql_real(qm->event_db, qm->pre_trans_execute, &errmsg); if (errmsg) { @@ -1623,7 +1617,7 @@ static uint32_t do_trans(switch_sql_queue_manager_t *qm) switch_mutex_lock(qm->mutex); for (i = 0; i < qm->numq; i++) { - qm->written[i] += qm->pre_written[i]; + qm->written[i] = qm->pre_written[i]; } switch_mutex_unlock(qm->mutex); From 9003aaf59fed0ae12847457b131bd55f5e306d71 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 22 Nov 2012 15:20:37 -0600 Subject: [PATCH 29/30] debump --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index c96f9f8dd9..367ab86350 100644 --- a/configure.in +++ b/configure.in @@ -3,10 +3,10 @@ # Must change all of the below together # For a release, set revision for that tagged release as well and uncomment -AC_INIT([freeswitch], [1.3.7b], bugs@freeswitch.org) +AC_INIT([freeswitch], [1.3.6], bugs@freeswitch.org) AC_SUBST(SWITCH_VERSION_MAJOR, [1]) AC_SUBST(SWITCH_VERSION_MINOR, [3]) -AC_SUBST(SWITCH_VERSION_MICRO, [7b]) +AC_SUBST(SWITCH_VERSION_MICRO, [6]) AC_SUBST(SWITCH_VERSION_REVISION, []) AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, []) From bef343aecf9a060a7d26785ec36e8ff2abcb10f4 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 22 Nov 2012 15:25:00 -0600 Subject: [PATCH 30/30] bump --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 367ab86350..c96f9f8dd9 100644 --- a/configure.in +++ b/configure.in @@ -3,10 +3,10 @@ # Must change all of the below together # For a release, set revision for that tagged release as well and uncomment -AC_INIT([freeswitch], [1.3.6], bugs@freeswitch.org) +AC_INIT([freeswitch], [1.3.7b], bugs@freeswitch.org) AC_SUBST(SWITCH_VERSION_MAJOR, [1]) AC_SUBST(SWITCH_VERSION_MINOR, [3]) -AC_SUBST(SWITCH_VERSION_MICRO, [6]) +AC_SUBST(SWITCH_VERSION_MICRO, [7b]) AC_SUBST(SWITCH_VERSION_REVISION, []) AC_SUBST(SWITCH_VERSION_REVISION_HUMAN, [])