freeswitch lua/luarun的执行过程
2018-01-02 15:15
573 查看
在mod_lua.cpp文件中定义了两个api
SWITCH_STANDARD_APP(lua_function)
SWITCH_STANDARD_API(luarun_api_function)
分别对应lua和luarun命令,所有以宏SWITCH_STANDARD_API定义的都是freeswitch暴露的api接口。
我们这里以luarun为例分析
所以当执行luarun的时候主要是调用lua_thread()函数处理。
在lua_thread中主要是创建一个新线程,并在线程里面执行:lua_thread_run
在lua_thread_run中先初始化了一个lua_State,然后调用lua_parse_and_execute去加载lua脚本文件并执行
前面一段都是在处理参数最核心的是下面这一行
加载文件并执行
最后调用lua_pcall执行lua脚本。
下面再介绍一下一个lua的接口怎么找到他对应的c++l代码:
所有的暴露给lua的接口都放在mod_lua_wrap.cpp这文件的swig_type_initial里面,然后lua模块启动的时候会逐个加载。
我们以Session的接口为例介绍一下,他在_swigt__p_CoreSession这个结构体里面描述。
被注册的方法放在swig_CoreSession_methods这个结构体里面:
在这里可以看到很熟悉的answer,bridge等方法了。
SWITCH_STANDARD_APP(lua_function)
SWITCH_STANDARD_API(luarun_api_function)
分别对应lua和luarun命令,所有以宏SWITCH_STANDARD_API定义的都是freeswitch暴露的api接口。
我们这里以luarun为例分析
SWITCH_STANDARD_API(luarun_api_function) { if (zstr(cmd)) { stream->write_function(stream, "-ERR no args specified!\n"); } else { lua_thread(cmd); stream->write_function(stream, "+OK\n"); } return SWITCH_STATUS_SUCCESS; }
所以当执行luarun的时候主要是调用lua_thread()函数处理。
int lua_thread(const char *text) { switch_thread_t *thread; switch_threadattr_t *thd_attr = NULL; switch_memory_pool_t *pool; lua_thread_helper *lth; switch_core_new_memory_pool(&pool); lth = (lua_thread_helper *) switch_core_alloc(pool, sizeof(*lth)); lth->pool = pool; lth->input_code = switch_core_strdup(lth->pool, text); switch_threadattr_create(&thd_attr, lth->pool); switch_threadattr_detach_set(thd_attr, 1); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); switch_thread_create(&thread, thd_attr, lua_thread_run, lth, lth->pool); return 0; }
在lua_thread中主要是创建一个新线程,并在线程里面执行:lua_thread_run
static void *SWITCH_THREAD_FUNC lua_thread_run(switch_thread_t *thread, void *obj) { struct lua_thread_helper *lth = (struct lua_thread_helper *) obj; switch_memory_pool_t *pool = lth->pool; lua_State *L = lua_init(); /* opens Lua */ lua_parse_and_execute(L, lth->input_code, NULL); lth = NULL; switch_core_destroy_memory_pool(&pool); lua_uninit(L); return NULL; }
在lua_thread_run中先初始化了一个lua_State,然后调用lua_parse_and_execute去加载lua脚本文件并执行
static int lua_parse_and_execute(lua_State * L, char *input_code, switch_core_session_t *session) { int error = 0; if (zstr(input_code)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No code to execute!\n"); return 1; } while(input_code && (*input_code == ' ' || *input_code == '\n' || *input_code == '\r')) input_code++; if (*input_code == '~') { char *buff = input_code + 1; error = luaL_loadbuffer(L, buff, strlen(buff), "line") || docall(L, 0, 0, 0, 1); //lua_pcall(L, 0, 0, 0); } else if (!strncasecmp(input_code, "#!/lua", 6)) { char *buff = input_code + 6; error = luaL_loadbuffer(L, buff, strlen(buff), "line") || docall(L, 0, 0, 0, 1); //lua_pcall(L, 0, 0, 0); } else { char *args = strchr(input_code, ' '); if (args) { char *code = NULL; int x, argc; char *argv[128] = { 0 }; *args++ = '\0'; if ((argc = switch_separate_string(args, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { switch_stream_handle_t stream = { 0 }; SWITCH_STANDARD_STREAM(stream); stream.write_function(&stream, " argv = {[0]='%y', ", input_code); for (x = 0; x < argc; x++) { stream.write_function(&stream, "'%y'%s", argv[x], x == argc - 1 ? "" : ", "); } stream.write_function(&stream, " };"); code = (char *) stream.data; } else { code = switch_mprintf("argv = {[0]='%s'};", input_code); } if (code) { error = luaL_loadbuffer(L, code, strlen(code), "line") || docall(L, 0, 0, 0, 1); switch_safe_free(code); } } else { // Force empty argv table char *code = NULL; code = switch_mprintf("argv = {[0]='%s'};", input_code); error = luaL_loadbuffer(L, code, strlen(code), "line") || docall(L, 0, 0, 0, 1); switch_safe_free(code); } if (!error) { char *file = input_code, *fdup = NULL; if (!switch_is_file_path(file)) { fdup = switch_mprintf("%s/%s", SWITCH_GLOBAL_dirs.script_dir, file); switch_assert(fdup); file = fdup; } error = luaL_loadfile(L, file) || docall(L, 0, 0, 0, 1); switch_safe_free(fdup); } } if (error) { const char *err = lua_tostring(L, -1); if (!zstr(err)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s\n", err); } lua_pop(L, 1); /* pop error message from the stack */ } return err e4a6 or; }
前面一段都是在处理参数最核心的是下面这一行
luaL_loadfile(L, file) || docall(L, 0, 0, 0, 1)
加载文件并执行
int docall(lua_State * L, int narg, int nresults, int perror, int fatal) { int status; int base = lua_gettop(L) - narg; /* function index */ lua_pushcfunction(L, traceback); /* push traceback function */ lua_insert(L, base); /* put it under chunk and args */ status = lua_pcall(L, narg, nresults, base); lua_remove(L, base); /* remove traceback function */ /* force a complete garbage collection in case of errors */ if (status != 0) { lua_gc(L, LUA_GCCOLLECT, 0); } if (status && perror) { const char *err = lua_tostring(L, -1); if (!zstr(err)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err); } // pass error up to top if (fatal) { lua_error(L); } else { lua_pop(L, 1); /* pop error message from the stack */ } } return status; }
最后调用lua_pcall执行lua脚本。
下面再介绍一下一个lua的接口怎么找到他对应的c++l代码:
所有的暴露给lua的接口都放在mod_lua_wrap.cpp这文件的swig_type_initial里面,然后lua模块启动的时候会逐个加载。
static swig_type_info *swig_type_initial[] = { &_swigt__p_API, &_swigt__p_CoreSession, &_swigt__p_DTMF, &_swigt__p_Event, &_swigt__p_EventConsumer, &_swigt__p_IVRMenu, &_swigt__p_LUA__Dbh, &_swigt__p_LUA__Session, &_swigt__p_SWIGLUA_FN, &_swigt__p_Stream, &_swigt__p_input_callback_state, &_swigt__p_int, &_swigt__p_lua_State, &_swigt__p_p_switch_event_node_t, &_swigt__p_session_flag_t, &_swigt__p_switch_call_cause_t, &_swigt__p_switch_channel_state_t, &_swigt__p_switch_channel_t, &_swigt__p_switch_core_session_t, &_swigt__p_switch_event_t, &_swigt__p_switch_event_types_t, &_swigt__p_switch_input_args_t, &_swigt__p_switch_input_type_t, &_swigt__p_switch_priority_t, &_swigt__p_switch_queue_t, &_swigt__p_switch_state_handler_table_t, &_swigt__p_switch_status_t, &_swigt__p_switch_stream_handle_t, &_swigt__p_uint32_t, &_swigt__p_void, };
我们以Session的接口为例介绍一下,他在_swigt__p_CoreSession这个结构体里面描述。
static swig_type_info _swigt__p_CoreSession = {"_p_CoreSession", "CoreSession *", 0, 0, (void*)&_wrap_class_CoreSession, 0};
static swig_lua_class _wrap_class_CoreSession = { "CoreSession", "CoreSession", &SWIGTYPE_p_CoreSession,0, swig_delete_CoreSession, swig_CoreSession_methods, swig_CoreSession_attributes, &swig_CoreSession_Sf_SwigStatic, swig_CoreSession_meta, swig_CoreSession_bases, swig_CoreSession_base_names };
被注册的方法放在swig_CoreSession_methods这个结构体里面:
static swig_lua_method swig_CoreSession_methods[]= { { "insertFile", _wrap_CoreSession_insertFile}, { "answer", _wrap_CoreSession_answer}, { "preAnswer", _wrap_CoreSession_preAnswer}, { "hangup", _wrap_CoreSession_hangup}, { "hangupState", _wrap_CoreSession_hangupState}, { "setVariable", _wrap_CoreSession_setVariable}, { "setPrivate", _wrap_CoreSession_setPrivate}, { "getPrivate", _wrap_CoreSession_getPrivate}, { "getVariable", _wrap_CoreSession_getVariable}, { "process_callback_result", _wrap_CoreSession_process_callback_result}, { "say", _wrap_CoreSession_say}, { "sayPhrase", _wrap_CoreSession_sayPhrase}, { "hangupCause", _wrap_CoreSession_hangupCause}, { "getState", _wrap_CoreSession_getState}, { "recordFile", _wrap_CoreSession_recordFile}, { "originate", _wrap_CoreSession_originate}, { "destroy", _wrap_CoreSession_destroy}, { "setDTMFCallback", _wrap_CoreSession_setDTMFCallback}, { "speak", _wrap_CoreSession_speak}, { "set_tts_parms", _wrap_CoreSession_set_tts_parms}, { "set_tts_params", _wrap_CoreSession_set_tts_params}, { "collectDigits", _wrap_CoreSession_collectDigits}, { "getDigits", _wrap_CoreSession_getDigits}, { "transfer", _wrap_CoreSession_transfer}, { "read", _wrap_CoreSession_read}, { "playAndGetDigits", _wrap_CoreSession_playAndGetDigits}, { "streamFile", _wrap_CoreSession_streamFile}, { "sleep", _wrap_CoreSession_sleep}, { "flushEvents", _wrap_CoreSession_flushEvents}, { "flushDigits", _wrap_CoreSession_flushDigits}, { "setAutoHangup", _wrap_CoreSession_setAutoHangup}, { "setHangupHook", _wrap_CoreSession_setHangupHook}, { "ready", _wrap_CoreSession_ready}, { "bridged", _wrap_CoreSession_bridged}, { "answered", _wrap_CoreSession_answered}, { "mediaReady", _wrap_CoreSession_mediaReady}, { "waitForAnswer", _wrap_CoreSession_waitForAnswer}, { "execute", _wrap_CoreSession_execute}, { "sendEvent", _wrap_CoreSession_sendEvent}, { "setEventData", _wrap_CoreSession_setEventData}, { "getXMLCDR", _wrap_CoreSession_getXMLCDR}, { "begin_allow_threads", _wrap_CoreSession_begin_allow_threads}, { "end_allow_threads", _wrap_CoreSession_end_allow_threads}, { "get_uuid", _wrap_CoreSession_get_uuid}, { "get_cb_args", _wrap_CoreSession_get_cb_args}, { "check_hangup_hook", _wrap_CoreSession_check_hangup_hook}, { "run_dtmf_callback", _wrap_CoreSession_run_dtmf_callback}, { "consoleLog", _wrap_CoreSession_consoleLog}, { "consoleLog2", _wrap_CoreSession_consoleLog2}, {0,0} };
在这里可以看到很熟悉的answer,bridge等方法了。
相关文章推荐
- lua执行字节码的过程介绍
- skynet lua服务callback执行过程
- 5.OP-TEE+qemu的启动过程分析--run-only目标执行
- lua服务执行过程中协程的挂起和重新唤醒
- Android探索之旅(第五篇) eclipse执行run之后的过程
- 网狐Lua客户端执行过程
- linux 进程调度switch_to宏浅析+系统执行过程总结
- freeswitch.Session的实现过程
- php中switch语句执行的过程
- 关于 switch 语句的执行过程
- (6)LUA程序设计-编译执行与错误(compile 、run & error)处理
- yii框架源码分析之Yii::createWebApplication()->run() 执行过程分析
- yii框架源码分析之Yii::createWebApplication()->run() 执行过程分析
- freeswitch Session dtmf callback的触发过程
- 网狐Lua客户端执行过程
- FreeSwitch Lua Welcome IVR
- 30 自制操作系统,qemu的运行记录,解释run.bat的执行过程
- lua执行字节码的过程介绍
- FreeSwitch LUA Briding two calls with retry带重试次数的两个呼叫的桥接
- CPU内部组成结构及指令执行过程