- 初始化
session在switch_core_session.c实现,在switch_core_pvt.h定义相关数据结构。在第2章节初始化的时候,在核心初始化里会调用session初始化。
- void switch_core_session_init(switch_memory_pool_t *pool)
- {
- memset(&session_manager, 0, sizeof(session_manager));
- session_manager.session_limit = 1000;
- session_manager.session_id = 1;
- session_manager.memory_pool = pool;
- switch_core_hash_init(&session_manager.session_table);
- switch_mutex_init(&session_manager.mutex, SWITCH_MUTEX_DEFAULT, session_manager.memory_pool);
- switch_thread_cond_create(&session_manager.cond, session_manager.memory_pool);
- switch_queue_create(&session_manager.thread_queue, 100000, session_manager.memory_pool);
- }
...
- struct switch_session_manager {
- switch_memory_pool_t *memory_pool;
- switch_hash_t *session_table;
- uint32_t session_count;
- uint32_t session_limit;
- switch_size_t session_id;
- switch_queue_t *thread_queue;
- switch_mutex_t *mutex;
- switch_thread_cond_t *cond;
- int running;
- int busy;
- };
- extern struct switch_session_manager session_manager;
初始化内容比较简单,就是对session全局结构体session_manager进行初始化默认值。这个结构体管理以后创建的会话,其中哈希表session_table作为会话容器,session_count表示当前会话个数,session_limit限制最大会话个数,session_id每次创建都会++,为会话生成唯一id,thread_queue线程队列,运行sesson可以使用此线程池,当然也可以不用线程池。
- 创建session
当收到invite信令的时候,sip逻辑层mod_sofia就会调用switch_core_session_request_uuid创建会话。
- SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(switch_endpoint_interface_t
- *endpoint_interface,
- switch_call_direction_t direction,
- switch_originate_flag_t originate_flags,
- switch_memory_pool_t **pool, const char *use_uuid)
- {
- switch_memory_pool_t *usepool;
- switch_core_session_t *session;
- switch_uuid_t uuid;
- //判断是否已经添加到哈希表
- if (use_uuid && switch_core_hash_find(session_manager.session_table, use_uuid)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Duplicate UUID!\n");
- return NULL;
- }
- //申请switch_core_session_t内存
- session = switch_core_alloc(usepool, sizeof(*session));
- session->pool = usepool;
- switch_core_memory_pool_set_data(session->pool, "__session", session);
- //申请session的channel内存
- if (switch_channel_alloc(&session->channel, direction, session->pool) != SWITCH_STATUS_SUCCESS) {
- abort();
- }
- //初始化channel
- switch_channel_init(session->channel, session, CS_NEW, 0);
- if (direction == SWITCH_CALL_DIRECTION_OUTBOUND) {
- switch_channel_set_flag(session->channel, CF_OUTBOUND);
- }
- //设置一些session和channel的值
- if (use_uuid) {
- switch_set_string(session->uuid_str, use_uuid);
- } else {
- switch_uuid_get(&uuid);
- switch_uuid_format(session->uuid_str, &uuid);
- }
- switch_channel_set_variable(session->channel, "uuid", session->uuid_str);
- switch_channel_set_variable(session->channel, "call_uuid", session->uuid_str);
- session->endpoint_interface = endpoint_interface;
- ...
- //创建消息队列
- switch_queue_create(&session->message_queue, SWITCH_MESSAGE_QUEUE_LEN, session->pool);
- //添加当前会话到会话容器哈希表,更新session_manager的一些值
- switch_mutex_lock(runtime.session_hash_mutex);
- switch_core_hash_insert(session_manager.session_table, session->uuid_str, session);
- session->id = session_manager.session_id++;
- session_manager.session_count++;
- switch_mutex_unlock(runtime.session_hash_mutex);
- switch_channel_set_variable_printf(session->channel, "session_id", "%u", session->id);
- return session;
- }
每个session对应一个channel,session更多地是描述信令状态,channel更多地描述传输状态。创建session的时候,同时会创建channel,session会添加到会话管理session_manager。创建的时候,会初始化session和channel的一些变量,这里比较重要的是session的消息队列message_queue。channel本章节先不讨论,下面看看session结构体。
- struct switch_core_session {
- switch_memory_pool_t *pool;
- switch_thread_t *thread;
- switch_thread_id_t thread_id;
- switch_endpoint_interface_t *endpoint_interface;
- switch_size_t id;
- switch_session_flag_t flags;
- switch_channel_t *channel;
- //codec相关
- switch_codec_t
- //消息队列
- switch_queue_t *event_queue;
- switch_queue_t *message_queue;
- //读写缓冲区相关
- switch_buffer_t *raw_write_buffer;
- switch_frame_t raw_write_frame;
- switch_frame_t enc_write_frame;
- uint8_t raw_write_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
- uint8_t enc_write_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
- switch_buffer_t *raw_read_buffer;
- switch_frame_t raw_read_frame;
- switch_frame_t enc_read_frame;
- uint8_t raw_read_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
- uint8_t enc_read_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
- };
session结构体有不少成员,这里列出比较重要的,一个session会有一个线程thread来处理消息,消息队列message_queue;有一个channel,有codec相关的结构体,读写一帧的缓冲区等。
- session线程
创建完session之后,还不能工作,会随后创建并启动session线程,至于在什么时候启动,后面分析mod_sofia会分析。这里查看session相关的API,启动session线程的接口有四个。
- //创建线程的四个接口
- switch_thread_pool_launch_thread(switch_thread_data_t **tdp);
- switch_core_session_thread_pool_launch(switch_core_session_t *session);
- switch_core_session_thread_launch(_In_ switch_core_session_t *session);
- switch_core_session_launch_thread(_In_ switch_core_session_t *session,
- _In_ void *(*func) (switch_thread_t *, void *), _In_opt_ void *obj);
前面两个是使用线程池,后面两个是普通线程。
- SWITCH_DECLARE(switch_status_t) switch_thread_pool_launch_thread(switch_thread_data_t **tdp)
- {
- switch_status_t status = SWITCH_STATUS_SUCCESS;
- switch_thread_data_t *td;
- td = *tdp;
- *tdp = NULL;
- status = switch_queue_push(session_manager.thread_queue, td);
- check_queue();
- return status;
- }
- SWITCH_DECLARE(switch_status_t) switch_core_session_thread_pool_launch(switch_core_session_t *session)
- {
- switch_status_t status = SWITCH_STATUS_INUSE;
- switch_thread_data_t *td;
- switch_mutex_lock(session->mutex);
- if (switch_test_flag(session, SSF_THREAD_RUNNING)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot double-launch thread!\n");
- } else if (switch_test_flag(session, SSF_THREAD_STARTED)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot launch thread again after it has already been run!\n");
- } else {
- switch_set_flag(session, SSF_THREAD_RUNNING);
- switch_set_flag(session, SSF_THREAD_STARTED);
- td = switch_core_session_alloc(session, sizeof(*td));
- td->obj = session;
- td->func = switch_core_session_thread;
- status = switch_queue_push(session_manager.thread_queue, td);
- check_queue();
- }
- switch_mutex_unlock(session->mutex);
- return status;
- }
如果使用线程池,则添加到会话管理session_manager.thread_queue线程队列,switch_thread_pool_launch_thread的线程执行函数由外部传入,switch_core_session_thread_pool_launch的线程执行函数是switch_core_session_thread,由此猜测,第一个函数主要给外部模块调用,第二个供core调用。然后再看看非线程池的两个接口。
- SWITCH_DECLARE(switch_status_t) switch_core_session_thread_launch(switch_core_session_t *session)
- {
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_thread_t *thread;
- switch_threadattr_t *thd_attr;
- if (switch_test_flag(session, SSF_THREAD_RUNNING) || switch_test_flag(session, SSF_THREAD_STARTED)) {
- status = SWITCH_STATUS_INUSE;
- goto end;
- }
- if (switch_test_flag((&runtime), SCF_SESSION_THREAD_POOL)) {
- return switch_core_session_thread_pool_launch(session);
- }
- switch_mutex_lock(session->mutex);
- if (switch_test_flag(session, SSF_THREAD_RUNNING)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot double-launch thread!\n");
- } else if (switch_test_flag(session, SSF_THREAD_STARTED)) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot launch thread again after it has already been run!\n");
- } else {
- switch_set_flag(session, SSF_THREAD_RUNNING);
- switch_set_flag(session, SSF_THREAD_STARTED);
- switch_threadattr_create(&thd_attr, session->pool);
- switch_threadattr_detach_set(thd_attr, 1);
- switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
- if (switch_thread_create(&thread, thd_attr, switch_core_session_thread, session, session->pool) == SWITCH_STATUS_SUCCESS) {
- switch_set_flag(session, SSF_THREAD_STARTED);
- status = SWITCH_STATUS_SUCCESS;
- } else {
- switch_clear_flag(session, SSF_THREAD_RUNNING);
- switch_clear_flag(session, SSF_THREAD_STARTED);
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot create thread!\n");
- thread_launch_failure();
- }
- }
- switch_mutex_unlock(session->mutex);
- end:
- return status;
- }
- SWITCH_DECLARE(void) switch_core_session_launch_thread(switch_core_session_t *session, switch_thread_start_t func, void *obj)
- {
- switch_thread_t *thread;
- switch_threadattr_t *thd_attr = NULL;
- switch_threadattr_create(&thd_attr, session->pool);
- switch_threadattr_detach_set(thd_attr, 1);
- switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
- if (switch_thread_create(&thread, thd_attr, func, obj, session->pool) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Cannot create thread!\n");
- thread_launch_failure();
- }
- }
同样的,switch_core_session_thread_launch默认使用执行函数switch_core_session_thread,switch_core_session_launch_thread使用外部自定义函数func。还有注意,把session作为参数传给switch_core_session_thread。如果全局配置标志位SCF_SESSION_THREAD_POOL,则使用线程池版本。
- 线程函数
- static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thread, void *obj)
- {
- switch_core_session_t *session = obj;
- session->thread = thread;
- session->thread_id = switch_thread_self();
- switch_core_session_run(session);
- ...
- switch_core_session_destroy(&session);
- return NULL;
- }
session线程函数除了赋值session->thread外,只调用switch_core_session_run。
- 状态机state_machine
- SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session)
- {
- switch_channel_state_t state = CS_NEW, midstate = CS_DESTROY, endstate;
- const switch_endpoint_interface_t *endpoint_interface;
- const switch_state_handler_table_t *driver_state_handler = NULL;
- const switch_state_handler_table_t *application_state_handler = NULL;
- endpoint_interface = session->endpoint_interface;
- driver_state_handler = endpoint_interface->state_handler;
- state = switch_channel_get_state(session->channel);
- if (state != switch_channel_get_running_state(session->channel))
- {
- switch (state) {
- case CS_NEW: /* Just created, Waiting for first instructions */
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) State NEW\n", switch_channel_get_name(session->channel));
- break;
- case CS_INIT: /* Basic setup tasks */
- {
- STATE_MACRO(init, "INIT");
- }
- break;
- ...
- default:
- break;
- }
- }
- }
如果channel的状态改变,则根据新状态执行不同的操作,比如CS_NEW只打印一条日志,CS_INIT调用宏STATE_MACRO,这里省略了大部分case,因为基本上都是调用STATE_MACRO。
-
- STATE_MACRO
- #define STATE_MACRO(__STATE, __STATE_STR) do {
- //1、先进行外部回调
- //通道channel的状态回调
- while (do_extra_handlers && (application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) {
- application_state_handler->on_##__STATE(session);
- }
- //runtime的状态回调
- while (do_extra_handlers && proceed && (application_state_handler = switch_core_get_state_handler(index++)) != 0) {
- }
- //2、驱动回调
- if (!driver_state_handler->on_##__STATE || (driver_state_handler->on_##__STATE(session) == SWITCH_STATUS_SUCCESS )) {
- }
- }while (silly)
STATE_MACRO宏展开大概如上,意思其实是调用状态回调接口xx_state_hander,这些回调接口有几类。第一类叫驱动回调driver_state_handler,从driver_state_handler = endpoint_interface->state_handler可以看出,驱动回调在端点接口,比如mod_sofia,在load函数中,会添加这个回调。
- sofia_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
- sofia_endpoint_interface->interface_name = "sofia";
- sofia_endpoint_interface->io_routines = &sofia_io_routines;
- sofia_endpoint_interface->state_handler = &sofia_event_handlers;
- sofia_endpoint_interface->recover_callback = sofia_recover_callback;
- switch_state_handler_table_t sofia_event_handlers = {
- /*.on_init */ sofia_on_init,
- /*.on_routing */ sofia_on_routing,
- /*.on_execute */ sofia_on_execute,
- /*.on_hangup */ sofia_on_hangup,
- /*.on_exchange_media */ sofia_on_exchange_media,
- /*.on_soft_execute */ sofia_on_soft_execute,
- /*.on_consume_media */ NULL,
- /*.on_hibernate */ sofia_on_hibernate,
- /*.on_reset */ sofia_on_reset,
- /*.on_park */ NULL,
- /*.on_reporting */ NULL,
- /*.on_destroy */ sofia_on_destroy
- };
应用回调application_state_handler,可以自定义往channel设置状态回调,然后此时通过switch_channel_get_state_handler就得到那些回调。