/src/mod/languages/mod_perl/freeswitch_perl.cpp

https://github.com/curriegrad2004/FreeSWITCH · C++ · 286 lines · 230 code · 55 blank · 1 comment · 45 complexity · 071a4acc97e90e951dffaf6d58e2a35e MD5 · raw file

  1. #include <switch.h>
  2. #include "freeswitch_perl.h"
  3. #include "mod_perl_extra.h"
  4. static STRLEN n_a;
  5. #define init_me() cb_function = hangup_func_str = NULL; hangup_func_arg = NULL; hh = mark = 0; my_perl = NULL; cb_arg = NULL
  6. using namespace PERL;
  7. Session::Session():CoreSession()
  8. {
  9. init_me();
  10. }
  11. Session::Session(char *uuid, CoreSession *a_leg):CoreSession(uuid, a_leg)
  12. {
  13. init_me();
  14. if (session && allocated) {
  15. suuid = switch_core_session_sprintf(session, "main::uuid_%s\n", switch_core_session_get_uuid(session));
  16. for (char *p = suuid; p && *p; p++) {
  17. if (*p == '-') {
  18. *p = '_';
  19. }
  20. if (*p == '\n') {
  21. *p = '\0';
  22. }
  23. }
  24. }
  25. }
  26. Session::Session(switch_core_session_t *new_session):CoreSession(new_session)
  27. {
  28. init_me();
  29. if (session) {
  30. suuid = switch_core_session_sprintf(session, "main::uuid_%s\n", switch_core_session_get_uuid(session));
  31. for (char *p = suuid; p && *p; p++) {
  32. if (*p == '-') {
  33. *p = '_';
  34. }
  35. }
  36. } else {
  37. //handle failure
  38. }
  39. }
  40. static switch_status_t perl_hanguphook(switch_core_session_t *session_hungup);
  41. void Session::destroy(void)
  42. {
  43. if (!allocated) {
  44. return;
  45. }
  46. if (session) {
  47. if (!channel) {
  48. channel = switch_core_session_get_channel(session);
  49. }
  50. switch_channel_set_private(channel, "CoreSession", NULL);
  51. switch_core_event_hook_remove_state_change(session, perl_hanguphook);
  52. }
  53. switch_safe_free(cb_function);
  54. switch_safe_free(cb_arg);
  55. switch_safe_free(hangup_func_str);
  56. switch_safe_free(hangup_func_arg);
  57. CoreSession::destroy();
  58. }
  59. Session::~Session()
  60. {
  61. destroy();
  62. }
  63. bool Session::begin_allow_threads()
  64. {
  65. do_hangup_hook();
  66. return true;
  67. }
  68. bool Session::end_allow_threads()
  69. {
  70. do_hangup_hook();
  71. return true;
  72. }
  73. void Session::setPERL(PerlInterpreter * pi)
  74. {
  75. my_perl = pi;
  76. }
  77. void Session::setME(SV *p)
  78. {
  79. sanity_check_noreturn;
  80. me = p;
  81. }
  82. PerlInterpreter *Session::getPERL()
  83. {
  84. if (!my_perl) {
  85. switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh!\n");
  86. }
  87. return my_perl;
  88. }
  89. bool Session::ready()
  90. {
  91. bool r;
  92. sanity_check(false);
  93. r = switch_channel_ready(channel) != 0;
  94. do_hangup_hook();
  95. return r;
  96. }
  97. void Session::check_hangup_hook()
  98. {
  99. if (hangup_func_str && (hook_state == CS_HANGUP || hook_state == CS_ROUTING)) {
  100. hh++;
  101. }
  102. }
  103. void Session::do_hangup_hook()
  104. {
  105. if (hh && !mark) {
  106. const char *err = NULL;
  107. mark++;
  108. char *code;
  109. if (!getPERL()) {
  110. return;
  111. }
  112. if (hangup_func_arg) {
  113. code = switch_mprintf("%s($%s,\"%s\",%s)", hangup_func_str, suuid, hook_state == CS_HANGUP ? "hangup" : "transfer", hangup_func_arg);
  114. } else {
  115. code = switch_mprintf("%s($%s,\"%s\")", hangup_func_str, suuid, hook_state == CS_HANGUP ? "hangup" : "transfer");
  116. }
  117. Perl_eval_pv(my_perl, code, TRUE);
  118. free(code);
  119. }
  120. }
  121. static switch_status_t perl_hanguphook(switch_core_session_t *session_hungup)
  122. {
  123. switch_channel_t *channel = switch_core_session_get_channel(session_hungup);
  124. CoreSession *coresession = NULL;
  125. switch_channel_state_t state = switch_channel_get_state(channel);
  126. if ((coresession = (CoreSession *) switch_channel_get_private(channel, "CoreSession"))) {
  127. if (coresession->hook_state != state) {
  128. coresession->hook_state = state;
  129. coresession->check_hangup_hook();
  130. }
  131. }
  132. return SWITCH_STATUS_SUCCESS;
  133. }
  134. void Session::setHangupHook(char *func, char *arg)
  135. {
  136. sanity_check_noreturn;
  137. switch_safe_free(hangup_func_str);
  138. if (func) {
  139. hangup_func_str = strdup(func);
  140. switch_channel_set_private(channel, "CoreSession", this);
  141. hook_state = switch_channel_get_state(channel);
  142. switch_core_event_hook_add_state_change(session, perl_hanguphook);
  143. if (arg) {
  144. hangup_func_arg = strdup(func);
  145. }
  146. }
  147. }
  148. void Session::unsetInputCallback(void)
  149. {
  150. sanity_check_noreturn;
  151. switch_safe_free(cb_function);
  152. switch_safe_free(cb_arg);
  153. switch_channel_set_private(channel, "CoreSession", NULL);
  154. args.input_callback = NULL;
  155. ap = NULL;
  156. }
  157. void Session::setInputCallback(char *cbfunc, char *funcargs)
  158. {
  159. sanity_check_noreturn;
  160. switch_safe_free(cb_function);
  161. if (cbfunc) {
  162. cb_function = strdup(cbfunc);
  163. }
  164. switch_safe_free(cb_arg);
  165. if (funcargs) {
  166. cb_arg = strdup(funcargs);
  167. }
  168. args.buf = this;
  169. switch_channel_set_private(channel, "CoreSession", this);
  170. args.input_callback = dtmf_callback;
  171. ap = &args;
  172. }
  173. switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t itype)
  174. {
  175. if (!getPERL()) {
  176. return SWITCH_STATUS_FALSE;;
  177. }
  178. switch (itype) {
  179. case SWITCH_INPUT_TYPE_DTMF:
  180. {
  181. switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
  182. char str[32] = "";
  183. int arg_count = 2;
  184. HV *hash;
  185. SV *this_sv;
  186. char *code;
  187. if (!(hash = get_hv("__dtmf", TRUE))) {
  188. abort();
  189. }
  190. str[0] = dtmf->digit;
  191. this_sv = newSV(strlen(str) + 1);
  192. sv_setpv(this_sv, str);
  193. hv_store(hash, "digit", 5, this_sv, 0);
  194. switch_snprintf(str, sizeof(str), "%d", dtmf->duration);
  195. this_sv = newSV(strlen(str) + 1);
  196. sv_setpv(this_sv, str);
  197. hv_store(hash, "duration", 8, this_sv, 0);
  198. code = switch_mprintf("eval { $__RV = &%s($%s, 'dtmf', \\%%__dtmf, %s);};", cb_function, suuid, switch_str_nil(cb_arg));
  199. Perl_eval_pv(my_perl, code, FALSE);
  200. free(code);
  201. return process_callback_result(SvPV(get_sv("__RV", TRUE), n_a));
  202. }
  203. break;
  204. case SWITCH_INPUT_TYPE_EVENT:
  205. {
  206. switch_event_t *event = (switch_event_t *) input;
  207. int arg_count = 2;
  208. char *code;
  209. switch_uuid_t uuid;
  210. char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
  211. char var_name[SWITCH_UUID_FORMATTED_LENGTH + 25];
  212. char *p;
  213. switch_uuid_get(&uuid);
  214. switch_uuid_format(uuid_str, &uuid);
  215. switch_snprintf(var_name, sizeof(var_name), "main::__event_%s", uuid_str);
  216. for(p = var_name; p && *p; p++) {
  217. if (*p == '-') {
  218. *p = '_';
  219. }
  220. }
  221. mod_perl_conjure_event(my_perl, event, var_name);
  222. code = switch_mprintf("eval {$__RV = &%s($%s, 'event', $%s, '%s');};$%s = undef;",
  223. cb_function, suuid, var_name, switch_str_nil(cb_arg), var_name);
  224. Perl_eval_pv(my_perl, code, FALSE);
  225. free(code);
  226. return process_callback_result(SvPV(get_sv("__RV", TRUE), n_a));
  227. }
  228. break;
  229. }
  230. return SWITCH_STATUS_SUCCESS;
  231. }