From 90815616ccb55494063dddfe3d35dafda704f17a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 20 Sep 2006 20:25:26 +0000 Subject: [PATCH] small core refactoring use -hp arg to gain high priority mode, add fsctl command USAGE: fsctl [hupall|pause|resume|shutdown] git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2765 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_core.h | 24 ++- src/include/switch_types.h | 13 +- .../applications/mod_commands/mod_commands.c | 52 ++++++- src/mod/endpoints/mod_sofia/mod_sofia.c | 5 +- src/switch.c | 143 ++++++++---------- src/switch_channel.c | 1 + src/switch_console.c | 21 ++- src/switch_core.c | 99 ++++++++++-- src/switch_rtp.c | 4 + 9 files changed, 262 insertions(+), 100 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index e2947ae4db..1ce8f616a9 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -409,8 +409,9 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_locate(char *uuid_st /*! \brief Hangup All Sessions + \param cause the hangup cause to apply to the hungup channels */ -SWITCH_DECLARE(void) switch_core_session_hupall(void); +SWITCH_DECLARE(void) switch_core_session_hupall(switch_call_cause_t cause); /*! \brief Send a message to another session using it's uuid @@ -1198,6 +1199,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_directory_close(switch_directory_han */ SWITCH_DECLARE(FILE *) switch_core_data_channel(switch_text_channel_t channel); + +/*! + \brief Set the maximum priority the process can obtain + \return 0 on success +*/ +SWITCH_DECLARE(int32_t) set_high_priority(void); + +/*! + \brief Run endlessly until the system is shutdown + \param bg divert console to the background +*/ +SWITCH_DECLARE(void) switch_core_runtime_loop(int bg); + /*! \brief Set the output console to the desired file \param console the file path @@ -1217,6 +1231,14 @@ SWITCH_DECLARE(void) switch_core_measure_time(switch_time_t total_ms, switch_cor */ SWITCH_DECLARE(switch_time_t) switch_core_uptime(void); +/*! + \brief send a control message to the core + \param cmd the command + \param val the command arguement (if needed) + \return 0 on success nonzero on error +*/ +SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, uint32_t *val); + /*! \brief Get the output console \return the FILE stream diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 2e9191beb4..3a7adc79f5 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -176,6 +176,7 @@ typedef enum { SWITCH_RTP_FLAG_VAD - Enable VAD SWITCH_RTP_FLAG_BREAK - Stop what you are doing and return SWITCH_STATUS_BREAK SWITCH_RTP_FLAG_MINI - Use mini RTP when possible + SWITCH_RTP_FLAG_DATAWAIT - Do not return from reads unless there is data even when non blocking */ typedef enum { @@ -189,7 +190,8 @@ typedef enum { SWITCH_RTP_FLAG_GOOGLEHACK = (1 << 7), SWITCH_RTP_FLAG_VAD = (1 << 8), SWITCH_RTP_FLAG_BREAK = ( 1 << 9), - SWITCH_RTP_FLAG_MINI = ( 1 << 10) + SWITCH_RTP_FLAG_MINI = ( 1 << 10), + SWITCH_RTP_FLAG_DATAWAIT = (1 << 11) } switch_rtp_flag_t; /*! @@ -690,9 +692,16 @@ typedef enum { SWITCH_CAUSE_INTERWORKING = 127, SWITCH_CAUSE_CRASH = 500, SWITCH_CAUSE_SYSTEM_SHUTDOWN = 501, - SWITCH_CAUSE_LOSE_RACE = 502 + SWITCH_CAUSE_LOSE_RACE = 502, + SWITCH_CAUSE_MANAGER_REQUEST = 503 } switch_call_cause_t; +typedef enum { + SCSC_PAUSE_INBOUND, + SCSC_HUPALL, + SCSC_SHUTDOWN, + SCSC_CHECK_RUNNING +} switch_session_ctl_t; typedef uint8_t switch_payload_t; typedef struct switch_rtp switch_rtp_t; diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index ad1a0ecd23..453fedb087 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -87,6 +87,49 @@ static switch_status_t status_function(char *cmd, switch_core_session_t *session return SWITCH_STATUS_SUCCESS; } +static switch_status_t ctl_function(char *data, switch_core_session_t *session, switch_stream_handle_t *stream) +{ + int argc; + char *mydata, *argv[5]; + uint32_t arg = 0; + + if (switch_strlen_zero(data)) { + stream->write_function(stream, "USAGE: fsctl [hupall|pause|resume|shutdown]\n"); + return SWITCH_STATUS_SUCCESS; + } + + if ((mydata = strdup(data))) { + argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + + if (!strcmp(argv[0], "hupall")) { + arg = 1; + switch_core_session_ctl(SCSC_HUPALL, &arg); + } else if (!strcmp(argv[0], "pause")) { + arg = 1; + switch_core_session_ctl(SCSC_PAUSE_INBOUND, &arg); + } else if (!strcmp(argv[0], "resume")) { + arg = 0; + switch_core_session_ctl(SCSC_PAUSE_INBOUND, &arg); + } else if (!strcmp(argv[0], "shutdown")) { + arg = 0; + switch_core_session_ctl(SCSC_SHUTDOWN, &arg); + } else { + stream->write_function(stream, "INVALID COMMAND [%s]\n", argv[0]); + goto end; + } + + stream->write_function(stream, "OK\n"); + end: + free(mydata); + } else { + stream->write_function(stream, "MEM ERR\n"); + } + + return SWITCH_STATUS_SUCCESS; + +} + + static switch_status_t load_function(char *mod, switch_core_session_t *session, switch_stream_handle_t *stream) { @@ -436,11 +479,18 @@ static switch_status_t show_function(char *cmd, switch_core_session_t *session, +static switch_api_interface_t ctl_api_interface = { + /*.interface_name */ "fsctl", + /*.desc */ "control messages", + /*.function */ ctl_function, + /*.next */ +}; + static switch_api_interface_t uuid_bridge_api_interface = { /*.interface_name */ "uuid_bridge", /*.desc */ "uuid_bridge", /*.function */ uuid_bridge_function, - /*.next */ NULL + /*.next */ &ctl_api_interface }; static switch_api_interface_t status_api_interface = { diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 3748361586..914e87e57e 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -727,7 +727,7 @@ static switch_status_t activate_rtp(private_object_t *tech_pvt) bw = tech_pvt->read_codec.implementation->bits_per_second; ms = tech_pvt->read_codec.implementation->microseconds_per_frame; - flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_RAW_WRITE | SWITCH_RTP_FLAG_MINI | SWITCH_RTP_FLAG_AUTOADJ); + flags = (switch_rtp_flag_t) (SWITCH_RTP_FLAG_RAW_WRITE | SWITCH_RTP_FLAG_MINI | SWITCH_RTP_FLAG_AUTOADJ | SWITCH_RTP_FLAG_DATAWAIT); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n", switch_channel_get_name(channel), @@ -812,6 +812,7 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f size_t bytes = 0, samples = 0, frames = 0, ms = 0; switch_channel_t *channel = NULL; int payload = 0; + //switch_time_t now, started = switch_time_now(), last_act = switch_time_now(); //unsigned int elapsed; //uint32_t hard_timeout = 60000 * 3; @@ -903,8 +904,6 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f tech_pvt->read_frame.samples = (int) samples; break; } - - switch_yield(1000); } } diff --git a/src/switch.c b/src/switch.c index 154ad49726..1277453202 100644 --- a/src/switch.c +++ b/src/switch.c @@ -35,7 +35,7 @@ #define PIDFILE "freeswitch.pid" #define LOGFILE "freeswitch.log" -static int RUNNING = 0; + static char *lfile = LOGFILE; static char *pfile = PIDFILE; #define SERVICENAME "Freeswitch" @@ -53,37 +53,12 @@ static HANDLE shutdown_event; static int handle_SIGHUP(int sig) { + uint32_t arg = 0; if(sig); - RUNNING = 0; + switch_core_session_ctl(SCSC_SHUTDOWN, &arg); return 0; } -static void set_high_priority() -{ -#ifdef WIN32 - SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); -#else - //nice(-19); -#endif -} - -static void freeswitch_runtime_loop(int bg) -{ - if (bg) { - bg = 0; -#ifdef WIN32 - WaitForSingleObject(shutdown_event, INFINITE); -#else - RUNNING = 1; - while(RUNNING) { - switch_yield(10000); - } -#endif - } else { - /* wait for console input */ - switch_console_loop(); - } -} static int freeswitch_kill_background() { @@ -175,6 +150,7 @@ int main(int argc, char *argv[]) int bg = 0; FILE *f; pid_t pid = 0; + int x, die = 0; #ifdef WIN32 SERVICE_TABLE_ENTRY dispatchTable[] = @@ -182,60 +158,71 @@ int main(int argc, char *argv[]) { SERVICENAME, &service_main }, { NULL, NULL } }; - - if (argv[1] && !strcmp(argv[1], "-service")) { - if(StartServiceCtrlDispatcher( dispatchTable ) == 0 ) - { - //Not loaded as a service - fprintf(stderr, "Error Freeswitch loaded as a console app with -service option\n"); - fprintf(stderr, "To install the service load freeswitch with -install\n"); - } - exit(0); - } - if (argv[1] && !strcmp(argv[1], "-install")) { - char exePath[1024]; - char servicePath[1024]; - - SC_HANDLE handle = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); - GetModuleFileName( NULL, exePath, 1024 ); - snprintf(servicePath, sizeof(servicePath), "%s -service", exePath); - CreateService( - handle, - SERVICENAME, - SERVICENAME, - GENERIC_READ | GENERIC_EXECUTE, - SERVICE_WIN32_OWN_PROCESS, - SERVICE_AUTO_START, - SERVICE_ERROR_IGNORE, - servicePath, - NULL, - NULL, - NULL, - NULL, - NULL - ); - exit(0); - } - if (argv[1] && !strcmp(argv[1], "-uninstall")) { - SC_HANDLE handle = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); - SC_HANDLE service = OpenService( handle, SERVICENAME, DELETE ); - if( service != NULL ) - { - // remove the service! - DeleteService( service ); - } - exit(0); - } #endif - set_high_priority(); + for (x = 1; x < argc; x++) { +#ifdef WIN32 + if (x == 1) { + if (argv[x] && !strcmp(argv[x], "-service")) { + if(StartServiceCtrlDispatcher( dispatchTable ) == 0 ) + { + //Not loaded as a service + fprintf(stderr, "Error Freeswitch loaded as a console app with -service option\n"); + fprintf(stderr, "To install the service load freeswitch with -install\n"); + } + exit(0); + } + if (argv[x] && !strcmp(argv[x], "-install")) { + char exePath[1024]; + char servicePath[1024]; - if (argv[1] && !strcmp(argv[1], "-stop")) { - return freeswitch_kill_background(); + SC_HANDLE handle = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); + GetModuleFileName( NULL, exePath, 1024 ); + snprintf(servicePath, sizeof(servicePath), "%s -service", exePath); + CreateService( + handle, + SERVICENAME, + SERVICENAME, + GENERIC_READ | GENERIC_EXECUTE, + SERVICE_WIN32_OWN_PROCESS, + SERVICE_AUTO_START, + SERVICE_ERROR_IGNORE, + servicePath, + NULL, + NULL, + NULL, + NULL, + NULL + ); + exit(0); + } + if (argv[x] && !strcmp(argv[x], "-uninstall")) { + SC_HANDLE handle = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); + SC_HANDLE service = OpenService( handle, SERVICENAME, DELETE ); + if( service != NULL ) + { + // remove the service! + DeleteService( service ); + } + exit(0); + } + } +#endif + if (argv[x] && !strcmp(argv[x], "-hp")) { + set_high_priority(); + } + + if (argv[x] && !strcmp(argv[x], "-stop")) { + die++; + } + + if (argv[x] && !strcmp(argv[x], "-nc")) { + bg++; + } } - if (argv[1] && !strcmp(argv[1], "-nc")) { - bg++; + if (die) { + return freeswitch_kill_background(); } if (bg) { @@ -270,7 +257,7 @@ int main(int argc, char *argv[]) fprintf(f, "%d", pid = getpid()); fclose(f); - freeswitch_runtime_loop(bg); + switch_core_runtime_loop(bg); return switch_core_destroy(); } diff --git a/src/switch_channel.c b/src/switch_channel.c index a74484ed93..b608598dfb 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -86,6 +86,7 @@ static struct switch_cause_table CAUSE_CHART[] = { { "CRASH", SWITCH_CAUSE_CRASH }, { "SYSTEM_SHUTDOWN", SWITCH_CAUSE_SYSTEM_SHUTDOWN }, { "LOSE_RACE", SWITCH_CAUSE_LOSE_RACE }, + { "MANAGER_REQUEST", SWITCH_CAUSE_MANAGER_REQUEST }, { NULL, 0 } }; diff --git a/src/switch_console.c b/src/switch_console.c index 26e6a13b71..9bf49c0b4c 100644 --- a/src/switch_console.c +++ b/src/switch_console.c @@ -203,20 +203,33 @@ SWITCH_DECLARE(void) switch_console_loop(void) { char hostname[256]; char cmd[2048]; - int running = 1, activity = 1; + uint32_t activity = 1, running = 1; switch_size_t x = 0; gethostname(hostname, sizeof(hostname)); - while (running) { + while(running) { + uint32_t arg; + fd_set rfds, efds; + struct timeval tv = {0, 20000}; + + switch_core_session_ctl(SCSC_CHECK_RUNNING, &arg); + if (!arg) { + break; + } + if (activity) { switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_CONSOLE, "\nfreeswitch@%s> ", hostname); } - //activity = switch_socket_waitfor(fileno(stdin), 100, POLLIN | POLLERR); + + FD_ZERO(&rfds); + FD_ZERO(&efds); + FD_SET(fileno(stdin), &rfds); + FD_SET(fileno(stdin), &efds); + activity = select(fileno(stdin)+1, &rfds, NULL, &efds, &tv); if (activity == 0) { fflush(stdout); - switch_sleep(100); continue; } diff --git a/src/switch_core.c b/src/switch_core.c index 0028e774a4..e3d9780e83 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -127,6 +127,9 @@ struct switch_core_runtime { uint32_t session_count; uint32_t session_limit; switch_queue_t *sql_queue; + uint32_t no_new_sessions; + uint32_t shutting_down; + uint8_t running; }; /* Prototypes */ @@ -536,7 +539,7 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_locate(char *uuid_st } } -SWITCH_DECLARE(void) switch_core_session_hupall(void) +SWITCH_DECLARE(void) switch_core_session_hupall(switch_call_cause_t cause) { switch_hash_index_t *hi; void *val; @@ -549,7 +552,7 @@ SWITCH_DECLARE(void) switch_core_session_hupall(void) if (val) { session = (switch_core_session_t *) val; channel = switch_core_session_get_channel(session); - switch_channel_hangup(channel, SWITCH_CAUSE_SYSTEM_SHUTDOWN); + switch_channel_hangup(channel, cause); } } switch_mutex_unlock(runtime.session_table_mutex); @@ -3111,6 +3114,11 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request(const switch return NULL; } + if (runtime.no_new_sessions || runtime.shutting_down) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Read my lips: no new sessions!\n"); + return NULL; + } + if (pool) { usepool = pool; } else if (switch_core_new_memory_pool(&usepool) != SWITCH_STATUS_SUCCESS) { @@ -3474,6 +3482,55 @@ SWITCH_DECLARE(uint32_t) switch_core_session_limit(uint32_t new_limit) return runtime.session_limit; } + +SWITCH_DECLARE(int32_t) set_high_priority(void) +{ +#ifdef __linux__ + struct sched_param sched = {0}; + sched.sched_priority = 1; + if (sched_setscheduler(0, SCHED_RR, &sched)) { + sched.sched_priority = 0; + if (sched_setscheduler(0, SCHED_OTHER, &sched)) { + return -1; + } + } +#endif + +#ifdef WIN32 + SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); +#else + nice(-10); +#endif + +#define USE_MLOCKALL +#ifdef HAVE_MLOCKALL +#ifdef USE_MLOCKALL + mlockall(MCL_CURRENT|MCL_FUTURE); +#endif +#endif + return 0; +} + + +SWITCH_DECLARE(void) switch_core_runtime_loop(int bg) +{ + if (bg) { + bg = 0; +#ifdef WIN32 + 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(switch_status_t) switch_core_init(char *console, const char **err) { switch_xml_t xml = NULL, cfg = NULL; @@ -3602,7 +3659,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(char *console, const char **err } runtime.session_id = 1; - + runtime.running = 1; switch_core_hash_init(&runtime.session_table, runtime.memory_pool); switch_mutex_init(&runtime.session_table_mutex, SWITCH_MUTEX_NESTED, runtime.memory_pool); #ifdef CRASH_PROT @@ -3662,13 +3719,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_init_and_modload(char *console, cons switch_event_fire(&event); } -//#define USE_MLOCKALL -#ifdef HAVE_MLOCKALL -#ifdef USE_MLOCKALL - mlockall(MCL_CURRENT|MCL_FUTURE); -#endif -#endif - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "\nFreeSWITCH Version %s Started.\nCrash Protection [%s]\nMax Sessions[%u]\n\n", SWITCH_VERSION_FULL, __CP, switch_core_session_limit(0)); return SWITCH_STATUS_SUCCESS; @@ -3696,6 +3746,31 @@ SWITCH_DECLARE(switch_time_t) switch_core_uptime(void) return switch_time_now() - runtime.initiated; } +SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, uint32_t *val) +{ + + if (runtime.shutting_down) { + return -1; + } + + switch (cmd) { + case SCSC_PAUSE_INBOUND: + runtime.no_new_sessions = *val; + 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; + } + + return 0; +} + SWITCH_DECLARE(switch_status_t) switch_core_destroy(void) { switch_event_t *event; @@ -3703,9 +3778,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void) switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Shutting Down"); switch_event_fire(&event); } + runtime.shutting_down = 1; + runtime.no_new_sessions = 1; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "End existing sessions\n"); - switch_core_session_hupall(); + 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(); diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 338125042e..e54c81321d 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -841,6 +841,10 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } if (status == SWITCH_STATUS_BREAK || bytes == 0) { + if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_DATAWAIT)) { + switch_yield(rtp_session->ms_per_packet); + continue; + } return 0; }