#include #include "freeswitch_lua.h" Session::Session() : CoreSession() { cb_function = cb_arg = hangup_func_str = hangup_func_arg = NULL; hh = mark = 0; } Session::Session(char *uuid) : CoreSession(uuid) { cb_function = cb_arg = hangup_func_str = hangup_func_arg = NULL; hh = mark = 0; } Session::Session(switch_core_session_t *new_session) : CoreSession(new_session) { cb_function = cb_arg = hangup_func_str = hangup_func_arg = NULL; hh = mark = 0; } static switch_status_t lua_hanguphook(switch_core_session_t *session_hungup); Session::~Session() { if (hangup_func_str) { if (session) { switch_core_event_hook_remove_state_change(session, lua_hanguphook); } free(hangup_func_str); } switch_safe_free(hangup_func_arg); switch_safe_free(cb_function); switch_safe_free(cb_arg); } bool Session::begin_allow_threads() { do_hangup_hook(); return true; } bool Session::end_allow_threads() { do_hangup_hook(); return true; } void Session::setLUA(lua_State *state) { L = state; } lua_State *Session::getLUA() { if (!L) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh!\n"); } return L; } bool Session::ready() { bool r; sanity_check(false); r = switch_channel_ready(channel) != 0; do_hangup_hook(); return r; } void Session::check_hangup_hook() { if (hangup_func_str && (hook_state == CS_HANGUP || hook_state == CS_ROUTING)) { hh++; } } void Session::do_hangup_hook() { if (hh && !mark) { const char *err = NULL; mark++; if (!getLUA()) { return; } lua_getfield(L, LUA_GLOBALSINDEX, (char *)hangup_func_str); lua_pushstring(L, hook_state == CS_HANGUP ? "hangup" : "transfer"); if (hangup_func_arg) { lua_pushstring(L, hangup_func_arg); } lua_call(L, 1, 1); err = lua_tostring(L, -1); if (!switch_strlen_zero(err)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err); } } } static switch_status_t lua_hanguphook(switch_core_session_t *session_hungup) { switch_channel_t *channel = switch_core_session_get_channel(session_hungup); CoreSession *coresession = NULL; switch_channel_state_t state = switch_channel_get_state(channel); if ((coresession = (CoreSession *) switch_channel_get_private(channel, "CoreSession"))) { if (coresession->hook_state != state) { coresession->hook_state = state; coresession->check_hangup_hook(); } } return SWITCH_STATUS_SUCCESS; } void Session::setHangupHook(char *func, char *arg) { sanity_check_noreturn; switch_safe_free(hangup_func_str); switch_safe_free(hangup_func_arg); if (func) { hangup_func_str = strdup(func); if (arg) { hangup_func_arg = strdup(arg); } switch_channel_set_private(channel, "CoreSession", this); hook_state = switch_channel_get_state(channel); switch_core_event_hook_add_state_change(session, lua_hanguphook); } } void Session::setInputCallback(char *cbfunc, char *funcargs) { sanity_check_noreturn; switch_safe_free(cb_function); if (cbfunc) { cb_function = strdup(cbfunc); } switch_safe_free(cb_arg); if (funcargs) { cb_arg = strdup(funcargs); } args.buf = this; switch_channel_set_private(channel, "CoreSession", this); args.input_callback = dtmf_callback; ap = &args; } switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t itype) { const char *ret; if (!getLUA()) { return SWITCH_STATUS_FALSE;; } switch (itype) { case SWITCH_INPUT_TYPE_DTMF: { switch_dtmf_t *dtmf = (switch_dtmf_t *) input; char str[2] = ""; int arg_count = 2; lua_getfield(L, LUA_GLOBALSINDEX, (char *)cb_function); lua_pushstring(L, "dtmf"); lua_newtable(L); lua_pushstring(L, "digit"); str[0] = dtmf->digit; lua_pushstring(L, str); lua_rawset(L, -3); lua_pushstring(L, "duration"); lua_pushnumber(L, dtmf->duration); lua_rawset(L, -3); if (cb_arg) { lua_getfield(L, LUA_GLOBALSINDEX, (char *)cb_arg); arg_count++; } lua_call(L, arg_count, 1); ret = lua_tostring(L, -1); lua_pop(L, 1); return process_callback_result((char *)ret); } break; case SWITCH_INPUT_TYPE_EVENT: { switch_event_t *event = (switch_event_t *) input; int arg_count = 2; lua_getfield(L, LUA_GLOBALSINDEX, (char *)cb_function); lua_pushstring(L, "event"); mod_lua_conjure_event(L, event, "__Input_Event__", 1); lua_getfield(L, LUA_GLOBALSINDEX, "__Input_Event__"); if (cb_arg) { lua_getfield(L, LUA_GLOBALSINDEX, (char *)cb_arg); arg_count++; } lua_call(L, 2, 1); ret = lua_tostring(L, -1); lua_pop(L, 1); return process_callback_result((char *)ret); } break; } return SWITCH_STATUS_SUCCESS; }