]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add session counter and make all sessions hang up elegantly on shutdown
authorAnthony Minessale <anthony.minessale@gmail.com>
Fri, 7 Jul 2006 18:59:14 +0000 (18:59 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Fri, 7 Jul 2006 18:59:14 +0000 (18:59 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@1788 d0543943-73ff-0310-b7d9-9358b9ac24b2

conf/freeswitch.xml
src/include/switch_core.h
src/include/switch_types.h
src/switch.c
src/switch_channel.c
src/switch_core.c

index 43d7e89028b4b700fe47a57961e18fbd6b5e7902..48f23b2d195a829e7fcd308b928048ad0c179aec 100644 (file)
@@ -1,6 +1,12 @@
 <?xml version="1.0"?>
 <document type="freeswitch/xml">
   <section name="configuration" description="Various Configuration">
+    <configuration name="modules.conf" description="Modules">
+      <settings>
+        <!--Most channels to allow at once -->
+        <param name="max-sessions" value="1000"/>
+      </settings>
+    </configuration>
     <configuration name="modules.conf" description="Modules">
       <modules>
         <!-- Loggers (I'd load these first) -->
index 95ef2073b6ec7ad384a086f5ea84c9d53d9bcd34..e4c6b79ca703188156ecf8fdebe48ca590eb6bb0 100644 (file)
@@ -116,6 +116,13 @@ struct switch_core_runtime;
 */
 SWITCH_DECLARE(switch_status_t) switch_core_init(char *console, const char **err);
 
+/*! 
+  \brief Set/Get Session Limit
+  \param new new value (if > 0)
+  \return the current session limit
+*/
+SWITCH_DECLARE(uint32_t) switch_core_session_limit(uint32_t new);
+
 /*! 
   \brief Destroy the core
   \note to be called at application shutdown
@@ -309,6 +316,11 @@ SWITCH_DECLARE(char *) switch_core_session_get_uuid(switch_core_session_t *sessi
 */
 SWITCH_DECLARE(switch_core_session_t *) switch_core_session_locate(char *uuid_str);
 
+/*! 
+  \brief Hangup All Sessions
+*/
+SWITCH_DECLARE(void) switch_core_session_hupall(void);
+
 /*! 
   \brief Send a message to another session using it's uuid
   \param uuid_str the unique id of the session you want to send a message to
index 072812a13a9c4b2143d505b105ec4d49d8564c2b..0db6c0fd4141485c3578fdc6306a7c3a6e15e5e5 100644 (file)
@@ -619,7 +619,8 @@ typedef enum {
        SWITCH_CAUSE_MANDATORY_IE_LENGTH_ERROR = 103,
        SWITCH_CAUSE_PROTOCOL_ERROR = 111,
        SWITCH_CAUSE_INTERWORKING = 127,
-       SWITCH_CAUSE_CRASH = 500
+       SWITCH_CAUSE_CRASH = 500,
+       SWITCH_CAUSE_SYSTEM_SHUTDOWN = 501
 } switch_call_cause_t;
 
 
index 41b0d170c812c6b2723fea1d2499fff0132ba7ed..0048050766e1b0d84070d8db40cef471bc880213 100644 (file)
@@ -188,7 +188,7 @@ int main(int argc, char *argv[])
 #define __CP "DISABLED"
 #endif
 
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "freeswitch Version %s Started. Crash Protection [%s]\n\n", SWITCH_VERSION_FULL, __CP);
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "freeswitch Version %s Started. Crash Protection [%s] Max Sessions[%u]\n\n", SWITCH_VERSION_FULL, __CP, switch_core_session_limit(0));
        snprintf(path, sizeof(path), "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, pfile);
 
        if (bg) {
@@ -217,6 +217,8 @@ int main(int argc, char *argv[])
                switch_event_fire(&event);
        }
 
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "End existing sessions\n");
+       switch_core_session_hupall();
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Clean up modules.\n");
        switch_loadable_module_shutdown();
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Tearing down environment.\n");
index e3189822f119921af9201508d14d5ab8e0ab1c70..599dfca64efdd00e557b63f721bb26b12b2fdb23 100644 (file)
@@ -83,6 +83,7 @@ static struct switch_cause_table CAUSE_CHART[] = {
        { "PROTOCOL_ERROR", SWITCH_CAUSE_PROTOCOL_ERROR },
        { "INTERWORKING", SWITCH_CAUSE_INTERWORKING },
        { "CRASH", SWITCH_CAUSE_CRASH },
+       { "SYSTEM_SHUTDOWN", SWITCH_CAUSE_SYSTEM_SHUTDOWN },
        { NULL, 0 }
 };
 
index 4fce2527477d156f7b2a6c3f96586f04bbc67fab..f77a8d72f058b166c0bbb27041bfddc6841e5c08 100644 (file)
@@ -85,6 +85,7 @@ struct switch_core_runtime {
        uint32_t session_id;
        apr_pool_t *memory_pool;
        switch_hash_t *session_table;
+       switch_mutex_t *session_table_mutex;
 #ifdef CRASH_PROT
        switch_hash_t *stack_table;
 #endif
@@ -93,6 +94,8 @@ struct switch_core_runtime {
        const switch_state_handler_table_t *state_handlers[SWITCH_MAX_STATE_HANDLERS];
     int state_handler_index;
        FILE *console;
+       uint32_t session_count;
+       uint32_t session_limit;
        switch_queue_t *sql_queue;
 };
 
@@ -246,6 +249,8 @@ SWITCH_DECLARE(void) switch_core_session_rwunlock(switch_core_session_t *session
 SWITCH_DECLARE(switch_core_session_t *) switch_core_session_locate(char *uuid_str)
 {
        switch_core_session_t *session;
+
+       switch_mutex_lock(runtime.session_table_mutex);
        if ((session = switch_core_hash_find(runtime.session_table, uuid_str))) {
                /* Acquire a read lock on the session */
                if (switch_thread_rwlock_tryrdlock(session->rwlock) != SWITCH_STATUS_SUCCESS) {
@@ -253,16 +258,41 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_locate(char *uuid_st
                        session = NULL;
                }
        }
+       switch_mutex_unlock(runtime.session_table_mutex);
 
        /* if its not NULL, now it's up to you to rwunlock this */
        return session;
 }
 
+SWITCH_DECLARE(void) switch_core_session_hupall(void)
+{
+       switch_hash_index_t *hi;
+       void *val;
+       switch_core_session_t *session;
+       switch_channel_t *channel;
+
+       switch_mutex_lock(runtime.session_table_mutex);
+       for (hi = switch_hash_first(runtime.memory_pool, runtime.session_table); hi; hi = switch_hash_next(hi)) {
+        switch_hash_this(hi, NULL, NULL, &val);
+               if (val) {
+                       session = (switch_core_session_t *) val;
+                       channel = switch_core_session_get_channel(session);
+                       switch_channel_hangup(channel, SWITCH_CAUSE_SYSTEM_SHUTDOWN);
+               }
+       }
+       switch_mutex_unlock(runtime.session_table_mutex);
+
+       while(runtime.session_count) {
+               switch_yield(1000);
+       }
+}
+
 SWITCH_DECLARE(switch_status_t) switch_core_session_message_send(char *uuid_str, switch_core_session_message_t *message)
 {
        switch_core_session_t *session = NULL;
        switch_status_t status = SWITCH_STATUS_FALSE;
 
+       switch_mutex_lock(runtime.session_table_mutex);
        if ((session = switch_core_hash_find(runtime.session_table, uuid_str)) != 0) {
                /* Acquire a read lock on the session or forget it the channel is dead */
                if (switch_thread_rwlock_tryrdlock(session->rwlock) == SWITCH_STATUS_SUCCESS) {
@@ -272,6 +302,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_message_send(char *uuid_str,
                        switch_thread_rwlock_unlock(session->rwlock);
                }
        }
+       switch_mutex_unlock(runtime.session_table_mutex);
 
        return status;
 }
@@ -281,6 +312,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_event_send(char *uuid_str, s
        switch_core_session_t *session = NULL;
        switch_status_t status = SWITCH_STATUS_FALSE;
 
+       switch_mutex_lock(runtime.session_table_mutex);
        if ((session = switch_core_hash_find(runtime.session_table, uuid_str)) != 0) {
                /* Acquire a read lock on the session or forget it the channel is dead */
                if (switch_thread_rwlock_tryrdlock(session->rwlock) == SWITCH_STATUS_SUCCESS) {
@@ -290,6 +322,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_event_send(char *uuid_str, s
                        switch_thread_rwlock_unlock(session->rwlock);
                }
        }
+       switch_mutex_unlock(runtime.session_table_mutex);
 
        return status;
 }
@@ -2344,6 +2377,9 @@ SWITCH_DECLARE(void) switch_core_session_destroy(switch_core_session_t **session
        apr_pool_destroy(pool);
        pool = NULL;
 
+       switch_mutex_lock(runtime.session_table_mutex);
+       runtime.session_count--;
+       switch_mutex_unlock(runtime.session_table_mutex);
 }
 
 SWITCH_DECLARE(switch_status_t) switch_core_hash_init(switch_hash_t **hash, switch_memory_pool_t *pool)
@@ -2434,18 +2470,21 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thre
 {
        switch_core_session_t *session = obj;
        session->thread = thread;
-       session->id = runtime.session_id++;
-
        snprintf(session->name, sizeof(session->name), "%u", session->id);
-
+       switch_mutex_lock(runtime.session_table_mutex);
+       session->id = runtime.session_id++;
        switch_core_hash_insert(runtime.session_table, session->uuid_str, session);
+       switch_mutex_unlock(runtime.session_table_mutex);
+
        switch_core_session_run(session);
        
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session %u (%s) Locked, Waiting on external entities\n", session->id, switch_channel_get_name(session->channel));
        switch_core_session_write_lock(session);
        switch_core_session_rwunlock(session);
 
+       switch_mutex_lock(runtime.session_table_mutex);
        switch_core_hash_delete(runtime.session_table, session->uuid_str);
+       switch_mutex_unlock(runtime.session_table_mutex);
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Session %u (%s) Ended\n", session->id, switch_channel_get_name(session->channel));
        switch_core_session_destroy(&session);
        return NULL;
@@ -2503,9 +2542,19 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request(const switch
        switch_memory_pool_t *usepool;
        switch_core_session_t *session;
        switch_uuid_t uuid;
+       uint32_t count = 0;
 
        assert(endpoint_interface != NULL);
 
+       switch_mutex_lock(runtime.session_table_mutex);
+       count = runtime.session_count;
+       switch_mutex_unlock(runtime.session_table_mutex);
+
+       if ((count + 1) > runtime.session_limit) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Over Session Limit!\n");
+               return NULL;
+       }
+
        if (pool) {
                usepool = pool;
        } else if (switch_core_new_memory_pool(&usepool) != SWITCH_STATUS_SUCCESS) {
@@ -2551,6 +2600,9 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request(const switch
        switch_thread_cond_create(&session->cond, session->pool);
        switch_thread_rwlock_create(&session->rwlock, session->pool);
 
+       switch_mutex_lock(runtime.session_table_mutex);
+       runtime.session_count++;
+       switch_mutex_unlock(runtime.session_table_mutex);
        return session;
 }
 
@@ -2806,10 +2858,22 @@ SWITCH_DECLARE(void) switch_core_set_globals(void)
 #endif
 }
 
+
+SWITCH_DECLARE(uint32_t) switch_core_session_limit(uint32_t new)
+{
+       if (new) {
+               runtime.session_limit = new;
+       }
+       
+       return runtime.session_limit;
+}
+
 SWITCH_DECLARE(switch_status_t) switch_core_init(char *console, const char **err)
 {
        memset(&runtime, 0, sizeof(runtime));
-       
+       runtime.session_limit = 1000;
+       switch_xml_t xml = NULL, cfg = NULL;
+
        switch_core_set_globals();
 
        /* INIT APR and Create the pool context */
@@ -2830,6 +2894,23 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(char *console, const char **err
                return SWITCH_STATUS_MEMERR;
        }
 
+
+       if ((xml = switch_xml_open_cfg("switch.conf", &cfg, NULL))) {
+               switch_xml_t settings, param;
+               
+               if ((settings = switch_xml_child(cfg, "settings"))) {
+                       for (param = switch_xml_child(settings, "param"); param; param = param->next) {
+                               char *var = (char *) switch_xml_attr_soft(param, "name");
+                               char *val = (char *) switch_xml_attr_soft(param, "value");
+                               
+                               if (!strcasecmp(var, "max-sessions")) {
+                                       runtime.session_limit = atoi(val);
+                               }
+                       }
+               }
+               switch_xml_free(xml);
+       }
+
        *err = NULL;
 
        if(console) {
@@ -2909,6 +2990,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(char *console, const char **err
        runtime.session_id = 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
        switch_core_hash_init(&runtime.stack_table, runtime.memory_pool);
 #endif