FreeSwitch系列之mod_sofia启动流程

模块加载过程

启动事件处理线程池

启动事件处理线程池 :

SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
    => sofia_msg_thread_start(0);
        => sofia_msg_thread_run
            => sofia_process_dispatch_event
                => our_sofia_event_callback : 处理消息

这个线程的主要流程很简单就是从队列mod_sofia_globals.msg_queue

取出消息,消息结构体是sofia_dispatch_event_t,然后执行

sofia_process_dispatch_event(&de)
    our_sofia_event_callback(de->data->e_event, de->data->e_status, de->data->e_phrase, de->nua, de->profile,
                             de->nh, sofia_private, de->sip, de, (tagi_t *) de->data->e_tags);

启动服务器监听

SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
    => config_sofia(0, NULL)
        => launch_sofia_profile_thread
            => sofia_profile_thread_run                
                => nua_create
                    => su_home_new
                    => nua_stack_init                    
                        => nta_agent_create
                            => nta_agent_add_tport                            
                                => tport_tbind
                                    => tport_bind_server
                                        => tport_listen : 监听客户端发来的数据   

 

1、sip默认有4个profile,internal、internal-ipv6、external、external-ipv6,所以会启动4条sofia_profile_thread_run线程,4个UA互不干扰。

2、profile线程的主流程

profile->s_root = su_root_create(NULL);
sofia_glue_init_sql(profile);
profile->nua = nua_create(profile->s_root,  /* Event loop */
                                  sofia_event_callback, /* Callback for processing events */
                                  profile,...);

switch_snprintf(qname, sizeof(qname), "sofia:%s", profile->name);
switch_sql_queue_manager_init_name(qname, &profile->qm, 2 ...);
switch_sql_queue_manager_start(profile->qm);

worker_thread = launch_sofia_worker_thread(profile);

while (mod_sofia_globals.running == 1 && sofia_test_pflag(profile, PFLAG_RUNNING) && sofia_test_pflag(profile, PFLAG_WORKER_RUNNING)) {
        su_root_step(profile->s_root, 1000);
        profile->last_root_step = switch_time_now();
}

通过代码可以看到profile线程创建了几个主要的线程:

2.1 调用协议栈API创建UA代理,并设置了回调sofia_event_callback。这边启动了clone_main线程。

2.2 数据库操作是在单独线程执行。

2.3 创建了profile worker线程。

方便术语统一分别称之为:

  • profile主线程
  • profile clone线程
  • profile db线程
  • profile worker线程

3、各个线程做了什么:

profile worker线程:从实际队列mod_sofia_globals.general_event_queue弹出一个事件对象,然后调用general_event_handler(event)处理该对象。所以general_event_handler用来处理事件消息。

        if (switch_queue_pop_timeout(mod_sofia_globals.general_event_queue, &pop, 100000) == SWITCH_STATUS_SUCCESS) {

            do {
                switch_event_t *event = (switch_event_t *) pop;
                general_event_handler(event);
                switch_event_destroy(&event);

                pop = NULL;
                switch_queue_trypop(mod_sofia_globals.general_event_queue, &pop);
            } while (pop);

        }

profile clone线程:实际接收消息的线程,并对消息进行处理。

可以看到几个点:

1、底层的wait事件的回调函数是tport_wakeup_pri

2、leg接收消息的回调函数是nua_stack_process_request

3、nua代理的回调函数是sofia_event_callback

nua->nua_api_root = root;
su_task_copy(nua->nua_client, su_root_task(root));
su_clone_start(root,nua->nua_clone,nua,nua_stack_init,nua_stack_deinit);
  => arg.create=su_epoll_port_create
  => arg.parent = root
  => arg.magic = nua
  => su_pthread_port_clone_main
    => task->sut_port = su_epoll_port_create();
    => task->sut_root = su_salloc(su_port_home(task->sut_port), sizeof * task->sut_root);
    => nua_stack_init(task->sut_root, arg->magic);
      =>nua->nua_root=task->sut_root
      =>nua_handle_t *dnh=su_home_clone(nua->nua_home, sizeof(*dnh) + sizeof(*dnh->nh_prefs));
      =>nua->nua_nta = nta_agent_create(root, NONE, NULL, NULL,..);
        =>agent = su_home_new(sizeof(*agent);
        =>incoming_queue_init(agent->sa_in..)
        =>outgoing_queue_init(agent->sa_out..)
        =>nta_agent_add_tport(agent, contact_url, ta_tags(ta)
          =>agent->sa_tports = tport_tcreate(agent, nta_agent_class, agent->sa_root, TPTAG_IDLE(1800000), TAG_NEXT(tags));
          =>tport_tbind(agent->sa_tports, tpn, tports, ta_tags(ta)
            =>tport_bind_server(mr, mytpn, transports, (enum tport_via)public, ta_args(ta));
              =>vtable = tport_vtable_by_name(ai->ai_canonname, public);
              =>tport_primary_t *pri = tport_listen(mr, vtable, tpname, ainfo, tags);
                =>pri = tport_alloc_primary(mr, vtable, tpn, ai, tags, &culprit);
                  =>vtable->vtp_init_primary(pri, tpn, ai, tags, return_culprit)
                =>su_wait_create(wait, tp->tp_socket, tp->tp_events);
                =>tport_t *tp = pri->pri_primary;
                =>tp->index = su_root_register(mr->mr_root, wait, tport_wakeup_pri, tp, 0);
      =>dnh->nh_ds->ds_leg = nta_leg_tcreate(nua->nua_nta, nua_stack_process_request, dnh, NTATAG_NO_DIALOG(1), TAG_END());
        =>leg = su_home_clone(NULL, sizeof(*leg);
        =>leg->leg_agent = agent;
        =>leg->leg_callback  = nua_stack_process_request
        =>leg->leg_magic = dnh
        =>agent->sa_default_leg = leg;
    => su_root_run(task->sut_root);
su_task_copy(nua->nua_server, su_clone_task(nua->nua_clone));
nua->nua_callback = sofia_event_callback;
nua->nua_magic = magic;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值