昆明做网站建设有哪些,鼓楼微网站开发,搜索引擎优化效果,广东建设安全质量协会网站unimrcp使用APR的内存池管理内存#xff0c;因此#xff0c;处理函数中一般都会传递一个pool指针#xff0c;需要内存时#xff0c;就从pool里分配一块#xff0c;一般也不需要关心内存的释放。因为#xff0c;一路呼叫关联一个session#xff0c;一个session对应一个po… unimrcp使用APR的内存池管理内存因此处理函数中一般都会传递一个pool指针需要内存时就从pool里分配一块一般也不需要关心内存的释放。因为一路呼叫关联一个session一个session对应一个pool。那么这个poll是怎么生成的又是怎样回收的呢
首先看一下mrcp_session_t结构的定义libs\mrcp-signaling\include\mrcp_session.h
struct mrcp_session_t {/** Memory pool to allocate memory from */apr_pool_t *pool;/** Whether the memory pool is self-owned or not */apt_bool_t self_owned;/** External object associated with session */void *obj;/** External logger object associated with session */void *log_obj;/** Informative name of the session used for debugging */const char *name;/** Signaling (session managment) agent */mrcp_sig_agent_t *signaling_agent;/** MRCPv2 connection agent, if any */void *connection_agent;/** Media processing engine */mpf_engine_t *media_engine;/** RTP termination factory */mpf_termination_factory_t *rtp_factory;/** Session identifier */apt_str_t id;/** Last request identifier sent for client, received for server */mrcp_request_id last_request_id;/** Virtual request methods */const mrcp_session_request_vtable_t *request_vtable;/** Virtual response methods */const mrcp_session_response_vtable_t *response_vtable;/** Virtual event methods */const mrcp_session_event_vtable_t *event_vtable;/** Custom headers */apr_table_t *custom_headers;/** Trace ID*/apt_str_t trace_id;
}; 在unimrcpserver启动时会加载一个sofiasip_task线程它的任务是接收处理SIP消息线程函数调用mrcp_sofia_task_run():
static apt_bool_t mrcp_sofia_task_run(apt_task_t *base)
{mrcp_sofia_task_t *task apt_task_object_get(base);if(!task-root || !task-nua) {apt_log(SIP_LOG_MARK,APT_PRIO_WARNING,Failed to Run Sofia-SIP Task);return FALSE;}/* Run event loop */su_root_run(task-root);apt_task_terminate_request_process(base);return TRUE;
}很简单就是su_base_port_run()函数(su_base_port.c)。
void su_base_port_run(su_port_t *self)
{su_duration_t tout 0, tout2 0;assert(su_port_own_thread(self));for (self-sup_running 1; self-sup_running;) {tout self-sup_max_defer;if (self-sup_prepoll)self-sup_prepoll(self-sup_pp_magic, self-sup_pp_root);if (self-sup_head)self-sup_vtable-su_port_getmsgs(self); if (self-sup_timers || self-sup_deferrable) {su_time_t now su_now();su_timer_expire(self-sup_timers, tout, now);su_timer_expire(self-sup_deferrable, tout2, now);}if (!self-sup_running)break;if (self-sup_head) /* if there are messages do a quick wait */tout 0;su_base_port_wait_events(self, tout);}
}当SIP消息到来时执行self-sup_vtable-su_port_getmsgs(self); 其实调用的是su_base_port_execute_msgs()函数(su_base_port.c)
static int su_base_port_execute_msgs(su_msg_t *queue)
{su_msg_t *msg;int n 0;for (msg queue; msg; msg queue) {su_msg_f f msg-sum_func;queue msg-sum_next, msg-sum_next NULL;if (f) {su_root_t *root msg-sum_to-sut_root;if (msg-sum_to-sut_port NULL)msg-sum_to-sut_root NULL;f(SU_ROOT_MAGIC(root), msg, msg-sum_data); } su_msg_delivery_report(msg);n;}return n;
}f(SU_ROOT_MAGIC(root), msg, msg-sum_data);这里f指向nua_application_event()函数它的实现在nua_stack.c:
关键调用在下面这一行 nua-nua_callback((enum nua_event_e)e-e_event, e-e_status, e-e_phrase,nua, nua-nua_magic,nh, nh ? nh-nh_magic : NULL,e-e_msg ? sip_object(e-e_msg) : NULL,e-e_tags);这个nua_callback批向mrcp_sofia_event_callback()函数它在mrcp_sofiasip_server_agent.c里实现。它分发处理SIP消息。如果是INVITE消息就是这个分支
case nua_i_invite:mrcp_sofia_on_invite(sofia_agent,nh,sofia_session,sip,tags);break;
跳转进去它调用mrcp_sofia_session_create()函数分配session对象
sofia_session mrcp_sofia_session_create(sofia_agent,nh);if(!sofia_session) {nua_respond(nh, SIP_488_NOT_ACCEPTABLE, TAG_END());return;}
static mrcp_sofia_session_t* mrcp_sofia_session_create(mrcp_sofia_agent_t *sofia_agent, nua_handle_t *nh)
{mrcp_sofia_session_t *sofia_session;mrcp_session_t* session sofia_agent-sig_agent-create_server_session(sofia_agent-sig_agent);if(!session) {return NULL;}session-response_vtable session_response_vtable;session-event_vtable session_event_vtable;sofia_session apr_palloc(session-pool,sizeof(mrcp_sofia_session_t));sofia_session-home su_home_new(sizeof(*sofia_session-home));sofia_session-session session;session-obj sofia_session;nua_handle_bind(nh, sofia_session);sofia_session-nh nh;mrcp_session_attribs_init(sofia_session-attribs);sofia_session-trace_id NULL;return sofia_session;
}这一行mrcp_session_t* session sofia_agent-sig_agent-create_server_session(sofia_agent-sig_agent);又跳转到 mrcp_server_sig_agent_session_create()函数它在mrcp_server.c里实现。
static mrcp_session_t* mrcp_server_sig_agent_session_create(mrcp_sig_agent_t *signaling_agent)
{mrcp_server_t *server signaling_agent-parent;mrcp_server_session_t *session mrcp_server_session_create();session-server server;session-profile mrcp_server_profile_get_by_agent(server,session,signaling_agent);if(!session-profile) {apt_log(APT_LOG_MARK,APT_PRIO_WARNING,Cannot Find Profile by Agent APT_NAMESID_FMT,session-base.name,MRCP_SESSION_SID(session-base));mrcp_session_destroy(session-base);return NULL;}apt_log(APT_LOG_MARK,APT_PRIO_INFO,Create Session APT_NAMESID_FMT [%s],session-base.name,MRCP_SESSION_SID(session-base), session-profile-id);session-base.signaling_agent signaling_agent;session-base.request_vtable session_request_vtable;return session-base;
}这里调用mrcp_server_session_create()分配对象跳转到mrcp_server_session.c。
mrcp_server_session_t* mrcp_server_session_create()
{mrcp_server_session_t *session (mrcp_server_session_t*) mrcp_session_create(sizeof(mrcp_server_session_t)-sizeof(mrcp_session_t));session-context NULL;session-terminations apr_array_make(session-base.pool,2,sizeof(mrcp_termination_slot_t));session-channels apr_array_make(session-base.pool,2,sizeof(mrcp_channel_t*));session-active_request NULL;session-request_queue apt_list_create(session-base.pool);session-offer NULL;session-answer NULL;session-last_offer NULL;session-last_answer NULL;session-mpf_task_msg NULL;session-subrequest_count 0;session-state SESSION_STATE_NONE;session-base.name apr_psprintf(session-base.pool,0x%pp,session);return session;
}
调用mrcp_session_create()函数可以在mrcp_sig_agent.c里找到。
MRCP_DECLARE(mrcp_session_t*) mrcp_session_create(apr_size_t padding)
{apr_pool_t *pool apt_pool_create();if(!pool) {return NULL;}return mrcp_session_create_ex(pool,TRUE,padding);
}
这里的apr_pool_create()就是根源了。 那么 这个pool是在哪释放的呢
实现plugin时要实现mrcp_engine_channel_method_vtable_t这个接口里面有一个close函数但是这个函数并不会直正释放资源只是告知channel即将被关闭。如果处理结束需要向server 对象发一条信号。
以demo_recog_engine为例
/** Close engine channel (asynchronous response MUST be sent)*/
static apt_bool_t demo_recog_channel_close(mrcp_engine_channel_t *channel)
{return demo_recog_msg_signal(DEMO_RECOG_MSG_CLOSE_CHANNEL,channel,NULL);
}这个信号是可以异步给的。引擎核心只有收到这个信号才会回SIP BYE消息并真正释放资源。
mrcp_server.c的mrcp_server_msg_process()函数是处理这个信号的地方。跟踪一下一路的调用链条是
mrcp_server_on_engine_channel_close()mrcp_server_session_subrequest_remove()mrcp_server_session_terminate_send()mrcp_session_terminate_responsemrcp_sofia_on_session_terminate()apr_pool_destroy()