FreeSwitch Lua编程接口(1)dialplan里的配置
Dialplan里的配置可以为freeswitch配置一个或若干个号码,当其他的sip终端通过拨打此号码时,通过拨号路由,查找到此号码,从而执行lua脚本。在Dialplan里的配置如下: ? ???? <extension name="1200"> ??????? <condition field="destination_number" expression="^1200$"> ????????? <action application="lua" data="test.lua"/> ??????? </condition> </extension> ? 需要说明的是: dialplan是通过xml寻找拨号规则的,具体流程为: ①sip信令到达,invite消息,抵达sip endpoint的回调机制,例如sofia终端,会到达sip_handle_sip_i_invite函数做相应处理。 ②在sofia_handle_sip_i_invite函数中,建立一个新的session,并未session创建一个channel。在channel中,包含一个caller_profile,这是一个类型为switch_caller_profile_t的结构体,记录了当前呼叫的各种必要属性。Caller_profile里记录了当前的route方式为“XML”,这里明确指明了通过xml文件查询拨号规则。(见该函数里的switch_channel_set_caller_profile(channel,tech_pvt->caller_profile)) ③除此之外,sofia_handle_sip_i_invite还根据sip消息设置channle和session的相关信息,其中包括remote_ip,sip_via_protocl等字段信息。 ④设置完毕后,一个相对较完整的session和channle便存在了,这时,sofia_handle_i_invite会启动session的状态机,根据channel的状态来执行相应处理。 ⑤于是,状态机启动,当执行到routing状态时(参见函数switch_core_session_run,switch_core_state_machine.c)。会执行标准的状态函数switch_core_standard_on_routing,在函数里,查询全局哈希表,得到名字为dpname的dialplan_interface: 108行dialplan_interface = switch_loadable_module_get_dialplan_interface(dpname) dpname为“XML”,该dialplan_interface是在mod_dialplan_xml模块中加加载时插入全局哈希表的。 当然,要首先从channel中取得当前的caller_profile: 85行 caller_profile = switch_channel_get_caller_profile(session->channel) 当找到dialplan_interface时,会调用 dialplan_interface->hunt_function(session,dparg,NULL),实际调用的是 SWITCH_STANDARD_DIALPLAN(dialplan_hunt),定义在mod_dialplan_xml.c中,该函数会查找相应的xml文件,并返回一个switch_caller_extension_t结构,该结构代表了上面xml文件里的标签<extension>…</extension>里的内容。而子文档元素<action application="lua" data="test.lua"/>说明的是,将“lua”应用插入到switch_caller_extension_t结构中,在switch_caller_extension_t中由switch_caller_application_t *applications指针将当前channel需要执行的应用函数串成一个链表。于是,当channel在状态机中状态经过routing,转化为execute时,就会通过switch_core_standard_on_exev()函数一次调用所有应用。 ⑥在这里,dialplan里只添加了一个extension,并且,只添加了一个应用接口,即为”lua”,所以当有拨打1200的sip消息到来时,将会在channel->state = on_execute时调用该应用。同样,会查询全局哈希表,找到application_interface,然后调用application_interface,调用流程如下: switch_core_standard_on_execute(session) switch_core_session_execute_application //宏,实际为switch_core_session_execute_application_get_flags switch_core_session_exec(session,application_interface,arg)//arg = “***.lua” 于是,就进入了lua的app应用接口 在mod_lua.cpp中得SWITCH_STANDARD_APP(lua_function)函数 ? Lua执行分析App函数展开SWITCH_STANDARD_APP(lua_function)展开后为: lua_function(switch_core_session_t *session,const char *data); 这里传入的data即是“***.lua”即lua的文件名。 ? Lua_function主要工作1.??????? 调用lua_init()函数为当前执行脚本创建一个lua_State实例,并用lua_State *L指针指向。 2.??????? 调用mod_lua_conjure_session(L,session,"session",1),创建一个Session类,该类从freeswitch提供的CoreSession类公有继承而来。其中,实参session指向的便是在sip_handle_sip_i_invite里新创建的switch_core_session_t类型的实例。 3.??????? 调用lua_parse_and_execute(L,mycmd)读取脚本文件并解释执行。mycmd=”***.lua” ? 具体的执行具体执行是在lua_parse_and_execute(…)函数里用 174行 error = luaL_loadfile(L,file) || docall(L,1) 语句完成的。 luaL_loadfile函数负责读取文件,docall函数负责解释执行。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |