PageRenderTime 27ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/src/mod/languages/mod_lua/freeswitch_lua.cpp

https://github.com/ppanhoto/Freeswitch-mod_mp4
C++ | 381 lines | 297 code | 84 blank | 0 comment | 59 complexity | b83ae360a06dd7354536d6133e5d6bc2 MD5 | raw file
  1. #include <switch.h>
  2. #include "freeswitch_lua.h"
  3. using namespace LUA;
  4. Session::Session():CoreSession()
  5. {
  6. cb_function = cb_arg = hangup_func_str = hangup_func_arg = NULL;
  7. hh = mark = 0;
  8. }
  9. Session::Session(char *nuuid, CoreSession *a_leg):CoreSession(nuuid, a_leg)
  10. {
  11. cb_function = cb_arg = hangup_func_str = hangup_func_arg = NULL;
  12. hh = mark = 0;
  13. }
  14. Session::Session(switch_core_session_t *new_session):CoreSession(new_session)
  15. {
  16. cb_function = cb_arg = hangup_func_str = hangup_func_arg = NULL;
  17. hh = mark = 0;
  18. }
  19. static switch_status_t lua_hanguphook(switch_core_session_t *session_hungup);
  20. void Session::destroy(void)
  21. {
  22. if (!allocated) {
  23. return;
  24. }
  25. if (session) {
  26. if (!channel) {
  27. channel = switch_core_session_get_channel(session);
  28. }
  29. switch_channel_set_private(channel, "CoreSession", NULL);
  30. switch_core_event_hook_remove_state_change(session, lua_hanguphook);
  31. }
  32. switch_safe_free(hangup_func_str);
  33. switch_safe_free(hangup_func_arg);
  34. switch_safe_free(cb_function);
  35. switch_safe_free(cb_arg);
  36. CoreSession::destroy();
  37. }
  38. Session::~Session()
  39. {
  40. destroy();
  41. }
  42. bool Session::begin_allow_threads()
  43. {
  44. do_hangup_hook();
  45. return true;
  46. }
  47. bool Session::end_allow_threads()
  48. {
  49. do_hangup_hook();
  50. return true;
  51. }
  52. void Session::setLUA(lua_State * state)
  53. {
  54. L = state;
  55. if (session && allocated && uuid) {
  56. lua_setglobal(L, uuid);
  57. lua_getfield(L, LUA_GLOBALSINDEX, uuid);
  58. }
  59. }
  60. int Session::originate(CoreSession *a_leg_session, char *dest, int timeout)
  61. {
  62. int x = CoreSession::originate(a_leg_session, dest, timeout);
  63. if (x) {
  64. setLUA(L);
  65. }
  66. return x;
  67. }
  68. lua_State *Session::getLUA()
  69. {
  70. if (!L) {
  71. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh!\n");
  72. }
  73. return L;
  74. }
  75. bool Session::ready()
  76. {
  77. bool r;
  78. if (!session) {
  79. return false;
  80. }
  81. sanity_check(false);
  82. r = switch_channel_ready(channel) != 0;
  83. do_hangup_hook();
  84. return r;
  85. }
  86. void Session::check_hangup_hook()
  87. {
  88. if (hangup_func_str && (hook_state == CS_HANGUP || hook_state == CS_ROUTING)) {
  89. hh++;
  90. }
  91. }
  92. void Session::do_hangup_hook()
  93. {
  94. if (hh && !mark) {
  95. const char *err = NULL;
  96. int arg_count = 2;
  97. mark++;
  98. if (!getLUA()) {
  99. return;
  100. }
  101. lua_getfield(L, LUA_GLOBALSINDEX, (char *) hangup_func_str);
  102. lua_getfield(L, LUA_GLOBALSINDEX, uuid);
  103. lua_pushstring(L, hook_state == CS_HANGUP ? "hangup" : "transfer");
  104. if (hangup_func_arg) {
  105. lua_getfield(L, LUA_GLOBALSINDEX, (char *) hangup_func_arg);
  106. arg_count++;
  107. }
  108. lua_call(L, arg_count, 1);
  109. err = lua_tostring(L, -1);
  110. if (!zstr(err)) {
  111. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err);
  112. }
  113. if (channel) {
  114. switch_channel_set_private(channel, "CoreSession", NULL);
  115. }
  116. if (session) {
  117. switch_core_event_hook_remove_state_change(session, lua_hanguphook);
  118. }
  119. switch_safe_free(hangup_func_str);
  120. }
  121. }
  122. static switch_status_t lua_hanguphook(switch_core_session_t *session_hungup)
  123. {
  124. switch_channel_t *channel = switch_core_session_get_channel(session_hungup);
  125. Session *coresession = NULL;
  126. switch_channel_state_t state = switch_channel_get_state(channel);
  127. if (session_hungup) {
  128. channel = switch_core_session_get_channel(session_hungup);
  129. if (channel) {
  130. void *vs = switch_channel_get_private(channel, "CoreSession");
  131. if (vs) {
  132. coresession = (Session *) vs;
  133. }
  134. }
  135. if (!(coresession && coresession->hook_state)) {
  136. return SWITCH_STATUS_FALSE;
  137. }
  138. if (coresession && coresession->allocated && (state == CS_HANGUP || state == CS_ROUTING) && coresession->hook_state != state) {
  139. coresession->hook_state = state;
  140. coresession->check_hangup_hook();
  141. switch_core_event_hook_remove_state_change(session_hungup, lua_hanguphook);
  142. }
  143. }
  144. return SWITCH_STATUS_SUCCESS;
  145. }
  146. void Session::setHangupHook(char *func, char *arg)
  147. {
  148. sanity_check_noreturn;
  149. switch_safe_free(hangup_func_str);
  150. switch_safe_free(hangup_func_arg);
  151. if (func) {
  152. hangup_func_str = strdup(func);
  153. if (!zstr(arg)) {
  154. hangup_func_arg = strdup(arg);
  155. }
  156. switch_channel_set_private(channel, "CoreSession", this);
  157. hook_state = switch_channel_get_state(channel);
  158. switch_core_event_hook_add_state_change(session, lua_hanguphook);
  159. }
  160. }
  161. void Session::unsetInputCallback(void)
  162. {
  163. sanity_check_noreturn;
  164. switch_safe_free(cb_function);
  165. switch_safe_free(cb_arg);
  166. args.input_callback = NULL;
  167. ap = NULL;
  168. }
  169. void Session::setInputCallback(char *cbfunc, char *funcargs)
  170. {
  171. sanity_check_noreturn;
  172. switch_safe_free(cb_function);
  173. if (cbfunc) {
  174. cb_function = strdup(cbfunc);
  175. }
  176. switch_safe_free(cb_arg);
  177. if (funcargs) {
  178. cb_arg = strdup(funcargs);
  179. }
  180. args.buf = this;
  181. switch_channel_set_private(channel, "CoreSession", this);
  182. args.input_callback = dtmf_callback;
  183. ap = &args;
  184. }
  185. switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t itype)
  186. {
  187. const char *ret;
  188. if (!getLUA()) {
  189. return SWITCH_STATUS_FALSE;;
  190. }
  191. switch (itype) {
  192. case SWITCH_INPUT_TYPE_DTMF:
  193. {
  194. switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
  195. char str[3] = "";
  196. int arg_count = 3;
  197. lua_getfield(L, LUA_GLOBALSINDEX, (char *) cb_function);
  198. lua_getfield(L, LUA_GLOBALSINDEX, uuid);
  199. lua_pushstring(L, "dtmf");
  200. lua_newtable(L);
  201. lua_pushstring(L, "digit");
  202. str[0] = dtmf->digit;
  203. lua_pushstring(L, str);
  204. lua_rawset(L, -3);
  205. lua_pushstring(L, "duration");
  206. lua_pushnumber(L, dtmf->duration);
  207. lua_rawset(L, -3);
  208. if (!zstr(cb_arg)) {
  209. lua_getfield(L, LUA_GLOBALSINDEX, (char *) cb_arg);
  210. arg_count++;
  211. }
  212. lua_call(L, arg_count, 1);
  213. ret = lua_tostring(L, -1);
  214. lua_pop(L, 1);
  215. return process_callback_result((char *) ret);
  216. }
  217. break;
  218. case SWITCH_INPUT_TYPE_EVENT:
  219. {
  220. switch_event_t *event = (switch_event_t *) input;
  221. int arg_count = 3;
  222. lua_getfield(L, LUA_GLOBALSINDEX, (char *) cb_function);
  223. lua_getfield(L, LUA_GLOBALSINDEX, uuid);
  224. lua_pushstring(L, "event");
  225. mod_lua_conjure_event(L, event, "__Input_Event__", 1);
  226. lua_getfield(L, LUA_GLOBALSINDEX, "__Input_Event__");
  227. if (!zstr(cb_arg)) {
  228. lua_getfield(L, LUA_GLOBALSINDEX, (char *) cb_arg);
  229. arg_count++;
  230. }
  231. lua_call(L, arg_count, 1);
  232. ret = lua_tostring(L, -1);
  233. lua_pop(L, 1);
  234. return process_callback_result((char *) ret);
  235. }
  236. break;
  237. }
  238. return SWITCH_STATUS_SUCCESS;
  239. }
  240. Dbh::Dbh(char *dsn, char *user, char *pass)
  241. {
  242. switch_cache_db_connection_options_t options = { {0} };
  243. options.odbc_options.dsn = dsn;
  244. options.odbc_options.user = user;
  245. options.odbc_options.pass = pass;
  246. if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) == SWITCH_STATUS_SUCCESS) {
  247. connected = true;
  248. } else {
  249. connected = false;
  250. }
  251. }
  252. Dbh::~Dbh()
  253. {
  254. release();
  255. }
  256. bool Dbh::release()
  257. {
  258. if (connected) {
  259. switch_cache_db_release_db_handle(&dbh);
  260. connected = false;
  261. return true;
  262. }
  263. return false;
  264. }
  265. int Dbh::query_callback(void *pArg, int argc, char **argv, char **cargv)
  266. {
  267. SWIGLUA_FN *lua_fun = (SWIGLUA_FN *)pArg;
  268. lua_pushvalue(lua_fun->L, lua_fun->idx); /* get the lua callback function onto the stack */
  269. lua_newtable(lua_fun->L); /* push a row (table) */
  270. for (int i = 0; i < argc; i++) {
  271. lua_pushstring(lua_fun->L, switch_str_nil(cargv[i]));
  272. lua_pushstring(lua_fun->L, switch_str_nil(argv[i]));
  273. lua_settable(lua_fun->L, -3);
  274. }
  275. lua_call(lua_fun->L, 1, 1); /* 1 in, 1 out */
  276. if (lua_isnumber(lua_fun->L, -1)) {
  277. if (lua_tonumber(lua_fun->L, -1) != 0) {
  278. return 1;
  279. }
  280. }
  281. return 0; /* 0 to continue with next row */
  282. }
  283. bool Dbh::query(char *sql, SWIGLUA_FN lua_fun)
  284. {
  285. if (connected) {
  286. if (lua_fun.L) {
  287. if (switch_cache_db_execute_sql_callback(dbh, sql, query_callback, &lua_fun, NULL) == SWITCH_STATUS_SUCCESS) {
  288. return true;
  289. }
  290. } else { /* if no lua_fun arg is passed from Lua, an empty initialized struct will be sent - see freeswitch.i */
  291. if (switch_cache_db_execute_sql(dbh, sql, NULL) == SWITCH_STATUS_SUCCESS) {
  292. return true;
  293. }
  294. }
  295. }
  296. return false;
  297. }