-/* \r
- * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application\r
- * Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>\r
- *\r
- * Version: MPL 1.1\r
- *\r
- * The contents of this file are subject to the Mozilla Public License Version\r
- * 1.1 (the "License"); you may not use this file except in compliance with\r
- * the License. You may obtain a copy of the License at\r
- * http://www.mozilla.org/MPL/\r
- *\r
- * Software distributed under the License is distributed on an "AS IS" basis,\r
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\r
- * for the specific language governing rights and limitations under the\r
- * License.\r
- *\r
- * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application\r
- *\r
- * The Initial Developer of the Original Code is\r
- * Anthony Minessale II <anthm@freeswitch.org>\r
- * Portions created by the Initial Developer are Copyright (C)\r
- * the Initial Developer. All Rights Reserved.\r
- *\r
- * Contributor(s):\r
- * \r
- * Anthony Minessale II <anthm@freeswitch.org>\r
- * Michael Jerris <mike@jerris.com>\r
- * Paul D. Tinsley <pdt at jackhammer.org>\r
- * Marcel Barbulescu <marcelbarbulescu@gmail.com>\r
- * Joseph Sullivan <jossulli@amazon.com>\r
- *\r
- *\r
- * switch_core.c -- Main Core Library\r
- *\r
- */\r
-\r
-\r
-\r
-#include <switch.h>\r
-#include <switch_ssl.h>\r
-#include <switch_stun.h>\r
-#include <switch_nat.h>\r
-#include <switch_version.h>\r
-#include "private/switch_core_pvt.h"\r
-#include <switch_curl.h>\r
-#ifndef WIN32\r
-#include <switch_private.h>\r
-#ifdef HAVE_SETRLIMIT\r
-#include <sys/resource.h>\r
-#endif\r
-#endif\r
-#include <errno.h>\r
-\r
-\r
-SWITCH_DECLARE_DATA switch_directories SWITCH_GLOBAL_dirs = { 0 };\r
-\r
-/* The main runtime obj we keep this hidden for ourselves */\r
-struct switch_runtime runtime = { 0 };\r
-static void switch_load_core_config(const char *file);\r
-\r
-static void send_heartbeat(void)\r
-{\r
- switch_event_t *event;\r
- switch_core_time_duration_t duration;\r
-\r
- switch_core_measure_time(switch_core_uptime(), &duration);\r
-\r
- if (switch_event_create(&event, SWITCH_EVENT_HEARTBEAT) == SWITCH_STATUS_SUCCESS) {\r
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready");\r
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Up-Time",\r
- "%u year%s, "\r
- "%u day%s, "\r
- "%u hour%s, "\r
- "%u minute%s, "\r
- "%u second%s, "\r
- "%u millisecond%s, "\r
- "%u microsecond%s",\r
- duration.yr, duration.yr == 1 ? "" : "s",\r
- duration.day, duration.day == 1 ? "" : "s",\r
- duration.hr, duration.hr == 1 ? "" : "s",\r
- duration.min, duration.min == 1 ? "" : "s",\r
- duration.sec, duration.sec == 1 ? "" : "s",\r
- duration.ms, duration.ms == 1 ? "" : "s", duration.mms, duration.mms == 1 ? "" : "s");\r
-\r
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "FreeSWITCH-Version", SWITCH_VERSION_FULL);\r
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Uptime-msec", "%"SWITCH_TIME_T_FMT, switch_core_uptime() / 1000);\r
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Count", "%u", switch_core_session_count());\r
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Max-Sessions", "%u", switch_core_session_limit(0));\r
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec", "%u", runtime.sps);\r
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Since-Startup", "%" SWITCH_SIZE_T_FMT, switch_core_session_id() - 1);\r
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Idle-CPU", "%f", switch_core_idle_cpu());\r
- switch_event_fire(&event);\r
- }\r
-}\r
-\r
-static char main_ip4[256] = "";\r
-static char main_ip6[256] = "";\r
-\r
-static void check_ip(void)\r
-{\r
- char guess_ip4[256] = "";\r
- char guess_ip6[256] = "";\r
- char old_ip4[256] = "";\r
- char old_ip6[256] = "";\r
- int ok4 = 1, ok6 = 1;\r
- int mask = 0;\r
-\r
- gethostname(runtime.hostname, sizeof(runtime.hostname));\r
- switch_core_set_variable("hostname", runtime.hostname);\r
-\r
- switch_find_local_ip(guess_ip4, sizeof(guess_ip4), &mask, AF_INET);\r
- switch_find_local_ip(guess_ip6, sizeof(guess_ip6), NULL, AF_INET6);\r
-\r
- if (!*main_ip4) {\r
- switch_set_string(main_ip4, guess_ip4);\r
- } else {\r
- if (!(ok4 = !strcmp(main_ip4, guess_ip4))) {\r
- struct in_addr in;\r
-\r
- in.s_addr = mask;\r
- switch_set_string(old_ip4, main_ip4);\r
- switch_set_string(main_ip4, guess_ip4);\r
- switch_core_set_variable("local_ip_v4", guess_ip4);\r
- switch_core_set_variable("local_mask_v4", inet_ntoa(in));\r
- }\r
- }\r
-\r
- if (!*main_ip6) {\r
- switch_set_string(main_ip6, guess_ip6);\r
- } else {\r
- if (!(ok6 = !strcmp(main_ip6, guess_ip6))) {\r
- switch_set_string(old_ip6, main_ip6);\r
- switch_set_string(main_ip6, guess_ip6);\r
- switch_core_set_variable("local_ip_v6", guess_ip6);\r
- }\r
- }\r
-\r
- if (!ok4 || !ok6) {\r
- switch_event_t *event;\r
-\r
- if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {\r
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "condition", "network-address-change");\r
- if (!ok4) {\r
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v4", old_ip4);\r
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v4", main_ip4);\r
- }\r
- if (!ok6) {\r
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-previous-v6", old_ip6);\r
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "network-address-change-v6", main_ip6);\r
- }\r
- switch_event_fire(&event);\r
- }\r
- }\r
-}\r
-\r
-SWITCH_STANDARD_SCHED_FUNC(heartbeat_callback)\r
-{\r
- send_heartbeat();\r
-\r
- /* reschedule this task */\r
- task->runtime = switch_epoch_time_now(NULL) + 20;\r
-}\r
-\r
-\r
-SWITCH_STANDARD_SCHED_FUNC(check_ip_callback)\r
-{\r
- check_ip();\r
-\r
- /* reschedule this task */\r
- task->runtime = switch_epoch_time_now(NULL) + 60;\r
-}\r
-\r
-\r
-SWITCH_DECLARE(switch_status_t) switch_core_set_console(const char *console)\r
-{\r
- if ((runtime.console = fopen(console, "a")) == 0) {\r
- fprintf(stderr, "Cannot open output file %s.\n", console);\r
- return SWITCH_STATUS_FALSE;\r
- }\r
-\r
- return SWITCH_STATUS_SUCCESS;\r
-}\r
-\r
-SWITCH_DECLARE(FILE *) switch_core_get_console(void)\r
-{\r
- return runtime.console;\r
-}\r
-\r
-#ifdef HAVE_SYS_IOCTL_H\r
-#include <sys/ioctl.h>\r
-#endif\r
-SWITCH_DECLARE(void) switch_core_screen_size(int *x, int *y)\r
-{\r
-\r
-#ifdef WIN32\r
- CONSOLE_SCREEN_BUFFER_INFO csbi;\r
- int ret;\r
-\r
- if ((ret = GetConsoleScreenBufferInfo(GetStdHandle( STD_OUTPUT_HANDLE ), &csbi))) {\r
- if (x) *x = csbi.dwSize.X;\r
- if (y) *y = csbi.dwSize.Y;\r
- }\r
-\r
-#elif defined(TIOCGWINSZ)\r
- struct winsize w;\r
- ioctl(0, TIOCGWINSZ, &w);\r
-\r
- if (x) *x = w.ws_col;\r
- if (y) *y = w.ws_row;\r
-#else\r
- if (x) *x = 80;\r
- if (y) *y = 24;\r
-#endif\r
-\r
-}\r
-\r
-SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel_t channel)\r
-{\r
- FILE *handle = stdout;\r
-\r
- switch (channel) {\r
- case SWITCH_CHANNEL_ID_LOG:\r
- case SWITCH_CHANNEL_ID_LOG_CLEAN:\r
- handle = runtime.console;\r
- break;\r
- default:\r
- handle = runtime.console;\r
- break;\r
- }\r
-\r
- return handle;\r
-}\r
-\r
-\r
-SWITCH_DECLARE(void) switch_core_remove_state_handler(const switch_state_handler_table_t *state_handler)\r
-{\r
- int index, tmp_index = 0;\r
- const switch_state_handler_table_t *tmp[SWITCH_MAX_STATE_HANDLERS + 1] = { 0 };\r
-\r
- switch_mutex_lock(runtime.global_mutex);\r
-\r
- for (index = 0; index < runtime.state_handler_index; index++) {\r
- const switch_state_handler_table_t *cur = runtime.state_handlers[index];\r
- runtime.state_handlers[index] = NULL;\r
- if (cur == state_handler) {\r
- continue;\r
- }\r
- tmp[tmp_index++] = cur;\r
- }\r
-\r
- runtime.state_handler_index = 0;\r
-\r
- for (index = 0; index < tmp_index; index++) {\r
- runtime.state_handlers[runtime.state_handler_index++] = tmp[index];\r
- }\r
- switch_mutex_unlock(runtime.global_mutex);\r
-}\r
-\r
-\r
-SWITCH_DECLARE(int) switch_core_add_state_handler(const switch_state_handler_table_t *state_handler)\r
-{\r
- int index;\r
-\r
- switch_mutex_lock(runtime.global_mutex);\r
- index = runtime.state_handler_index++;\r
-\r
- if (runtime.state_handler_index >= SWITCH_MAX_STATE_HANDLERS) {\r
- index = -1;\r
- } else {\r
- runtime.state_handlers[index] = state_handler;\r
- }\r
-\r
- switch_mutex_unlock(runtime.global_mutex);\r
- return index;\r
-}\r
-\r
-SWITCH_DECLARE(const switch_state_handler_table_t *) switch_core_get_state_handler(int index)\r
-{\r
-\r
- if (index >= SWITCH_MAX_STATE_HANDLERS || index > runtime.state_handler_index) {\r
- return NULL;\r
- }\r
-\r
- return runtime.state_handlers[index];\r
-}\r
-\r
-SWITCH_DECLARE(void) switch_core_dump_variables(switch_stream_handle_t *stream)\r
-{\r
- switch_event_header_t *hi;\r
-\r
- switch_mutex_lock(runtime.global_mutex);\r
- for (hi = runtime.global_vars->headers; hi; hi = hi->next) {\r
- stream->write_function(stream, "%s=%s\n", hi->name, hi->value);\r
- }\r
- switch_mutex_unlock(runtime.global_mutex);\r
-}\r
-\r
-SWITCH_DECLARE(const char *) switch_core_get_hostname(void)\r
-{\r
- return runtime.hostname;\r
-}\r
-\r
-SWITCH_DECLARE(const char *) switch_core_get_switchname(void)\r
-{\r
- if (!zstr(runtime.switchname)) return runtime.switchname;\r
- return runtime.hostname;\r
-}\r
-\r
-\r
-SWITCH_DECLARE(char *) switch_core_get_variable(const char *varname)\r
-{\r
- char *val;\r
- switch_thread_rwlock_rdlock(runtime.global_var_rwlock);\r
- val = (char *) switch_event_get_header(runtime.global_vars, varname);\r
- switch_thread_rwlock_unlock(runtime.global_var_rwlock);\r
- return val;\r
-}\r
-\r
-SWITCH_DECLARE(char *) switch_core_get_variable_dup(const char *varname)\r
-{\r
- char *val = NULL, *v;\r
-\r
- switch_thread_rwlock_rdlock(runtime.global_var_rwlock);\r
- if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) {\r
- val = strdup(v);\r
- }\r
- switch_thread_rwlock_unlock(runtime.global_var_rwlock);\r
-\r
- return val;\r
-}\r
-\r
-SWITCH_DECLARE(char *) switch_core_get_variable_pdup(const char *varname, switch_memory_pool_t *pool)\r
-{\r
- char *val = NULL, *v;\r
-\r
- switch_thread_rwlock_rdlock(runtime.global_var_rwlock);\r
- if ((v = (char *) switch_event_get_header(runtime.global_vars, varname))) {\r
- val = switch_core_strdup(pool, v);\r
- }\r
- switch_thread_rwlock_unlock(runtime.global_var_rwlock);\r
-\r
- return val;\r
-}\r
-\r
-static void switch_core_unset_variables(void)\r
-{\r
- switch_thread_rwlock_wrlock(runtime.global_var_rwlock);\r
- switch_event_destroy(&runtime.global_vars);\r
- switch_event_create_plain(&runtime.global_vars, SWITCH_EVENT_CHANNEL_DATA);\r
- switch_thread_rwlock_unlock(runtime.global_var_rwlock);\r
-}\r
-\r
-SWITCH_DECLARE(void) switch_core_set_variable(const char *varname, const char *value)\r
-{\r
- char *val;\r
-\r
- if (varname) {\r
- switch_thread_rwlock_wrlock(runtime.global_var_rwlock);\r
- val = (char *) switch_event_get_header(runtime.global_vars, varname);\r
- if (val) {\r
- switch_event_del_header(runtime.global_vars, varname);\r
- }\r
- if (value) {\r
- char *v = strdup(value);\r
- switch_string_var_check(v, SWITCH_TRUE);\r
- switch_event_add_header_string(runtime.global_vars, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, varname, v);\r
- } else {\r
- switch_event_del_header(runtime.global_vars, varname);\r
- }\r
- switch_thread_rwlock_unlock(runtime.global_var_rwlock);\r
- }\r
-}\r
-\r
-SWITCH_DECLARE(switch_bool_t) switch_core_set_var_conditional(const char *varname, const char *value, const char *val2)\r
-{\r
- char *val;\r
-\r
- if (varname) {\r
- switch_thread_rwlock_wrlock(runtime.global_var_rwlock);\r
- val = (char *) switch_event_get_header(runtime.global_vars, varname);\r
-\r
- if (val) {\r
- if (!val2 || strcmp(val, val2) != 0) {\r
- switch_thread_rwlock_unlock(runtime.global_var_rwlock);\r
- return SWITCH_FALSE;\r
- }\r
- switch_event_del_header(runtime.global_vars, varname);\r
- } else if (!zstr(val2)) {\r
- switch_thread_rwlock_unlock(runtime.global_var_rwlock);\r
- return SWITCH_FALSE;\r
- }\r
-\r
- if (value) {\r
- char *v = strdup(value);\r
- switch_string_var_check(v, SWITCH_TRUE);\r
- switch_event_add_header_string(runtime.global_vars, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, varname, v);\r
- } else {\r
- switch_event_del_header(runtime.global_vars, varname);\r
- }\r
- switch_thread_rwlock_unlock(runtime.global_var_rwlock);\r
- }\r
- return SWITCH_TRUE;\r
-}\r
-\r
-SWITCH_DECLARE(char *) switch_core_get_uuid(void)\r
-{\r
- return runtime.uuid_str;\r
-}\r
-\r
-\r
-static void *SWITCH_THREAD_FUNC switch_core_service_thread(switch_thread_t *thread, void *obj)\r
-{\r
- switch_core_session_t *session = obj;\r
- switch_channel_t *channel;\r
- switch_frame_t *read_frame;\r
-\r
-// switch_assert(thread != NULL);\r
-// switch_assert(session != NULL);\r
-\r
- if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {\r
- return NULL;\r
- }\r
-\r
- switch_mutex_lock(session->frame_read_mutex);\r
-\r
- channel = switch_core_session_get_channel(session);\r
-\r
- switch_channel_set_flag(channel, CF_SERVICE);\r
- while (switch_channel_test_flag(channel, CF_SERVICE)) {\r
-\r
- if (switch_channel_test_flag(channel, CF_SERVICE_AUDIO)) {\r
- switch (switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0)) {\r
- case SWITCH_STATUS_SUCCESS:\r
- case SWITCH_STATUS_TIMEOUT:\r
- case SWITCH_STATUS_BREAK:\r
- break;\r
- default:\r
- switch_channel_clear_flag(channel, CF_SERVICE);\r
- break;\r
- }\r
- }\r
-\r
- if (switch_channel_test_flag(channel, CF_SERVICE_VIDEO) && switch_channel_test_flag(channel, CF_VIDEO)) {\r
- switch (switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0)) {\r
- case SWITCH_STATUS_SUCCESS:\r
- case SWITCH_STATUS_TIMEOUT:\r
- case SWITCH_STATUS_BREAK:\r
- break;\r
- default:\r
- switch_channel_clear_flag(channel, CF_SERVICE);\r
- break;\r
- }\r
- }\r
- }\r
-\r
- switch_mutex_unlock(session->frame_read_mutex);\r
-\r
- switch_channel_clear_flag(channel, CF_SERVICE_AUDIO);\r
- switch_channel_clear_flag(channel, CF_SERVICE_VIDEO);\r
-\r
- switch_core_session_rwunlock(session);\r
-\r
- return NULL;\r
-}\r
-\r
-/* Either add a timeout here or make damn sure the thread cannot get hung somehow (my preference) */\r
-SWITCH_DECLARE(void) switch_core_thread_session_end(switch_core_session_t *session)\r
-{\r
- switch_channel_t *channel;\r
- switch_assert(session);\r
-\r
- channel = switch_core_session_get_channel(session);\r
- switch_assert(channel);\r
-\r
- switch_channel_clear_flag(channel, CF_SERVICE);\r
- switch_channel_clear_flag(channel, CF_SERVICE_AUDIO);\r
- switch_channel_clear_flag(channel, CF_SERVICE_VIDEO);\r
-\r
- switch_core_session_kill_channel(session, SWITCH_SIG_BREAK);\r
- \r
-}\r
-\r
-SWITCH_DECLARE(void) switch_core_service_session_av(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video)\r
-{\r
- switch_channel_t *channel;\r
- switch_assert(session);\r
-\r
- channel = switch_core_session_get_channel(session);\r
- switch_assert(channel);\r
-\r
- if (audio) switch_channel_set_flag(channel, CF_SERVICE_AUDIO);\r
- if (video) switch_channel_set_flag(channel, CF_SERVICE_VIDEO);\r
-\r
- switch_core_session_launch_thread(session, (void *(*)(switch_thread_t *,void *))switch_core_service_thread, session);\r
-}\r
-\r
-/* This function abstracts the thread creation for modules by allowing you to pass a function ptr and\r
- a void object and trust that that the function will be run in a thread with arg This lets\r
- you request and activate a thread without giving up any knowledge about what is in the thread\r
- neither the core nor the calling module know anything about each other.\r
-\r
- This thread is expected to never exit until the application exits so the func is responsible\r
- to make sure that is the case.\r
-\r
- The typical use for this is so switch_loadable_module.c can start up a thread for each module\r
- passing the table of module methods as a session obj into the core without actually allowing\r
- the core to have any clue and keeping switch_loadable_module.c from needing any thread code.\r
-\r
-*/\r
-\r
-SWITCH_DECLARE(switch_thread_t *) switch_core_launch_thread(switch_thread_start_t func, void *obj, switch_memory_pool_t *pool)\r
-{\r
- switch_thread_t *thread = NULL;\r
- switch_threadattr_t *thd_attr = NULL;\r
- switch_core_thread_session_t *ts;\r
- int mypool;\r
-\r
- mypool = pool ? 0 : 1;\r
-\r
- if (!pool && switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory pool\n");\r
- return NULL;\r
- }\r
-\r
- switch_threadattr_create(&thd_attr, pool);\r
-\r
- if ((ts = switch_core_alloc(pool, sizeof(*ts))) == 0) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not allocate memory\n");\r
- } else {\r
- if (mypool) {\r
- ts->pool = pool;\r
- }\r
- ts->objs[0] = obj;\r
- ts->objs[1] = thread;\r
- switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);\r
- switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME);\r
- switch_thread_create(&thread, thd_attr, func, ts, pool);\r
- }\r
-\r
- return thread;\r
-}\r
-\r
-SWITCH_DECLARE(void) switch_core_set_globals(void)\r
-{\r
-#define BUFSIZE 1024\r
-#ifdef WIN32\r
- char lpPathBuffer[BUFSIZE];\r
- DWORD dwBufSize = BUFSIZE;\r
- char base_dir[1024];\r
- char *lastbacklash;\r
- char *tmp;\r
-\r
- GetModuleFileName(NULL, base_dir, BUFSIZE);\r
- lastbacklash = strrchr(base_dir, '\\');\r
- base_dir[(lastbacklash - base_dir)] = '\0';\r
- /* 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 */\r
- SetCurrentDirectory(base_dir);\r
- tmp = switch_string_replace(base_dir, "\\", "/");\r
- strcpy(base_dir, tmp);\r
- free(tmp);\r
-\r
-#else\r
- char base_dir[1024] = SWITCH_PREFIX_DIR;\r
-#endif\r
-\r
- if (!SWITCH_GLOBAL_dirs.base_dir && (SWITCH_GLOBAL_dirs.base_dir = (char *) malloc(BUFSIZE))) {\r
- switch_snprintf(SWITCH_GLOBAL_dirs.base_dir, BUFSIZE, "%s", base_dir);\r
- }\r
-\r
- if (!SWITCH_GLOBAL_dirs.mod_dir && (SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(BUFSIZE))) {\r
-#ifdef SWITCH_MOD_DIR\r
- switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s", SWITCH_MOD_DIR);\r
-#else\r
- switch_snprintf(SWITCH_GLOBAL_dirs.mod_dir, BUFSIZE, "%s%smod", base_dir, SWITCH_PATH_SEPARATOR);\r
-#endif\r
- }\r
-\r
- if (!SWITCH_GLOBAL_dirs.lib_dir && (SWITCH_GLOBAL_dirs.lib_dir = (char *) malloc(BUFSIZE))) {\r
-#ifdef SWITCH_LIB_DIR\r
- switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s", SWITCH_LIB_DIR);\r
-#else\r
- switch_snprintf(SWITCH_GLOBAL_dirs.lib_dir, BUFSIZE, "%s%slib", base_dir, SWITCH_PATH_SEPARATOR);\r
-#endif\r
- }\r
-\r
- if (!SWITCH_GLOBAL_dirs.conf_dir && (SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(BUFSIZE))) {\r
-#ifdef SWITCH_CONF_DIR\r
- switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s", SWITCH_CONF_DIR);\r
-#else\r
- switch_snprintf(SWITCH_GLOBAL_dirs.conf_dir, BUFSIZE, "%s%sconf", base_dir, SWITCH_PATH_SEPARATOR);\r
-#endif\r
- }\r
-\r
- if (!SWITCH_GLOBAL_dirs.log_dir && (SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(BUFSIZE))) {\r
-#ifdef SWITCH_LOG_DIR\r
- switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s", SWITCH_LOG_DIR);\r
-#else\r
- switch_snprintf(SWITCH_GLOBAL_dirs.log_dir, BUFSIZE, "%s%slog", base_dir, SWITCH_PATH_SEPARATOR);\r
-#endif\r
- }\r
-\r
- if (!SWITCH_GLOBAL_dirs.run_dir && (SWITCH_GLOBAL_dirs.run_dir = (char *) malloc(BUFSIZE))) {\r
-#ifdef SWITCH_RUN_DIR\r
- switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s", SWITCH_RUN_DIR);\r
-#else\r
- switch_snprintf(SWITCH_GLOBAL_dirs.run_dir, BUFSIZE, "%s%srun", base_dir, SWITCH_PATH_SEPARATOR);\r
-#endif\r
- }\r
-\r
- if (!SWITCH_GLOBAL_dirs.recordings_dir && (SWITCH_GLOBAL_dirs.recordings_dir = (char *) malloc(BUFSIZE))) {\r
-#ifdef SWITCH_RECORDINGS_DIR\r
- switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s", SWITCH_RECORDINGS_DIR);\r
-#else\r
- switch_snprintf(SWITCH_GLOBAL_dirs.recordings_dir, BUFSIZE, "%s%srecordings", base_dir, SWITCH_PATH_SEPARATOR);\r
-#endif\r
- }\r
-\r
- if (!SWITCH_GLOBAL_dirs.sounds_dir && (SWITCH_GLOBAL_dirs.sounds_dir = (char *) malloc(BUFSIZE))) {\r
-#ifdef SWITCH_SOUNDS_DIR\r
- switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s", SWITCH_SOUNDS_DIR);\r
-#else\r
- switch_snprintf(SWITCH_GLOBAL_dirs.sounds_dir, BUFSIZE, "%s%ssounds", base_dir, SWITCH_PATH_SEPARATOR);\r
-#endif\r
- }\r
-\r
- if (!SWITCH_GLOBAL_dirs.storage_dir && (SWITCH_GLOBAL_dirs.storage_dir = (char *) malloc(BUFSIZE))) {\r
-#ifdef SWITCH_STORAGE_DIR\r
- switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s", SWITCH_STORAGE_DIR);\r
-#else\r
- switch_snprintf(SWITCH_GLOBAL_dirs.storage_dir, BUFSIZE, "%s%sstorage", base_dir, SWITCH_PATH_SEPARATOR);\r
-#endif\r
- }\r
-\r
- if (!SWITCH_GLOBAL_dirs.db_dir && (SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(BUFSIZE))) {\r
-#ifdef SWITCH_DB_DIR\r
- switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s", SWITCH_DB_DIR);\r
-#else\r
- switch_snprintf(SWITCH_GLOBAL_dirs.db_dir, BUFSIZE, "%s%sdb", base_dir, SWITCH_PATH_SEPARATOR);\r
-#endif\r
- }\r
-\r
- if (!SWITCH_GLOBAL_dirs.script_dir && (SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(BUFSIZE))) {\r
-#ifdef SWITCH_SCRIPT_DIR\r
- switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s", SWITCH_SCRIPT_DIR);\r
-#else\r
- switch_snprintf(SWITCH_GLOBAL_dirs.script_dir, BUFSIZE, "%s%sscripts", base_dir, SWITCH_PATH_SEPARATOR);\r
-#endif\r
- }\r
-\r
- if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(BUFSIZE))) {\r
-#ifdef SWITCH_HTDOCS_DIR\r
- switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s", SWITCH_HTDOCS_DIR);\r
-#else\r
- switch_snprintf(SWITCH_GLOBAL_dirs.htdocs_dir, BUFSIZE, "%s%shtdocs", base_dir, SWITCH_PATH_SEPARATOR);\r
-#endif\r
- }\r
-\r
- if (!SWITCH_GLOBAL_dirs.grammar_dir && (SWITCH_GLOBAL_dirs.grammar_dir = (char *) malloc(BUFSIZE))) {\r
-#ifdef SWITCH_GRAMMAR_DIR\r
- switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s", SWITCH_GRAMMAR_DIR);\r
-#else\r
- switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s%sgrammar", base_dir, SWITCH_PATH_SEPARATOR);\r
-#endif\r
- }\r
-\r
- if (!SWITCH_GLOBAL_dirs.temp_dir && (SWITCH_GLOBAL_dirs.temp_dir = (char *) malloc(BUFSIZE))) {\r
-#ifdef SWITCH_TEMP_DIR\r
- switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", SWITCH_TEMP_DIR);\r
-#else\r
-#ifdef WIN32\r
- GetTempPath(dwBufSize, lpPathBuffer);\r
- lpPathBuffer[strlen(lpPathBuffer)-1] = 0;\r
- tmp = switch_string_replace(lpPathBuffer, "\\", "/");\r
- strcpy(lpPathBuffer, tmp);\r
- free(tmp);\r
- switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", lpPathBuffer);\r
-#else\r
- switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", "/tmp");\r
-#endif\r
-#endif\r
- }\r
-\r
- switch_assert(SWITCH_GLOBAL_dirs.base_dir);\r
- switch_assert(SWITCH_GLOBAL_dirs.mod_dir);\r
- switch_assert(SWITCH_GLOBAL_dirs.lib_dir);\r
- switch_assert(SWITCH_GLOBAL_dirs.conf_dir);\r
- switch_assert(SWITCH_GLOBAL_dirs.log_dir);\r
- switch_assert(SWITCH_GLOBAL_dirs.run_dir);\r
- switch_assert(SWITCH_GLOBAL_dirs.db_dir);\r
- switch_assert(SWITCH_GLOBAL_dirs.script_dir);\r
- switch_assert(SWITCH_GLOBAL_dirs.htdocs_dir);\r
- switch_assert(SWITCH_GLOBAL_dirs.grammar_dir);\r
- switch_assert(SWITCH_GLOBAL_dirs.recordings_dir);\r
- switch_assert(SWITCH_GLOBAL_dirs.sounds_dir);\r
- switch_assert(SWITCH_GLOBAL_dirs.temp_dir);\r
-}\r
-\r
-\r
-SWITCH_DECLARE(int32_t) set_low_priority(void)\r
-{\r
-\r
-\r
-#ifdef WIN32\r
- SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);\r
-#else\r
-#ifdef USE_SCHED_SETSCHEDULER\r
- /*\r
- * Try to use a normal scheduler\r
- */\r
- struct sched_param sched = { 0 };\r
- sched.sched_priority = 0;\r
- if (sched_setscheduler(0, SCHED_OTHER, &sched)) {\r
- return -1;\r
- }\r
-#endif\r
-\r
-#ifdef HAVE_SETPRIORITY\r
- /*\r
- * setpriority() works on FreeBSD (6.2), nice() doesn't\r
- */\r
- if (setpriority(PRIO_PROCESS, getpid(), 19) < 0) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n");\r
- return -1;\r
- }\r
-#else\r
- if (nice(19) != 19) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n");\r
- return -1;\r
- }\r
-#endif\r
-#endif\r
-\r
- return 0;\r
-}\r
-\r
-SWITCH_DECLARE(int32_t) set_realtime_priority(void)\r
-{\r
-#ifdef WIN32\r
- SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);\r
-#else\r
-#ifdef USE_SCHED_SETSCHEDULER\r
- /*\r
- * Try to use a round-robin scheduler\r
- * with a fallback if that does not work\r
- */\r
- struct sched_param sched = { 0 };\r
- sched.sched_priority = SWITCH_PRI_LOW;\r
- if (sched_setscheduler(0, SCHED_FIFO, &sched)) {\r
- sched.sched_priority = 0;\r
- if (sched_setscheduler(0, SCHED_OTHER, &sched)) {\r
- return -1;\r
- }\r
- }\r
-#endif\r
-\r
- \r
-\r
-#ifdef HAVE_SETPRIORITY\r
- /*\r
- * setpriority() works on FreeBSD (6.2), nice() doesn't\r
- */\r
- if (setpriority(PRIO_PROCESS, getpid(), -10) < 0) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n");\r
- return -1;\r
- }\r
-#else\r
- if (nice(-10) != -10) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n");\r
- return -1;\r
- }\r
-#endif\r
-#endif\r
- return 0;\r
-}\r
-\r
-SWITCH_DECLARE(uint32_t) switch_core_cpu_count(void)\r
-{\r
- return runtime.cpu_count;\r
-}\r
-\r
-SWITCH_DECLARE(int32_t) set_normal_priority(void)\r
-{\r
- return 0;\r
-}\r
-\r
-SWITCH_DECLARE(int32_t) set_auto_priority(void)\r
-{\r
-#ifndef WIN32\r
- runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN);\r
-#else\r
- SYSTEM_INFO sysinfo;\r
- GetSystemInfo( &sysinfo );\r
- runtime.cpu_count = sysinfo.dwNumberOfProcessors;\r
-#endif\r
-\r
- if (!runtime.cpu_count) runtime.cpu_count = 1;\r
-\r
- /* If we have more than 1 cpu, we should use realtime priority so we can have priority threads */\r
- if (runtime.cpu_count > 1) {\r
- return set_realtime_priority();\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-SWITCH_DECLARE(int32_t) change_user_group(const char *user, const char *group)\r
-{\r
-#ifndef WIN32\r
- uid_t runas_uid = 0;\r
- gid_t runas_gid = 0;\r
- struct passwd *runas_pw = NULL;\r
-\r
- if (user) {\r
- /*\r
- * Lookup user information in the system's db\r
- */\r
- runas_pw = getpwnam(user);\r
- if (!runas_pw) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unknown user \"%s\"\n", user);\r
- return -1;\r
- }\r
- runas_uid = runas_pw->pw_uid;\r
- }\r
-\r
- if (group) {\r
- struct group *gr = NULL;\r
-\r
- /*\r
- * Lookup group information in the system's db\r
- */\r
- gr = getgrnam(group);\r
- if (!gr) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unknown group \"%s\"\n", group);\r
- return -1;\r
- }\r
- runas_gid = gr->gr_gid;\r
- }\r
-\r
- if (runas_uid && getuid() == runas_uid && (!runas_gid || runas_gid == getgid())) {\r
- /* already running as the right user and group, nothing to do! */\r
- return 0;\r
- }\r
-\r
- if (runas_uid) {\r
-#ifdef HAVE_SETGROUPS\r
- /*\r
- * Drop all group memberships prior to changing anything\r
- * or else we're going to inherit the parent's list of groups\r
- * (which is not what we want...)\r
- */\r
- if (setgroups(0, NULL) < 0) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to drop group access list\n");\r
- return -1;\r
- }\r
-#endif\r
- if (runas_gid) {\r
- /*\r
- * A group has been passed, switch to it\r
- * (without loading the user's other groups)\r
- */\r
- if (setgid(runas_gid) < 0) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change gid!\n");\r
- return -1;\r
- }\r
- } else {\r
- /*\r
- * No group has been passed, use the user's primary group in this case\r
- */\r
- if (setgid(runas_pw->pw_gid) < 0) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change gid!\n");\r
- return -1;\r
- }\r
-#ifdef HAVE_INITGROUPS\r
- /*\r
- * Set all the other groups the user is a member of\r
- * (This can be really useful for fine-grained access control)\r
- */\r
- if (initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to set group access list for user\n");\r
- return -1;\r
- }\r
-#endif\r
- }\r
-\r
- /*\r
- * Finally drop all privileges by switching to the new userid\r
- */\r
- if (setuid(runas_uid) < 0) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to change uid!\n");\r
- return -1;\r
- }\r
- }\r
-#endif\r
- return 0;\r
-}\r
-\r
-SWITCH_DECLARE(void) switch_core_runtime_loop(int bg)\r
-{\r
-#ifdef WIN32\r
- HANDLE shutdown_event;\r
- char path[256] = "";\r
-#endif\r
- if (bg) {\r
- bg = 0;\r
-#ifdef WIN32\r
- switch_snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid());\r
- shutdown_event = CreateEvent(NULL, FALSE, FALSE, path);\r
- if (shutdown_event) {\r
- WaitForSingleObject(shutdown_event, INFINITE);\r
- }\r
-#else\r
- runtime.running = 1;\r
- while (runtime.running) {\r
- switch_yield(1000000);\r
- }\r
-#endif\r
- } else {\r
- /* wait for console input */\r
- switch_console_loop();\r
- }\r
-}\r
-\r
-SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext)\r
-{\r
- if (!ext) {\r
- return NULL;\r
- }\r
- return (const char *) switch_core_hash_find(runtime.mime_types, ext);\r
-}\r
-\r
-\r
-SWITCH_DECLARE(switch_hash_index_t *) switch_core_mime_index(void)\r
-{\r
- return switch_hash_first(NULL, runtime.mime_types);\r
-}\r
-\r
-SWITCH_DECLARE(switch_status_t) switch_core_mime_add_type(const char *type, const char *ext)\r
-{\r
- const char *check;\r
- switch_status_t status = SWITCH_STATUS_FALSE;\r
-\r
- switch_assert(type);\r
- switch_assert(ext);\r
-\r
- check = (const char *) switch_core_hash_find(runtime.mime_types, ext);\r
-\r
- if (!check) {\r
- char *ptype = switch_core_permanent_strdup(type);\r
- char *ext_list = strdup(ext);\r
- int argc = 0;\r
- char *argv[20] = { 0 };\r
- int x;\r
-\r
- switch_assert(ext_list);\r
-\r
- if ((argc = switch_separate_string(ext_list, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {\r
-\r
- for (x = 0; x < argc; x++) {\r
- if (argv[x] && ptype) {\r
- switch_core_hash_insert(runtime.mime_types, argv[x], ptype);\r
- }\r
- }\r
-\r
- status = SWITCH_STATUS_SUCCESS;\r
- }\r
-\r
- free(ext_list);\r
- }\r
-\r
- return status;\r
-}\r
-\r
-static void load_mime_types(void)\r
-{\r
- char *cf = "mime.types";\r
- FILE *fd = NULL;\r
- char *line_buf = NULL;\r
- switch_size_t llen = 0;\r
- char *mime_path = NULL;\r
-\r
- mime_path = switch_mprintf("%s/%s", SWITCH_GLOBAL_dirs.conf_dir, cf);\r
- switch_assert(mime_path);\r
-\r
- fd = fopen(mime_path, "rb");\r
-\r
- if (fd == NULL) {\r
- goto end;\r
- }\r
-\r
- while ((switch_fp_read_dline(fd, &line_buf, &llen))) {\r
- char *p;\r
- char *type = line_buf;\r
-\r
- if (*line_buf == '#') {\r
- continue;\r
- }\r
-\r
- if ((p = strchr(line_buf, '\r')) || (p = strchr(line_buf, '\n'))) {\r
- *p = '\0';\r
- }\r
-\r
- if ((p = strchr(type, '\t')) || (p = strchr(type, ' '))) {\r
- *p++ = '\0';\r
-\r
- while (*p == ' ' || *p == '\t') {\r
- p++;\r
- }\r
-\r
- switch_core_mime_add_type(type, p);\r
- }\r
-\r
- }\r
-\r
- switch_safe_free(line_buf);\r
-\r
- if (fd) {\r
- fclose(fd);\r
- fd = NULL;\r
- }\r
-\r
- end:\r
-\r
- switch_safe_free(mime_path);\r
-\r
-}\r
-\r
-SWITCH_DECLARE(void) switch_core_setrlimits(void)\r
-{\r
-#ifdef HAVE_SETRLIMIT\r
- struct rlimit rlp;\r
-\r
- /* \r
- Setting the stack size on FreeBSD results in an instant crash.\r
-\r
- If anyone knows how to fix this,\r
- feel free to submit a patch to http://jira.freeswitch.org \r
- */\r
-\r
-#ifndef __FreeBSD__\r
- memset(&rlp, 0, sizeof(rlp));\r
- rlp.rlim_cur = SWITCH_THREAD_STACKSIZE;\r
- rlp.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE;\r
- setrlimit(RLIMIT_STACK, &rlp);\r
-#endif\r
-\r
- memset(&rlp, 0, sizeof(rlp));\r
- rlp.rlim_cur = 999999;\r
- rlp.rlim_max = 999999;\r
- setrlimit(RLIMIT_NOFILE, &rlp);\r
-\r
- memset(&rlp, 0, sizeof(rlp));\r
- rlp.rlim_cur = RLIM_INFINITY;\r
- rlp.rlim_max = RLIM_INFINITY;\r
-\r
- setrlimit(RLIMIT_CPU, &rlp);\r
- setrlimit(RLIMIT_DATA, &rlp);\r
- setrlimit(RLIMIT_FSIZE, &rlp);\r
-#ifdef RLIMIT_NPROC\r
- setrlimit(RLIMIT_NPROC, &rlp);\r
-#endif\r
-#ifdef RLIMIT_RTPRIO\r
- setrlimit(RLIMIT_RTPRIO, &rlp);\r
-#endif\r
-\r
-#if !defined(__OpenBSD__) && !defined(__NetBSD__)\r
- setrlimit(RLIMIT_AS, &rlp);\r
-#endif\r
-#endif\r
- return;\r
-}\r
-\r
-typedef struct {\r
- switch_memory_pool_t *pool;\r
- switch_hash_t *hash;\r
-} switch_ip_list_t;\r
-\r
-static switch_ip_list_t IP_LIST = { 0 };\r
-\r
-SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_str, const char *list_name, const char **token)\r
-{\r
- switch_network_list_t *list;\r
- ip_t ip, mask, net;\r
- uint32_t bits;\r
- char *ipv6 = strchr(ip_str,':');\r
- switch_bool_t ok = SWITCH_FALSE;\r
-\r
- switch_mutex_lock(runtime.global_mutex);\r
- if (ipv6) {\r
- switch_inet_pton(AF_INET6, ip_str, &ip);\r
- } else {\r
- switch_inet_pton(AF_INET, ip_str, &ip);\r
- ip.v4 = htonl(ip.v4);\r
- }\r
-\r
- if ((list = switch_core_hash_find(IP_LIST.hash, list_name))) {\r
- if (ipv6) {\r
- ok = switch_network_list_validate_ip6_token(list, ip, token);\r
- } else {\r
- ok = switch_network_list_validate_ip_token(list, ip.v4, token);\r
- }\r
- } else if (strchr(list_name, '/')) {\r
- if (strchr(list_name, ',')) {\r
- char *list_name_dup = strdup(list_name);\r
- char *argv[32];\r
- int argc;\r
-\r
- switch_assert(list_name_dup);\r
-\r
- if ((argc = switch_separate_string(list_name_dup, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {\r
- int i;\r
- for (i = 0; i < argc; i++) {\r
- switch_parse_cidr(argv[i], &net, &mask, &bits);\r
- if (ipv6) {\r
- if ((ok = switch_testv6_subnet(ip, net, mask))){\r
- break;\r
- }\r
- } else {\r
- if ((ok = switch_test_subnet(ip.v4, net.v4, mask.v4))) {\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- free(list_name_dup);\r
- } else {\r
- switch_parse_cidr(list_name, &net, &mask, &bits);\r
- ok = switch_test_subnet(ip.v4, net.v4, mask.v4);\r
- }\r
- }\r
- switch_mutex_unlock(runtime.global_mutex);\r
-\r
- return ok;\r
-}\r
-\r
-\r
-SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)\r
-{\r
- switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, x_node = NULL, cfg = NULL;\r
- switch_network_list_t *rfc_list, *list;\r
- char guess_ip[16] = "";\r
- int mask = 0;\r
- char guess_mask[16] = "";\r
- char *tmp_name;\r
- struct in_addr in;\r
-\r
- switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET);\r
- in.s_addr = mask;\r
- switch_set_string(guess_mask, inet_ntoa(in));\r
-\r
- switch_mutex_lock(runtime.global_mutex);\r
-\r
- if (IP_LIST.hash) {\r
- switch_core_hash_destroy(&IP_LIST.hash);\r
- }\r
-\r
- if (IP_LIST.pool) {\r
- switch_core_destroy_memory_pool(&IP_LIST.pool);\r
- }\r
-\r
- memset(&IP_LIST, 0, sizeof(IP_LIST));\r
- switch_core_new_memory_pool(&IP_LIST.pool);\r
- switch_core_hash_init(&IP_LIST.hash, IP_LIST.pool);\r
-\r
-\r
- tmp_name = "rfc1918.auto";\r
- switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);\r
- switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE);\r
- switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE);\r
- switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE);\r
- switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);\r
-\r
- tmp_name = "wan.auto";\r
- switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool);\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name);\r
- switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_FALSE);\r
- switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_FALSE);\r
- switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_FALSE);\r
- switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);\r
-\r
- tmp_name = "nat.auto";\r
- switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);\r
- if (switch_network_list_add_host_mask(rfc_list, guess_ip, guess_mask, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s/%s (deny) to list %s\n", guess_ip, guess_mask, tmp_name);\r
- }\r
- switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE);\r
- switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE);\r
- switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE);\r
- switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);\r
-\r
- tmp_name = "loopback.auto";\r
- switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);\r
- switch_network_list_add_cidr(rfc_list, "127.0.0.0/8", SWITCH_TRUE);\r
- switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);\r
-\r
- tmp_name = "localnet.auto";\r
- switch_network_list_create(&list, tmp_name, SWITCH_FALSE, IP_LIST.pool);\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);\r
-\r
- if (switch_network_list_add_host_mask(list, guess_ip, guess_mask, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s/%s (allow) to list %s\n", guess_ip, guess_mask, tmp_name);\r
- }\r
- switch_core_hash_insert(IP_LIST.hash, tmp_name, list);\r
-\r
-\r
- if ((xml = switch_xml_open_cfg("acl.conf", &cfg, NULL))) {\r
- if ((x_lists = switch_xml_child(cfg, "network-lists"))) {\r
- for (x_list = switch_xml_child(x_lists, "list"); x_list; x_list = x_list->next) {\r
- const char *name = switch_xml_attr(x_list, "name");\r
- const char *dft = switch_xml_attr(x_list, "default");\r
- switch_bool_t default_type = SWITCH_TRUE;\r
-\r
- if (zstr(name)) {\r
- continue;\r
- }\r
-\r
- if (dft) {\r
- default_type = switch_true(dft);\r
- }\r
-\r
- if (switch_network_list_create(&list, name, default_type, IP_LIST.pool) != SWITCH_STATUS_SUCCESS) {\r
- abort();\r
- }\r
-\r
- if (reload) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny");\r
- } else {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny");\r
- }\r
-\r
-\r
- for (x_node = switch_xml_child(x_list, "node"); x_node; x_node = x_node->next) {\r
- const char *cidr = NULL, *host = NULL, *mask = NULL, *domain = NULL;\r
- switch_bool_t ok = default_type;\r
- const char *type = switch_xml_attr(x_node, "type");\r
-\r
- if (type) {\r
- ok = switch_true(type);\r
- }\r
-\r
- cidr = switch_xml_attr(x_node, "cidr");\r
- host = switch_xml_attr(x_node, "host");\r
- mask = switch_xml_attr(x_node, "mask");\r
- domain = switch_xml_attr(x_node, "domain");\r
-\r
- if (domain) {\r
- switch_event_t *my_params = NULL;\r
- switch_xml_t x_domain, xml_root;\r
- switch_xml_t gt, gts, ut, uts;\r
-\r
- switch_event_create(&my_params, SWITCH_EVENT_GENERAL);\r
- switch_assert(my_params);\r
- switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "domain", domain);\r
- switch_event_add_header_string(my_params, SWITCH_STACK_BOTTOM, "purpose", "network-list");\r
-\r
- if (switch_xml_locate_domain(domain, my_params, &xml_root, &x_domain) != SWITCH_STATUS_SUCCESS) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot locate domain %s\n", domain);\r
- switch_event_destroy(&my_params);\r
- continue;\r
- }\r
-\r
- switch_event_destroy(&my_params);\r
-\r
- for (ut = switch_xml_child(x_domain, "user"); ut; ut = ut->next) {\r
- const char *user_cidr = switch_xml_attr(ut, "cidr");\r
- const char *id = switch_xml_attr(ut, "id");\r
-\r
- if (id && user_cidr) {\r
- char *token = switch_mprintf("%s@%s", id, domain);\r
- switch_assert(token);\r
- switch_network_list_add_cidr_token(list, user_cidr, ok, token);\r
- free(token);\r
- }\r
- }\r
-\r
- for (gts = switch_xml_child(x_domain, "groups"); gts; gts = gts->next) {\r
- for (gt = switch_xml_child(gts, "group"); gt; gt = gt->next) {\r
- for (uts = switch_xml_child(gt, "users"); uts; uts = uts->next) {\r
- for (ut = switch_xml_child(uts, "user"); ut; ut = ut->next) {\r
- const char *user_cidr = switch_xml_attr(ut, "cidr");\r
- const char *id = switch_xml_attr(ut, "id");\r
-\r
- if (id && user_cidr) {\r
- char *token = switch_mprintf("%s@%s", id, domain);\r
- switch_assert(token);\r
- switch_network_list_add_cidr_token(list, user_cidr, ok, token);\r
- free(token);\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- switch_xml_free(xml_root);\r
- } else if (cidr) {\r
- if (switch_network_list_add_cidr(list, cidr, ok) == SWITCH_STATUS_SUCCESS) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name);\r
- } else {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,\r
- "Error Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name);\r
- }\r
- } else if (host && mask) {\r
- if (switch_network_list_add_host_mask(list, host, mask, ok) == SWITCH_STATUS_SUCCESS) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,\r
- "Adding %s/%s (%s) to list %s\n", host, mask, ok ? "allow" : "deny", name);\r
- }\r
- }\r
-\r
- switch_core_hash_insert(IP_LIST.hash, name, list);\r
- }\r
- }\r
- }\r
-\r
- switch_xml_free(xml);\r
- }\r
-\r
- switch_mutex_unlock(runtime.global_mutex);\r
-}\r
-\r
-SWITCH_DECLARE(uint32_t) switch_core_max_dtmf_duration(uint32_t duration)\r
-{\r
- if (duration) {\r
- if (duration > SWITCH_MAX_DTMF_DURATION) {\r
- duration = SWITCH_MAX_DTMF_DURATION;\r
- }\r
- if (duration < SWITCH_MIN_DTMF_DURATION) {\r
- duration = SWITCH_MIN_DTMF_DURATION;\r
- }\r
- runtime.max_dtmf_duration = duration;\r
- if (duration < runtime.min_dtmf_duration) {\r
- runtime.min_dtmf_duration = duration;\r
- }\r
- }\r
- return runtime.max_dtmf_duration;\r
-}\r
-\r
-SWITCH_DECLARE(uint32_t) switch_core_default_dtmf_duration(uint32_t duration)\r
-{\r
- if (duration) {\r
- if (duration < SWITCH_MIN_DTMF_DURATION) {\r
- duration = SWITCH_MIN_DTMF_DURATION;\r
- }\r
- if (duration > SWITCH_MAX_DTMF_DURATION) {\r
- duration = SWITCH_MAX_DTMF_DURATION;\r
- }\r
- runtime.default_dtmf_duration = duration;\r
-\r
- if (duration < runtime.min_dtmf_duration) {\r
- runtime.min_dtmf_duration = duration;\r
- }\r
-\r
- if (duration > runtime.max_dtmf_duration) {\r
- runtime.max_dtmf_duration = duration;\r
- }\r
-\r
- }\r
- return runtime.default_dtmf_duration;\r
-}\r
-\r
-SWITCH_DECLARE(uint32_t) switch_core_min_dtmf_duration(uint32_t duration)\r
-{\r
- if (duration) {\r
- if (duration < SWITCH_MIN_DTMF_DURATION) {\r
- duration = SWITCH_MIN_DTMF_DURATION;\r
- }\r
- if (duration > SWITCH_MAX_DTMF_DURATION) {\r
- duration = SWITCH_MAX_DTMF_DURATION;\r
- }\r
-\r
- runtime.min_dtmf_duration = duration;\r
-\r
- if (duration > runtime.max_dtmf_duration) {\r
- runtime.max_dtmf_duration = duration;\r
- }\r
- }\r
- return runtime.min_dtmf_duration;\r
-}\r
-\r
-SWITCH_DECLARE(switch_status_t) switch_core_thread_set_cpu_affinity(int cpu)\r
-{\r
- switch_status_t status = SWITCH_STATUS_FALSE;\r
-\r
- if (cpu > -1) {\r
-\r
-#ifdef HAVE_CPU_SET_MACROS\r
- cpu_set_t set;\r
-\r
- CPU_ZERO(&set);\r
- CPU_SET(cpu, &set);\r
-\r
- if (!sched_setaffinity(0, sizeof(set), &set)) {\r
- status = SWITCH_STATUS_SUCCESS;\r
- }\r
- \r
-#else\r
-#if WIN32\r
- if (SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR) cpu)) {\r
- status = SWITCH_STATUS_SUCCESS;\r
- }\r
-#endif\r
-#endif\r
- }\r
-\r
- return status;\r
-}\r
-\r
-\r
-static void switch_core_set_serial(void)\r
-{\r
- char buf[13] = "";\r
- char path[256];\r
-\r
- int fd = -1, write_fd = -1;\r
- switch_ssize_t bytes = 0;\r
-\r
- switch_snprintf(path, sizeof(path), "%s%sfreeswitch.serial", SWITCH_GLOBAL_dirs.conf_dir, SWITCH_PATH_SEPARATOR);\r
-\r
-\r
- if ((fd = open(path, O_RDONLY, 0)) < 0) {\r
- char *ip = switch_core_get_variable_dup("local_ip_v4");\r
- uint32_t ipi = 0;\r
- switch_byte_t *byte;\r
- int i = 0;\r
-\r
- if (ip) {\r
- switch_inet_pton(AF_INET, ip, &ipi);\r
- free(ip);\r
- ip = NULL;\r
- }\r
-\r
-\r
- byte = (switch_byte_t *) & ipi;\r
-\r
- for (i = 0; i < 8; i += 2) {\r
- switch_snprintf(buf + i, sizeof(buf) - i, "%0.2x", *byte);\r
- byte++;\r
- }\r
-\r
- switch_stun_random_string(buf + 8, 4, "0123456789abcdef");\r
-\r
- if ((write_fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) >= 0) {\r
- bytes = write(write_fd, buf, sizeof(buf));\r
- bytes++;\r
- close(write_fd);\r
- write_fd = -1;\r
- }\r
- } else {\r
- bytes = read(fd, buf, sizeof(buf));\r
- close(fd);\r
- fd = -1;\r
- }\r
-\r
- switch_core_set_variable("switch_serial", buf);\r
-}\r
-\r
-\r
-SWITCH_DECLARE(int) switch_core_test_flag(int flag)\r
-{\r
- return switch_test_flag((&runtime), flag);\r
-}\r
-\r
-\r
-SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switch_bool_t console, const char **err)\r
-{\r
- switch_uuid_t uuid;\r
- char guess_ip[256];\r
- int mask = 0;\r
- struct in_addr in;\r
-\r
-\r
- if (runtime.runlevel > 0) {\r
- /* one per customer */\r
- return SWITCH_STATUS_SUCCESS;\r
- }\r
- \r
- memset(&runtime, 0, sizeof(runtime));\r
- gethostname(runtime.hostname, sizeof(runtime.hostname));\r
-\r
- runtime.max_db_handles = 50;\r
- runtime.db_handle_timeout = 5000000;\r
- \r
- runtime.runlevel++;\r
- runtime.dummy_cng_frame.data = runtime.dummy_data;\r
- runtime.dummy_cng_frame.datalen = sizeof(runtime.dummy_data);\r
- runtime.dummy_cng_frame.buflen = sizeof(runtime.dummy_data);\r
- runtime.dbname = "core";\r
- switch_set_flag((&runtime.dummy_cng_frame), SFF_CNG);\r
- switch_set_flag((&runtime), SCF_AUTO_SCHEMAS);\r
- switch_set_flag((&runtime), SCF_CLEAR_SQL);\r
- switch_set_flag((&runtime), SCF_API_EXPANSION);\r
- switch_set_flag((&runtime), SCF_SESSION_THREAD_POOL);\r
-#ifdef WIN32\r
- switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);\r
-#endif\r
- switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);\r
- runtime.hard_log_level = SWITCH_LOG_DEBUG;\r
- runtime.mailer_app = "sendmail";\r
- runtime.mailer_app_args = "-t";\r
- runtime.max_dtmf_duration = SWITCH_MAX_DTMF_DURATION;\r
- runtime.default_dtmf_duration = SWITCH_DEFAULT_DTMF_DURATION;\r
- runtime.min_dtmf_duration = SWITCH_MIN_DTMF_DURATION;\r
- runtime.odbc_dbtype = DBTYPE_DEFAULT;\r
- runtime.dbname = NULL;\r
-#ifndef WIN32\r
- runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN);\r
-#else\r
- {\r
- SYSTEM_INFO sysinfo;\r
- GetSystemInfo( &sysinfo );\r
- runtime.cpu_count = sysinfo.dwNumberOfProcessors;\r
- }\r
-#endif \r
-\r
- if (!runtime.cpu_count) runtime.cpu_count = 1;\r
-\r
-\r
- /* INIT APR and Create the pool context */\r
- if (apr_initialize() != SWITCH_STATUS_SUCCESS) {\r
- *err = "FATAL ERROR! Could not initialize APR\n";\r
- return SWITCH_STATUS_MEMERR;\r
- }\r
-\r
- if (!(runtime.memory_pool = switch_core_memory_init())) {\r
- *err = "FATAL ERROR! Could not allocate memory pool\n";\r
- return SWITCH_STATUS_MEMERR;\r
- }\r
- switch_assert(runtime.memory_pool != NULL);\r
-\r
- switch_dir_make_recursive(SWITCH_GLOBAL_dirs.base_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);\r
- switch_dir_make_recursive(SWITCH_GLOBAL_dirs.mod_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);\r
- switch_dir_make_recursive(SWITCH_GLOBAL_dirs.conf_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);\r
- switch_dir_make_recursive(SWITCH_GLOBAL_dirs.log_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);\r
- switch_dir_make_recursive(SWITCH_GLOBAL_dirs.run_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);\r
- switch_dir_make_recursive(SWITCH_GLOBAL_dirs.db_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);\r
- switch_dir_make_recursive(SWITCH_GLOBAL_dirs.script_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);\r
- switch_dir_make_recursive(SWITCH_GLOBAL_dirs.htdocs_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);\r
- switch_dir_make_recursive(SWITCH_GLOBAL_dirs.grammar_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);\r
- switch_dir_make_recursive(SWITCH_GLOBAL_dirs.recordings_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);\r
- switch_dir_make_recursive(SWITCH_GLOBAL_dirs.sounds_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);\r
- switch_dir_make_recursive(SWITCH_GLOBAL_dirs.temp_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);\r
-\r
-\r
- switch_mutex_init(&runtime.uuid_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);\r
-\r
- switch_mutex_init(&runtime.throttle_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);\r
-\r
- switch_mutex_init(&runtime.session_hash_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);\r
- switch_mutex_init(&runtime.global_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);\r
-\r
- switch_thread_rwlock_create(&runtime.global_var_rwlock, runtime.memory_pool);\r
- switch_core_set_globals();\r
- switch_core_session_init(runtime.memory_pool);\r
- switch_event_create_plain(&runtime.global_vars, SWITCH_EVENT_CHANNEL_DATA);\r
- switch_core_hash_init(&runtime.mime_types, runtime.memory_pool);\r
- switch_core_hash_init_case(&runtime.ptimes, runtime.memory_pool, SWITCH_FALSE);\r
- load_mime_types();\r
- runtime.flags |= flags;\r
- runtime.sps_total = 30;\r
-\r
- *err = NULL;\r
-\r
- if (console) {\r
- runtime.console = stdout;\r
- }\r
-\r
- switch_ssl_init_ssl_locks();\r
- switch_curl_init();\r
-\r
- switch_core_set_variable("hostname", runtime.hostname);\r
- switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET);\r
- switch_core_set_variable("local_ip_v4", guess_ip);\r
- in.s_addr = mask;\r
- switch_core_set_variable("local_mask_v4", inet_ntoa(in));\r
-\r
-\r
- switch_find_local_ip(guess_ip, sizeof(guess_ip), NULL, AF_INET6);\r
- switch_core_set_variable("local_ip_v6", guess_ip);\r
- switch_core_set_variable("base_dir", SWITCH_GLOBAL_dirs.base_dir);\r
- switch_core_set_variable("recordings_dir", SWITCH_GLOBAL_dirs.recordings_dir);\r
- switch_core_set_variable("sound_prefix", SWITCH_GLOBAL_dirs.sounds_dir);\r
- switch_core_set_variable("sounds_dir", SWITCH_GLOBAL_dirs.sounds_dir);\r
- switch_core_set_serial();\r
-\r
- switch_console_init(runtime.memory_pool);\r
- switch_event_init(runtime.memory_pool);\r
-\r
- if (switch_xml_init(runtime.memory_pool, err) != SWITCH_STATUS_SUCCESS) {\r
- apr_terminate();\r
- return SWITCH_STATUS_MEMERR;\r
- }\r
-\r
- if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) {\r
- switch_nat_init(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_NAT_MAPPING));\r
- }\r
-\r
- switch_log_init(runtime.memory_pool, runtime.colorize_console);\r
-\r
- if (flags & SCF_MINIMAL) return SWITCH_STATUS_SUCCESS;\r
- \r
- runtime.tipping_point = 0;\r
- runtime.timer_affinity = -1;\r
- runtime.microseconds_per_tick = 20000;\r
-\r
- switch_load_core_config("switch.conf");\r
-\r
- switch_core_state_machine_init(runtime.memory_pool);\r
-\r
- if (switch_core_sqldb_start(runtime.memory_pool, switch_test_flag((&runtime), SCF_USE_SQL) ? SWITCH_TRUE : SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) {\r
- *err = "Error activating database";\r
- return SWITCH_STATUS_FALSE;\r
- }\r
-\r
- switch_scheduler_task_thread_start();\r
-\r
- switch_nat_late_init();\r
-\r
- switch_rtp_init(runtime.memory_pool);\r
-\r
- runtime.running = 1;\r
- runtime.initiated = switch_time_now();\r
- runtime.mono_initiated = switch_mono_micro_time_now();\r
- \r
- switch_scheduler_add_task(switch_epoch_time_now(NULL), heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL);\r
-\r
- 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);\r
-\r
- switch_uuid_get(&uuid);\r
- switch_uuid_format(runtime.uuid_str, &uuid);\r
- switch_core_set_variable("core_uuid", runtime.uuid_str);\r
-\r
-\r
- return SWITCH_STATUS_SUCCESS;\r
-}\r
-\r
-\r
-#ifndef WIN32\r
-static void handle_SIGCHLD(int sig)\r
-{\r
- int status = 0;\r
-\r
- wait(&status);\r
- return;\r
-}\r
-#endif\r
-\r
-#ifdef TRAP_BUS\r
-static void handle_SIGBUS(int sig)\r
-{\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Sig BUS!\n");\r
- return;\r
-}\r
-#endif\r
-\r
-static void handle_SIGHUP(int sig)\r
-{\r
- if (sig) {\r
- switch_event_t *event;\r
-\r
- if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {\r
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Trapped-Signal", "HUP");\r
- switch_event_fire(&event);\r
- }\r
- }\r
- return;\r
-}\r
-\r
-\r
-SWITCH_DECLARE(uint32_t) switch_default_ptime(const char *name, uint32_t number)\r
-{\r
- uint32_t *p;\r
-\r
- if ((p = switch_core_hash_find(runtime.ptimes, name))) {\r
- return *p;\r
- }\r
-\r
- return 20;\r
-}\r
-\r
-static uint32_t d_30 = 30;\r
-\r
-static void switch_load_core_config(const char *file)\r
-{\r
- switch_xml_t xml = NULL, cfg = NULL;\r
-\r
- switch_core_hash_insert(runtime.ptimes, "ilbc", &d_30);\r
- switch_core_hash_insert(runtime.ptimes, "G723", &d_30);\r
-\r
- if ((xml = switch_xml_open_cfg(file, &cfg, NULL))) {\r
- switch_xml_t settings, param;\r
-\r
- if ((settings = switch_xml_child(cfg, "default-ptimes"))) {\r
- for (param = switch_xml_child(settings, "codec"); param; param = param->next) {\r
- const char *var = switch_xml_attr_soft(param, "name");\r
- const char *val = switch_xml_attr_soft(param, "ptime");\r
- \r
- if (!zstr(var) && !zstr(val)) {\r
- uint32_t *p;\r
- uint32_t v = switch_atoul(val);\r
-\r
- if (!strcasecmp(var, "G723") || !strcasecmp(var, "iLBC")) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding %s, defaults cannot be changed\n", var);\r
- continue;\r
- }\r
- \r
- if (v == 0) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding %s, invalid ptime\n", var);\r
- continue;\r
- }\r
-\r
- p = switch_core_alloc(runtime.memory_pool, sizeof(*p));\r
- *p = v;\r
- switch_core_hash_insert(runtime.ptimes, var, p);\r
- }\r
-\r
- }\r
- }\r
-\r
- if ((settings = switch_xml_child(cfg, "settings"))) {\r
- for (param = switch_xml_child(settings, "param"); param; param = param->next) {\r
- const char *var = switch_xml_attr_soft(param, "name");\r
- const char *val = switch_xml_attr_soft(param, "value");\r
-\r
- if (!strcasecmp(var, "loglevel")) {\r
- int level;\r
- if (*val > 47 && *val < 58) {\r
- level = atoi(val);\r
- } else {\r
- level = switch_log_str2level(val);\r
- }\r
-\r
- if (level != SWITCH_LOG_INVALID) {\r
- switch_core_session_ctl(SCSC_LOGLEVEL, &level);\r
- }\r
-#ifdef HAVE_SETRLIMIT\r
- } else if (!strcasecmp(var, "dump-cores") && switch_true(val)) {\r
- struct rlimit rlp;\r
- memset(&rlp, 0, sizeof(rlp));\r
- rlp.rlim_cur = RLIM_INFINITY;\r
- rlp.rlim_max = RLIM_INFINITY;\r
- setrlimit(RLIMIT_CORE, &rlp);\r
-#endif\r
- } else if (!strcasecmp(var, "debug-level")) {\r
- int tmp = atoi(val);\r
- if (tmp > -1 && tmp < 11) {\r
- switch_core_session_ctl(SCSC_DEBUG_LEVEL, &tmp);\r
- }\r
- } else if (!strcasecmp(var, "max-db-handles")) {\r
- long tmp = atol(val);\r
-\r
- if (tmp > 4 && tmp < 5001) {\r
- runtime.max_db_handles = (uint32_t) tmp;\r
- } else {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "max-db-handles must be between 5 and 5000\n");\r
- }\r
- } else if (!strcasecmp(var, "db-handle-timeout")) {\r
- long tmp = atol(val);\r
- \r
- if (tmp > 0 && tmp < 5001) {\r
- runtime.db_handle_timeout = (uint32_t) tmp * 1000000;\r
- } else {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "db-handle-timeout must be between 1 and 5000\n");\r
- }\r
- \r
- } else if (!strcasecmp(var, "multiple-registrations")) {\r
- runtime.multiple_registrations = switch_true(val);\r
- } else if (!strcasecmp(var, "auto-create-schemas")) {\r
- if (switch_true(val)) {\r
- switch_set_flag((&runtime), SCF_AUTO_SCHEMAS);\r
- } else {\r
- switch_clear_flag((&runtime), SCF_AUTO_SCHEMAS);\r
- }\r
- } else if (!strcasecmp(var, "session-thread-pool")) {\r
- if (switch_true(val)) {\r
- switch_set_flag((&runtime), SCF_SESSION_THREAD_POOL);\r
- } else {\r
- switch_clear_flag((&runtime), SCF_SESSION_THREAD_POOL);\r
- }\r
- } else if (!strcasecmp(var, "auto-clear-sql")) {\r
- if (switch_true(val)) {\r
- switch_set_flag((&runtime), SCF_CLEAR_SQL);\r
- } else {\r
- switch_clear_flag((&runtime), SCF_CLEAR_SQL);\r
- }\r
- } else if (!strcasecmp(var, "api-expansion")) {\r
- if (switch_true(val)) {\r
- switch_set_flag((&runtime), SCF_API_EXPANSION);\r
- } else {\r
- switch_clear_flag((&runtime), SCF_API_EXPANSION);\r
- }\r
- } else if (!strcasecmp(var, "enable-early-hangup") && switch_true(val)) {\r
- switch_set_flag((&runtime), SCF_EARLY_HANGUP);\r
- } else if (!strcasecmp(var, "colorize-console") && switch_true(val)) {\r
- runtime.colorize_console = SWITCH_TRUE;\r
- } else if (!strcasecmp(var, "core-db-pre-trans-execute") && !zstr(val)) {\r
- runtime.core_db_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val);\r
- } else if (!strcasecmp(var, "core-db-post-trans-execute") && !zstr(val)) {\r
- runtime.core_db_post_trans_execute = switch_core_strdup(runtime.memory_pool, val);\r
- } else if (!strcasecmp(var, "core-db-inner-pre-trans-execute") && !zstr(val)) {\r
- runtime.core_db_inner_pre_trans_execute = switch_core_strdup(runtime.memory_pool, val);\r
- } else if (!strcasecmp(var, "core-db-inner-post-trans-execute") && !zstr(val)) {\r
- runtime.core_db_inner_post_trans_execute = switch_core_strdup(runtime.memory_pool, val);\r
- } else if (!strcasecmp(var, "mailer-app") && !zstr(val)) {\r
- runtime.mailer_app = switch_core_strdup(runtime.memory_pool, val);\r
- } else if (!strcasecmp(var, "mailer-app-args") && val) {\r
- runtime.mailer_app_args = switch_core_strdup(runtime.memory_pool, val);\r
- } else if (!strcasecmp(var, "sessions-per-second") && !zstr(val)) {\r
- switch_core_sessions_per_second(atoi(val));\r
- } else if (!strcasecmp(var, "max-dtmf-duration") && !zstr(val)) {\r
- int tmp = atoi(val);\r
- if (tmp > 0) {\r
- switch_core_max_dtmf_duration((uint32_t) tmp);\r
- }\r
- } else if (!strcasecmp(var, "min-dtmf-duration") && !zstr(val)) {\r
- int tmp = atoi(val);\r
- if (tmp > 0) {\r
- switch_core_min_dtmf_duration((uint32_t) tmp);\r
- }\r
- } else if (!strcasecmp(var, "default-dtmf-duration") && !zstr(val)) {\r
- int tmp = atoi(val);\r
- if (tmp > 0) {\r
- switch_core_default_dtmf_duration((uint32_t) tmp);\r
- }\r
- } else if (!strcasecmp(var, "enable-use-system-time")) {\r
- switch_time_set_use_system_time(switch_true(val));\r
- } else if (!strcasecmp(var, "enable-monotonic-timing")) {\r
- switch_time_set_monotonic(switch_true(val));\r
- } else if (!strcasecmp(var, "enable-softtimer-timerfd")) {\r
- switch_time_set_timerfd(switch_true(val));\r
- } else if (!strcasecmp(var, "enable-clock-nanosleep")) {\r
- switch_time_set_nanosleep(switch_true(val));\r
- } else if (!strcasecmp(var, "enable-cond-yield")) {\r
- switch_time_set_cond_yield(switch_true(val));\r
- } else if (!strcasecmp(var, "enable-timer-matrix")) {\r
- switch_time_set_matrix(switch_true(val));\r
- } else if (!strcasecmp(var, "max-sessions") && !zstr(val)) {\r
- switch_core_session_limit(atoi(val));\r
- } else if (!strcasecmp(var, "verbose-channel-events") && !zstr(val)) {\r
- int v = switch_true(val);\r
- if (v) {\r
- switch_set_flag((&runtime), SCF_VERBOSE_EVENTS);\r
- } else {\r
- switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS);\r
- }\r
- } else if (!strcasecmp(var, "threaded-system-exec") && !zstr(val)) {\r
-#ifdef WIN32\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "threaded-system-exec is not implemented on this platform\n");\r
-#else\r
- int v = switch_true(val);\r
- if (v) {\r
- switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);\r
- } else {\r
- switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);\r
- }\r
-#endif\r
- } else if (!strcasecmp(var, "min-idle-cpu") && !zstr(val)) {\r
- switch_core_min_idle_cpu(atof(val));\r
- } else if (!strcasecmp(var, "tipping-point") && !zstr(val)) {\r
- runtime.tipping_point = atoi(val);\r
- } else if (!strcasecmp(var, "initial-event-threads") && !zstr(val)) {\r
- int tmp = atoi(val);\r
-\r
-\r
- if (tmp > runtime.cpu_count / 2) {\r
- tmp = runtime.cpu_count / 2;\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "This value cannot be higher than %d so setting it to that value\n", \r
- runtime.cpu_count / 2);\r
- }\r
-\r
- if (tmp < 1) {\r
- tmp = 1;\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "This value cannot be lower than 1 so setting it to that level\n");\r
- }\r
-\r
- switch_event_launch_dispatch_threads(tmp);\r
-\r
- } else if (!strcasecmp(var, "1ms-timer") && switch_true(val)) {\r
- runtime.microseconds_per_tick = 1000;\r
- } else if (!strcasecmp(var, "timer-affinity") && !zstr(val)) {\r
- if (!strcasecmp(val, "disabled")) {\r
- runtime.timer_affinity = -1;\r
- } else {\r
- runtime.timer_affinity = atoi(val);\r
- }\r
- } else if (!strcasecmp(var, "rtp-start-port") && !zstr(val)) {\r
- switch_rtp_set_start_port((switch_port_t) atoi(val));\r
- } else if (!strcasecmp(var, "rtp-end-port") && !zstr(val)) {\r
- switch_rtp_set_end_port((switch_port_t) atoi(val));\r
- } else if (!strcasecmp(var, "core-db-name") && !zstr(val)) {\r
- runtime.dbname = switch_core_strdup(runtime.memory_pool, val);\r
- } else if (!strcasecmp(var, "core-db-dsn") && !zstr(val)) {\r
- if (switch_odbc_available() || switch_pgsql_available()) {\r
- runtime.odbc_dsn = switch_core_strdup(runtime.memory_pool, val);\r
- } else {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC AND PGSQL ARE NOT AVAILABLE!\n");\r
- }\r
- } else if (!strcasecmp(var, "core-non-sqlite-db-required") && !zstr(val)) {\r
- switch_set_flag((&runtime), SCF_CORE_NON_SQLITE_DB_REQ);\r
- } else if (!strcasecmp(var, "core-dbtype") && !zstr(val)) {\r
- if (!strcasecmp(val, "MSSQL")) {\r
- runtime.odbc_dbtype = DBTYPE_MSSQL;\r
- } else {\r
- runtime.odbc_dbtype = DBTYPE_DEFAULT;\r
- }\r
-#ifdef ENABLE_ZRTP\r
- } else if (!strcasecmp(var, "rtp-enable-zrtp")) {\r
- switch_core_set_variable("zrtp_enabled", val);\r
-#endif\r
- } else if (!strcasecmp(var, "switchname") && !zstr(val)) {\r
- runtime.switchname = switch_core_strdup(runtime.memory_pool, val);\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Set switchname to %s\n", runtime.switchname);\r
- }\r
- }\r
- }\r
-\r
- if ((settings = switch_xml_child(cfg, "variables"))) {\r
- for (param = switch_xml_child(settings, "variable"); param; param = param->next) {\r
- const char *var = switch_xml_attr_soft(param, "name");\r
- const char *val = switch_xml_attr_soft(param, "value");\r
- if (var && val) {\r
- switch_core_set_variable(var, val);\r
- }\r
- }\r
- }\r
-\r
- switch_xml_free(xml);\r
- }\r
-\r
-\r
-}\r
-\r
-SWITCH_DECLARE(const char *) switch_core_banner(void)\r
-{\r
-\r
- return ("\n"\r
- ".=============================================================.\n"\r
- "| _____ ______ _____ _____ ____ _ _ |\n"\r
- "| | ___| __ ___ ___/ ___\\ \\ / /_ _|_ _/ ___| | | | |\n"\r
- "| | |_ | '__/ _ \\/ _ \\___ \\\\ \\ /\\ / / | | | || | | |_| | |\n"\r
- "| | _|| | | __/ __/___) |\\ V V / | | | || |___| _ | |\n"\r
- "| |_| |_| \\___|\\___|____/ \\_/\\_/ |___| |_| \\____|_| |_| |\n"\r
- "| |\n"\r
- ".=============================================================."\r
- "\n"\r
-\r
- "| Anthony Minessale II, Michael Jerris, Brian West, Others |\n"\r
- "| FreeSWITCH (http://www.freeswitch.org) |\n"\r
- "| Paypal Donations Appreciated: paypal@freeswitch.org |\n"\r
- "| Brought to you by ClueCon http://www.cluecon.com/ |\n" \r
- ".=============================================================.\n" \r
- "\n");\r
-}\r
-\r
-\r
-SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t flags, switch_bool_t console, const char **err)\r
-{\r
- switch_event_t *event;\r
- char *cmd;\r
- int x = 0;\r
- const char *use = NULL;\r
-#include "cc.h"\r
-\r
-\r
- if (switch_core_init(flags, console, err) != SWITCH_STATUS_SUCCESS) {\r
- return SWITCH_STATUS_GENERR;\r
- }\r
- \r
- if (runtime.runlevel > 1) {\r
- /* one per customer */\r
- return SWITCH_STATUS_SUCCESS;\r
- }\r
-\r
- runtime.runlevel++;\r
-\r
- switch_core_set_signal_handlers();\r
- switch_load_network_lists(SWITCH_FALSE);\r
-\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Bringing up environment.\n");\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Loading Modules.\n");\r
- if (switch_loadable_module_init(SWITCH_TRUE) != SWITCH_STATUS_SUCCESS) {\r
- *err = "Cannot load modules";\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error: %s\n", *err);\r
- return SWITCH_STATUS_GENERR;\r
- }\r
-\r
- switch_load_network_lists(SWITCH_FALSE);\r
-\r
- switch_load_core_config("post_load_switch.conf");\r
-\r
- switch_core_set_signal_handlers();\r
-\r
- if (switch_event_create(&event, SWITCH_EVENT_STARTUP) == SWITCH_STATUS_SUCCESS) {\r
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready");\r
- switch_event_fire(&event);\r
- }\r
-\r
- switch_core_screen_size(&x, NULL);\r
-\r
- use = (x > 100) ? cc : cc_s;\r
-\r
-#ifdef WIN32\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s\n\n", switch_core_banner(), use);\r
-#else\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "%s%s%s%s%s%s\n\n", \r
- SWITCH_SEQ_DEFAULT_COLOR,\r
- SWITCH_SEQ_FYELLOW, SWITCH_SEQ_BBLUE,\r
- switch_core_banner(), \r
- use, SWITCH_SEQ_DEFAULT_COLOR);\r
- \r
-#endif\r
-\r
-\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE,\r
- "\nFreeSWITCH Version %s (%s)\n\nFreeSWITCH Started\nMax Sessions [%u]\nSession Rate [%d]\nSQL [%s]\n",\r
- SWITCH_VERSION_FULL, SWITCH_VERSION_REVISION_HUMAN,\r
- switch_core_session_limit(0),\r
- switch_core_sessions_per_second(0), switch_test_flag((&runtime), SCF_USE_SQL) ? "Enabled" : "Disabled");\r
-\r
-\r
- if (x < 160) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\n[This app Best viewed at 160x60 or more..]\n");\r
- }\r
-\r
- switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS);\r
-\r
- if ((cmd = switch_core_get_variable_dup("api_on_startup"))) {\r
- switch_stream_handle_t stream = { 0 };\r
- SWITCH_STANDARD_STREAM(stream);\r
- switch_console_execute(cmd, 0, &stream);\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Startup command [%s] executed. Output:\n%s\n", cmd, (char *)stream.data);\r
- free(stream.data);\r
- free(cmd);\r
- }\r
-\r
- return SWITCH_STATUS_SUCCESS;\r
-\r
-}\r
-\r
-SWITCH_DECLARE(void) switch_core_measure_time(switch_time_t total_ms, switch_core_time_duration_t *duration)\r
-{\r
- switch_time_t temp = total_ms / 1000;\r
- memset(duration, 0, sizeof(*duration));\r
- duration->mms = (uint32_t) (total_ms % 1000);\r
- duration->ms = (uint32_t) (temp % 1000);\r
- temp = temp / 1000;\r
- duration->sec = (uint32_t) (temp % 60);\r
- temp = temp / 60;\r
- duration->min = (uint32_t) (temp % 60);\r
- temp = temp / 60;\r
- duration->hr = (uint32_t) (temp % 24);\r
- temp = temp / 24;\r
- duration->day = (uint32_t) (temp % 365);\r
- duration->yr = (uint32_t) (temp / 365);\r
-}\r
-\r
-SWITCH_DECLARE(switch_time_t) switch_core_uptime(void)\r
-{\r
- return switch_mono_micro_time_now() - runtime.mono_initiated;\r
-}\r
-\r
-\r
-#ifdef _MSC_VER\r
-static void win_shutdown(void)\r
-{\r
-\r
- HANDLE shutdown_event;\r
- char path[512];\r
- /* for windows we need the event to signal for shutting down a background FreeSWITCH */\r
- snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid());\r
-\r
- /* open the event so we can signal it */\r
- shutdown_event = OpenEvent(EVENT_MODIFY_STATE, FALSE, path);\r
-\r
- if (shutdown_event) {\r
- /* signal the event to shutdown */\r
- SetEvent(shutdown_event);\r
- /* cleanup */\r
- CloseHandle(shutdown_event);\r
- }\r
-}\r
-#endif\r
-\r
-SWITCH_DECLARE(void) switch_core_set_signal_handlers(void)\r
-{\r
- /* set signal handlers */\r
- signal(SIGINT, SIG_IGN);\r
-#ifndef WIN32\r
- if (switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC)) {\r
- signal(SIGCHLD, SIG_DFL);\r
- } else {\r
- signal(SIGCHLD, handle_SIGCHLD);\r
- }\r
-#endif\r
-#ifdef SIGPIPE\r
- signal(SIGPIPE, SIG_IGN);\r
-#endif\r
-#ifdef SIGQUIT\r
- signal(SIGQUIT, SIG_IGN);\r
-#endif\r
-#ifdef SIGPOLL\r
- signal(SIGPOLL, SIG_IGN);\r
-#endif\r
-#ifdef SIGIO\r
- signal(SIGIO, SIG_IGN);\r
-#endif\r
-#ifdef TRAP_BUS\r
- signal(SIGBUS, handle_SIGBUS);\r
-#endif\r
-#ifdef SIGUSR1\r
- signal(SIGUSR1, handle_SIGHUP);\r
-#endif\r
- signal(SIGHUP, handle_SIGHUP);\r
-}\r
-\r
-SWITCH_DECLARE(uint32_t) switch_core_debug_level(void)\r
-{\r
- return runtime.debug_level;\r
-}\r
-\r
-\r
-SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, void *val)\r
-{\r
- int *intval = (int *) val;\r
- int oldintval = 0, newintval = 0;\r
- \r
- if (intval) {\r
- oldintval = *intval;\r
- }\r
-\r
- if (switch_test_flag((&runtime), SCF_SHUTTING_DOWN)) {\r
- return -1;\r
- }\r
-\r
- switch (cmd) {\r
- case SCSC_RECOVER:\r
- {\r
- char *arg = (char *) val;\r
- char *tech = NULL, *prof = NULL;\r
- int r, flush = 0;\r
-\r
- if (!zstr(arg)) {\r
- tech = strdup(arg);\r
- \r
- if ((prof = strchr(tech, ':'))) {\r
- *prof++ = '\0';\r
- }\r
-\r
- if (!strcasecmp(tech, "flush")) {\r
- flush++;\r
-\r
- if (prof) {\r
- tech = prof;\r
- if ((prof = strchr(tech, ':'))) {\r
- *prof++ = '\0';\r
- }\r
- }\r
- }\r
-\r
- }\r
-\r
- if (flush) {\r
- switch_core_recovery_flush(tech, prof);\r
- r = -1;\r
- } else {\r
- r = switch_core_recovery_recover(tech, prof);\r
- }\r
-\r
- switch_safe_free(tech);\r
- return r;\r
-\r
- }\r
- break;\r
- case SCSC_DEBUG_SQL:\r
- {\r
- if (switch_test_flag((&runtime), SCF_DEBUG_SQL)) {\r
- switch_clear_flag((&runtime), SCF_DEBUG_SQL);\r
- newintval = 0;\r
- } else {\r
- switch_set_flag((&runtime), SCF_DEBUG_SQL);\r
- newintval = 1;\r
- }\r
- }\r
- break;\r
- case SCSC_VERBOSE_EVENTS:\r
- if (intval) {\r
- if (oldintval > -1) {\r
- if (oldintval) {\r
- switch_set_flag((&runtime), SCF_VERBOSE_EVENTS);\r
- } else {\r
- switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS);\r
- }\r
- }\r
- newintval = switch_test_flag((&runtime), SCF_VERBOSE_EVENTS);\r
- }\r
- break;\r
- case SCSC_API_EXPANSION:\r
- if (intval) {\r
- if (oldintval > -1) {\r
- if (oldintval) {\r
- switch_set_flag((&runtime), SCF_API_EXPANSION);\r
- } else {\r
- switch_clear_flag((&runtime), SCF_API_EXPANSION);\r
- }\r
- }\r
- newintval = switch_test_flag((&runtime), SCF_API_EXPANSION);\r
- }\r
- break;\r
- case SCSC_THREADED_SYSTEM_EXEC:\r
- if (intval) {\r
- if (oldintval > -1) {\r
- if (oldintval) {\r
- switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);\r
- } else {\r
- switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);\r
- }\r
- }\r
- newintval = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC);\r
- }\r
- break;\r
- case SCSC_CALIBRATE_CLOCK:\r
- switch_time_calibrate_clock();\r
- break;\r
- case SCSC_FLUSH_DB_HANDLES:\r
- switch_cache_db_flush_handles();\r
- break;\r
- case SCSC_SEND_SIGHUP:\r
- handle_SIGHUP(1);\r
- break;\r
- case SCSC_SYNC_CLOCK:\r
- switch_time_sync();\r
- newintval = 0;\r
- break;\r
- case SCSC_SYNC_CLOCK_WHEN_IDLE:\r
- newintval = switch_core_session_sync_clock();\r
- break;\r
- case SCSC_SQL:\r
- if (oldintval) {\r
- switch_core_sqldb_resume();\r
- } else {\r
- switch_core_sqldb_pause();\r
- }\r
- break;\r
- case SCSC_PAUSE_ALL:\r
- if (oldintval) {\r
- switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);\r
- } else {\r
- switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS);\r
- }\r
- break;\r
- case SCSC_PAUSE_INBOUND:\r
- if (oldintval) {\r
- switch_set_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS);\r
- } else {\r
- switch_clear_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS);\r
- }\r
- break;\r
- case SCSC_PAUSE_OUTBOUND:\r
- if (oldintval) {\r
- switch_set_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS);\r
- } else {\r
- switch_clear_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS);\r
- }\r
- break;\r
- case SCSC_HUPALL:\r
- switch_core_session_hupall(SWITCH_CAUSE_MANAGER_REQUEST);\r
- break;\r
- case SCSC_CANCEL_SHUTDOWN:\r
- switch_clear_flag((&runtime), SCF_SHUTDOWN_REQUESTED);\r
- break;\r
- case SCSC_SAVE_HISTORY:\r
- switch_console_save_history();\r
- break;\r
- case SCSC_CRASH:\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Declinatio Mortuus Obfirmo!\n");\r
- switch_console_save_history();\r
- abort();\r
- break;\r
- case SCSC_SHUTDOWN_NOW:\r
- switch_console_save_history();\r
- exit(0);\r
- break;\r
- case SCSC_SHUTDOWN_ELEGANT:\r
- case SCSC_SHUTDOWN_ASAP:\r
- {\r
- int x = 19;\r
- uint32_t count;\r
-\r
- switch_set_flag((&runtime), SCF_SHUTDOWN_REQUESTED);\r
- if (cmd == SCSC_SHUTDOWN_ASAP) {\r
- switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);\r
- }\r
-\r
- while (runtime.running && switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED) && (count = switch_core_session_count())) {\r
- switch_yield(500000);\r
- if (++x == 20) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,\r
- "Shutdown in progress, %u session(s) remain.\nShutting down %s\n",\r
- count, cmd == SCSC_SHUTDOWN_ASAP ? "ASAP" : "once there are no active calls.");\r
- x = 0;\r
- }\r
- }\r
-\r
- if (switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED)) {\r
- switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);\r
-#ifdef _MSC_VER\r
- win_shutdown();\r
-#endif\r
-\r
- if (oldintval) {\r
- switch_set_flag((&runtime), SCF_RESTART);\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Restarting\n");\r
- } else {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutting down\n");\r
-#ifdef _MSC_VER\r
- fclose(stdin);\r
-#endif\r
- }\r
- runtime.running = 0;\r
- } else {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutdown Cancelled\n");\r
- switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS);\r
- }\r
- }\r
- break;\r
- case SCSC_PAUSE_CHECK:\r
- newintval = !!(switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS) == SCF_NO_NEW_SESSIONS);\r
- break;\r
- case SCSC_PAUSE_INBOUND_CHECK:\r
- newintval = !!switch_test_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS);\r
- break;\r
- case SCSC_PAUSE_OUTBOUND_CHECK:\r
- newintval = !!switch_test_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS);\r
- break;\r
- case SCSC_READY_CHECK:\r
- newintval = switch_core_ready();\r
- break;\r
- case SCSC_SHUTDOWN_CHECK:\r
- newintval = !!switch_test_flag((&runtime), SCF_SHUTDOWN_REQUESTED);\r
- break;\r
- case SCSC_SHUTDOWN:\r
-\r
-#ifdef _MSC_VER\r
- win_shutdown();\r
-#endif\r
-\r
- if (oldintval) {\r
- switch_set_flag((&runtime), SCF_RESTART);\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Restarting\n");\r
- } else {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Shutting down\n");\r
-#ifdef _MSC_VER\r
- fclose(stdin);\r
-#endif\r
- }\r
- runtime.running = 0;\r
- break;\r
- case SCSC_CHECK_RUNNING:\r
- newintval = runtime.running;\r
- break;\r
- case SCSC_LOGLEVEL:\r
- if (oldintval > -1) {\r
- runtime.hard_log_level = oldintval;\r
- }\r
-\r
- if (runtime.hard_log_level > SWITCH_LOG_DEBUG) {\r
- runtime.hard_log_level = SWITCH_LOG_DEBUG;\r
- }\r
- newintval = runtime.hard_log_level;\r
- break;\r
- case SCSC_DEBUG_LEVEL:\r
- if (oldintval > -1) {\r
- if (oldintval > 10)\r
- newintval = 10;\r
- runtime.debug_level = oldintval;\r
- }\r
- newintval = runtime.debug_level;\r
- break;\r
- case SCSC_MIN_IDLE_CPU:\r
- {\r
- double *dval = (double *) val;\r
- if (dval) {\r
- *dval = switch_core_min_idle_cpu(*dval);\r
- }\r
- intval = NULL;\r
- }\r
- break;\r
- case SCSC_MAX_SESSIONS:\r
- newintval = switch_core_session_limit(oldintval);\r
- break;\r
- case SCSC_LAST_SPS:\r
- newintval = runtime.sps_last;\r
- break;\r
- case SCSC_MAX_DTMF_DURATION:\r
- newintval = switch_core_max_dtmf_duration(oldintval);\r
- break;\r
- case SCSC_MIN_DTMF_DURATION:\r
- newintval = switch_core_min_dtmf_duration(oldintval);\r
- break;\r
- case SCSC_DEFAULT_DTMF_DURATION:\r
- newintval = switch_core_default_dtmf_duration(oldintval);\r
- break;\r
- case SCSC_SPS:\r
- switch_mutex_lock(runtime.throttle_mutex);\r
- if (oldintval > 0) {\r
- runtime.sps_total = oldintval;\r
- }\r
- newintval = runtime.sps_total;\r
- switch_mutex_unlock(runtime.throttle_mutex);\r
- break;\r
-\r
- case SCSC_RECLAIM:\r
- switch_core_memory_reclaim_all();\r
- newintval = 0;\r
- break;\r
- }\r
-\r
- if (intval) {\r
- *intval = newintval;\r
- }\r
-\r
-\r
- return 0;\r
-}\r
-\r
-SWITCH_DECLARE(switch_core_flag_t) switch_core_flags(void)\r
-{\r
- return runtime.flags;\r
-}\r
-\r
-SWITCH_DECLARE(switch_bool_t) switch_core_ready(void)\r
-{\r
- return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS) == SCF_NO_NEW_SESSIONS) ? SWITCH_FALSE : SWITCH_TRUE;\r
-}\r
-\r
-SWITCH_DECLARE(switch_bool_t) switch_core_ready_inbound(void)\r
-{\r
- return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_INBOUND_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE;\r
-}\r
-\r
-SWITCH_DECLARE(switch_bool_t) switch_core_ready_outbound(void)\r
-{\r
- return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_OUTBOUND_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE;\r
-}\r
-\r
-SWITCH_DECLARE(switch_status_t) switch_core_destroy(void)\r
-{\r
- switch_event_t *event;\r
-\r
- if (switch_event_create(&event, SWITCH_EVENT_SHUTDOWN) == SWITCH_STATUS_SUCCESS) {\r
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Shutting Down");\r
- switch_event_fire(&event);\r
- }\r
-\r
- switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);\r
- switch_set_flag((&runtime), SCF_SHUTTING_DOWN);\r
-\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "End existing sessions\n");\r
- switch_core_session_hupall(SWITCH_CAUSE_SYSTEM_SHUTDOWN);\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Clean up modules.\n");\r
-\r
- switch_loadable_module_shutdown();\r
-\r
- switch_ssl_destroy_ssl_locks();\r
-\r
- if (switch_test_flag((&runtime), SCF_USE_SQL)) {\r
- switch_core_sqldb_stop();\r
- }\r
- switch_scheduler_task_thread_stop();\r
-\r
- switch_rtp_shutdown();\r
-\r
- if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) {\r
- switch_nat_shutdown();\r
- }\r
- switch_xml_destroy();\r
- switch_core_session_uninit();\r
- switch_console_shutdown();\r
-\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Closing Event Engine.\n");\r
- switch_event_shutdown();\r
-\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n");\r
- switch_log_shutdown();\r
-\r
- switch_core_unset_variables();\r
- switch_core_memory_stop();\r
-\r
- if (runtime.console && runtime.console != stdout && runtime.console != stderr) {\r
- fclose(runtime.console);\r
- runtime.console = NULL;\r
- }\r
-\r
- switch_safe_free(SWITCH_GLOBAL_dirs.base_dir);\r
- switch_safe_free(SWITCH_GLOBAL_dirs.mod_dir);\r
- switch_safe_free(SWITCH_GLOBAL_dirs.conf_dir);\r
- switch_safe_free(SWITCH_GLOBAL_dirs.log_dir);\r
- switch_safe_free(SWITCH_GLOBAL_dirs.db_dir);\r
- switch_safe_free(SWITCH_GLOBAL_dirs.script_dir);\r
- switch_safe_free(SWITCH_GLOBAL_dirs.htdocs_dir);\r
- switch_safe_free(SWITCH_GLOBAL_dirs.grammar_dir);\r
- switch_safe_free(SWITCH_GLOBAL_dirs.storage_dir);\r
- switch_safe_free(SWITCH_GLOBAL_dirs.recordings_dir);\r
- switch_safe_free(SWITCH_GLOBAL_dirs.sounds_dir);\r
- switch_safe_free(SWITCH_GLOBAL_dirs.run_dir);\r
- switch_safe_free(SWITCH_GLOBAL_dirs.temp_dir);\r
-\r
- switch_event_destroy(&runtime.global_vars);\r
- switch_core_hash_destroy(&runtime.ptimes);\r
- switch_core_hash_destroy(&runtime.mime_types);\r
-\r
- if (IP_LIST.hash) {\r
- switch_core_hash_destroy(&IP_LIST.hash);\r
- }\r
-\r
- if (IP_LIST.pool) {\r
- switch_core_destroy_memory_pool(&IP_LIST.pool);\r
- }\r
-\r
- if (runtime.memory_pool) {\r
- apr_pool_destroy(runtime.memory_pool);\r
- apr_terminate();\r
- }\r
-\r
- return switch_test_flag((&runtime), SCF_RESTART) ? SWITCH_STATUS_RESTART : SWITCH_STATUS_SUCCESS;\r
-}\r
-\r
-SWITCH_DECLARE(switch_status_t) switch_core_management_exec(char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen)\r
-{\r
- const switch_management_interface_t *ptr;\r
- switch_status_t status = SWITCH_STATUS_FALSE;\r
-\r
- if ((ptr = switch_loadable_module_get_management_interface(relative_oid))) {\r
- status = ptr->management_function(relative_oid, action, data, datalen);\r
- }\r
-\r
- return status;\r
-}\r
-\r
-SWITCH_DECLARE(void) switch_core_memory_reclaim_all(void)\r
-{\r
- switch_core_memory_reclaim_logger();\r
- switch_core_memory_reclaim_events();\r
- switch_core_memory_reclaim();\r
-}\r
-\r
-\r
-struct system_thread_handle {\r
- const char *cmd;\r
- switch_thread_cond_t *cond;\r
- switch_mutex_t *mutex;\r
- switch_memory_pool_t *pool;\r
- int ret;\r
- int *fds;\r
-};\r
-\r
-static void *SWITCH_THREAD_FUNC system_thread(switch_thread_t *thread, void *obj)\r
-{\r
- struct system_thread_handle *sth = (struct system_thread_handle *) obj;\r
-\r
-#if 0 // if we are a luser we can never turn this back down, didn't we already set the stack size?\r
-#if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__)\r
- struct rlimit rlim;\r
-\r
- rlim.rlim_cur = SWITCH_SYSTEM_THREAD_STACKSIZE;\r
- rlim.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE;\r
- if (setrlimit(RLIMIT_STACK, &rlim) < 0) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno));\r
- }\r
-#endif\r
-#endif\r
-\r
- if (sth->fds) {\r
- dup2(sth->fds[1], STDOUT_FILENO);\r
- }\r
-\r
- sth->ret = system(sth->cmd);\r
-\r
-#if 0\r
-#if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__)\r
- rlim.rlim_cur = SWITCH_THREAD_STACKSIZE;\r
- rlim.rlim_max = SWITCH_SYSTEM_THREAD_STACKSIZE;\r
- if (setrlimit(RLIMIT_STACK, &rlim) < 0) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Setting stack size failed! (%s)\n", strerror(errno));\r
- }\r
-#endif\r
-#endif\r
-\r
- switch_mutex_lock(sth->mutex);\r
- switch_thread_cond_signal(sth->cond);\r
- switch_mutex_unlock(sth->mutex);\r
-\r
- switch_core_destroy_memory_pool(&sth->pool);\r
-\r
- return NULL;\r
-}\r
-\r
-\r
-static int switch_system_thread(const char *cmd, switch_bool_t wait)\r
-{\r
- switch_thread_t *thread;\r
- switch_threadattr_t *thd_attr;\r
- int ret = 0;\r
- struct system_thread_handle *sth;\r
- switch_memory_pool_t *pool;\r
-\r
- if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Pool Failure\n");\r
- return 1;\r
- }\r
-\r
- if (!(sth = switch_core_alloc(pool, sizeof(struct system_thread_handle)))) {\r
- switch_core_destroy_memory_pool(&pool);\r
- return 1;\r
- }\r
-\r
- sth->pool = pool;\r
- sth->cmd = switch_core_strdup(pool, cmd);\r
-\r
- switch_thread_cond_create(&sth->cond, sth->pool);\r
- switch_mutex_init(&sth->mutex, SWITCH_MUTEX_NESTED, sth->pool);\r
- switch_mutex_lock(sth->mutex);\r
-\r
- switch_threadattr_create(&thd_attr, sth->pool);\r
- switch_threadattr_stacksize_set(thd_attr, SWITCH_SYSTEM_THREAD_STACKSIZE);\r
- switch_threadattr_detach_set(thd_attr, 1);\r
- switch_thread_create(&thread, thd_attr, system_thread, sth, sth->pool);\r
-\r
- if (wait) {\r
- switch_thread_cond_wait(sth->cond, sth->mutex);\r
- ret = sth->ret;\r
- }\r
- switch_mutex_unlock(sth->mutex);\r
-\r
- return ret;\r
-}\r
-\r
-SWITCH_DECLARE(int) switch_max_file_desc(void)\r
-{\r
- int max = 0;\r
-\r
-#ifndef WIN32\r
-#if defined(HAVE_GETDTABLESIZE)\r
- max = getdtablesize();\r
-#else\r
- max = sysconf(_SC_OPEN_MAX);\r
-#endif\r
-#endif\r
-\r
- return max;\r
-\r
-}\r
-\r
-SWITCH_DECLARE(void) switch_close_extra_files(int *keep, int keep_ttl)\r
-{\r
- int open_max = switch_max_file_desc();\r
- int i, j;\r
-\r
- for (i = 3; i < open_max; i++) {\r
- if (keep) {\r
- for (j = 0; j < keep_ttl; j++) {\r
- if (i == keep[j]) {\r
- goto skip;\r
- }\r
- }\r
- }\r
-\r
- close(i);\r
-\r
- skip:\r
-\r
- continue;\r
-\r
- }\r
-}\r
-\r
-\r
-#ifdef WIN32\r
-static int switch_system_fork(const char *cmd, switch_bool_t wait)\r
-{\r
- return switch_system_thread(cmd, wait);\r
-}\r
-\r
-SWITCH_DECLARE(pid_t) switch_fork(void)\r
-{\r
- return -1;\r
-}\r
-\r
-\r
-#else\r
-\r
-SWITCH_DECLARE(pid_t) switch_fork(void)\r
-{\r
- int i = fork();\r
-\r
- if (!i) {\r
- set_low_priority();\r
- }\r
-\r
- return i;\r
-}\r
-\r
-\r
-\r
-static int switch_system_fork(const char *cmd, switch_bool_t wait)\r
-{\r
- int pid;\r
- char *dcmd = strdup(cmd);\r
-\r
- switch_core_set_signal_handlers();\r
-\r
- pid = switch_fork();\r
- \r
- if (pid) {\r
- if (wait) {\r
- waitpid(pid, NULL, 0);\r
- }\r
- free(dcmd);\r
- } else {\r
- switch_close_extra_files(NULL, 0);\r
- \r
- if (system(dcmd) == -1) {\r
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to execute because of a command error : %s\n", dcmd);\r
- }\r
- free(dcmd);\r
- exit(0);\r
- }\r
-\r
- return 0;\r
-}\r
-#endif\r
-\r
-\r
-\r
-SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait)\r
-{\r
- int (*sys_p)(const char *cmd, switch_bool_t wait);\r
-\r
- sys_p = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC) ? switch_system_thread : switch_system_fork;\r
-\r
- return sys_p(cmd, wait);\r
-\r
-}\r
-\r
-\r
-\r
-SWITCH_DECLARE(int) switch_stream_system_fork(const char *cmd, switch_stream_handle_t *stream)\r
-{\r
-#ifdef WIN32\r
- return switch_system(cmd, SWITCH_TRUE);\r
-#else\r
- int fds[2], pid = 0;\r
-\r
- if (pipe(fds)) {\r
- goto end;\r
- } else { /* good to go */\r
- pid = switch_fork();\r
-\r
- if (pid < 0) { /* ok maybe not */\r
- close(fds[0]);\r
- close(fds[1]);\r
- goto end;\r
- } else if (pid) { /* parent */\r
- char buf[1024] = "";\r
- int bytes;\r
- close(fds[1]);\r
- while ((bytes = read(fds[0], buf, sizeof(buf))) > 0) {\r
- stream->raw_write_function(stream, (unsigned char *)buf, bytes);\r
- }\r
- close(fds[0]);\r
- waitpid(pid, NULL, 0);\r
- } else { /* child */\r
- switch_close_extra_files(fds, 2);\r
- close(fds[0]);\r
- dup2(fds[1], STDOUT_FILENO);\r
- switch_system(cmd, SWITCH_TRUE);\r
- close(fds[1]);\r
- exit(0);\r
- }\r
- }\r
-\r
- end:\r
-\r
- return 0;\r
-\r
-#endif\r
-\r
-}\r
-\r
-SWITCH_DECLARE(switch_status_t) switch_core_get_stacksizes(switch_size_t *cur, switch_size_t *max)\r
-{\r
-#ifdef HAVE_SETRLIMIT\r
- struct rlimit rlp;\r
-\r
- memset(&rlp, 0, sizeof(rlp));\r
- getrlimit(RLIMIT_STACK, &rlp);\r
-\r
- *cur = rlp.rlim_cur;\r
- *max = rlp.rlim_max;\r
-\r
- return SWITCH_STATUS_SUCCESS;\r
-\r
-#else\r
-\r
- return SWITCH_STATUS_FALSE;\r
-\r
-#endif\r
-\r
-\r
-\r
-}\r
-\r
-\r
-SWITCH_DECLARE(int) switch_stream_system(const char *cmd, switch_stream_handle_t *stream)\r
-{\r
-#ifdef WIN32\r
- stream->write_function(stream, "Capturing output not supported.\n");\r
- return switch_system(cmd, SWITCH_TRUE);\r
-#else\r
- return switch_stream_system_fork(cmd, stream);\r
-#endif\r
-\r
-}\r
-\r
-/* For Emacs:\r
- * Local Variables:\r
- * mode:c\r
- * indent-tabs-mode:t\r
- * tab-width:4\r
- * c-basic-offset:4\r
- * End:\r
- * For VIM:\r
- * vim:set softtabstop=4 shiftwidth=4 tabstop=4:\r
- */\r
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
+ *
+ * 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 <anthm@freeswitch.org>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Anthony Minessale II <anthm@freeswitch.org>
+ * Michael Jerris <mike@jerris.com>
+ * Paul D. Tinsley <pdt at jackhammer.org>
+ * Marcel Barbulescu <marcelbarbulescu@gmail.com>
+ * Joseph Sullivan <jossulli@amazon.com>
+ *
+ *
+ * switch_core.c -- Main Core Library
+ *
+ */
+
+
+
+#include <switch.h>
+#include <switch_ssl.h>
+#include <switch_stun.h>
+#include <switch_nat.h>
+#include <switch_version.h>
+#include "private/switch_core_pvt.h"
+#include <switch_curl.h>
+#ifndef WIN32
+#include <switch_private.h>
+#ifdef HAVE_SETRLIMIT
+#include <sys/resource.h>
+#endif
+#endif
+#include <errno.h>
+
+
+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 <sys/ioctl.h>
+#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:
+ */