2005-11-19 20:07:43 +00:00
|
|
|
/*
|
|
|
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
|
|
|
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
|
|
|
|
*
|
|
|
|
* 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 <anthmct@yahoo.com>
|
|
|
|
* Portions created by the Initial Developer are Copyright (C)
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
|
|
|
* Anthony Minessale II <anthmct@yahoo.com>
|
2006-09-18 05:08:55 +00:00
|
|
|
* Michael Jerris <mike@jerris.com>
|
|
|
|
* Paul D. Tinsley <pdt at jackhammer.org>
|
2007-04-07 03:07:43 +00:00
|
|
|
* Marcel Barbulescu <marcelbarbulescu@gmail.com>
|
2005-11-19 20:07:43 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* switch_core.c -- Main Core Library
|
|
|
|
*
|
|
|
|
*/
|
2006-04-12 15:25:26 +00:00
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
#include <switch.h>
|
2006-08-19 18:51:22 +00:00
|
|
|
#include <switch_version.h>
|
2007-05-14 17:10:46 +00:00
|
|
|
#include "private/switch_core_pvt.h"
|
2007-12-18 17:00:42 +00:00
|
|
|
#ifndef WIN32
|
2007-12-18 16:55:39 +00:00
|
|
|
#include <switch_private.h>
|
2007-12-18 17:00:42 +00:00
|
|
|
#endif
|
2006-02-28 21:21:48 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
SWITCH_DECLARE_DATA switch_directories SWITCH_GLOBAL_dirs = { 0 };
|
2007-03-28 23:37:12 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
/* The main runtime obj we keep this hidden for ourselves */
|
2007-05-10 16:56:29 +00:00
|
|
|
struct switch_runtime runtime;
|
2005-12-21 22:25:22 +00:00
|
|
|
|
2007-03-28 23:37:12 +00:00
|
|
|
static void send_heartbeat(void)
|
|
|
|
{
|
|
|
|
switch_event_t *event;
|
|
|
|
switch_core_time_duration_t duration;
|
|
|
|
|
|
|
|
switch_core_measure_time(switch_core_uptime(), &duration);
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2007-03-28 23:37:12 +00:00
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_HEARTBEAT) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Ready");
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Up-Time",
|
2007-03-28 23:37:12 +00:00
|
|
|
"%u year%s, "
|
|
|
|
"%u day%s, "
|
|
|
|
"%u hour%s, "
|
|
|
|
"%u minute%s, "
|
|
|
|
"%u second%s, "
|
|
|
|
"%u millisecond%s, "
|
2007-06-12 01:24:29 +00:00
|
|
|
"%u microsecond%s",
|
2007-03-28 23:37:12 +00:00
|
|
|
duration.yr, duration.yr == 1 ? "" : "s",
|
|
|
|
duration.day, duration.day == 1 ? "" : "s",
|
2007-03-29 22:31:56 +00:00
|
|
|
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");
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Count", "%u", switch_core_session_count());
|
2008-01-07 17:10:48 +00:00
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Session-Per-Sec", "%u", runtime.sps);
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_event_fire(&event);
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-05-12 21:43:41 +00:00
|
|
|
SWITCH_STANDARD_SCHED_FUNC(heartbeat_callback)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-03-29 22:31:56 +00:00
|
|
|
send_heartbeat();
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
/* reschedule this task */
|
2008-01-11 00:43:49 +00:00
|
|
|
task->runtime = switch_timestamp(NULL) + 20;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-05-12 14:48:14 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_set_console(const char *console)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-03-29 22:31:56 +00:00
|
|
|
if ((runtime.console = fopen(console, "a")) == 0) {
|
|
|
|
fprintf(stderr, "Cannot open output file %s.\n", console);
|
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
2006-03-27 17:42:59 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
SWITCH_DECLARE(FILE *) switch_core_get_console(void)
|
|
|
|
{
|
|
|
|
return runtime.console;
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel_t channel)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-03-29 22:31:56 +00:00
|
|
|
FILE *handle = stdout;
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
switch (channel) {
|
|
|
|
case SWITCH_CHANNEL_ID_LOG:
|
|
|
|
case SWITCH_CHANNEL_ID_LOG_CLEAN:
|
|
|
|
handle = runtime.console;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
handle = runtime.console;
|
|
|
|
break;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
return handle;
|
|
|
|
}
|
2006-07-07 18:59:14 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
SWITCH_DECLARE(int) switch_core_add_state_handler(const switch_state_handler_table_t *state_handler)
|
|
|
|
{
|
|
|
|
int index = runtime.state_handler_index++;
|
2006-07-07 18:59:14 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
if (runtime.state_handler_index >= SWITCH_MAX_STATE_HANDLERS) {
|
|
|
|
return -1;
|
2006-09-20 20:25:26 +00:00
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
runtime.state_handlers[index] = state_handler;
|
|
|
|
return index;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
SWITCH_DECLARE(const switch_state_handler_table_t *) switch_core_get_state_handler(int index)
|
|
|
|
{
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2007-12-17 20:44:48 +00:00
|
|
|
if (index >= SWITCH_MAX_STATE_HANDLERS || index > runtime.state_handler_index) {
|
2005-11-19 20:07:43 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
return runtime.state_handlers[index];
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2007-05-12 14:48:14 +00:00
|
|
|
SWITCH_DECLARE(char *) switch_core_get_variable(const char *varname)
|
2006-09-18 22:22:25 +00:00
|
|
|
{
|
2007-11-09 15:55:40 +00:00
|
|
|
char *val;
|
2007-12-22 00:32:20 +00:00
|
|
|
switch_mutex_lock(runtime.global_mutex);
|
2007-11-09 15:55:40 +00:00
|
|
|
val = (char *) switch_core_hash_find(runtime.global_vars, varname);
|
2007-12-22 00:32:20 +00:00
|
|
|
switch_mutex_unlock(runtime.global_mutex);
|
2007-11-09 15:55:40 +00:00
|
|
|
return val;
|
2006-09-18 22:22:25 +00:00
|
|
|
}
|
|
|
|
|
2007-05-12 14:48:14 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_set_variable(const char *varname, const char *value)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-11-09 15:55:40 +00:00
|
|
|
char *val;
|
|
|
|
|
2007-11-09 16:12:11 +00:00
|
|
|
if (varname) {
|
2007-12-22 00:32:20 +00:00
|
|
|
switch_mutex_lock(runtime.global_mutex);
|
2007-11-09 16:12:11 +00:00
|
|
|
val = (char *) switch_core_hash_find(runtime.global_vars, varname);
|
|
|
|
if (val) {
|
|
|
|
free(val);
|
|
|
|
}
|
|
|
|
if (value) {
|
|
|
|
switch_core_hash_insert(runtime.global_vars, varname, strdup(value));
|
|
|
|
} else {
|
|
|
|
switch_core_hash_delete(runtime.global_vars, varname);
|
|
|
|
}
|
2007-12-22 00:32:20 +00:00
|
|
|
switch_mutex_unlock(runtime.global_mutex);
|
2007-11-09 15:55:40 +00:00
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
SWITCH_DECLARE(char *) switch_core_get_uuid(void)
|
2007-02-23 16:42:40 +00:00
|
|
|
{
|
2007-03-29 22:31:56 +00:00
|
|
|
return runtime.uuid_str;
|
|
|
|
}
|
2007-02-23 16:42:40 +00:00
|
|
|
|
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
static void *switch_core_service_thread(switch_thread_t * thread, void *obj)
|
2007-03-29 22:31:56 +00:00
|
|
|
{
|
|
|
|
switch_core_thread_session_t *data = obj;
|
|
|
|
switch_core_session_t *session = data->objs[0];
|
|
|
|
int *stream_id_p = data->objs[1];
|
|
|
|
switch_channel_t *channel;
|
|
|
|
switch_frame_t *read_frame;
|
|
|
|
int stream_id = *stream_id_p;
|
2007-02-23 16:42:40 +00:00
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(thread != NULL);
|
|
|
|
switch_assert(session != NULL);
|
2007-03-29 22:31:56 +00:00
|
|
|
channel = switch_core_session_get_channel(session);
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(channel != NULL);
|
2007-02-23 16:42:40 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_channel_set_flag(channel, CF_SERVICE);
|
|
|
|
while (data->running > 0) {
|
|
|
|
switch (switch_core_session_read_frame(session, &read_frame, -1, stream_id)) {
|
|
|
|
case SWITCH_STATUS_SUCCESS:
|
|
|
|
case SWITCH_STATUS_TIMEOUT:
|
|
|
|
case SWITCH_STATUS_BREAK:
|
2007-02-23 16:42:40 +00:00
|
|
|
break;
|
2007-03-29 22:31:56 +00:00
|
|
|
default:
|
|
|
|
data->running = -1;
|
|
|
|
continue;
|
2007-02-23 16:42:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_channel_clear_flag(channel, CF_SERVICE);
|
|
|
|
data->running = 0;
|
|
|
|
return NULL;
|
2007-02-23 16:42:40 +00:00
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
/* 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_thread_session_t *thread_session)
|
2005-12-21 22:25:22 +00:00
|
|
|
{
|
2007-03-29 22:31:56 +00:00
|
|
|
if (thread_session->running > 0) {
|
|
|
|
thread_session->running = -1;
|
2006-04-26 17:18:33 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
while (thread_session->running) {
|
|
|
|
switch_yield(1000);
|
2006-04-26 17:18:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-04-04 21:26:21 +00:00
|
|
|
|
2007-03-30 00:13:31 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_service_session(switch_core_session_t *session, switch_core_thread_session_t *thread_session, int stream_id)
|
2006-04-26 17:18:33 +00:00
|
|
|
{
|
2007-03-29 22:31:56 +00:00
|
|
|
thread_session->running = 1;
|
|
|
|
thread_session->objs[0] = session;
|
|
|
|
thread_session->objs[1] = &stream_id;
|
|
|
|
switch_core_session_launch_thread(session, switch_core_service_thread, thread_session);
|
|
|
|
}
|
2006-09-18 22:22:25 +00:00
|
|
|
|
2007-02-22 17:38:34 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
/* 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.
|
2006-09-18 22:22:25 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
This thread is expected to never exit until the application exits so the func is responsible
|
|
|
|
to make sure that is the case.
|
2006-09-18 22:22:25 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
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.
|
2006-04-26 17:18:33 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
*/
|
2006-04-26 17:18:33 +00:00
|
|
|
|
2007-03-30 00:15:25 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_launch_thread(switch_thread_start_t func, void *obj, switch_memory_pool_t *pool)
|
2006-04-26 17:18:33 +00:00
|
|
|
{
|
2006-04-29 01:00:52 +00:00
|
|
|
switch_thread_t *thread;
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_threadattr_t *thd_attr = NULL;
|
|
|
|
switch_core_thread_session_t *ts;
|
|
|
|
int mypool;
|
2006-04-26 17:18:33 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
mypool = pool ? 0 : 1;
|
2006-04-26 17:18:33 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
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;
|
|
|
|
}
|
2006-04-26 17:18:33 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_threadattr_create(&thd_attr, pool);
|
|
|
|
switch_threadattr_detach_set(thd_attr, 1);
|
2006-04-04 21:26:21 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
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;
|
2007-02-23 20:13:15 +00:00
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
ts->objs[0] = obj;
|
|
|
|
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
|
|
|
switch_thread_create(&thread, thd_attr, func, ts, pool);
|
2005-12-21 22:25:22 +00:00
|
|
|
}
|
2006-04-04 21:26:21 +00:00
|
|
|
|
2005-12-21 22:25:22 +00:00
|
|
|
}
|
2007-03-11 01:07:47 +00:00
|
|
|
|
2006-03-01 17:06:10 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_set_globals(void)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2007-10-16 17:30:42 +00:00
|
|
|
char *dir_path;
|
2006-08-20 03:04:55 +00:00
|
|
|
#define BUFSIZE 1024
|
2007-03-11 01:07:47 +00:00
|
|
|
#ifdef WIN32
|
2007-03-29 22:31:56 +00:00
|
|
|
char lpPathBuffer[BUFSIZE];
|
|
|
|
DWORD dwBufSize = BUFSIZE;
|
2007-03-11 01:07:47 +00:00
|
|
|
char base_dir[1024];
|
2006-08-20 03:04:55 +00:00
|
|
|
char *lastbacklash;
|
2007-03-29 22:31:56 +00:00
|
|
|
GetModuleFileName(NULL, base_dir, BUFSIZE);
|
|
|
|
lastbacklash = strrchr(base_dir, '\\');
|
2007-03-11 01:07:47 +00:00
|
|
|
base_dir[(lastbacklash - base_dir)] = '\0';
|
|
|
|
#else
|
|
|
|
char base_dir[1024] = SWITCH_PREFIX_DIR;
|
|
|
|
#endif
|
|
|
|
|
2006-08-20 03:36:14 +00:00
|
|
|
if (!SWITCH_GLOBAL_dirs.base_dir && (SWITCH_GLOBAL_dirs.base_dir = (char *) malloc(BUFSIZE))) {
|
2007-03-11 01:07:47 +00:00
|
|
|
switch_snprintf(SWITCH_GLOBAL_dirs.base_dir, BUFSIZE, "%s", base_dir);
|
2006-08-20 03:04:55 +00:00
|
|
|
}
|
2007-03-11 01:07:47 +00:00
|
|
|
|
2006-08-20 03:36:14 +00:00
|
|
|
if (!SWITCH_GLOBAL_dirs.mod_dir && (SWITCH_GLOBAL_dirs.mod_dir = (char *) malloc(BUFSIZE))) {
|
2007-03-11 01:07:47 +00:00
|
|
|
#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
|
2006-08-20 03:04:55 +00:00
|
|
|
}
|
2007-03-11 01:07:47 +00:00
|
|
|
|
2006-08-20 03:36:14 +00:00
|
|
|
if (!SWITCH_GLOBAL_dirs.conf_dir && (SWITCH_GLOBAL_dirs.conf_dir = (char *) malloc(BUFSIZE))) {
|
2007-03-11 01:07:47 +00:00
|
|
|
#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
|
2006-08-20 03:04:55 +00:00
|
|
|
}
|
2007-03-11 01:07:47 +00:00
|
|
|
|
2006-08-20 03:36:14 +00:00
|
|
|
if (!SWITCH_GLOBAL_dirs.log_dir && (SWITCH_GLOBAL_dirs.log_dir = (char *) malloc(BUFSIZE))) {
|
2007-03-11 01:07:47 +00:00
|
|
|
#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
|
2006-08-20 03:04:55 +00:00
|
|
|
}
|
2007-03-11 01:07:47 +00:00
|
|
|
|
2007-10-12 03:28:59 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2006-08-20 03:36:14 +00:00
|
|
|
if (!SWITCH_GLOBAL_dirs.db_dir && (SWITCH_GLOBAL_dirs.db_dir = (char *) malloc(BUFSIZE))) {
|
2007-03-11 01:07:47 +00:00
|
|
|
#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
|
2006-08-20 03:04:55 +00:00
|
|
|
}
|
2007-03-11 01:07:47 +00:00
|
|
|
|
2006-08-20 03:36:14 +00:00
|
|
|
if (!SWITCH_GLOBAL_dirs.script_dir && (SWITCH_GLOBAL_dirs.script_dir = (char *) malloc(BUFSIZE))) {
|
2007-03-11 01:07:47 +00:00
|
|
|
#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
|
2006-08-20 03:04:55 +00:00
|
|
|
}
|
2007-03-11 01:07:47 +00:00
|
|
|
|
2006-08-20 03:36:14 +00:00
|
|
|
if (!SWITCH_GLOBAL_dirs.htdocs_dir && (SWITCH_GLOBAL_dirs.htdocs_dir = (char *) malloc(BUFSIZE))) {
|
2007-03-11 01:07:47 +00:00
|
|
|
#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
|
2006-11-09 05:39:04 +00:00
|
|
|
}
|
2007-03-11 01:07:47 +00:00
|
|
|
|
|
|
|
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);
|
2006-08-20 03:04:55 +00:00
|
|
|
#else
|
2007-03-11 01:07:47 +00:00
|
|
|
switch_snprintf(SWITCH_GLOBAL_dirs.grammar_dir, BUFSIZE, "%s%sgrammar", base_dir, SWITCH_PATH_SEPARATOR);
|
2006-08-20 03:04:55 +00:00
|
|
|
#endif
|
2007-03-11 01:07:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!SWITCH_GLOBAL_dirs.temp_dir && (SWITCH_GLOBAL_dirs.temp_dir = (char *) malloc(BUFSIZE))) {
|
2006-03-01 06:25:56 +00:00
|
|
|
#ifdef SWITCH_TEMP_DIR
|
2007-03-11 01:07:47 +00:00
|
|
|
switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", SWITCH_TEMP_DIR);
|
2006-03-01 06:25:56 +00:00
|
|
|
#else
|
|
|
|
#ifdef WIN32
|
2007-03-11 01:07:47 +00:00
|
|
|
GetTempPath(dwBufSize, lpPathBuffer);
|
|
|
|
switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", lpPathBuffer);
|
2006-03-01 06:25:56 +00:00
|
|
|
#else
|
2007-03-11 01:07:47 +00:00
|
|
|
switch_snprintf(SWITCH_GLOBAL_dirs.temp_dir, BUFSIZE, "%s", "/tmp/");
|
2006-03-01 06:25:56 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
2007-03-11 01:07:47 +00:00
|
|
|
}
|
|
|
|
|
2007-10-16 17:30:42 +00:00
|
|
|
|
|
|
|
dir_path = switch_mprintf("%s%ssounds", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR);
|
|
|
|
switch_dir_make_recursive(dir_path,
|
|
|
|
SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE | SWITCH_FPROT_UEXECUTE | SWITCH_FPROT_GREAD | SWITCH_FPROT_GEXECUTE,
|
|
|
|
runtime.memory_pool);
|
|
|
|
switch_safe_free(dir_path);
|
2007-12-28 15:48:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
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.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.temp_dir, SWITCH_DEFAULT_DIR_PERMS, runtime.memory_pool);
|
|
|
|
|
|
|
|
|
|
|
|
|
2006-03-01 17:06:10 +00:00
|
|
|
}
|
|
|
|
|
2006-07-07 18:59:14 +00:00
|
|
|
|
2006-09-20 20:25:26 +00:00
|
|
|
SWITCH_DECLARE(int32_t) set_high_priority(void)
|
|
|
|
{
|
2007-10-23 15:56:23 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
|
|
|
|
#else
|
|
|
|
|
|
|
|
#ifdef USE_SETRLIMIT
|
|
|
|
struct rlimit lim = { RLIM_INFINITY, RLIM_INFINITY };
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef USE_SCHED_SETSCHEDULER
|
|
|
|
/*
|
|
|
|
* Try to use a round-robin scheduler
|
|
|
|
* with a fallback if that does not work
|
|
|
|
*/
|
2007-03-29 22:31:56 +00:00
|
|
|
struct sched_param sched = { 0 };
|
2006-09-20 20:25:26 +00:00
|
|
|
sched.sched_priority = 1;
|
|
|
|
if (sched_setscheduler(0, SCHED_RR, &sched)) {
|
2007-03-29 22:31:56 +00:00
|
|
|
sched.sched_priority = 0;
|
|
|
|
if (sched_setscheduler(0, SCHED_OTHER, &sched)) {
|
2006-09-20 20:25:26 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-10-23 15:56:23 +00:00
|
|
|
#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");
|
|
|
|
}
|
2006-09-20 20:25:26 +00:00
|
|
|
#else
|
2007-10-23 15:56:23 +00:00
|
|
|
if (nice(-10) != -10) {
|
2007-09-21 18:49:14 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n");
|
|
|
|
}
|
2006-09-20 20:25:26 +00:00
|
|
|
#endif
|
|
|
|
|
2007-10-23 15:56:23 +00:00
|
|
|
#ifdef USE_SETRLIMIT
|
|
|
|
/*
|
|
|
|
* The amount of memory which can be mlocked is limited for non-root users.
|
|
|
|
* FS will segfault (= hitting the limit) soon after mlockall has been called
|
|
|
|
* and we've switched to a different user.
|
|
|
|
* So let's try to remove the mlock limit here...
|
|
|
|
*/
|
|
|
|
if (setrlimit(RLIMIT_MEMLOCK, &lim) < 0) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT,
|
|
|
|
"Failed to disable memlock limit, application may crash if run as non-root user!\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-09-20 20:25:26 +00:00
|
|
|
#ifdef USE_MLOCKALL
|
2007-10-23 15:56:23 +00:00
|
|
|
/*
|
|
|
|
* Pin memory pages to RAM to prevent being swapped to disk
|
|
|
|
*/
|
2007-03-29 22:31:56 +00:00
|
|
|
mlockall(MCL_CURRENT | MCL_FUTURE);
|
2006-09-20 20:25:26 +00:00
|
|
|
#endif
|
2007-10-23 15:56:23 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
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) {
|
|
|
|
#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;
|
|
|
|
}
|
|
|
|
}
|
2006-09-20 20:25:26 +00:00
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(void) switch_core_runtime_loop(int bg)
|
|
|
|
{
|
2006-09-20 20:47:28 +00:00
|
|
|
#ifdef WIN32
|
|
|
|
HANDLE shutdown_event;
|
|
|
|
char path[256] = "";
|
|
|
|
#endif
|
2006-09-20 20:25:26 +00:00
|
|
|
if (bg) {
|
|
|
|
bg = 0;
|
|
|
|
#ifdef WIN32
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(path, sizeof(path), "Global\\Freeswitch.%d", getpid());
|
2007-03-29 22:31:56 +00:00
|
|
|
shutdown_event = CreateEvent(NULL, FALSE, FALSE, path);
|
2007-12-11 21:31:57 +00:00
|
|
|
if (shutdown_event) {
|
|
|
|
WaitForSingleObject(shutdown_event, INFINITE);
|
|
|
|
}
|
2006-09-20 20:25:26 +00:00
|
|
|
#else
|
|
|
|
runtime.running = 1;
|
2007-03-29 22:31:56 +00:00
|
|
|
while (runtime.running) {
|
2006-09-20 20:25:26 +00:00
|
|
|
switch_yield(1000000);
|
|
|
|
}
|
|
|
|
#endif
|
2007-03-29 22:31:56 +00:00
|
|
|
} else {
|
2006-09-20 20:25:26 +00:00
|
|
|
/* wait for console input */
|
|
|
|
switch_console_loop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-26 23:41:00 +00:00
|
|
|
SWITCH_DECLARE(const char *) switch_core_mime_ext2type(const char *ext)
|
|
|
|
{
|
2007-11-28 19:56:25 +00:00
|
|
|
if (!ext) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-11-26 23:41:00 +00:00
|
|
|
return (const char *) switch_core_hash_find(runtime.mime_types, ext);
|
|
|
|
}
|
|
|
|
|
2007-11-28 20:44:18 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_hash_index_t *) switch_core_mime_index(void)
|
|
|
|
{
|
|
|
|
return switch_hash_first(NULL, runtime.mime_types);
|
|
|
|
}
|
|
|
|
|
2007-11-26 23:41:00 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_mime_add_type(const char *type, const char *ext)
|
|
|
|
{
|
|
|
|
const char *check = (const char *) switch_core_hash_find(runtime.mime_types, ext);
|
|
|
|
switch_status_t status = SWITCH_STATUS_FALSE;
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(type);
|
|
|
|
switch_assert(ext);
|
2007-11-26 23:41:00 +00:00
|
|
|
|
|
|
|
if (!check) {
|
|
|
|
char *ptype = switch_core_permanent_strdup(type);
|
|
|
|
char *ext_list = strdup(ext);
|
|
|
|
int argc = 0;
|
|
|
|
char *argv[20] = { 0 };
|
|
|
|
int x;
|
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(ext_list);
|
2007-11-26 23:41:00 +00:00
|
|
|
|
|
|
|
if ((argc = switch_separate_string(ext_list, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
|
|
|
|
|
|
|
|
for (x = 0; x < argc; x++) {
|
|
|
|
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";
|
|
|
|
int fd = -1;
|
|
|
|
char line_buf[1024] = "";
|
|
|
|
char *mime_path = NULL;
|
|
|
|
|
|
|
|
mime_path = switch_mprintf("%s/%s", SWITCH_GLOBAL_dirs.conf_dir, cf);
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(mime_path);
|
2007-11-26 23:41:00 +00:00
|
|
|
|
2007-12-03 16:17:28 +00:00
|
|
|
fd = open(mime_path, O_RDONLY);
|
|
|
|
if (fd <= 0) {
|
2007-11-26 23:41:00 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while((switch_fd_read_line(fd, line_buf, sizeof(line_buf)))) {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fd > -1) {
|
|
|
|
close(fd);
|
|
|
|
fd = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2006-09-20 20:25:26 +00:00
|
|
|
|
2008-01-07 20:40:59 +00:00
|
|
|
|
|
|
|
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_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);
|
|
|
|
setrlimit(RLIMIT_AS, &rlp);
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-06 13:40:00 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switch_bool_t console, const char **err)
|
2006-03-01 17:06:10 +00:00
|
|
|
{
|
2006-07-11 20:59:07 +00:00
|
|
|
switch_xml_t xml = NULL, cfg = NULL;
|
2007-02-22 23:12:58 +00:00
|
|
|
switch_uuid_t uuid;
|
2007-10-17 15:38:57 +00:00
|
|
|
char guess_ip[256];
|
2006-03-01 17:06:10 +00:00
|
|
|
|
2007-10-17 20:14:19 +00:00
|
|
|
memset(&runtime, 0, sizeof(runtime));
|
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);
|
2007-10-04 17:25:06 +00:00
|
|
|
runtime.hard_log_level = SWITCH_LOG_DEBUG;
|
2007-11-05 18:45:26 +00:00
|
|
|
runtime.mailer_app = "sendmail";
|
|
|
|
runtime.mailer_app_args = "-t";
|
2007-07-06 16:29:25 +00:00
|
|
|
|
2006-04-11 21:13:44 +00:00
|
|
|
/* INIT APR and Create the pool context */
|
|
|
|
if (apr_initialize() != SWITCH_STATUS_SUCCESS) {
|
2008-01-07 10:55:15 +00:00
|
|
|
*err = "FATAL ERROR! Could not initialize APR\n";
|
2006-04-11 21:13:44 +00:00
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
if (!(runtime.memory_pool = switch_core_memory_init())) {
|
2008-01-07 10:55:15 +00:00
|
|
|
*err = "FATAL ERROR! Could not allocate memory pool\n";
|
2006-04-11 21:13:44 +00:00
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
}
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(runtime.memory_pool != NULL);
|
2007-10-03 16:44:11 +00:00
|
|
|
switch_mutex_init(&runtime.throttle_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
|
2007-12-22 00:32:20 +00:00
|
|
|
switch_mutex_init(&runtime.global_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool);
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_core_set_globals();
|
|
|
|
switch_core_session_init(runtime.memory_pool);
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
switch_core_hash_init(&runtime.global_vars, runtime.memory_pool);
|
2007-11-26 23:41:00 +00:00
|
|
|
switch_core_hash_init(&runtime.mime_types, runtime.memory_pool);
|
|
|
|
load_mime_types();
|
2007-09-29 01:06:08 +00:00
|
|
|
runtime.flags = flags;
|
2007-10-03 16:44:11 +00:00
|
|
|
runtime.sps_total = 30;
|
2007-03-30 02:20:13 +00:00
|
|
|
|
2007-10-17 15:38:57 +00:00
|
|
|
switch_find_local_ip(guess_ip, sizeof(guess_ip), AF_INET);
|
|
|
|
switch_core_set_variable("local_ip_v4", guess_ip);
|
|
|
|
switch_find_local_ip(guess_ip, sizeof(guess_ip), AF_INET6);
|
|
|
|
switch_core_set_variable("local_ip_v6", guess_ip);
|
2007-12-06 19:51:55 +00:00
|
|
|
switch_core_set_variable("base_dir", SWITCH_GLOBAL_dirs.base_dir);
|
2007-10-17 15:38:57 +00:00
|
|
|
|
|
|
|
|
2007-12-18 16:55:39 +00:00
|
|
|
|
2006-06-05 18:36:02 +00:00
|
|
|
if (switch_xml_init(runtime.memory_pool, err) != SWITCH_STATUS_SUCCESS) {
|
2006-05-15 18:16:43 +00:00
|
|
|
apr_terminate();
|
2006-05-10 03:23:05 +00:00
|
|
|
return SWITCH_STATUS_MEMERR;
|
|
|
|
}
|
2007-11-26 23:41:00 +00:00
|
|
|
|
2006-07-07 18:59:14 +00:00
|
|
|
if ((xml = switch_xml_open_cfg("switch.conf", &cfg, NULL))) {
|
|
|
|
switch_xml_t settings, param;
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-07-07 18:59:14 +00:00
|
|
|
if ((settings = switch_xml_child(cfg, "settings"))) {
|
|
|
|
for (param = switch_xml_child(settings, "param"); param; param = param->next) {
|
2007-02-16 23:36:10 +00:00
|
|
|
const char *var = switch_xml_attr_soft(param, "name");
|
|
|
|
const char *val = switch_xml_attr_soft(param, "value");
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2007-05-10 16:56:29 +00:00
|
|
|
if (!strcasecmp(var, "crash-protection")) {
|
2007-09-29 01:06:08 +00:00
|
|
|
if (switch_true(val)) {
|
|
|
|
switch_set_flag((&runtime), SCF_CRASH_PROT);
|
|
|
|
}
|
2007-10-05 18:59:18 +00:00
|
|
|
} else if (!strcasecmp(var, "loglevel")) {
|
|
|
|
int level;
|
|
|
|
if (*val > 47 && *val < 58) {
|
|
|
|
level = atoi(val);
|
|
|
|
} else {
|
|
|
|
level = switch_log_str2level(val);
|
|
|
|
}
|
|
|
|
|
2007-12-10 19:16:50 +00:00
|
|
|
if (level != SWITCH_LOG_INVALID) {
|
|
|
|
switch_core_session_ctl(SCSC_LOGLEVEL, &level);
|
|
|
|
}
|
2007-10-05 18:59:18 +00:00
|
|
|
|
2007-12-18 16:55:39 +00:00
|
|
|
#ifdef HAVE_SETRLIMIT
|
|
|
|
} else if (!strcasecmp(var, "dump-cores")) {
|
|
|
|
struct rlimit rlp;
|
|
|
|
memset(&rlp, 0, sizeof(rlp));
|
|
|
|
rlp.rlim_cur = RLIM_INFINITY;
|
|
|
|
rlp.rlim_max = RLIM_INFINITY;
|
|
|
|
setrlimit(RLIMIT_CORE, &rlp);
|
|
|
|
#endif
|
|
|
|
|
2007-11-05 18:45:26 +00:00
|
|
|
} else if (!strcasecmp(var, "mailer-app")) {
|
|
|
|
runtime.mailer_app = switch_core_strdup(runtime.memory_pool, val);
|
|
|
|
} else if (!strcasecmp(var, "mailer-app-args")) {
|
|
|
|
runtime.mailer_app_args = switch_core_strdup(runtime.memory_pool, val);
|
2007-10-03 16:44:11 +00:00
|
|
|
} else if (!strcasecmp(var, "sessions-per-second")) {
|
|
|
|
switch_core_sessions_per_second(atoi(val));
|
2007-05-10 16:56:29 +00:00
|
|
|
} else if (!strcasecmp(var, "max-sessions")) {
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_core_session_limit(atoi(val));
|
2006-07-07 18:59:14 +00:00
|
|
|
}
|
2007-04-07 03:07:43 +00:00
|
|
|
else if (!strcasecmp(var, "rtp-start-port")) {
|
2007-04-08 16:16:00 +00:00
|
|
|
switch_rtp_set_start_port((switch_port_t)atoi(val));
|
2007-04-07 03:07:43 +00:00
|
|
|
}
|
|
|
|
else if (!strcasecmp(var, "rtp-end-port")) {
|
2007-04-08 16:16:00 +00:00
|
|
|
switch_rtp_set_end_port((switch_port_t)atoi(val));
|
2007-04-07 03:07:43 +00:00
|
|
|
}
|
2006-07-07 18:59:14 +00:00
|
|
|
}
|
|
|
|
}
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
|
|
|
|
if ((settings = switch_xml_child(cfg, "variables"))) {
|
|
|
|
for (param = switch_xml_child(settings, "variable"); param; param = param->next) {
|
2007-02-16 23:36:10 +00:00
|
|
|
const char *var = switch_xml_attr_soft(param, "name");
|
|
|
|
const char *val = switch_xml_attr_soft(param, "value");
|
Ringback (sponsored by Front Logic)
This addition lets you set artifical ringback on a channel
that is waiting for an originated call to be answered.
the syntax is
<action application="set" data="ringback=[data]"/>
where data is either the full path to an audio file
or a teletone generation script..
syntax of teletone scripts
LEGEND:
0-9,a-d,*,# (standard dtmf tones)
variables: c,r,d,v,>,<,+,w,l,L,%
c (channels) - Sets the number of channels.
r (rate) - Sets the sample rate.
d (duration) - Sets the default tone duration.
v (volume) - Sets the default volume.
> (decrease vol) - factor to decrease volume by per frame (0 for even decrease across duration).
< (increase vol) - factor to increase volume by per frame (0 for even increase across duration).
+ (step) - factor to step by used by < and >.
w (wait) - default silence after each tone.
l (loops) - number of times to repeat each tone in the script.
L (LOOPS) - number of times to repeat the the whole script.
% (manual tone) - a generic tone specified by a duration, a wait and a list of frequencies.
standard tones can have custom duration per use with the () modifier
7(1000, 500) to generate DTMF 7 for 1 second then pause .5 seconds
EXAMPLES
UK Ring Tone [400+450 hz on for 400ms off for 200ms then 400+450 hz on for 400ms off for 2200ms]
%(400,200,400,450);%(400,2200,400,450)
US Ring Tone [440+480 hz on for 2000ms off for 4000ms]
%(2000,4000,440,480)
ATT BONG [volume level 4000, even decay, step by 2, # key for 60ms with no wait, volume level 2000, 350+440hz {us dialtone} for 940ms
v=4000;>=0;+=2;#(60,0);v=2000;%(940,0,350,440)
SIT Tone 913.8 hz for 274 ms with no wait, 1370.6 hz for 274 ms with no wait, 1776.7 hz for 380ms with no wait
%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)
ATTN TONE (phone's off the hook!) 1400+2060+2450+2600 hz for 100ms with 100ms wait
%(100,100,1400,2060,2450,2600)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3408 d0543943-73ff-0310-b7d9-9358b9ac24b2
2006-11-19 01:05:06 +00:00
|
|
|
char *varr = NULL, *vall = NULL;
|
|
|
|
|
|
|
|
varr = switch_core_strdup(runtime.memory_pool, var);
|
|
|
|
vall = switch_core_strdup(runtime.memory_pool, val);
|
|
|
|
switch_core_hash_insert(runtime.global_vars, varr, vall);
|
|
|
|
}
|
|
|
|
}
|
2006-07-07 18:59:14 +00:00
|
|
|
switch_xml_free(xml);
|
|
|
|
}
|
|
|
|
|
2007-05-10 16:56:29 +00:00
|
|
|
switch_core_state_machine_init(runtime.memory_pool);
|
|
|
|
|
2006-06-05 18:36:02 +00:00
|
|
|
*err = NULL;
|
|
|
|
|
2007-12-06 13:40:00 +00:00
|
|
|
if (console) {
|
|
|
|
runtime.console = stdout;
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2007-12-11 19:23:57 +00:00
|
|
|
switch_assert(runtime.memory_pool != NULL);
|
2006-04-26 19:11:49 +00:00
|
|
|
switch_log_init(runtime.memory_pool);
|
2005-12-13 19:53:29 +00:00
|
|
|
switch_event_init(runtime.memory_pool);
|
2007-03-30 17:25:48 +00:00
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
if (switch_test_flag((&runtime), SCF_USE_SQL)) {
|
|
|
|
switch_core_sqldb_start(runtime.memory_pool);
|
|
|
|
}
|
2006-04-05 20:17:22 +00:00
|
|
|
switch_rtp_init(runtime.memory_pool);
|
2007-03-29 22:31:56 +00:00
|
|
|
runtime.running = 1;
|
2005-12-28 05:17:21 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_scheduler_task_thread_start();
|
2006-05-10 03:23:05 +00:00
|
|
|
runtime.initiated = switch_time_now();
|
2007-02-22 17:38:34 +00:00
|
|
|
|
2008-01-11 00:43:49 +00:00
|
|
|
switch_scheduler_add_task(switch_timestamp(NULL), heartbeat_callback, "heartbeat", "core", 0, NULL, SSHF_NONE | SSHF_NO_DEL);
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2007-02-22 17:38:34 +00:00
|
|
|
|
|
|
|
switch_uuid_get(&uuid);
|
|
|
|
switch_uuid_format(runtime.uuid_str, &uuid);
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
2006-11-20 21:43:44 +00:00
|
|
|
|
2006-08-19 18:51:22 +00:00
|
|
|
#ifdef SIGPIPE
|
2006-10-02 16:48:00 +00:00
|
|
|
static void handle_SIGPIPE(int sig)
|
2006-08-19 18:51:22 +00:00
|
|
|
{
|
2007-03-29 22:31:56 +00:00
|
|
|
if (sig);
|
2006-08-19 18:51:22 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Sig Pipe!\n");
|
2006-10-02 16:48:00 +00:00
|
|
|
return;
|
2006-08-19 18:51:22 +00:00
|
|
|
}
|
|
|
|
#endif
|
2006-11-20 21:43:44 +00:00
|
|
|
|
|
|
|
#ifdef SIGPOLL
|
|
|
|
static void handle_SIGPOLL(int sig)
|
|
|
|
{
|
2007-03-29 22:31:56 +00:00
|
|
|
if (sig);
|
2006-11-20 21:43:44 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Sig Poll!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef SIGIO
|
|
|
|
static void handle_SIGIO(int sig)
|
|
|
|
{
|
2007-03-29 22:31:56 +00:00
|
|
|
if (sig);
|
2006-11-20 21:43:44 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Sig I/O!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-08-19 18:51:22 +00:00
|
|
|
#ifdef TRAP_BUS
|
2006-10-02 16:48:00 +00:00
|
|
|
static void handle_SIGBUS(int sig)
|
2006-08-19 18:51:22 +00:00
|
|
|
{
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Sig BUS!\n");
|
2006-10-02 16:48:00 +00:00
|
|
|
return;
|
2006-08-19 18:51:22 +00:00
|
|
|
}
|
|
|
|
#endif
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-08-19 18:51:22 +00:00
|
|
|
/* no ctl-c mofo */
|
2006-10-02 16:48:00 +00:00
|
|
|
static void handle_SIGINT(int sig)
|
2006-08-19 18:51:22 +00:00
|
|
|
{
|
|
|
|
if (sig);
|
2006-10-02 16:48:00 +00:00
|
|
|
return;
|
2006-08-19 18:51:22 +00:00
|
|
|
}
|
2007-12-06 19:51:55 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2007-12-06 13:40:00 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(switch_core_flag_t flags, switch_bool_t console, const char **err)
|
2006-08-19 18:51:22 +00:00
|
|
|
{
|
|
|
|
switch_event_t *event;
|
2007-12-06 13:40:00 +00:00
|
|
|
if (switch_core_init(flags, console, err) != SWITCH_STATUS_SUCCESS) {
|
2006-08-19 18:51:22 +00:00
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set signal handlers */
|
2006-10-02 16:48:00 +00:00
|
|
|
signal(SIGINT, handle_SIGINT);
|
2006-08-19 18:51:22 +00:00
|
|
|
#ifdef SIGPIPE
|
2006-10-02 16:48:00 +00:00
|
|
|
signal(SIGPIPE, handle_SIGPIPE);
|
2006-08-19 18:51:22 +00:00
|
|
|
#endif
|
2006-11-20 21:43:44 +00:00
|
|
|
#ifdef SIGPOLL
|
2007-10-04 17:25:06 +00:00
|
|
|
signal(SIGPOLL, handle_SIGPOLL);
|
2006-11-20 21:43:44 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGIO
|
2007-10-04 17:25:06 +00:00
|
|
|
signal(SIGIO, handle_SIGIO);
|
2006-11-20 21:43:44 +00:00
|
|
|
#endif
|
2006-08-19 18:51:22 +00:00
|
|
|
#ifdef TRAP_BUS
|
2006-10-02 16:48:00 +00:00
|
|
|
signal(SIGBUS, handle_SIGBUS);
|
2006-08-19 18:51:22 +00:00
|
|
|
#endif
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2007-12-06 19:51:55 +00:00
|
|
|
signal(SIGHUP, handle_SIGHUP);
|
|
|
|
|
2006-08-19 18:51:22 +00:00
|
|
|
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_STATUS_SUCCESS) {
|
|
|
|
*err = "Cannot load modules";
|
2007-11-23 18:50:54 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error: %s\n", *err);
|
2006-08-19 18:51:22 +00:00
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE,
|
2007-10-03 16:44:11 +00:00
|
|
|
"\nFreeSWITCH Version %s Started.\nCrash Protection [%s]\nMax Sessions[%u]\nSession Rate[%d]\nSQL [%s]\n", SWITCH_VERSION_FULL,
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_test_flag((&runtime), SCF_CRASH_PROT) ? "Enabled" : "Disabled",
|
|
|
|
switch_core_session_limit(0),
|
2007-10-03 16:44:11 +00:00
|
|
|
switch_core_sessions_per_second(0),
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_test_flag((&runtime), SCF_USE_SQL) ? "Enabled" : "Disabled"
|
|
|
|
);
|
2007-07-06 16:29:25 +00:00
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS);
|
2007-07-06 16:29:25 +00:00
|
|
|
|
2006-08-19 18:51:22 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
}
|
2005-11-19 20:07:43 +00:00
|
|
|
|
2006-05-10 03:23:05 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_measure_time(switch_time_t total_ms, switch_core_time_duration_t *duration)
|
|
|
|
{
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_time_t temp = total_ms / 1000;
|
2006-05-10 04:05:07 +00:00
|
|
|
memset(duration, 0, sizeof(*duration));
|
2007-03-29 22:31:56 +00:00
|
|
|
duration->mms = (uint32_t) (total_ms % 1000);
|
|
|
|
duration->ms = (uint32_t) (temp % 1000);
|
|
|
|
temp = temp / 1000;
|
|
|
|
duration->sec = (uint32_t) (temp % 60);
|
2006-05-10 04:42:31 +00:00
|
|
|
temp = temp / 60;
|
2007-03-29 22:31:56 +00:00
|
|
|
duration->min = (uint32_t) (temp % 60);
|
|
|
|
temp = temp / 60;
|
|
|
|
duration->hr = (uint32_t) (temp % 24);
|
2006-05-10 04:42:31 +00:00
|
|
|
temp = temp / 24;
|
2007-03-29 22:31:56 +00:00
|
|
|
duration->day = (uint32_t) (temp % 365);
|
|
|
|
duration->yr = (uint32_t) (temp / 365);
|
2006-05-10 03:23:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_time_t) switch_core_uptime(void)
|
|
|
|
{
|
2008-01-11 00:43:49 +00:00
|
|
|
return switch_timestamp_now() - runtime.initiated;
|
2006-05-10 03:23:05 +00:00
|
|
|
}
|
|
|
|
|
2007-10-03 23:43:01 +00:00
|
|
|
SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, int32_t * val)
|
2006-09-20 20:25:26 +00:00
|
|
|
{
|
2007-09-29 01:06:08 +00:00
|
|
|
if (switch_test_flag((&runtime), SCF_SHUTTING_DOWN)) {
|
2006-09-20 20:25:26 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (cmd) {
|
2008-01-11 00:43:49 +00:00
|
|
|
case SCSC_SYNC_CLOCK:
|
|
|
|
switch_time_sync();
|
|
|
|
*val = 0;
|
|
|
|
break;
|
2006-09-20 20:25:26 +00:00
|
|
|
case SCSC_PAUSE_INBOUND:
|
2007-09-29 01:06:08 +00:00
|
|
|
if (*val) {
|
|
|
|
switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);
|
|
|
|
} else {
|
|
|
|
switch_clear_flag((&runtime), SCF_NO_NEW_SESSIONS);
|
|
|
|
}
|
2006-09-20 20:25:26 +00:00
|
|
|
break;
|
|
|
|
case SCSC_HUPALL:
|
|
|
|
switch_core_session_hupall(SWITCH_CAUSE_MANAGER_REQUEST);
|
|
|
|
break;
|
|
|
|
case SCSC_SHUTDOWN:
|
|
|
|
runtime.running = 0;
|
|
|
|
break;
|
|
|
|
case SCSC_CHECK_RUNNING:
|
|
|
|
*val = runtime.running;
|
|
|
|
break;
|
2007-10-03 23:43:01 +00:00
|
|
|
case SCSC_LOGLEVEL:
|
|
|
|
if (*val > -1) {
|
|
|
|
runtime.hard_log_level = *val;
|
|
|
|
}
|
|
|
|
|
2007-10-04 17:25:06 +00:00
|
|
|
if (runtime.hard_log_level > SWITCH_LOG_DEBUG) {
|
|
|
|
runtime.hard_log_level = SWITCH_LOG_DEBUG;
|
2007-10-03 23:43:01 +00:00
|
|
|
}
|
|
|
|
*val = runtime.hard_log_level;
|
|
|
|
break;
|
2007-10-05 13:42:11 +00:00
|
|
|
case SCSC_MAX_SESSIONS:
|
|
|
|
*val = switch_core_session_limit(*val);
|
|
|
|
break;
|
2007-10-04 21:35:50 +00:00
|
|
|
case SCSC_LAST_SPS:
|
|
|
|
*val = runtime.sps_last;
|
|
|
|
break;
|
2007-10-04 14:19:51 +00:00
|
|
|
case SCSC_SPS:
|
|
|
|
switch_mutex_lock(runtime.throttle_mutex);
|
|
|
|
if (*val > 0) {
|
|
|
|
runtime.sps_total = *val;
|
|
|
|
}
|
|
|
|
*val = runtime.sps_total;
|
|
|
|
switch_mutex_unlock(runtime.throttle_mutex);
|
|
|
|
break;
|
2007-10-04 17:25:06 +00:00
|
|
|
|
|
|
|
case SCSC_RECLAIM:
|
|
|
|
switch_core_memory_reclaim_all();
|
|
|
|
*val = 0;
|
|
|
|
break;
|
2006-09-20 20:25:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
|
|
|
|
SWITCH_DECLARE(switch_core_flag_t) switch_core_flags(void)
|
|
|
|
{
|
|
|
|
return runtime.flags;
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
SWITCH_DECLARE(switch_bool_t) switch_core_ready(void)
|
|
|
|
{
|
2007-09-29 01:06:08 +00:00
|
|
|
return (switch_test_flag((&runtime), SCF_SHUTTING_DOWN) || switch_test_flag((&runtime), SCF_NO_NEW_SESSIONS)) ? SWITCH_FALSE : SWITCH_TRUE;
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-01 17:23:02 +00:00
|
|
|
SWITCH_DECLARE(switch_status_t) switch_core_destroy(void)
|
2005-11-19 20:07:43 +00:00
|
|
|
{
|
2006-08-19 18:51:22 +00:00
|
|
|
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);
|
|
|
|
}
|
2007-09-29 01:06:08 +00:00
|
|
|
|
|
|
|
switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS);
|
|
|
|
switch_set_flag((&runtime), SCF_SHUTTING_DOWN);
|
2006-08-19 18:51:22 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-08-19 18:51:22 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "End existing sessions\n");
|
2006-09-20 20:25:26 +00:00
|
|
|
switch_core_session_hupall(SWITCH_CAUSE_SYSTEM_SHUTDOWN);
|
2006-08-19 18:51:22 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Clean up modules.\n");
|
|
|
|
switch_loadable_module_shutdown();
|
2005-12-14 20:22:19 +00:00
|
|
|
|
2006-08-15 19:02:06 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Closing Event Engine.\n");
|
|
|
|
switch_event_shutdown();
|
2007-03-28 23:37:12 +00:00
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
if (switch_test_flag((&runtime), SCF_USE_SQL)) {
|
|
|
|
switch_core_sqldb_stop();
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_scheduler_task_thread_stop();
|
2007-03-28 23:37:12 +00:00
|
|
|
|
2007-12-11 19:15:02 +00:00
|
|
|
switch_rtp_shutdown();
|
2006-05-10 03:23:05 +00:00
|
|
|
switch_xml_destroy();
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_core_memory_stop();
|
2006-08-15 19:02:06 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Finalizing Shutdown.\n");
|
2006-08-15 17:52:12 +00:00
|
|
|
switch_log_shutdown();
|
2007-03-28 23:37:12 +00:00
|
|
|
|
2007-12-07 02:04:23 +00:00
|
|
|
if (runtime.console && runtime.console != stdout && runtime.console != stderr) {
|
2006-02-26 03:13:01 +00:00
|
|
|
fclose(runtime.console);
|
|
|
|
runtime.console = NULL;
|
|
|
|
}
|
2005-12-14 21:29:46 +00:00
|
|
|
|
2007-03-11 01:07:47 +00:00
|
|
|
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.temp_dir);
|
2006-08-20 03:36:14 +00:00
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
|
|
|
|
switch_core_hash_destroy(&runtime.global_vars);
|
2007-11-26 23:41:00 +00:00
|
|
|
switch_core_hash_destroy(&runtime.mime_types);
|
2007-09-29 01:06:08 +00:00
|
|
|
|
2007-01-22 17:16:25 +00:00
|
|
|
if (runtime.memory_pool) {
|
|
|
|
apr_pool_destroy(runtime.memory_pool);
|
2007-03-04 01:47:08 +00:00
|
|
|
/* apr_terminate(); */
|
2007-01-22 17:16:25 +00:00
|
|
|
}
|
|
|
|
|
2005-11-19 20:07:43 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
2006-11-27 22:30:48 +00:00
|
|
|
|
2007-12-11 19:15:02 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2007-10-04 17:25:06 +00:00
|
|
|
SWITCH_DECLARE(void) switch_core_memory_reclaim_all(void)
|
|
|
|
{
|
|
|
|
switch_core_memory_reclaim_logger();
|
|
|
|
switch_core_memory_reclaim_events();
|
|
|
|
switch_core_memory_reclaim();
|
|
|
|
}
|
2007-02-21 21:46:32 +00:00
|
|
|
|
2006-11-27 22:30:48 +00:00
|
|
|
/* For Emacs:
|
|
|
|
* Local Variables:
|
|
|
|
* mode:c
|
2007-02-09 02:36:03 +00:00
|
|
|
* indent-tabs-mode:t
|
2006-11-27 22:30:48 +00:00
|
|
|
* tab-width:4
|
|
|
|
* c-basic-offset:4
|
|
|
|
* End:
|
|
|
|
* For VIM:
|
|
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
|
|
*/
|