-/*
- * 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:
- */
+/* \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