mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-14 15:24:13 +00:00
indent pass 2
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@8689 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
1 parent
9bbcabbbdd
commit
f930eaeec7
101 files changed
+31644
-31458
No files matched your search
@@ -3,19 +3,19 @@
|
||||
#include "freeswitch_lua.h"
|
||||
using namespace LUA;
|
||||
|
||||
Session::Session() : CoreSession()
|
||||
Session::Session():CoreSession()
|
||||
{
|
||||
cb_function = cb_arg = hangup_func_str = hangup_func_arg = NULL;
|
||||
hh = mark = 0;
|
||||
}
|
||||
|
||||
Session::Session(char *uuid) : CoreSession(uuid)
|
||||
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)
|
||||
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;
|
||||
@@ -30,25 +30,25 @@ Session::~Session()
|
||||
}
|
||||
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()
|
||||
bool Session::begin_allow_threads()
|
||||
{
|
||||
do_hangup_hook();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Session::end_allow_threads()
|
||||
bool Session::end_allow_threads()
|
||||
{
|
||||
do_hangup_hook();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Session::setLUA(lua_State *state)
|
||||
void Session::setLUA(lua_State * state)
|
||||
{
|
||||
L = state;
|
||||
}
|
||||
@@ -56,30 +56,31 @@ void Session::setLUA(lua_State *state)
|
||||
lua_State *Session::getLUA()
|
||||
{
|
||||
if (!L) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh!\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh!\n");
|
||||
}
|
||||
return L;
|
||||
}
|
||||
|
||||
|
||||
bool Session::ready() {
|
||||
bool Session::ready()
|
||||
{
|
||||
bool r;
|
||||
|
||||
sanity_check(false);
|
||||
sanity_check(false);
|
||||
r = switch_channel_ready(channel) != 0;
|
||||
do_hangup_hook();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void Session::check_hangup_hook()
|
||||
void Session::check_hangup_hook()
|
||||
{
|
||||
if (hangup_func_str && (hook_state == CS_HANGUP || hook_state == CS_ROUTING)) {
|
||||
hh++;
|
||||
}
|
||||
}
|
||||
|
||||
void Session::do_hangup_hook()
|
||||
void Session::do_hangup_hook()
|
||||
{
|
||||
if (hh && !mark) {
|
||||
const char *err = NULL;
|
||||
@@ -90,25 +91,25 @@ void Session::do_hangup_hook()
|
||||
return;
|
||||
}
|
||||
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, (char *)hangup_func_str);
|
||||
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, (char *) hangup_func_str);
|
||||
|
||||
lua_pushstring(L, hook_state == CS_HANGUP ? "hangup" : "transfer");
|
||||
|
||||
if (hangup_func_arg) {
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, (char *)hangup_func_arg);
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, (char *) hangup_func_arg);
|
||||
arg_count++;
|
||||
}
|
||||
|
||||
|
||||
lua_call(L, arg_count, 1);
|
||||
err = lua_tostring(L, -1);
|
||||
|
||||
if (!switch_strlen_zero(err)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", 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)
|
||||
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;
|
||||
@@ -125,13 +126,14 @@ static switch_status_t lua_hanguphook(switch_core_session_t *session_hungup)
|
||||
}
|
||||
|
||||
|
||||
void Session::setHangupHook(char *func, char *arg) {
|
||||
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 (!switch_strlen_zero(arg)) {
|
||||
@@ -143,7 +145,8 @@ void Session::setHangupHook(char *func, char *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
void Session::setInputCallback(char *cbfunc, char *funcargs) {
|
||||
void Session::setInputCallback(char *cbfunc, char *funcargs)
|
||||
{
|
||||
|
||||
sanity_check_noreturn;
|
||||
|
||||
@@ -156,15 +159,15 @@ void Session::setInputCallback(char *cbfunc, char *funcargs) {
|
||||
if (funcargs) {
|
||||
cb_arg = strdup(funcargs);
|
||||
}
|
||||
|
||||
|
||||
args.buf = this;
|
||||
switch_channel_set_private(channel, "CoreSession", this);
|
||||
|
||||
args.input_callback = dtmf_callback;
|
||||
args.input_callback = dtmf_callback;
|
||||
ap = &args;
|
||||
}
|
||||
|
||||
switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t itype)
|
||||
switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t itype)
|
||||
{
|
||||
const char *ret;
|
||||
|
||||
@@ -173,27 +176,27 @@ switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t ityp
|
||||
}
|
||||
|
||||
switch (itype) {
|
||||
case SWITCH_INPUT_TYPE_DTMF:
|
||||
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_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);
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, (char *) cb_arg);
|
||||
arg_count++;
|
||||
}
|
||||
|
||||
@@ -201,30 +204,30 @@ switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t ityp
|
||||
ret = lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return process_callback_result((char *)ret);
|
||||
return process_callback_result((char *) ret);
|
||||
}
|
||||
break;
|
||||
case SWITCH_INPUT_TYPE_EVENT:
|
||||
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_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);
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, (char *) cb_arg);
|
||||
arg_count++;
|
||||
}
|
||||
|
||||
lua_call(L, 2, 1);
|
||||
|
||||
ret = lua_tostring(L, -1);
|
||||
ret = lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return process_callback_result((char *)ret);
|
||||
|
||||
return process_callback_result((char *) ret);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -45,23 +45,23 @@ static struct {
|
||||
char *xml_handler;
|
||||
} globals;
|
||||
|
||||
int luaopen_freeswitch(lua_State* L);
|
||||
int luaopen_freeswitch(lua_State * L);
|
||||
|
||||
static int panic (lua_State *L)
|
||||
static int panic(lua_State * L)
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "unprotected error in call to Lua API (%s)\n",
|
||||
lua_tostring(L, -1));
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "unprotected error in call to Lua API (%s)\n", lua_tostring(L, -1));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lua_uninit(lua_State *L)
|
||||
static void lua_uninit(lua_State * L)
|
||||
{
|
||||
lua_gc(L, LUA_GCCOLLECT, 0);
|
||||
lua_close(L);
|
||||
}
|
||||
|
||||
static int traceback (lua_State *L) {
|
||||
static int traceback(lua_State * L)
|
||||
{
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, "debug");
|
||||
if (!lua_istable(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
@@ -72,30 +72,32 @@ static int traceback (lua_State *L) {
|
||||
lua_pop(L, 2);
|
||||
return 1;
|
||||
}
|
||||
lua_pushvalue(L, 1); /* pass error message */
|
||||
lua_pushinteger(L, 2); /* skip this function and traceback */
|
||||
lua_call(L, 2, 1); /* call debug.traceback */
|
||||
lua_pushvalue(L, 1); /* pass error message */
|
||||
lua_pushinteger(L, 2); /* skip this function and traceback */
|
||||
lua_call(L, 2, 1); /* call debug.traceback */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int docall (lua_State *L, int narg, int clear) {
|
||||
static int docall(lua_State * L, int narg, int clear)
|
||||
{
|
||||
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 */
|
||||
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, (clear ? 0 : LUA_MULTRET), base);
|
||||
|
||||
lua_remove(L, base); /* remove traceback function */
|
||||
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 != 0)
|
||||
lua_gc(L, LUA_GCCOLLECT, 0);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static lua_State *lua_init(void)
|
||||
static lua_State *lua_init(void)
|
||||
{
|
||||
lua_State *L = lua_open();
|
||||
int error = 0;
|
||||
@@ -108,12 +110,12 @@ static lua_State *lua_init(void)
|
||||
lua_gc(L, LUA_GCRESTART, 0);
|
||||
lua_atpanic(L, panic);
|
||||
error = luaL_loadbuffer(L, buff, strlen(buff), "line") || docall(L, 0, 1);
|
||||
}
|
||||
}
|
||||
return L;
|
||||
}
|
||||
|
||||
|
||||
static int lua_parse_and_execute(lua_State *L, char *input_code)
|
||||
static int lua_parse_and_execute(lua_State * L, char *input_code)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
@@ -124,7 +126,7 @@ static int lua_parse_and_execute(lua_State *L, char *input_code)
|
||||
|
||||
if (*input_code == '~') {
|
||||
char *buff = input_code + 1;
|
||||
error = luaL_loadbuffer(L, buff, strlen(buff), "line") || docall(L, 0, 1); //lua_pcall(L, 0, 0, 0);
|
||||
error = luaL_loadbuffer(L, buff, strlen(buff), "line") || docall(L, 0, 1); //lua_pcall(L, 0, 0, 0);
|
||||
} else {
|
||||
char *args = strchr(input_code, ' ');
|
||||
if (args) {
|
||||
@@ -136,13 +138,13 @@ static int lua_parse_and_execute(lua_State *L, char *input_code)
|
||||
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 = { ");
|
||||
for (x = 0; x < argc; x++) {
|
||||
stream.write_function(&stream, "'%s'%s", argv[x], x == argc-1 ? "" : ", ");
|
||||
stream.write_function(&stream, "'%s'%s", argv[x], x == argc - 1 ? "" : ", ");
|
||||
}
|
||||
stream.write_function(&stream, " };");
|
||||
code = (char *)stream.data;
|
||||
code = (char *) stream.data;
|
||||
} else {
|
||||
code = switch_mprintf("argv = {};");
|
||||
}
|
||||
@@ -154,7 +156,7 @@ static int lua_parse_and_execute(lua_State *L, char *input_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);
|
||||
@@ -170,7 +172,7 @@ static int lua_parse_and_execute(lua_State *L, char *input_code)
|
||||
if (!switch_strlen_zero(err)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err);
|
||||
}
|
||||
lua_pop(L, 1); /* pop error message from the stack */
|
||||
lua_pop(L, 1); /* pop error message from the stack */
|
||||
}
|
||||
|
||||
return error;
|
||||
@@ -179,10 +181,10 @@ static int lua_parse_and_execute(lua_State *L, char *input_code)
|
||||
static void *SWITCH_THREAD_FUNC lua_thread_run(switch_thread_t *thread, void *obj)
|
||||
{
|
||||
char *input_code = (char *) obj;
|
||||
lua_State *L = lua_init(); /* opens Lua */
|
||||
lua_State *L = lua_init(); /* opens Lua */
|
||||
|
||||
lua_parse_and_execute(L, input_code);
|
||||
|
||||
|
||||
if (input_code) {
|
||||
free(input_code);
|
||||
}
|
||||
@@ -193,12 +195,8 @@ static void *SWITCH_THREAD_FUNC lua_thread_run(switch_thread_t *thread, void *ob
|
||||
}
|
||||
|
||||
|
||||
static switch_xml_t lua_fetch(const char *section,
|
||||
const char *tag_name,
|
||||
const char *key_name,
|
||||
const char *key_value,
|
||||
switch_event_t *params,
|
||||
void *user_data)
|
||||
static switch_xml_t lua_fetch(const char *section,
|
||||
const char *tag_name, const char *key_name, const char *key_value, switch_event_t *params, void *user_data)
|
||||
{
|
||||
|
||||
switch_xml_t xml = NULL;
|
||||
@@ -238,11 +236,11 @@ static switch_xml_t lua_fetch(const char *section,
|
||||
if (str) {
|
||||
if (switch_strlen_zero(str)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Result\n");
|
||||
} else if (!(xml = switch_xml_parse_str((char *)str, strlen(str)))) {
|
||||
} else if (!(xml = switch_xml_parse_str((char *) str, strlen(str)))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Parsing XML Result!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lua_uninit(L);
|
||||
free(mycmd);
|
||||
}
|
||||
@@ -304,13 +302,13 @@ SWITCH_STANDARD_APP(lua_function)
|
||||
|
||||
if (switch_strlen_zero(data)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no args specified!\n");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(code, sizeof(code), "~session = freeswitch.Session(\"%s\");", switch_core_session_get_uuid(session));
|
||||
error = lua_parse_and_execute(L, code);
|
||||
|
||||
mycmd = strdup((char *)data);
|
||||
mycmd = strdup((char *) data);
|
||||
switch_assert(mycmd);
|
||||
|
||||
lua_parse_and_execute(L, mycmd);
|
||||
@@ -319,8 +317,9 @@ SWITCH_STANDARD_APP(lua_function)
|
||||
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_API(luarun_api_function) {
|
||||
|
||||
SWITCH_STANDARD_API(luarun_api_function)
|
||||
{
|
||||
|
||||
if (switch_strlen_zero(cmd)) {
|
||||
stream->write_function(stream, "-ERR no args specified!\n");
|
||||
} else {
|
||||
@@ -332,7 +331,8 @@ SWITCH_STANDARD_API(luarun_api_function) {
|
||||
}
|
||||
|
||||
|
||||
SWITCH_STANDARD_API(lua_api_function) {
|
||||
SWITCH_STANDARD_API(lua_api_function)
|
||||
{
|
||||
|
||||
lua_State *L = lua_init();
|
||||
char *mycmd;
|
||||
@@ -370,13 +370,13 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_lua_load)
|
||||
|
||||
/* connect my internal structure to the blank pointer passed to me */
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
|
||||
SWITCH_ADD_API(api_interface, "luarun", "run a script", luarun_api_function, "<script>");
|
||||
SWITCH_ADD_API(api_interface, "lua", "run a script as an api function", lua_api_function, "<script>");
|
||||
SWITCH_ADD_APP(app_interface, "lua", "Launch LUA ivr", "Run a lua ivr on a channel", lua_function, "<script>", SAF_SUPPORT_NOMEDIA);
|
||||
|
||||
|
||||
|
||||
|
||||
globals.pool = pool;
|
||||
do_config();
|
||||
|
||||
@@ -385,7 +385,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_lua_load)
|
||||
}
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
SWITCH_BEGIN_EXTERN_C
|
||||
|
||||
|
||||
void mod_lua_conjure_event(lua_State *L, switch_event_t *event, const char *name, int destroy_me)
|
||||
SWITCH_BEGIN_EXTERN_C void mod_lua_conjure_event(lua_State * L, switch_event_t *event, const char *name, int destroy_me)
|
||||
{
|
||||
Event *result = new Event(event);
|
||||
SWIG_NewPointerObj(L,result,SWIGTYPE_p_Event, destroy_me);
|
||||
SWIG_NewPointerObj(L, result, SWIGTYPE_p_Event, destroy_me);
|
||||
lua_setglobal(L, name);
|
||||
}
|
||||
|
||||
|
||||
void mod_lua_conjure_stream(lua_State *L, switch_stream_handle_t *stream, const char *name, int destroy_me)
|
||||
void mod_lua_conjure_stream(lua_State * L, switch_stream_handle_t *stream, const char *name, int destroy_me)
|
||||
{
|
||||
Stream *result = new Stream(stream);
|
||||
SWIG_NewPointerObj(L,result,SWIGTYPE_p_Stream, destroy_me);
|
||||
SWIG_NewPointerObj(L, result, SWIGTYPE_p_Stream, destroy_me);
|
||||
lua_setglobal(L, name);
|
||||
}
|
||||
|
||||
|
||||
+6273
-5806
File diff suppressed because it is too large.
Load diff
@@ -27,8 +27,8 @@
|
||||
*
|
||||
* freeswitch_mono.cpp -- Mono-specific CoreSession subclass
|
||||
*
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#include <switch_cpp.h>
|
||||
#include <glib.h>
|
||||
@@ -38,77 +38,71 @@
|
||||
#include <mono/metadata/threads.h>
|
||||
#include <mono/metadata/metadata.h>
|
||||
#include "freeswitch_mono.h"
|
||||
MonoSession::MonoSession():CoreSession()
|
||||
{
|
||||
}
MonoSession::MonoSession(char *uuid):CoreSession(uuid)
|
||||
{
|
||||
}
MonoSession::MonoSession(switch_core_session_t *session):CoreSession(session)
|
||||
{
|
||||
}
MonoSession::~MonoSession()
|
||||
{
|
||||
mono_thread_attach(globals.domain);
|
||||
if (dtmfDelegateHandle)
|
||||
mono_gchandle_free(dtmfDelegateHandle);
|
||||
if (hangupDelegateHandle)
|
||||
mono_gchandle_free(hangupDelegateHandle);
|
||||
}
|
||||
|
||||
bool MonoSession::begin_allow_threads()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MonoSession::end_allow_threads()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
void MonoSession::check_hangup_hook()
|
||||
{
|
||||
mono_thread_attach(globals.domain);
|
||||
if (!hangupDelegateHandle) {
|
||||
return;
|
||||
}
|
||||
MonoObject * hangupDelegate = mono_gchandle_get_target(hangupDelegateHandle);
|
||||
if (!hangupDelegate) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "hangupDelegateHandle didn't get an object.");
|
||||
return;
|
||||
}
|
||||
MonoObject * ex = NULL;
|
||||
mono_runtime_delegate_invoke(hangupDelegate, NULL, &ex);
|
||||
if (ex) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "hangupDelegate threw an exception.");
|
||||
}
|
||||
}
|
||||
switch_status_t MonoSession::run_dtmf_callback(void *input, switch_input_type_t itype)
|
||||
{
|
||||
mono_thread_attach(globals.domain);
|
||||
if (!dtmfDelegateHandle) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
MonoObject * dtmfDelegate = mono_gchandle_get_target(dtmfDelegateHandle);
|
||||
if (!dtmfDelegate) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "dtmfDelegateHandle didn't get an object.");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
void *args[2];
|
||||
args[0] = &input;
|
||||
args[1] = &itype;
|
||||
MonoObject * ex = NULL;
|
||||
MonoObject * res = mono_runtime_delegate_invoke(dtmfDelegate, args, &ex);
|
||||
if (ex) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "dtmfDelegate threw an exception.");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
char *resPtr = mono_string_to_utf8((MonoString *) res);
|
||||
switch_status_t status = process_callback_result(resPtr);
|
||||
g_free(resPtr);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
MonoSession::MonoSession() : CoreSession()
|
||||
{
|
||||
}
|
||||
|
||||
MonoSession::MonoSession(char *uuid) : CoreSession(uuid)
|
||||
{
|
||||
}
|
||||
|
||||
MonoSession::MonoSession(switch_core_session_t *session) : CoreSession(session)
|
||||
{
|
||||
}
|
||||
|
||||
MonoSession::~MonoSession()
|
||||
{
|
||||
mono_thread_attach(globals.domain);
|
||||
if (dtmfDelegateHandle) mono_gchandle_free(dtmfDelegateHandle);
|
||||
if (hangupDelegateHandle) mono_gchandle_free(hangupDelegateHandle);
|
||||
}
|
||||
|
||||
bool MonoSession::begin_allow_threads()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MonoSession::end_allow_threads()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void MonoSession::check_hangup_hook()
|
||||
{
|
||||
mono_thread_attach(globals.domain);
|
||||
if (!hangupDelegateHandle) {
|
||||
return;
|
||||
}
|
||||
MonoObject *hangupDelegate = mono_gchandle_get_target(hangupDelegateHandle);
|
||||
if (!hangupDelegate) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "hangupDelegateHandle didn't get an object.");
|
||||
return;
|
||||
}
|
||||
MonoObject *ex = NULL;
|
||||
mono_runtime_delegate_invoke(hangupDelegate, NULL, &ex);
|
||||
if (ex) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "hangupDelegate threw an exception.");
|
||||
}
|
||||
}
|
||||
|
||||
switch_status_t MonoSession::run_dtmf_callback(void *input, switch_input_type_t itype)
|
||||
{
|
||||
mono_thread_attach(globals.domain);
|
||||
if (!dtmfDelegateHandle) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
MonoObject *dtmfDelegate = mono_gchandle_get_target(dtmfDelegateHandle);
|
||||
if (!dtmfDelegate) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "dtmfDelegateHandle didn't get an object.");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
void *args[2];
|
||||
args[0] = &input;
|
||||
args[1] = &itype;
|
||||
MonoObject *ex = NULL;
|
||||
MonoObject *res = mono_runtime_delegate_invoke(dtmfDelegate, args, &ex);
|
||||
if (ex) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "dtmfDelegate threw an exception.");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
char *resPtr = mono_string_to_utf8((MonoString*)res);
|
||||
switch_status_t status = process_callback_result(resPtr);
|
||||
|
||||
g_free(resPtr);
|
||||
return status;
|
||||
}
|
||||
@@ -30,13 +30,10 @@
|
||||
* Most of mod_mono is implmented in the mod_mono_managed Loader class.
|
||||
* The native code just handles getting the Mono runtime up and down
|
||||
* and passing pointers into managed code.
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
|
||||
|
||||
SWITCH_BEGIN_EXTERN_C
|
||||
|
||||
SWITCH_BEGIN_EXTERN_C
|
||||
#include "freeswitch_mono.h"
|
||||
#include <glib.h>
|
||||
#include <mono/jit/jit.h>
|
||||
@@ -44,284 +41,278 @@ SWITCH_BEGIN_EXTERN_C
|
||||
#include <mono/metadata/environment.h>
|
||||
#include <mono/metadata/threads.h>
|
||||
#include <mono/metadata/debug-helpers.h>
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#include <shlobj.h>
|
||||
#define EXPORT __declspec(dllexport)
|
||||
#elif
|
||||
#define EXPORT
|
||||
#endif
|
||||
|
||||
#endif /*
*/
|
||||
|
||||
#define MOD_MONO_MANAGED_DLL "mod_mono_managed.dll"
|
||||
|
||||
mod_mono_globals globals = { 0 };
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_mono_load);
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mono_shutdown);
|
||||
SWITCH_MODULE_DEFINITION(mod_mono, mod_mono_load, mod_mono_shutdown, NULL);
|
||||
|
||||
SWITCH_STANDARD_API(monorun_api_function); /* ExecuteBackground */
|
||||
SWITCH_STANDARD_API(mono_api_function); /* Execute */
|
||||
SWITCH_STANDARD_APP(mono_app_function); /* Run */
|
||||
|
||||
|
||||
mod_mono_globals globals = {
|
||||
0};
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_mono_load);
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mono_shutdown);
|
||||
SWITCH_MODULE_DEFINITION(mod_mono, mod_mono_load, mod_mono_shutdown, NULL);
|
||||
SWITCH_STANDARD_API(monorun_api_function); /* ExecuteBackground */
|
||||
SWITCH_STANDARD_API(mono_api_function); /* Execute */
|
||||
SWITCH_STANDARD_APP(mono_app_function); /* Run */
|
||||
|
||||
// Sets up delegates (and anything else needed) on the MonoSession object
|
||||
// Called via internalcall
|
||||
SWITCH_MOD_DECLARE(void) InitMonoSession(MonoSession *session, MonoObject *dtmfDelegate, MonoObject *hangupDelegate)
|
||||
{
|
||||
switch_assert(session);
|
||||
if (!session) return;
|
||||
session->setDTMFCallback(NULL, "");
|
||||
session->setHangupHook(NULL);
|
||||
session->dtmfDelegateHandle = mono_gchandle_new(dtmfDelegate, FALSE);
|
||||
session->hangupDelegateHandle = mono_gchandle_new(hangupDelegate, FALSE);
|
||||
}
|
||||
|
||||
switch_status_t setMonoDirs()
|
||||
{
|
||||
SWITCH_MOD_DECLARE(void) InitMonoSession(MonoSession * session, MonoObject * dtmfDelegate, MonoObject * hangupDelegate)
|
||||
{
|
||||
switch_assert(session);
|
||||
if (!session)
|
||||
return;
|
||||
session->setDTMFCallback(NULL, "");
|
||||
session->setHangupHook(NULL);
|
||||
session->dtmfDelegateHandle = mono_gchandle_new(dtmfDelegate, FALSE);
|
||||
session->hangupDelegateHandle = mono_gchandle_new(hangupDelegate, FALSE);
|
||||
}
|
||||
switch_status_t setMonoDirs()
|
||||
{
|
||||
|
||||
#ifdef WIN32
|
||||
/* Win32 Mono installs can't figure out their own path
|
||||
// Guys in #mono say we should just deploy all the libs we need
|
||||
// I think it's much nicer to let the user deal with installing Mono
|
||||
// and we'll just look for it in program files. */
|
||||
HANDLE hFind;
|
||||
WIN32_FIND_DATA findData;
|
||||
char progFilesPath[MAX_PATH];
|
||||
char findPath[MAX_PATH];
|
||||
SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, progFilesPath);
|
||||
switch_snprintf(findPath, MAX_PATH, "%s\\Mono-*", progFilesPath);
|
||||
hFind = FindFirstFile(findPath, &findData);
|
||||
if (hFind == INVALID_HANDLE_VALUE) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error looking for Mono in Program Files.\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
while((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) {
|
||||
if (FindNextFile(hFind, &findData) == 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find Mono directory in Program Files.\n");
|
||||
FindClose(hFind);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
}
|
||||
/* Got it */
|
||||
{
|
||||
char libPath[MAX_PATH];
|
||||
char etcPath[MAX_PATH];
|
||||
switch_snprintf(libPath, MAX_PATH, "%s\\%s\\lib", progFilesPath, findData.cFileName);
|
||||
switch_snprintf(etcPath, MAX_PATH, "%s\\%s\\etc", progFilesPath, findData.cFileName);
|
||||
FindClose(hFind);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Using Mono paths '%s' and '%s'.\n", libPath, etcPath);
|
||||
mono_set_dirs(libPath, etcPath);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
/* Win32 Mono installs can't figure out their own path
|
||||
// Guys in #mono say we should just deploy all the libs we need
|
||||
// I think it's much nicer to let the user deal with installing Mono
|
||||
// and we'll just look for it in program files. */
|
||||
HANDLE hFind;
|
||||
WIN32_FIND_DATA findData;
|
||||
char progFilesPath[MAX_PATH];
|
||||
char findPath[MAX_PATH];
|
||||
SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, progFilesPath);
|
||||
switch_snprintf(findPath, MAX_PATH, "%s\\Mono-*", progFilesPath);
|
||||
hFind = FindFirstFile(findPath, &findData);
|
||||
if (hFind == INVALID_HANDLE_VALUE) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error looking for Mono in Program Files.\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
while ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) {
|
||||
if (FindNextFile(hFind, &findData) == 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find Mono directory in Program Files.\n");
|
||||
FindClose(hFind);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Got it */
|
||||
{
|
||||
char libPath[MAX_PATH];
|
||||
char etcPath[MAX_PATH];
|
||||
switch_snprintf(libPath, MAX_PATH, "%s\\%s\\lib", progFilesPath, findData.cFileName);
|
||||
switch_snprintf(etcPath, MAX_PATH, "%s\\%s\\etc", progFilesPath, findData.cFileName);
|
||||
FindClose(hFind);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Using Mono paths '%s' and '%s'.\n", libPath, etcPath);
|
||||
mono_set_dirs(libPath, etcPath);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#elif
|
||||
// On other platforms, it should just work if it hasn't been relocated
|
||||
mono_set_dirs(NULL, NULL);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
switch_status_t loadModMonoManaged()
|
||||
{
|
||||
/* Find and load mod_mono_managed.exe */
|
||||
char filename[256];
|
||||
switch_snprintf(filename, 256, "%s%s%s", SWITCH_GLOBAL_dirs.mod_dir, SWITCH_PATH_SEPARATOR, MOD_MONO_MANAGED_DLL);
|
||||
globals.domain = mono_jit_init(filename);
|
||||
|
||||
if (!globals.domain) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mono_jit_init failed.\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
/* Open the assembly */
|
||||
globals.mod_mono_asm = mono_domain_assembly_open(globals.domain, filename);
|
||||
if (!globals.mod_mono_asm) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mono_domain_assembly_open failed.\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
MonoMethod *getMethod(const char *name, MonoClass *klass)
|
||||
{
|
||||
MonoMethodDesc *desc;
|
||||
MonoMethod *method;
|
||||
desc = mono_method_desc_new(name, TRUE);
|
||||
method = mono_method_desc_search_in_class(desc, klass);
|
||||
if (!method) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find %s method.\n", name);
|
||||
return NULL;
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
switch_status_t findLoader()
|
||||
{
|
||||
/* Find loader class and methods*/
|
||||
MonoImage* img;
|
||||
MonoClass* loaderClass;
|
||||
img = mono_assembly_get_image(globals.mod_mono_asm);
|
||||
loaderClass = mono_class_from_name(img, "FreeSWITCH", "Loader");
|
||||
if (!loaderClass) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find FreeSWITCH.Loader class.\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
globals.loadMethod = getMethod("FreeSWITCH.Loader:Load()", loaderClass);
|
||||
if (!globals.loadMethod) return SWITCH_STATUS_FALSE;
|
||||
|
||||
globals.unloadMethod = getMethod("FreeSWITCH.Loader:Unload()", loaderClass);
|
||||
if (!globals.unloadMethod) return SWITCH_STATUS_FALSE;
|
||||
|
||||
globals.runMethod = getMethod("FreeSWITCH.Loader:Run(string,intptr)", loaderClass);
|
||||
if (!globals.runMethod) return SWITCH_STATUS_FALSE;
|
||||
|
||||
globals.executeMethod = getMethod("FreeSWITCH.Loader:Execute(string,intptr,intptr)", loaderClass);
|
||||
if (!globals.executeMethod) return SWITCH_STATUS_FALSE;
|
||||
// On other platforms, it should just work if it hasn't been relocated
|
||||
mono_set_dirs(NULL, NULL);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
globals.executeBackgroundMethod = getMethod("FreeSWITCH.Loader:ExecuteBackground(string)", loaderClass);
|
||||
if (!globals.executeBackgroundMethod) return SWITCH_STATUS_FALSE;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found all loader functions.\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_mono_load)
|
||||
{
|
||||
/* connect my internal structure to the blank pointer passed to me */
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
globals.pool = pool;
|
||||
|
||||
if (setMonoDirs() != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
if (loadModMonoManaged() != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
if (findLoader() != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
/* Not sure if this is necesary on the loading thread */
|
||||
mono_thread_attach(globals.domain);
|
||||
mono_add_internal_call("FreeSWITCH.Native.MonoSession::InitMonoSession", InitMonoSession);
|
||||
|
||||
/* Run loader */
|
||||
MonoObject *objResult;
|
||||
MonoObject *exception = NULL;
|
||||
objResult = mono_runtime_invoke(globals.loadMethod, NULL, NULL, &exception);
|
||||
if (exception) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Load threw an exception.\n");
|
||||
mono_print_unhandled_exception(exception);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
if (*(int*)mono_object_unbox(objResult)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Load completed successfully.\n");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Load did not return true.\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* We're good to register */
|
||||
switch_api_interface_t *api_interface;
|
||||
switch_application_interface_t *app_interface;
|
||||
|
||||
SWITCH_ADD_API(api_interface, "monorun", "Run a module (ExecuteBackground)", monorun_api_function, "<module> [<args>]");
|
||||
SWITCH_ADD_API(api_interface, "mono", "Run a module as an API function (Execute)", mono_api_function, "<module> [<args>]");
|
||||
SWITCH_ADD_APP(app_interface, "mono", "Run Mono IVR", "Run a Mono IVR on a channel", mono_app_function, "<modulename> [<args>]", SAF_NONE);
|
||||
#endif /*
*/
|
||||
}
|
||||
switch_status_t loadModMonoManaged()
|
||||
{
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_API(monorun_api_function)
|
||||
{
|
||||
// TODO: Should we be detaching after all this?
|
||||
mono_thread_attach(globals.domain);
|
||||
if (switch_strlen_zero(cmd)) {
|
||||
stream->write_function(stream, "-ERR no args specified!\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// ExecuteBackground(string command)
|
||||
void *args[1];
|
||||
args[0] = mono_string_new(globals.domain, cmd);
|
||||
MonoObject *exception = NULL;
|
||||
MonoObject *objResult = mono_runtime_invoke(globals.executeBackgroundMethod, NULL, args, &exception);
|
||||
if (exception) {
|
||||
stream->write_function(stream, "-ERR FreeSWITCH.Loader.ExecuteBackground threw an exception.\n");
|
||||
mono_print_unhandled_exception(exception);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
if (*(int*)mono_object_unbox(objResult)) {
|
||||
stream->write_function(stream, "+OK\n");
|
||||
} else {
|
||||
stream->write_function(stream, "-ERR ExecuteBackground returned false (unknown module?).\n");
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_API(mono_api_function)
|
||||
{
|
||||
mono_thread_attach(globals.domain);
|
||||
if (switch_strlen_zero(cmd)) {
|
||||
stream->write_function(stream, "-ERR no args specified!\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
/* Find and load mod_mono_managed.exe */
|
||||
char filename[256];
|
||||
switch_snprintf(filename, 256, "%s%s%s", SWITCH_GLOBAL_dirs.mod_dir, SWITCH_PATH_SEPARATOR, MOD_MONO_MANAGED_DLL);
|
||||
globals.domain = mono_jit_init(filename);
|
||||
if (!globals.domain) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mono_jit_init failed.\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
/* Open the assembly */
|
||||
globals.mod_mono_asm = mono_domain_assembly_open(globals.domain, filename);
|
||||
if (!globals.mod_mono_asm) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mono_domain_assembly_open failed.\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
MonoMethod * getMethod(const char *name, MonoClass * klass)
|
||||
{
|
||||
MonoMethodDesc * desc;
|
||||
MonoMethod * method;
|
||||
desc = mono_method_desc_new(name, TRUE);
|
||||
method = mono_method_desc_search_in_class(desc, klass);
|
||||
if (!method) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find %s method.\n", name);
|
||||
return NULL;
|
||||
}
|
||||
return method;
|
||||
}
|
||||
switch_status_t findLoader()
|
||||
{
|
||||
|
||||
// Method is: Execute(string command, IntPtr streamPtr, IntPtr eventPtr)
|
||||
void *args[3];
|
||||
args[0] = mono_string_new(globals.domain, cmd);
|
||||
args[1] = &stream; // Address of the arguments
|
||||
args[2] = &(stream->param_event);
|
||||
/* Find loader class and methods */
|
||||
MonoImage * img;
|
||||
MonoClass * loaderClass;
|
||||
img = mono_assembly_get_image(globals.mod_mono_asm);
|
||||
loaderClass = mono_class_from_name(img, "FreeSWITCH", "Loader");
|
||||
if (!loaderClass) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not find FreeSWITCH.Loader class.\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
globals.loadMethod = getMethod("FreeSWITCH.Loader:Load()", loaderClass);
|
||||
if (!globals.loadMethod)
|
||||
return SWITCH_STATUS_FALSE;
|
||||
globals.unloadMethod = getMethod("FreeSWITCH.Loader:Unload()", loaderClass);
|
||||
if (!globals.unloadMethod)
|
||||
return SWITCH_STATUS_FALSE;
|
||||
globals.runMethod = getMethod("FreeSWITCH.Loader:Run(string,intptr)", loaderClass);
|
||||
if (!globals.runMethod)
|
||||
return SWITCH_STATUS_FALSE;
|
||||
globals.executeMethod = getMethod("FreeSWITCH.Loader:Execute(string,intptr,intptr)", loaderClass);
|
||||
if (!globals.executeMethod)
|
||||
return SWITCH_STATUS_FALSE;
|
||||
globals.executeBackgroundMethod = getMethod("FreeSWITCH.Loader:ExecuteBackground(string)", loaderClass);
|
||||
if (!globals.executeBackgroundMethod)
|
||||
return SWITCH_STATUS_FALSE;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found all loader functions.\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_mono_load)
|
||||
{
|
||||
|
||||
MonoObject *exception = NULL;
|
||||
MonoObject *objResult = mono_runtime_invoke(globals.executeMethod, NULL, args, &exception);
|
||||
if (exception) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute mono %s.\n", cmd);
|
||||
mono_print_unhandled_exception(exception);
|
||||
}
|
||||
if (!(*(int*)mono_object_unbox(objResult))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Execute failed for %s (unknown module?).\n", cmd);
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_APP(mono_app_function)
|
||||
{
|
||||
mono_thread_attach(globals.domain);
|
||||
if (switch_strlen_zero(data)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No args specified!\n");
|
||||
}
|
||||
|
||||
// bool Run(string command, IntPtr sessionHandle)
|
||||
void *args[2];
|
||||
args[0] = mono_string_new(globals.domain, data);
|
||||
args[1] = &session;
|
||||
|
||||
MonoObject *exception = NULL;
|
||||
MonoObject *objResult = mono_runtime_invoke(globals.runMethod, NULL, args, &exception);
|
||||
if (exception) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute application mono %s.\n", data);
|
||||
mono_print_unhandled_exception(exception);
|
||||
}
|
||||
if (!(*(int*)mono_object_unbox(objResult))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application run failed for %s (unknown module?).\n", data);
|
||||
}
|
||||
}
|
||||
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mono_shutdown)
|
||||
{
|
||||
mono_thread_attach(globals.domain);
|
||||
MonoObject *ex;
|
||||
mono_runtime_invoke(globals.unloadMethod, NULL, NULL, &ex);
|
||||
if (ex) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception occurred in Loader::Unload.\n");
|
||||
mono_print_unhandled_exception(ex);
|
||||
}
|
||||
mono_runtime_set_shutting_down();
|
||||
mono_runtime_cleanup(globals.domain);
|
||||
mono_runtime_quit();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
/* connect my internal structure to the blank pointer passed to me */
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
globals.pool = pool;
|
||||
if (setMonoDirs() != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
if (loadModMonoManaged() != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
if (findLoader() != SWITCH_STATUS_SUCCESS) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
/* Not sure if this is necesary on the loading thread */
|
||||
mono_thread_attach(globals.domain);
|
||||
mono_add_internal_call("FreeSWITCH.Native.MonoSession::InitMonoSession", InitMonoSession);
|
||||
|
||||
/* Run loader */
|
||||
MonoObject * objResult;
|
||||
MonoObject * exception = NULL;
|
||||
objResult = mono_runtime_invoke(globals.loadMethod, NULL, NULL, &exception);
|
||||
if (exception) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Load threw an exception.\n");
|
||||
mono_print_unhandled_exception(exception);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
if (*(int *) mono_object_unbox(objResult)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Load completed successfully.\n");
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Load did not return true.\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
/* We're good to register */
|
||||
switch_api_interface_t *api_interface;
|
||||
switch_application_interface_t *app_interface;
|
||||
SWITCH_ADD_API(api_interface, "monorun", "Run a module (ExecuteBackground)", monorun_api_function, "<module> [<args>]");
|
||||
SWITCH_ADD_API(api_interface, "mono", "Run a module as an API function (Execute)", mono_api_function, "<module> [<args>]");
|
||||
SWITCH_ADD_APP(app_interface, "mono", "Run Mono IVR", "Run a Mono IVR on a channel", mono_app_function, "<modulename> [<args>]", SAF_NONE);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_API(monorun_api_function)
|
||||
{
|
||||
|
||||
// TODO: Should we be detaching after all this?
|
||||
mono_thread_attach(globals.domain);
|
||||
if (switch_strlen_zero(cmd)) {
|
||||
stream->write_function(stream, "-ERR no args specified!\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// ExecuteBackground(string command)
|
||||
void *args[1];
|
||||
args[0] = mono_string_new(globals.domain, cmd);
|
||||
MonoObject * exception = NULL;
|
||||
MonoObject * objResult = mono_runtime_invoke(globals.executeBackgroundMethod, NULL, args, &exception);
|
||||
if (exception) {
|
||||
stream->write_function(stream, "-ERR FreeSWITCH.Loader.ExecuteBackground threw an exception.\n");
|
||||
mono_print_unhandled_exception(exception);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
if (*(int *) mono_object_unbox(objResult)) {
|
||||
stream->write_function(stream, "+OK\n");
|
||||
} else {
|
||||
stream->write_function(stream, "-ERR ExecuteBackground returned false (unknown module?).\n");
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_API(mono_api_function)
|
||||
{
|
||||
mono_thread_attach(globals.domain);
|
||||
if (switch_strlen_zero(cmd)) {
|
||||
stream->write_function(stream, "-ERR no args specified!\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Method is: Execute(string command, IntPtr streamPtr, IntPtr eventPtr)
|
||||
void *args[3];
|
||||
args[0] = mono_string_new(globals.domain, cmd);
|
||||
args[1] = &stream; // Address of the arguments
|
||||
args[2] = &(stream->param_event);
|
||||
MonoObject * exception = NULL;
|
||||
MonoObject * objResult = mono_runtime_invoke(globals.executeMethod, NULL, args, &exception);
|
||||
if (exception) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute mono %s.\n", cmd);
|
||||
mono_print_unhandled_exception(exception);
|
||||
}
|
||||
if (!(*(int *) mono_object_unbox(objResult))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Execute failed for %s (unknown module?).\n", cmd);
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_APP(mono_app_function)
|
||||
{
|
||||
mono_thread_attach(globals.domain);
|
||||
if (switch_strlen_zero(data)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No args specified!\n");
|
||||
}
|
||||
|
||||
// bool Run(string command, IntPtr sessionHandle)
|
||||
void *args[2];
|
||||
args[0] = mono_string_new(globals.domain, data);
|
||||
args[1] = &session;
|
||||
MonoObject * exception = NULL;
|
||||
MonoObject * objResult = mono_runtime_invoke(globals.runMethod, NULL, args, &exception);
|
||||
if (exception) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute application mono %s.\n", data);
|
||||
mono_print_unhandled_exception(exception);
|
||||
}
|
||||
if (!(*(int *) mono_object_unbox(objResult))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application run failed for %s (unknown module?).\n", data);
|
||||
}
|
||||
}
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mono_shutdown)
|
||||
{
|
||||
mono_thread_attach(globals.domain);
|
||||
MonoObject * ex;
|
||||
mono_runtime_invoke(globals.unloadMethod, NULL, NULL, &ex);
|
||||
if (ex) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception occurred in Loader::Unload.\n");
|
||||
mono_print_unhandled_exception(ex);
|
||||
}
|
||||
mono_runtime_set_shutting_down();
|
||||
mono_runtime_cleanup(globals.domain);
|
||||
mono_runtime_quit();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
@@ -8,17 +8,17 @@ static STRLEN n_a;
|
||||
|
||||
using namespace PERL;
|
||||
|
||||
Session::Session() : CoreSession()
|
||||
Session::Session():CoreSession()
|
||||
{
|
||||
init_me();
|
||||
}
|
||||
|
||||
Session::Session(char *uuid) : CoreSession(uuid)
|
||||
Session::Session(char *uuid):CoreSession(uuid)
|
||||
{
|
||||
init_me();
|
||||
}
|
||||
|
||||
Session::Session(switch_core_session_t *new_session) : CoreSession(new_session)
|
||||
Session::Session(switch_core_session_t *new_session):CoreSession(new_session)
|
||||
{
|
||||
init_me();
|
||||
}
|
||||
@@ -37,19 +37,19 @@ Session::~Session()
|
||||
|
||||
}
|
||||
|
||||
bool Session::begin_allow_threads()
|
||||
bool Session::begin_allow_threads()
|
||||
{
|
||||
do_hangup_hook();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Session::end_allow_threads()
|
||||
bool Session::end_allow_threads()
|
||||
{
|
||||
do_hangup_hook();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Session::setPERL(PerlInterpreter *pi)
|
||||
void Session::setPERL(PerlInterpreter * pi)
|
||||
{
|
||||
my_perl = pi;
|
||||
}
|
||||
@@ -57,30 +57,31 @@ void Session::setPERL(PerlInterpreter *pi)
|
||||
PerlInterpreter *Session::getPERL()
|
||||
{
|
||||
if (!my_perl) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh!\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Doh!\n");
|
||||
}
|
||||
return my_perl;
|
||||
}
|
||||
|
||||
|
||||
bool Session::ready() {
|
||||
bool Session::ready()
|
||||
{
|
||||
bool r;
|
||||
|
||||
sanity_check(false);
|
||||
sanity_check(false);
|
||||
r = switch_channel_ready(channel) != 0;
|
||||
do_hangup_hook();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void Session::check_hangup_hook()
|
||||
void Session::check_hangup_hook()
|
||||
{
|
||||
if (hangup_func_str && (hook_state == CS_HANGUP || hook_state == CS_ROUTING)) {
|
||||
hh++;
|
||||
}
|
||||
}
|
||||
|
||||
void Session::do_hangup_hook()
|
||||
void Session::do_hangup_hook()
|
||||
{
|
||||
if (hh && !mark) {
|
||||
const char *err = NULL;
|
||||
@@ -101,7 +102,7 @@ void Session::do_hangup_hook()
|
||||
}
|
||||
}
|
||||
|
||||
static switch_status_t perl_hanguphook(switch_core_session_t *session_hungup)
|
||||
static switch_status_t perl_hanguphook(switch_core_session_t *session_hungup)
|
||||
{
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session_hungup);
|
||||
CoreSession *coresession = NULL;
|
||||
@@ -118,7 +119,8 @@ static switch_status_t perl_hanguphook(switch_core_session_t *session_hungup)
|
||||
}
|
||||
|
||||
|
||||
void Session::setHangupHook(char *func, char *arg) {
|
||||
void Session::setHangupHook(char *func, char *arg)
|
||||
{
|
||||
|
||||
sanity_check_noreturn;
|
||||
|
||||
@@ -135,7 +137,8 @@ void Session::setHangupHook(char *func, char *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
void Session::setInputCallback(char *cbfunc, char *funcargs) {
|
||||
void Session::setInputCallback(char *cbfunc, char *funcargs)
|
||||
{
|
||||
|
||||
sanity_check_noreturn;
|
||||
|
||||
@@ -148,22 +151,22 @@ void Session::setInputCallback(char *cbfunc, char *funcargs) {
|
||||
if (funcargs) {
|
||||
cb_arg = strdup(funcargs);
|
||||
}
|
||||
|
||||
|
||||
args.buf = this;
|
||||
switch_channel_set_private(channel, "CoreSession", this);
|
||||
|
||||
args.input_callback = dtmf_callback;
|
||||
args.input_callback = dtmf_callback;
|
||||
ap = &args;
|
||||
}
|
||||
|
||||
switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t itype)
|
||||
switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t itype)
|
||||
{
|
||||
if (!getPERL()) {
|
||||
return SWITCH_STATUS_FALSE;;
|
||||
}
|
||||
|
||||
switch (itype) {
|
||||
case SWITCH_INPUT_TYPE_DTMF:
|
||||
case SWITCH_INPUT_TYPE_DTMF:
|
||||
{
|
||||
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
|
||||
char str[32] = "";
|
||||
@@ -177,14 +180,14 @@ switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t ityp
|
||||
}
|
||||
|
||||
str[0] = dtmf->digit;
|
||||
this_sv = newSV(strlen(str)+1);
|
||||
this_sv = newSV(strlen(str) + 1);
|
||||
sv_setpv(this_sv, str);
|
||||
hv_store(hash, "digit", 5, this_sv, 0);
|
||||
|
||||
switch_snprintf(str, sizeof(str), "%d", dtmf->duration);
|
||||
this_sv = newSV(strlen(str)+1);
|
||||
this_sv = newSV(strlen(str) + 1);
|
||||
sv_setpv(this_sv, str);
|
||||
hv_store(hash, "duration", 8, this_sv, 0);
|
||||
hv_store(hash, "duration", 8, this_sv, 0);
|
||||
|
||||
code = switch_mprintf("$__RV = %s('dtmf', \\%%__dtmf, %s);", cb_function, switch_str_nil(cb_arg));
|
||||
Perl_eval_pv(my_perl, code, FALSE);
|
||||
@@ -193,18 +196,18 @@ switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t ityp
|
||||
return process_callback_result(SvPV(get_sv("__RV", TRUE), n_a));
|
||||
}
|
||||
break;
|
||||
case SWITCH_INPUT_TYPE_EVENT:
|
||||
case SWITCH_INPUT_TYPE_EVENT:
|
||||
{
|
||||
switch_event_t *event = (switch_event_t *) input;
|
||||
int arg_count = 2;
|
||||
char *code;
|
||||
|
||||
mod_perl_conjure_event(my_perl, event, "__Input_Event__");
|
||||
|
||||
|
||||
code = switch_mprintf("$__RV = %s('event', $__Input_Event__, %s);", cb_function, switch_str_nil(cb_arg));
|
||||
Perl_eval_pv(my_perl, code, TRUE);
|
||||
free(code);
|
||||
|
||||
|
||||
return process_callback_result(SvPV(get_sv("__RV", TRUE), n_a));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -58,7 +58,7 @@ static struct {
|
||||
|
||||
|
||||
|
||||
static int Perl_safe_eval(PerlInterpreter *my_perl, const char *string)
|
||||
static int Perl_safe_eval(PerlInterpreter * my_perl, const char *string)
|
||||
{
|
||||
char *err = NULL;
|
||||
|
||||
@@ -73,7 +73,7 @@ static int Perl_safe_eval(PerlInterpreter *my_perl, const char *string)
|
||||
|
||||
|
||||
|
||||
static int perl_parse_and_execute(PerlInterpreter *my_perl, char *input_code, char *setup_code)
|
||||
static int perl_parse_and_execute(PerlInterpreter * my_perl, char *input_code, char *setup_code)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
@@ -103,10 +103,10 @@ static int perl_parse_and_execute(PerlInterpreter *my_perl, char *input_code, ch
|
||||
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 = ( ");
|
||||
for (x = 0; x < argc; x++) {
|
||||
stream.write_function(&stream, "'%s'%s", argv[x], x == argc-1 ? "" : ", ");
|
||||
stream.write_function(&stream, "'%s'%s", argv[x], x == argc - 1 ? "" : ", ");
|
||||
}
|
||||
stream.write_function(&stream, " );");
|
||||
code = stream.data;
|
||||
@@ -130,7 +130,7 @@ static int perl_parse_and_execute(PerlInterpreter *my_perl, char *input_code, ch
|
||||
file = switch_mprintf("require '%s';", file);
|
||||
switch_assert(file);
|
||||
}
|
||||
|
||||
|
||||
error = Perl_safe_eval(my_perl, file);
|
||||
switch_safe_free(file);
|
||||
}
|
||||
@@ -154,14 +154,15 @@ static PerlInterpreter *clone_perl(void)
|
||||
}
|
||||
|
||||
#if 0
|
||||
static perl_parse_and_execute (PerlInterpreter *my_perl, char *input_code, char *setup_code)
|
||||
static perl_parse_and_execute(PerlInterpreter * my_perl, char *input_code, char *setup_code)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
if (*input_code == '~') {
|
||||
char *buff = input_code + 1;
|
||||
perl_parse(my_perl, xs_init, 3, embedding, NULL);
|
||||
if (setup_code) Perl_safe_eval(my_perl, setup_code);
|
||||
if (setup_code)
|
||||
Perl_safe_eval(my_perl, setup_code);
|
||||
Perl_safe_eval(my_perl, buff);
|
||||
} else {
|
||||
int argc = 0;
|
||||
@@ -169,43 +170,38 @@ static perl_parse_and_execute (PerlInterpreter *my_perl, char *input_code, char
|
||||
char *err;
|
||||
argv[0] = "FreeSWITCH";
|
||||
argc++;
|
||||
|
||||
|
||||
argc += switch_separate_string(input_code, ' ', &argv[1], (sizeof(argv) / sizeof(argv[0])) - 1);
|
||||
if (!perl_parse(my_perl, xs_init, argc, argv, (char **)NULL)) {
|
||||
if (!perl_parse(my_perl, xs_init, argc, argv, (char **) NULL)) {
|
||||
if (setup_code) {
|
||||
if (!Perl_safe_eval(my_perl, setup_code)) {
|
||||
perl_run(my_perl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((err = SvPV(get_sv("@", TRUE), n_a)) && !switch_strlen_zero(err)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", err);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void perl_function(switch_core_session_t *session, char *data)
|
||||
{
|
||||
char *uuid = switch_core_session_get_uuid(session);
|
||||
PerlInterpreter *my_perl = clone_perl();
|
||||
char code[1024];
|
||||
|
||||
|
||||
perl_parse(my_perl, xs_init, 3, embedding, NULL);
|
||||
Perl_safe_eval(my_perl, code);
|
||||
|
||||
switch_snprintf(code, sizeof(code),
|
||||
"use lib '%s/perl';\n"
|
||||
"use freeswitch;\n"
|
||||
"$SWITCH_ENV{UUID} = \"%s\";\n"
|
||||
"$session = new freeswitch::Session(\"%s\")"
|
||||
,
|
||||
SWITCH_GLOBAL_dirs.base_dir,
|
||||
uuid,
|
||||
uuid);
|
||||
switch_snprintf(code, sizeof(code),
|
||||
"use lib '%s/perl';\n"
|
||||
"use freeswitch;\n"
|
||||
"$SWITCH_ENV{UUID} = \"%s\";\n" "$session = new freeswitch::Session(\"%s\")", SWITCH_GLOBAL_dirs.base_dir, uuid, uuid);
|
||||
|
||||
perl_parse_and_execute(my_perl, data, code);
|
||||
Perl_safe_eval(my_perl, "undef $session;");
|
||||
@@ -244,16 +240,10 @@ static void *SWITCH_THREAD_FUNC perl_thread_run(switch_thread_t *thread, void *o
|
||||
if (session) {
|
||||
uuid = switch_core_session_get_uuid(session);
|
||||
}
|
||||
|
||||
switch_snprintf(code, sizeof(code),
|
||||
"use lib '%s/perl';\n"
|
||||
"use freeswitch;\n"
|
||||
"$SWITCH_ENV{UUID} = \"%s\";\n"
|
||||
,
|
||||
|
||||
SWITCH_GLOBAL_dirs.base_dir,
|
||||
switch_str_nil(uuid)
|
||||
);
|
||||
switch_snprintf(code, sizeof(code),
|
||||
"use lib '%s/perl';\n" "use freeswitch;\n" "$SWITCH_ENV{UUID} = \"%s\";\n", SWITCH_GLOBAL_dirs.base_dir, switch_str_nil(uuid)
|
||||
);
|
||||
|
||||
perl_parse(my_perl, xs_init, 3, embedding, NULL);
|
||||
Perl_safe_eval(my_perl, code);
|
||||
@@ -273,7 +263,7 @@ static void *SWITCH_THREAD_FUNC perl_thread_run(switch_thread_t *thread, void *o
|
||||
//Perl_safe_eval(my_perl, cmd);
|
||||
perl_parse_and_execute(my_perl, cmd, NULL);
|
||||
}
|
||||
|
||||
|
||||
if (uuid) {
|
||||
switch_snprintf(code, sizeof(code), "undef $session;", uuid);
|
||||
Perl_safe_eval(my_perl, code);
|
||||
@@ -301,7 +291,7 @@ int perl_thread(const char *text)
|
||||
memset(po, 0, sizeof(*po));
|
||||
po->cmd = strdup(text);
|
||||
po->d = 1;
|
||||
|
||||
|
||||
switch_threadattr_create(&thd_attr, globals.pool);
|
||||
switch_threadattr_detach_set(thd_attr, 1);
|
||||
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
||||
@@ -310,7 +300,8 @@ int perl_thread(const char *text)
|
||||
return 0;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_API(perlrun_api_function) {
|
||||
SWITCH_STANDARD_API(perlrun_api_function)
|
||||
{
|
||||
|
||||
if (switch_strlen_zero(cmd)) {
|
||||
stream->write_function(stream, "-ERR Missing args.\n");
|
||||
@@ -322,7 +313,8 @@ SWITCH_STANDARD_API(perlrun_api_function) {
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_STANDARD_API(perl_api_function) {
|
||||
SWITCH_STANDARD_API(perl_api_function)
|
||||
{
|
||||
|
||||
struct perl_o po = { 0 };
|
||||
|
||||
@@ -337,12 +329,8 @@ SWITCH_STANDARD_API(perl_api_function) {
|
||||
perl_thread_run(NULL, &po);
|
||||
}
|
||||
|
||||
static switch_xml_t perl_fetch(const char *section,
|
||||
const char *tag_name,
|
||||
const char *key_name,
|
||||
const char *key_value,
|
||||
switch_event_t *params,
|
||||
void *user_data)
|
||||
static switch_xml_t perl_fetch(const char *section,
|
||||
const char *tag_name, const char *key_name, const char *key_value, switch_event_t *params, void *user_data)
|
||||
{
|
||||
|
||||
char *argv[128] = { 0 };
|
||||
@@ -359,10 +347,10 @@ static switch_xml_t perl_fetch(const char *section,
|
||||
|
||||
argv[argc++] = "FreeSWITCH";
|
||||
argv[argc++] = globals.xml_handler;
|
||||
|
||||
|
||||
PERL_SET_CONTEXT(my_perl);
|
||||
|
||||
if (perl_parse(my_perl, xs_init, argc, argv, (char **)NULL)) {
|
||||
|
||||
if (perl_parse(my_perl, xs_init, argc, argv, (char **) NULL)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Parsing Result!\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -375,15 +363,15 @@ static switch_xml_t perl_fetch(const char *section,
|
||||
section = "";
|
||||
}
|
||||
|
||||
this = newSV(strlen(section)+1);
|
||||
this = newSV(strlen(section) + 1);
|
||||
sv_setpv(this, section);
|
||||
hv_store(hash, "section", 7, this, 0);
|
||||
|
||||
|
||||
if (switch_strlen_zero(tag_name)) {
|
||||
tag_name = "";
|
||||
}
|
||||
|
||||
this = newSV(strlen(tag_name)+1);
|
||||
this = newSV(strlen(tag_name) + 1);
|
||||
sv_setpv(this, tag_name);
|
||||
hv_store(hash, "tag_name", 8, this, 0);
|
||||
|
||||
@@ -391,7 +379,7 @@ static switch_xml_t perl_fetch(const char *section,
|
||||
key_name = "";
|
||||
}
|
||||
|
||||
this = newSV(strlen(key_name)+1);
|
||||
this = newSV(strlen(key_name) + 1);
|
||||
sv_setpv(this, key_name);
|
||||
hv_store(hash, "key_name", 8, this, 0);
|
||||
|
||||
@@ -399,28 +387,23 @@ static switch_xml_t perl_fetch(const char *section,
|
||||
key_value = "";
|
||||
}
|
||||
|
||||
this = newSV(strlen(key_value)+1);
|
||||
this = newSV(strlen(key_value) + 1);
|
||||
sv_setpv(this, key_value);
|
||||
hv_store(hash, "key_value", 9, this, 0);
|
||||
|
||||
|
||||
if (!(hash = get_hv("XML_DATA", TRUE))) {
|
||||
abort();
|
||||
}
|
||||
|
||||
if (params) {
|
||||
for (hp = params->headers; hp; hp = hp->next) {
|
||||
this = newSV(strlen(hp->value)+1);
|
||||
this = newSV(strlen(hp->value) + 1);
|
||||
sv_setpv(this, hp->value);
|
||||
hv_store(hash, hp->name, strlen(hp->name), this, 0);
|
||||
}
|
||||
}
|
||||
|
||||
switch_snprintf(code, sizeof(code),
|
||||
"use lib '%s/perl';\n"
|
||||
"use freeswitch;\n"
|
||||
,
|
||||
SWITCH_GLOBAL_dirs.base_dir
|
||||
);
|
||||
switch_snprintf(code, sizeof(code), "use lib '%s/perl';\n" "use freeswitch;\n", SWITCH_GLOBAL_dirs.base_dir);
|
||||
Perl_safe_eval(my_perl, code);
|
||||
|
||||
if (params) {
|
||||
@@ -437,7 +420,7 @@ static switch_xml_t perl_fetch(const char *section,
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Parsing XML Result!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
destroy_perl(&my_perl);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +1,21 @@
|
||||
SWITCH_BEGIN_EXTERN_C
|
||||
|
||||
|
||||
void mod_perl_conjure_event(PerlInterpreter *my_perl, switch_event_t *event, const char *name)
|
||||
SWITCH_BEGIN_EXTERN_C void mod_perl_conjure_event(PerlInterpreter * my_perl, switch_event_t *event, const char *name)
|
||||
{
|
||||
Event *result = 0 ;
|
||||
Event *result = 0;
|
||||
SV *sv;
|
||||
PERL_SET_CONTEXT(my_perl);
|
||||
sv = sv_2mortal(get_sv(name, TRUE));
|
||||
result = (Event *)new Event(event);
|
||||
sv = sv_2mortal(get_sv(name, TRUE));
|
||||
result = (Event *) new Event(event);
|
||||
SWIG_Perl_MakePtr(sv, result, SWIGTYPE_p_Event, SWIG_OWNER | SWIG_SHADOW);
|
||||
}
|
||||
|
||||
|
||||
void mod_perl_conjure_stream(PerlInterpreter *my_perl, switch_stream_handle_t *stream, const char *name)
|
||||
void mod_perl_conjure_stream(PerlInterpreter * my_perl, switch_stream_handle_t *stream, const char *name)
|
||||
{
|
||||
Stream *result = 0 ;
|
||||
Stream *result = 0;
|
||||
SV *sv;
|
||||
PERL_SET_CONTEXT(my_perl);
|
||||
sv = sv_2mortal(get_sv(name, TRUE));
|
||||
result = (Stream *)new Stream(stream);
|
||||
sv = sv_2mortal(get_sv(name, TRUE));
|
||||
result = (Stream *) new Stream(stream);
|
||||
SWIG_Perl_MakePtr(sv, result, SWIGTYPE_p_Stream, SWIG_OWNER | SWIG_SHADOW);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,13 +1,12 @@
|
||||
#include <EXTERN.h>
|
||||
#include <perl.h>
|
||||
|
||||
EXTERN_C void xs_init (pTHX);
|
||||
EXTERN_C void xs_init(pTHX);
|
||||
|
||||
EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
|
||||
EXTERN_C void boot_freeswitch (pTHX_ CV* cv);
|
||||
EXTERN_C void boot_DynaLoader(pTHX_ CV * cv);
|
||||
EXTERN_C void boot_freeswitch(pTHX_ CV * cv);
|
||||
|
||||
EXTERN_C void
|
||||
xs_init(pTHX)
|
||||
EXTERN_C void xs_init(pTHX)
|
||||
{
|
||||
char *file = __FILE__;
|
||||
dXSUB_SYS;
|
||||
|
||||
@@ -3,336 +3,317 @@
|
||||
#define sanity_check(x) do { if (!session) { switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "session is not initalized\n"); return x;}} while(0)
|
||||
#define init_vars() do { caller_profile.source = "mod_python"; swapstate = S_SWAPPED_IN; } while(0)
|
||||
|
||||
PySession::PySession() : CoreSession()
|
||||
PySession::PySession():CoreSession()
|
||||
{
|
||||
init_vars();
|
||||
}
|
||||
|
||||
PySession::PySession(char *uuid) : CoreSession(uuid)
|
||||
PySession::PySession(char *uuid):CoreSession(uuid)
|
||||
{
|
||||
init_vars();
|
||||
}
|
||||
|
||||
PySession::PySession(switch_core_session_t *new_session) : CoreSession(new_session)
|
||||
PySession::PySession(switch_core_session_t *new_session):CoreSession(new_session)
|
||||
{
|
||||
init_vars();
|
||||
}
|
||||
|
||||
|
||||
void PySession::setDTMFCallback(PyObject *pyfunc, char *funcargs)
|
||||
void PySession::setDTMFCallback(PyObject * pyfunc, char *funcargs)
|
||||
{
|
||||
sanity_check();
|
||||
sanity_check();
|
||||
|
||||
if (!PyCallable_Check(pyfunc)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "DTMF function is not a python function.\n");
|
||||
return;
|
||||
}
|
||||
Py_XINCREF(pyfunc);
|
||||
CoreSession::setDTMFCallback((void *) pyfunc, funcargs);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PySession::setHangupHook(PyObject * pyfunc)
|
||||
{
|
||||
|
||||
if (!PyCallable_Check(pyfunc)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Hangup hook is not a python function.\n");
|
||||
return;
|
||||
}
|
||||
// without this Py_XINCREF, there will be segfaults. basically the python
|
||||
// interpreter will not know that it should not GC this object.
|
||||
// callback example: http://docs.python.org/ext/callingPython.html
|
||||
Py_XINCREF(pyfunc);
|
||||
CoreSession::setHangupHook((void *) pyfunc);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void PySession::check_hangup_hook()
|
||||
{
|
||||
PyObject *func;
|
||||
PyObject *result;
|
||||
char *resultStr;
|
||||
bool did_swap_in = false;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
|
||||
"check_hangup_hook has been DISABLED, please do not use hangup hooks in python code until further notice!\n");
|
||||
|
||||
if (!session) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No valid session\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PyCallable_Check(pyfunc)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "DTMF function is not a python function.\n");
|
||||
return;
|
||||
}
|
||||
Py_XINCREF(pyfunc);
|
||||
CoreSession::setDTMFCallback((void *) pyfunc, funcargs);
|
||||
|
||||
/*! NEEDS TO BE FIXED:
|
||||
|
||||
// The did_swap_in boolean was added to fix the following problem:
|
||||
// Design flaw - we swap in threadstate based on the assumption that thread state
|
||||
// is currently _swapped out_ when this hangup hook is called. However, nothing known to
|
||||
// guarantee that, and if thread state is already swapped in when this is invoked,
|
||||
// bad things will happen.
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "check hangup hook end_allow_threads\n");
|
||||
did_swap_in = end_allow_threads();
|
||||
|
||||
if (on_hangup == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "on_hangup is null\n");
|
||||
return;
|
||||
}
|
||||
|
||||
func = (PyObject *) on_hangup;
|
||||
|
||||
// TODO: to match js implementation, should pass the _python_ PySession
|
||||
// object instance wrapping this C++ PySession instance. but how do we do that?
|
||||
// for now, pass the uuid since its better than nothing
|
||||
PyObject* func_arg = Py_BuildValue("(s)", uuid);
|
||||
|
||||
result = PyEval_CallObject(func, func_arg);
|
||||
Py_XDECREF(func_arg);
|
||||
|
||||
if (result) {
|
||||
resultStr = (char *) PyString_AsString(result);
|
||||
// currently just ignore the result
|
||||
}
|
||||
else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to call python hangup callback\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "check hangup hook begin_allow_threads\n");
|
||||
if (did_swap_in) {
|
||||
begin_allow_threads();
|
||||
}
|
||||
|
||||
Py_XDECREF(result);
|
||||
*/
|
||||
}
|
||||
|
||||
switch_status_t PySession::run_dtmf_callback(void *input, switch_input_type_t itype)
|
||||
{
|
||||
|
||||
PyObject *func, *arglist;
|
||||
PyObject *pyresult;
|
||||
PyObject *headerdict;
|
||||
|
||||
char *resultStr;
|
||||
char *funcargs;
|
||||
switch_file_handle_t *fh = NULL;
|
||||
bool did_swap_in = false;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback\n");
|
||||
|
||||
|
||||
if (!cb_state.function) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "cb_state->function is null\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
func = (PyObject *) cb_state.function;
|
||||
if (!func) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "cb_state->function is null\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "cb_state->function is NOT null\n");
|
||||
}
|
||||
if (!PyCallable_Check(func)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "function not callable\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
funcargs = (char *) cb_state.funcargs;
|
||||
|
||||
if (itype == SWITCH_INPUT_TYPE_DTMF) {
|
||||
|
||||
arglist = Py_BuildValue("(sis)", input, itype, funcargs);
|
||||
} else if (itype == SWITCH_INPUT_TYPE_EVENT) {
|
||||
// DUNNO if this is correct in the case we have an event
|
||||
// will be of type switch_event_t *event;
|
||||
// http://www.freeswitch.org/docs/structswitch__event.html
|
||||
switch_event_t *event = (switch_event_t *) input;
|
||||
arglist = Py_BuildValue("({s:s}is)", "body", event->body, itype, funcargs);
|
||||
|
||||
// build a dictionary with all the headers
|
||||
|
||||
switch_event_header_t *hp;
|
||||
headerdict = PyDict_New();
|
||||
for (hp = event->headers; hp; hp = hp->next) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding event header to result");
|
||||
|
||||
// TODO: create PyObject pointers for name and value
|
||||
// and explicitly decref them. all ref counting stuff is
|
||||
// a mess and needs to be tested and looked at closer.
|
||||
PyDict_SetItem(headerdict, Py_BuildValue("s", hp->name), Py_BuildValue("s", hp->value));
|
||||
|
||||
}
|
||||
|
||||
// add it to the main event dictionary (first arg in list)
|
||||
// under key 'headers'
|
||||
PyObject *dict = PyTuple_GetItem(arglist, 0);
|
||||
PyDict_SetItemString(dict, "headers", headerdict);
|
||||
|
||||
Py_XDECREF(headerdict);
|
||||
|
||||
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown input type: %d\n", itype);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (!arglist) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error building arglist");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback end_allow_threads\n");
|
||||
did_swap_in = end_allow_threads();
|
||||
|
||||
pyresult = PyEval_CallObject(func, arglist);
|
||||
|
||||
|
||||
Py_XDECREF(arglist); // Trash arglist
|
||||
|
||||
if (pyresult && pyresult != Py_None) {
|
||||
resultStr = (char *) PyString_AsString(pyresult);
|
||||
switch_status_t cbresult = process_callback_result(resultStr);
|
||||
return cbresult;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Python callback\n returned None");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback begin_allow_threads\n");
|
||||
if (did_swap_in) {
|
||||
begin_allow_threads();
|
||||
}
|
||||
|
||||
Py_XDECREF(pyresult);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
bool PySession::begin_allow_threads(void)
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::begin_allow_threads() called\n");
|
||||
|
||||
if (!session) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No valid session\n");
|
||||
return false;
|
||||
}
|
||||
// swap out threadstate and store in instance variable
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
PyThreadState *swapin_tstate = (PyThreadState *) switch_channel_get_private(channel, "SwapInThreadState");
|
||||
// so lets assume the thread state was swapped in when the python script was started,
|
||||
// therefore swapin_tstate will be NULL (because there is nothing to swap in, since its
|
||||
// _already_ swapped in.)
|
||||
if (swapin_tstate == NULL) {
|
||||
// currently swapped in
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Threadstate swap-out!\n");
|
||||
swapin_tstate = PyEval_SaveThread();
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "swapin_tstate: %p\n", swapin_tstate);
|
||||
// give future swapper-inners something to actually swap in
|
||||
switch_channel_set_private(channel, "SwapInThreadState", (void *) swapin_tstate);
|
||||
cb_state.threadState = threadState; // TODO: get rid of this
|
||||
args.buf = &cb_state;
|
||||
ap = &args;
|
||||
return true;
|
||||
|
||||
} else {
|
||||
// currently swapped out
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool PySession::end_allow_threads(void)
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::end_allow_threads() called\n");
|
||||
// swap in threadstate from instance variable saved earlier
|
||||
if (!session) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No valid session\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
PyThreadState *swapin_tstate = (PyThreadState *) switch_channel_get_private(channel, "SwapInThreadState");
|
||||
if (swapin_tstate == NULL) {
|
||||
// currently swapped in
|
||||
return false;
|
||||
} else {
|
||||
// currently swapped out
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Threadstate swap-in!\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "swapin_tstate: %p\n", swapin_tstate);
|
||||
PyEval_RestoreThread(swapin_tstate);
|
||||
// dont give any swapper-inners the opportunity to do a double swap
|
||||
switch_channel_set_private(channel, "SwapInThreadState", NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PySession::setHangupHook(PyObject *pyfunc) {
|
||||
void PySession::hangup(char *cause)
|
||||
{
|
||||
|
||||
if (!PyCallable_Check(pyfunc)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Hangup hook is not a python function.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// without this Py_XINCREF, there will be segfaults. basically the python
|
||||
// interpreter will not know that it should not GC this object.
|
||||
// callback example: http://docs.python.org/ext/callingPython.html
|
||||
Py_XINCREF(pyfunc);
|
||||
CoreSession::setHangupHook((void *) pyfunc);
|
||||
// since we INCREF'd this function pointer earlier (so the py gc didnt reclaim it)
|
||||
// we have to DECREF it, or else the PySession dtor will never get called and
|
||||
// a zombie channel will be left over using up resources
|
||||
|
||||
if (cb_state.function != NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "xdecref on cb_state_function\n");
|
||||
PyObject *func = (PyObject *) cb_state.function;
|
||||
Py_XDECREF(func);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "cb_state.function is null\n");
|
||||
}
|
||||
|
||||
|
||||
CoreSession::hangup(cause);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void PySession::check_hangup_hook() {
|
||||
PyObject *func;
|
||||
PyObject *result;
|
||||
char *resultStr;
|
||||
bool did_swap_in = false;
|
||||
PySession::~PySession()
|
||||
{
|
||||
// Should we do any cleanup here?
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::~PySession started\n");
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "check_hangup_hook has been DISABLED, please do not use hangup hooks in python code until further notice!\n");
|
||||
|
||||
if (!session) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No valid session\n");
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
/*! NEEDS TO BE FIXED:
|
||||
|
||||
// The did_swap_in boolean was added to fix the following problem:
|
||||
// Design flaw - we swap in threadstate based on the assumption that thread state
|
||||
// is currently _swapped out_ when this hangup hook is called. However, nothing known to
|
||||
// guarantee that, and if thread state is already swapped in when this is invoked,
|
||||
// bad things will happen.
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "check hangup hook end_allow_threads\n");
|
||||
did_swap_in = end_allow_threads();
|
||||
|
||||
if (on_hangup == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "on_hangup is null\n");
|
||||
return;
|
||||
}
|
||||
|
||||
func = (PyObject *) on_hangup;
|
||||
|
||||
// TODO: to match js implementation, should pass the _python_ PySession
|
||||
// object instance wrapping this C++ PySession instance. but how do we do that?
|
||||
// for now, pass the uuid since its better than nothing
|
||||
PyObject* func_arg = Py_BuildValue("(s)", uuid);
|
||||
|
||||
result = PyEval_CallObject(func, func_arg);
|
||||
Py_XDECREF(func_arg);
|
||||
|
||||
if (result) {
|
||||
resultStr = (char *) PyString_AsString(result);
|
||||
// currently just ignore the result
|
||||
}
|
||||
else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to call python hangup callback\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "check hangup hook begin_allow_threads\n");
|
||||
if (did_swap_in) {
|
||||
begin_allow_threads();
|
||||
}
|
||||
|
||||
Py_XDECREF(result);
|
||||
*/
|
||||
}
|
||||
|
||||
switch_status_t PySession::run_dtmf_callback(void *input,
|
||||
switch_input_type_t itype) {
|
||||
|
||||
PyObject *func, *arglist;
|
||||
PyObject *pyresult;
|
||||
PyObject *headerdict;
|
||||
|
||||
char *resultStr;
|
||||
char *funcargs;
|
||||
switch_file_handle_t *fh = NULL;
|
||||
bool did_swap_in = false;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback\n");
|
||||
if (on_hangup) {
|
||||
PyObject *func = (PyObject *) on_hangup;
|
||||
Py_XDECREF(func);
|
||||
}
|
||||
|
||||
|
||||
if (!cb_state.function) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "cb_state->function is null\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
if (cb_state.function != NULL) {
|
||||
PyObject *func = (PyObject *) cb_state.function;
|
||||
Py_XDECREF(func);
|
||||
}
|
||||
|
||||
func = (PyObject *) cb_state.function;
|
||||
if (!func) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "cb_state->function is null\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "cb_state->function is NOT null\n");
|
||||
}
|
||||
if (!PyCallable_Check(func)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "function not callable\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
funcargs = (char *) cb_state.funcargs;
|
||||
|
||||
if (itype == SWITCH_INPUT_TYPE_DTMF) {
|
||||
|
||||
arglist = Py_BuildValue("(sis)", input, itype, funcargs);
|
||||
}
|
||||
else if (itype == SWITCH_INPUT_TYPE_EVENT) {
|
||||
// DUNNO if this is correct in the case we have an event
|
||||
// will be of type switch_event_t *event;
|
||||
// http://www.freeswitch.org/docs/structswitch__event.html
|
||||
switch_event_t *event = (switch_event_t *) input;
|
||||
arglist = Py_BuildValue("({s:s}is)",
|
||||
"body", event->body,
|
||||
itype,
|
||||
funcargs);
|
||||
|
||||
// build a dictionary with all the headers
|
||||
|
||||
switch_event_header_t *hp;
|
||||
headerdict = PyDict_New();
|
||||
for (hp = event->headers; hp; hp = hp->next) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding event header to result");
|
||||
|
||||
// TODO: create PyObject pointers for name and value
|
||||
// and explicitly decref them. all ref counting stuff is
|
||||
// a mess and needs to be tested and looked at closer.
|
||||
PyDict_SetItem(headerdict,
|
||||
Py_BuildValue("s", hp->name),
|
||||
Py_BuildValue("s", hp->value));
|
||||
|
||||
}
|
||||
|
||||
// add it to the main event dictionary (first arg in list)
|
||||
// under key 'headers'
|
||||
PyObject *dict = PyTuple_GetItem(arglist, 0);
|
||||
PyDict_SetItemString(dict,
|
||||
"headers",
|
||||
headerdict);
|
||||
|
||||
Py_XDECREF(headerdict);
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown input type: %d\n", itype);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (!arglist) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error building arglist");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback end_allow_threads\n");
|
||||
did_swap_in = end_allow_threads();
|
||||
|
||||
pyresult = PyEval_CallObject(func, arglist);
|
||||
|
||||
|
||||
Py_XDECREF(arglist); // Trash arglist
|
||||
|
||||
if (pyresult && pyresult != Py_None) {
|
||||
resultStr = (char *) PyString_AsString(pyresult);
|
||||
switch_status_t cbresult = process_callback_result(resultStr);
|
||||
return cbresult;
|
||||
}
|
||||
else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Python callback\n returned None");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback begin_allow_threads\n");
|
||||
if (did_swap_in) {
|
||||
begin_allow_threads();
|
||||
}
|
||||
|
||||
Py_XDECREF(pyresult);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::~PySession finished\n");
|
||||
|
||||
}
|
||||
|
||||
bool PySession::begin_allow_threads(void) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::begin_allow_threads() called\n");
|
||||
|
||||
if (!session) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No valid session\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// swap out threadstate and store in instance variable
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
PyThreadState *swapin_tstate = (PyThreadState *) switch_channel_get_private(channel, "SwapInThreadState");
|
||||
// so lets assume the thread state was swapped in when the python script was started,
|
||||
// therefore swapin_tstate will be NULL (because there is nothing to swap in, since its
|
||||
// _already_ swapped in.)
|
||||
if (swapin_tstate == NULL) {
|
||||
// currently swapped in
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Threadstate swap-out!\n");
|
||||
swapin_tstate = PyEval_SaveThread();
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "swapin_tstate: %p\n", swapin_tstate);
|
||||
// give future swapper-inners something to actually swap in
|
||||
switch_channel_set_private(channel, "SwapInThreadState", (void *) swapin_tstate);
|
||||
cb_state.threadState = threadState; // TODO: get rid of this
|
||||
args.buf = &cb_state;
|
||||
ap = &args;
|
||||
return true;
|
||||
|
||||
}
|
||||
else {
|
||||
// currently swapped out
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool PySession::end_allow_threads(void) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::end_allow_threads() called\n");
|
||||
// swap in threadstate from instance variable saved earlier
|
||||
if (!session) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No valid session\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
PyThreadState *swapin_tstate = (PyThreadState *) switch_channel_get_private(channel, "SwapInThreadState");
|
||||
if (swapin_tstate == NULL) {
|
||||
// currently swapped in
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// currently swapped out
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Threadstate swap-in!\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "swapin_tstate: %p\n", swapin_tstate);
|
||||
PyEval_RestoreThread(swapin_tstate);
|
||||
// dont give any swapper-inners the opportunity to do a double swap
|
||||
switch_channel_set_private(channel, "SwapInThreadState", NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PySession::hangup(char *cause) {
|
||||
|
||||
|
||||
// since we INCREF'd this function pointer earlier (so the py gc didnt reclaim it)
|
||||
// we have to DECREF it, or else the PySession dtor will never get called and
|
||||
// a zombie channel will be left over using up resources
|
||||
|
||||
if (cb_state.function != NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "xdecref on cb_state_function\n");
|
||||
PyObject * func = (PyObject *) cb_state.function;
|
||||
Py_XDECREF(func);
|
||||
}
|
||||
else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "cb_state.function is null\n");
|
||||
}
|
||||
|
||||
|
||||
CoreSession::hangup(cause);
|
||||
|
||||
}
|
||||
|
||||
|
||||
PySession::~PySession() {
|
||||
// Should we do any cleanup here?
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::~PySession started\n");
|
||||
|
||||
if (on_hangup) {
|
||||
PyObject * func = (PyObject *) on_hangup;
|
||||
Py_XDECREF(func);
|
||||
}
|
||||
|
||||
|
||||
if (cb_state.function != NULL) {
|
||||
PyObject * func = (PyObject *) cb_state.function;
|
||||
Py_XDECREF(func);
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::~PySession finished\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ static void eval_some_python(char *uuid, char *args, switch_core_session_t *sess
|
||||
{
|
||||
PyThreadState *tstate = NULL;
|
||||
char *dupargs = NULL;
|
||||
char *argv[128] = {0};
|
||||
char *argv[128] = { 0 };
|
||||
int argc;
|
||||
int lead = 0;
|
||||
char *script = NULL;
|
||||
@@ -68,16 +68,16 @@ static void eval_some_python(char *uuid, char *args, switch_core_session_t *sess
|
||||
PyObject *result = NULL;
|
||||
|
||||
if (args) {
|
||||
dupargs = strdup(args);
|
||||
dupargs = strdup(args);
|
||||
} else {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(dupargs != NULL);
|
||||
|
||||
|
||||
if (!(argc = switch_separate_string(dupargs, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No module name specified!\n");
|
||||
goto done;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No module name specified!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
script = argv[0];
|
||||
@@ -87,80 +87,76 @@ static void eval_some_python(char *uuid, char *args, switch_core_session_t *sess
|
||||
|
||||
tstate = PyThreadState_New(mainThreadState->interp);
|
||||
if (!tstate) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error acquiring tstate\n");
|
||||
goto done;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error acquiring tstate\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
// swap in thread state
|
||||
PyEval_AcquireThread(tstate);
|
||||
if (session) {
|
||||
// record the fact that thread state is swapped in
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
switch_channel_set_private(channel, "SwapInThreadState", NULL);
|
||||
// record the fact that thread state is swapped in
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
switch_channel_set_private(channel, "SwapInThreadState", NULL);
|
||||
}
|
||||
init_freeswitch();
|
||||
init_freeswitch();
|
||||
|
||||
// import the module
|
||||
module = PyImport_ImportModule( (char *) script);
|
||||
module = PyImport_ImportModule((char *) script);
|
||||
if (!module) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error importing module\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
goto done_swap_out;
|
||||
}
|
||||
|
||||
// reload the module
|
||||
module = PyImport_ReloadModule(module);
|
||||
if (!module) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error reloading module\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
goto done_swap_out;
|
||||
}
|
||||
|
||||
// get the handler function to be called
|
||||
function = PyObject_GetAttrString(module, "handler");
|
||||
if (!function) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Module does not define handler(uuid)\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
goto done_swap_out;
|
||||
}
|
||||
|
||||
if (uuid) {
|
||||
// build a tuple to pass the args, the uuid of session
|
||||
arg = Py_BuildValue("(s)", uuid);
|
||||
if (!arg) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error building args\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error importing module\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
goto done_swap_out;
|
||||
}
|
||||
}
|
||||
else {
|
||||
arg = PyTuple_New(1);
|
||||
PyObject *nada = Py_BuildValue("");
|
||||
PyTuple_SetItem(arg, 0, nada);
|
||||
// reload the module
|
||||
module = PyImport_ReloadModule(module);
|
||||
if (!module) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error reloading module\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
goto done_swap_out;
|
||||
}
|
||||
// get the handler function to be called
|
||||
function = PyObject_GetAttrString(module, "handler");
|
||||
if (!function) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Module does not define handler(uuid)\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
goto done_swap_out;
|
||||
}
|
||||
|
||||
if (uuid) {
|
||||
// build a tuple to pass the args, the uuid of session
|
||||
arg = Py_BuildValue("(s)", uuid);
|
||||
if (!arg) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error building args\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
goto done_swap_out;
|
||||
}
|
||||
} else {
|
||||
arg = PyTuple_New(1);
|
||||
PyObject *nada = Py_BuildValue("");
|
||||
PyTuple_SetItem(arg, 0, nada);
|
||||
}
|
||||
|
||||
// invoke the handler
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call python script \n");
|
||||
result = PyEval_CallObjectWithKeywords(function, arg, (PyObject *)NULL);
|
||||
result = PyEval_CallObjectWithKeywords(function, arg, (PyObject *) NULL);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Finished calling python script \n");
|
||||
|
||||
// check the result and print out any errors
|
||||
if (!result) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error calling python script\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error calling python script\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
goto done_swap_out;
|
||||
|
||||
done:
|
||||
done:
|
||||
switch_safe_free(dupargs);
|
||||
|
||||
done_swap_out:
|
||||
done_swap_out:
|
||||
// decrement ref counts
|
||||
Py_XDECREF(module);
|
||||
Py_XDECREF(function);
|
||||
@@ -183,14 +179,12 @@ static void eval_some_python(char *uuid, char *args, switch_core_session_t *sess
|
||||
PyThreadState *cur_tstate = PyThreadState_Get();
|
||||
PyThreadState_Clear(cur_tstate);
|
||||
PyEval_ReleaseThread(cur_tstate);
|
||||
PyThreadState_Delete(cur_tstate);
|
||||
}
|
||||
else {
|
||||
PyThreadState_Delete(cur_tstate);
|
||||
} else {
|
||||
// thread state is already swapped out, so, nothing for us to do
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "according to chan priv data, already swapped out \n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// they ran python script from cmd line, behave a bit differently (untested)
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No session: Threadstate mod_python.c swap-out! \n");
|
||||
PyEval_ReleaseThread(tstate);
|
||||
@@ -203,8 +197,8 @@ static void eval_some_python(char *uuid, char *args, switch_core_session_t *sess
|
||||
|
||||
SWITCH_STANDARD_APP(python_function)
|
||||
{
|
||||
eval_some_python(switch_core_session_get_uuid(session), (char *)data, session);
|
||||
|
||||
eval_some_python(switch_core_session_get_uuid(session), (char *) data, session);
|
||||
|
||||
}
|
||||
|
||||
struct switch_py_thread {
|
||||
@@ -228,7 +222,7 @@ static void *SWITCH_THREAD_FUNC py_thread_run(switch_thread_t *thread, void *obj
|
||||
SWITCH_STANDARD_API(launch_python)
|
||||
{
|
||||
switch_thread_t *thread;
|
||||
switch_threadattr_t *thd_attr = NULL;
|
||||
switch_threadattr_t *thd_attr = NULL;
|
||||
switch_memory_pool_t *pool;
|
||||
struct switch_py_thread *pt;
|
||||
|
||||
@@ -236,7 +230,7 @@ SWITCH_STANDARD_API(launch_python)
|
||||
stream->write_function(stream, "USAGE: %s\n", python_run_interface.syntax);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
switch_core_new_memory_pool(&pool);
|
||||
assert(pool != NULL);
|
||||
|
||||
@@ -245,11 +239,11 @@ SWITCH_STANDARD_API(launch_python)
|
||||
|
||||
pt->pool = pool;
|
||||
pt->args = switch_core_strdup(pt->pool, cmd);
|
||||
|
||||
switch_threadattr_create(&thd_attr, pt->pool);
|
||||
switch_threadattr_detach_set(thd_attr, 1);
|
||||
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
||||
switch_thread_create(&thread, thd_attr, py_thread_run, pt, pt->pool);
|
||||
|
||||
switch_threadattr_create(&thd_attr, pt->pool);
|
||||
switch_threadattr_detach_set(thd_attr, 1);
|
||||
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
||||
switch_thread_create(&thread, thd_attr, py_thread_run, pt, pt->pool);
|
||||
|
||||
stream->write_function(stream, "OK\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
@@ -290,7 +284,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_python_load)
|
||||
/* connect my internal structure to the blank pointer passed to me */
|
||||
*module_interface = &python_module_interface;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Python Framework Loading...\n");
|
||||
|
||||
|
||||
if (!Py_IsInitialized()) {
|
||||
|
||||
// initialize python system
|
||||
@@ -302,13 +296,13 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_python_load)
|
||||
// save threadstate since it's interp field will be needed
|
||||
// to create new threadstates, and will be needed for shutdown
|
||||
mainThreadState = PyThreadState_Get();
|
||||
|
||||
|
||||
// swap out threadstate since the call threads will create
|
||||
// their own and swap in their threadstate
|
||||
PyThreadState_Swap(NULL);
|
||||
PyThreadState_Swap(NULL);
|
||||
|
||||
// release GIL
|
||||
PyEval_ReleaseLock();
|
||||
PyEval_ReleaseLock();
|
||||
}
|
||||
|
||||
/* indicate that the module should continue to be loaded */
|
||||
@@ -319,18 +313,18 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_python_load)
|
||||
Called when the system shuts down*/
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_python_shutdown)
|
||||
{
|
||||
PyInterpreterState *mainInterpreterState;
|
||||
PyThreadState *myThreadState;
|
||||
PyInterpreterState *mainInterpreterState;
|
||||
PyThreadState *myThreadState;
|
||||
|
||||
PyEval_AcquireLock();
|
||||
mainInterpreterState = mainThreadState->interp;
|
||||
myThreadState = PyThreadState_New(mainInterpreterState);
|
||||
PyThreadState_Swap(myThreadState);
|
||||
PyEval_ReleaseLock();
|
||||
PyEval_AcquireLock();
|
||||
mainInterpreterState = mainThreadState->interp;
|
||||
myThreadState = PyThreadState_New(mainInterpreterState);
|
||||
PyThreadState_Swap(myThreadState);
|
||||
PyEval_ReleaseLock();
|
||||
|
||||
Py_Finalize();
|
||||
PyEval_ReleaseLock();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
Py_Finalize();
|
||||
PyEval_ReleaseLock();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -571,7 +571,7 @@ extern "C" {
|
||||
* type checking.
|
||||
*
|
||||
* Author : David Beazley (beazley@cs.uchicago.edu)
|
||||
************************************************************************//* Common SWIG API */
|
||||
************************************************************************//* Common SWIG API */
|
||||
#define SWIG_ConvertPtr(obj, pp, type, flags) SWIG_Python_ConvertPtr(obj, pp, type, flags)
|
||||
#define SWIG_NewPointerObj(p, type, flags) SWIG_Python_NewPointerObj(p, type, flags)
|
||||
#define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags)
|
||||
@@ -583,11 +583,11 @@ extern "C" {
|
||||
#define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer)
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Pointer declarations
|
||||
* ----------------------------------------------------------------------------- *//*
|
||||
Use SWIG_NO_COBJECT_TYPES to force the use of strings to represent
|
||||
C/C++ pointers in the python side. Very useful for debugging, but
|
||||
not always safe.
|
||||
*/
|
||||
* ----------------------------------------------------------------------------- *//*
|
||||
Use SWIG_NO_COBJECT_TYPES to force the use of strings to represent
|
||||
C/C++ pointers in the python side. Very useful for debugging, but
|
||||
not always safe.
|
||||
*/
|
||||
#if !defined(SWIG_NO_COBJECT_TYPES) && !defined(SWIG_COBJECT_TYPES)
|
||||
# define SWIG_COBJECT_TYPES
|
||||
#endif
|
||||
@@ -1538,8 +1538,7 @@ extern "C" {
|
||||
resultobj = Py_None;
|
||||
return resultobj;
|
||||
fail:return NULL;
|
||||
}
|
||||
static PyObject *_wrap_fs_core_init(PyObject * self, PyObject * args) {
|
||||
} static PyObject *_wrap_fs_core_init(PyObject * self, PyObject * args) {
|
||||
PyObject *resultobj = NULL;
|
||||
char *arg1 = (char *) 0;
|
||||
int result;
|
||||
@@ -2683,8 +2682,7 @@ extern "C" {
|
||||
SWIGINTERN PyObject *swig_varlink_repr(swig_varlinkobject * v) {
|
||||
v = v;
|
||||
return PyString_FromString("<Swig global variables>");
|
||||
}
|
||||
SWIGINTERN int swig_varlink_print(swig_varlinkobject * v, FILE * fp, int flags) {
|
||||
} SWIGINTERN int swig_varlink_print(swig_varlinkobject * v, FILE * fp, int flags) {
|
||||
swig_globalvar *var;
|
||||
flags = flags;
|
||||
fprintf(fp, "Swig global variables { ");
|
||||
|
||||
@@ -184,7 +184,7 @@ static JSBool request_write(JSContext * cx, JSObject * obj, uintN argc, jsval *
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool request_add_header(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool request_add_header(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
struct request_obj *ro = JS_GetPrivate(cx, obj);
|
||||
|
||||
@@ -226,7 +226,7 @@ static JSBool request_get_header(JSContext * cx, JSObject * obj, uintN argc, jsv
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool request_dump_env(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool request_dump_env(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
struct request_obj *ro = JS_GetPrivate(cx, obj);
|
||||
char *how = "text";
|
||||
@@ -244,10 +244,10 @@ static JSBool request_dump_env(JSContext *cx, JSObject *obj, uintN argc, jsval *
|
||||
switch_xml_t xml;
|
||||
char *xmlstr;
|
||||
if ((xml = switch_event_xmlize(ro->stream->param_event, SWITCH_VA_NONE))) {
|
||||
xmlstr = switch_xml_toxml(xml, SWITCH_FALSE);
|
||||
xmlstr = switch_xml_toxml(xml, SWITCH_FALSE);
|
||||
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, xmlstr));
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char *buf;
|
||||
switch_event_serialize(ro->stream->param_event, &buf, SWITCH_TRUE);
|
||||
@@ -264,7 +264,7 @@ static JSBool request_dump_env(JSContext *cx, JSObject *obj, uintN argc, jsval *
|
||||
|
||||
static void request_destroy(JSContext * cx, JSObject * obj)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
enum request_tinyid {
|
||||
@@ -284,7 +284,7 @@ static JSPropertySpec request_props[] = {
|
||||
{0}
|
||||
};
|
||||
|
||||
static JSBool request_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
static JSBool request_getProperty(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
|
||||
{
|
||||
JSBool res = JS_TRUE;
|
||||
struct request_obj *ro = JS_GetPrivate(cx, obj);
|
||||
@@ -320,12 +320,11 @@ JSClass request_class = {
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, request_destroy, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
static JSObject *new_request(JSContext *cx, JSObject *obj, struct request_obj *ro)
|
||||
static JSObject *new_request(JSContext * cx, JSObject * obj, struct request_obj *ro)
|
||||
{
|
||||
JSObject *Request;
|
||||
if ((Request = JS_DefineObject(cx, obj, "request", &request_class, NULL, 0))) {
|
||||
if ((JS_SetPrivate(cx, Request, ro) &&
|
||||
JS_DefineProperties(cx, Request, request_props) && JS_DefineFunctions(cx, Request, request_methods))) {
|
||||
if ((JS_SetPrivate(cx, Request, ro) && JS_DefineProperties(cx, Request, request_props) && JS_DefineFunctions(cx, Request, request_methods))) {
|
||||
return Request;
|
||||
}
|
||||
}
|
||||
@@ -375,12 +374,12 @@ static JSBool pcre_compile(JSContext * cx, JSObject * obj, uintN argc, jsval * a
|
||||
char *string, *regex_string;
|
||||
|
||||
if (argc > 1) {
|
||||
string = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
||||
regex_string = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
|
||||
string = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
||||
regex_string = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
|
||||
switch_regex_safe_free(pcre_obj->re);
|
||||
switch_safe_free(pcre_obj->string);
|
||||
pcre_obj->string = strdup(string);
|
||||
pcre_obj->proceed = switch_regex_perform(pcre_obj->string, regex_string, &pcre_obj->re, pcre_obj->ovector,
|
||||
pcre_obj->proceed = switch_regex_perform(pcre_obj->string, regex_string, &pcre_obj->re, pcre_obj->ovector,
|
||||
sizeof(pcre_obj->ovector) / sizeof(pcre_obj->ovector[0]));
|
||||
*rval = BOOLEAN_TO_JSVAL(pcre_obj->proceed ? JS_TRUE : JS_FALSE);
|
||||
} else {
|
||||
@@ -401,10 +400,10 @@ static JSBool pcre_substitute(JSContext * cx, JSObject * obj, uintN argc, jsval
|
||||
eval_some_js("~throw new Error(\"REGEX is not compiled or has no matches\");", cx, obj, rval);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (argc > 0) {
|
||||
uint32_t len;
|
||||
subst_string = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
||||
subst_string = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
||||
len = (uint32_t) (strlen(pcre_obj->string) + strlen(subst_string) + 10);
|
||||
substituted = malloc(len);
|
||||
switch_assert(substituted != NULL);
|
||||
@@ -841,7 +840,7 @@ static JSBool dtmf_getProperty(JSContext * cx, JSObject * obj, jsval id, jsval *
|
||||
|
||||
case DTMF_DURATION:
|
||||
{
|
||||
*vp = INT_TO_JSVAL((int)dtmf->duration);
|
||||
*vp = INT_TO_JSVAL((int) dtmf->duration);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1097,10 +1096,10 @@ static switch_status_t js_common_callback(switch_core_session_t *session, void *
|
||||
uintN argc = 0;
|
||||
jsval argv[4];
|
||||
JSObject *Event = NULL;
|
||||
jsval nval , *rval = &nval;
|
||||
jsval nval, *rval = &nval;
|
||||
JSContext *cx = cb_state->cx;
|
||||
JSObject *obj = cb_state->obj;
|
||||
|
||||
|
||||
METHOD_SANITY_CHECK();
|
||||
|
||||
jss->stack_depth++;
|
||||
@@ -1126,10 +1125,10 @@ static switch_status_t js_common_callback(switch_core_session_t *session, void *
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
break;
|
||||
case SWITCH_INPUT_TYPE_DTMF:
|
||||
case SWITCH_INPUT_TYPE_DTMF:
|
||||
{
|
||||
switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
|
||||
|
||||
|
||||
if (dtmf) {
|
||||
if ((Event = new_js_dtmf(dtmf, "_XX_DTMF_XX_", cb_state->cx, cb_state->obj))) {
|
||||
argv[argc++] = STRING_TO_JSVAL(JS_NewStringCopyZ(cb_state->cx, "dtmf"));
|
||||
@@ -1624,7 +1623,7 @@ static JSBool session_streamfile(JSContext * cx, JSObject * obj, uintN argc, jsv
|
||||
switch_input_args_t args = { 0 };
|
||||
const char *prebuf;
|
||||
char posbuf[35] = "";
|
||||
|
||||
|
||||
METHOD_SANITY_CHECK();
|
||||
channel = switch_core_session_get_channel(jss->session);
|
||||
CHANNEL_SANITY_CHECK();
|
||||
@@ -1660,13 +1659,13 @@ static JSBool session_streamfile(JSContext * cx, JSObject * obj, uintN argc, jsv
|
||||
JS_ValueToInt32(cx, argv[3], &samps);
|
||||
fh.samples = samps;
|
||||
}
|
||||
|
||||
if ((prebuf = switch_channel_get_variable(channel, "stream_prebuffer"))) {
|
||||
int maybe = atoi(prebuf);
|
||||
if (maybe > 0) {
|
||||
fh.prebuf = maybe;
|
||||
}
|
||||
}
|
||||
|
||||
if ((prebuf = switch_channel_get_variable(channel, "stream_prebuffer"))) {
|
||||
int maybe = atoi(prebuf);
|
||||
if (maybe > 0) {
|
||||
fh.prebuf = maybe;
|
||||
}
|
||||
}
|
||||
|
||||
cb_state.extra = &fh;
|
||||
cb_state.ret = BOOLEAN_TO_JSVAL(JS_FALSE);
|
||||
@@ -1825,7 +1824,7 @@ static JSBool session_speak(JSContext * cx, JSObject * obj, uintN argc, jsval *
|
||||
if (jss->speech && strcasecmp(jss->speech->sh.name, tts_name)) {
|
||||
destroy_speech_engine(jss);
|
||||
}
|
||||
|
||||
|
||||
if (jss->speech) {
|
||||
switch_core_speech_text_param_tts(&jss->speech->sh, "voice", voice_name);
|
||||
} else {
|
||||
@@ -1861,7 +1860,7 @@ static JSBool session_speak(JSContext * cx, JSObject * obj, uintN argc, jsval *
|
||||
args.input_callback = dtmf_func;
|
||||
args.buf = bp;
|
||||
args.buflen = len;
|
||||
|
||||
|
||||
switch_core_speech_flush_tts(&jss->speech->sh);
|
||||
switch_ivr_speak_text_handle(jss->session, &jss->speech->sh, &jss->speech->codec, NULL, text, &args);
|
||||
JS_ResumeRequest(cx, cb_state.saveDepth);
|
||||
@@ -2174,12 +2173,11 @@ static JSBool session_hangup(JSContext * cx, JSObject * obj, uintN argc, jsval *
|
||||
CHANNEL_SANITY_CHECK();
|
||||
|
||||
if (argc > 1) {
|
||||
if(JSVAL_IS_INT(argv[0])) {
|
||||
if (JSVAL_IS_INT(argv[0])) {
|
||||
int32 i = 0;
|
||||
JS_ValueToInt32(cx, argv[0], &i);
|
||||
cause = i;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
cause_name = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
||||
cause = switch_channel_str2cause(cause_name);
|
||||
}
|
||||
@@ -2204,7 +2202,7 @@ struct fetch_url_data {
|
||||
JSObject *obj;
|
||||
switch_size_t buffer_size;
|
||||
switch_size_t data_len;
|
||||
char* buffer;
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
static size_t hash_callback(void *ptr, size_t size, size_t nmemb, void *data)
|
||||
@@ -2257,7 +2255,7 @@ static size_t file_callback(void *ptr, size_t size, size_t nmemb, void *data)
|
||||
register unsigned int realsize = (unsigned int) (size * nmemb);
|
||||
struct config_data *config_data = data;
|
||||
|
||||
if ((write(config_data->fd, ptr, realsize) != (int)realsize)) {
|
||||
if ((write(config_data->fd, ptr, realsize) != (int) realsize)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to write all bytes!\n");
|
||||
}
|
||||
return realsize;
|
||||
@@ -2412,7 +2410,7 @@ static JSBool js_fetchurl(JSContext * cx, JSObject * obj, uintN argc, jsval * ar
|
||||
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, config_data.buffer));
|
||||
} else {
|
||||
char errmsg[256];
|
||||
switch_snprintf(errmsg, 256, "~throw new Error(\"Curl returned error %u.\");", (unsigned)code);
|
||||
switch_snprintf(errmsg, 256, "~throw new Error(\"Curl returned error %u.\");", (unsigned) code);
|
||||
eval_some_js(errmsg, cx, obj, rval);
|
||||
}
|
||||
|
||||
@@ -2593,7 +2591,7 @@ static JSObject *new_js_session(JSContext * cx, JSObject * obj, switch_core_sess
|
||||
*jss = malloc(sizeof(**jss));
|
||||
switch_assert(*jss);
|
||||
memset(*jss, 0, sizeof(**jss));
|
||||
|
||||
|
||||
(*jss)->session = session;
|
||||
(*jss)->flags = flags;
|
||||
(*jss)->cx = cx;
|
||||
@@ -2628,7 +2626,7 @@ static JSBool session_construct(JSContext * cx, JSObject * obj, uintN argc, jsva
|
||||
jss->cx = cx;
|
||||
jss->obj = obj;
|
||||
JS_SetPrivate(cx, obj, jss);
|
||||
|
||||
|
||||
if (argc > 0) {
|
||||
char *uuid = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
||||
if (uuid) {
|
||||
@@ -2649,7 +2647,7 @@ static JSBool session_set_callerdata(JSContext * cx, JSObject * obj, uintN argc,
|
||||
char *var, *val, **toset = NULL;
|
||||
var = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
||||
val = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
|
||||
|
||||
|
||||
if (!strcasecmp(var, "dialplan")) {
|
||||
toset = &jss->dialplan;
|
||||
} else if (!strcasecmp(var, "username")) {
|
||||
@@ -2670,15 +2668,15 @@ static JSBool session_set_callerdata(JSContext * cx, JSObject * obj, uintN argc,
|
||||
toset = &jss->destination_number;
|
||||
} else if (!strcasecmp(var, "context")) {
|
||||
toset = &jss->context;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (toset) {
|
||||
switch_safe_free(*toset);
|
||||
*toset = strdup(val);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@@ -2727,14 +2725,22 @@ static JSBool session_originate(JSContext * cx, JSObject * obj, uintN argc, jsva
|
||||
}
|
||||
}
|
||||
|
||||
if (!switch_strlen_zero(jss->dialplan)) dialplan = jss->dialplan;
|
||||
if (!switch_strlen_zero(jss->caller_id_name)) cid_name = jss->caller_id_name;
|
||||
if (!switch_strlen_zero(jss->caller_id_number)) cid_num = jss->caller_id_number;
|
||||
if (!switch_strlen_zero(jss->ani)) ani = jss->ani;
|
||||
if (!switch_strlen_zero(jss->aniii)) aniii = jss->aniii;
|
||||
if (!switch_strlen_zero(jss->rdnis)) rdnis = jss->rdnis;
|
||||
if (!switch_strlen_zero(jss->context)) context = jss->context;
|
||||
if (!switch_strlen_zero(jss->username)) username = jss->username;
|
||||
if (!switch_strlen_zero(jss->dialplan))
|
||||
dialplan = jss->dialplan;
|
||||
if (!switch_strlen_zero(jss->caller_id_name))
|
||||
cid_name = jss->caller_id_name;
|
||||
if (!switch_strlen_zero(jss->caller_id_number))
|
||||
cid_num = jss->caller_id_number;
|
||||
if (!switch_strlen_zero(jss->ani))
|
||||
ani = jss->ani;
|
||||
if (!switch_strlen_zero(jss->aniii))
|
||||
aniii = jss->aniii;
|
||||
if (!switch_strlen_zero(jss->rdnis))
|
||||
rdnis = jss->rdnis;
|
||||
if (!switch_strlen_zero(jss->context))
|
||||
context = jss->context;
|
||||
if (!switch_strlen_zero(jss->username))
|
||||
username = jss->username;
|
||||
|
||||
dest = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
|
||||
|
||||
@@ -2747,16 +2753,15 @@ static JSBool session_originate(JSContext * cx, JSObject * obj, uintN argc, jsva
|
||||
tmp = JS_GetStringBytes(JS_ValueToString(cx, argv[2]));
|
||||
if (!switch_strlen_zero(tmp)) {
|
||||
to = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
caller_profile = switch_caller_profile_new(pool,username, dialplan, cid_name, cid_num, network_addr,
|
||||
ani, aniii, rdnis, modname, context, dest);
|
||||
caller_profile = switch_caller_profile_new(pool, username, dialplan, cid_name, cid_num, network_addr, ani, aniii, rdnis, modname, context, dest);
|
||||
|
||||
saveDepth = JS_SuspendRequest(cx);
|
||||
status = switch_ivr_originate(session, &peer_session, &jss->cause, dest, to ? atoi(to) : 60, NULL, NULL, NULL, caller_profile, SOF_NONE);
|
||||
@@ -2766,7 +2771,7 @@ static JSBool session_originate(JSContext * cx, JSObject * obj, uintN argc, jsva
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot Create Outgoing Channel! [%s]\n", dest);
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
jss->session = peer_session;
|
||||
switch_set_flag(jss, S_HUP);
|
||||
*rval = BOOLEAN_TO_JSVAL(JS_TRUE);
|
||||
@@ -2783,21 +2788,21 @@ static JSBool session_originate(JSContext * cx, JSObject * obj, uintN argc, jsva
|
||||
static void session_destroy(JSContext * cx, JSObject * obj)
|
||||
{
|
||||
struct js_session *jss;
|
||||
|
||||
|
||||
if (cx && obj) {
|
||||
if ((jss = JS_GetPrivate(cx, obj))) {
|
||||
JS_SetPrivate(cx, obj, NULL);
|
||||
if (jss->speech && *jss->speech->sh.name) {
|
||||
destroy_speech_engine(jss);
|
||||
}
|
||||
|
||||
|
||||
if (jss->session) {
|
||||
switch_core_session_t *session = jss->session;
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
|
||||
|
||||
switch_channel_set_private(channel, "jss", NULL);
|
||||
switch_core_event_hook_remove_state_change(session, hanguphook);
|
||||
|
||||
|
||||
if (switch_test_flag(jss, S_HUP)) {
|
||||
switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
|
||||
}
|
||||
@@ -2816,7 +2821,7 @@ static void session_destroy(JSContext * cx, JSObject * obj)
|
||||
}
|
||||
|
||||
free(jss);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3025,7 +3030,7 @@ JSClass fileio_class = {
|
||||
static JSBool js_exit(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
char *supplied_error, code_buf[256] = "";
|
||||
|
||||
|
||||
if (argc > 0 && (supplied_error = JS_GetStringBytes(JS_ValueToString(cx, argv[0])))) {
|
||||
switch_snprintf(code_buf, sizeof(code_buf), "~throw new Error(\"%s\");", supplied_error);
|
||||
eval_some_js(code_buf, cx, obj, rval);
|
||||
@@ -3078,7 +3083,7 @@ static JSBool js_global_set(JSContext * cx, JSObject * obj, uintN argc, jsval *
|
||||
char *var_name = NULL, *val = NULL;
|
||||
if (argc > 1) {
|
||||
var_name = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
||||
val = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
|
||||
val = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
|
||||
switch_core_set_variable(var_name, val);
|
||||
return JS_TRUE;
|
||||
}
|
||||
@@ -3153,7 +3158,7 @@ static JSBool js_api_execute(JSContext * cx, JSObject * obj, uintN argc, jsval *
|
||||
if (argc > 1) {
|
||||
arg = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
|
||||
}
|
||||
|
||||
|
||||
if (argc > 2) {
|
||||
JSObject *session_obj;
|
||||
struct js_session *jss;
|
||||
@@ -3384,7 +3389,7 @@ SWITCH_STANDARD_APP(js_dp_function)
|
||||
js_parse_and_execute(session, data, NULL);
|
||||
}
|
||||
|
||||
static void *SWITCH_THREAD_FUNC js_thread_run(switch_thread_t * thread, void *obj)
|
||||
static void *SWITCH_THREAD_FUNC js_thread_run(switch_thread_t *thread, void *obj)
|
||||
{
|
||||
char *input_code = obj;
|
||||
|
||||
@@ -3419,17 +3424,17 @@ static void js_thread_launch(const char *text)
|
||||
|
||||
SWITCH_STANDARD_API(jsapi_function)
|
||||
{
|
||||
struct request_obj ro = {0};
|
||||
struct request_obj ro = { 0 };
|
||||
char *path_info = NULL;
|
||||
|
||||
if (stream->param_event) {
|
||||
if (stream->param_event) {
|
||||
path_info = switch_event_get_header(stream->param_event, "http-path-info");
|
||||
}
|
||||
|
||||
if (switch_strlen_zero(cmd) && path_info) {
|
||||
cmd = path_info;
|
||||
}
|
||||
|
||||
|
||||
if (switch_strlen_zero(cmd)) {
|
||||
stream->write_function(stream, "USAGE: %s\n", jsapi_interface.syntax);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
@@ -3456,14 +3461,14 @@ SWITCH_STANDARD_API(launch_async)
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void message_query_handler(switch_event_t *event)
|
||||
static void message_query_handler(switch_event_t *event)
|
||||
{
|
||||
char *account = switch_event_get_header(event, "message-account");
|
||||
|
||||
if (account) {
|
||||
char *path, *cmd;
|
||||
|
||||
path = switch_mprintf("%s%smwi.js", SWITCH_GLOBAL_dirs.script_dir, SWITCH_PATH_SEPARATOR);
|
||||
path = switch_mprintf("%s%smwi.js", SWITCH_GLOBAL_dirs.script_dir, SWITCH_PATH_SEPARATOR);
|
||||
switch_assert(path != NULL);
|
||||
|
||||
if (switch_file_exists(path, NULL) == SWITCH_STATUS_SUCCESS) {
|
||||
@@ -3497,7 +3502,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_spidermonkey_load)
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
SWITCH_ADD_API(api_interface, "jsrun", "run a script", launch_async, "jsrun <script> [additional_vars [...]]");
|
||||
SWITCH_ADD_API(api_interface, "jsapi", "execute an api call", jsapi_function, "jsapi <script> [additional_vars [...]]");
|
||||
SWITCH_ADD_APP(app_interface, "javascript", "Launch JS ivr", "Run a javascript ivr on a channel", js_dp_function, "<script> [additional_vars [...]]", SAF_SUPPORT_NOMEDIA);
|
||||
SWITCH_ADD_APP(app_interface, "javascript", "Launch JS ivr", "Run a javascript ivr on a channel", js_dp_function, "<script> [additional_vars [...]]",
|
||||
SAF_SUPPORT_NOMEDIA);
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
|
||||
@@ -73,10 +73,10 @@ static JSBool db_construct(JSContext * cx, JSObject * obj, uintN argc, jsval * a
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static JSBool db_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool db_close(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
struct db_obj *dbo = JS_GetPrivate(cx, obj);
|
||||
|
||||
|
||||
if (dbo) {
|
||||
if (dbo->stmt) {
|
||||
switch_core_db_finalize(dbo->stmt);
|
||||
@@ -91,7 +91,7 @@ static JSBool db_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, js
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static void db_destroy(JSContext *cx, JSObject *obj)
|
||||
static void db_destroy(JSContext * cx, JSObject * obj)
|
||||
{
|
||||
struct db_obj *dbo = JS_GetPrivate(cx, obj);
|
||||
|
||||
@@ -215,7 +215,7 @@ static JSBool db_fetch(JSContext * cx, JSObject * obj, uintN argc, jsval * argv,
|
||||
}
|
||||
for (x = 0; x < colcount; x++) {
|
||||
switch_snprintf(code, sizeof(code), "~_dB_RoW_DaTa_[\"%s\"] = \"%s\"",
|
||||
(char *) switch_core_db_column_name(dbo->stmt, x), (char *) switch_core_db_column_text(dbo->stmt, x));
|
||||
(char *) switch_core_db_column_name(dbo->stmt, x), (char *) switch_core_db_column_text(dbo->stmt, x));
|
||||
|
||||
eval_some_js(code, dbo->cx, dbo->obj, rval);
|
||||
if (*rval == JS_FALSE) {
|
||||
@@ -275,7 +275,7 @@ static JSPropertySpec db_props[] = {
|
||||
};
|
||||
|
||||
|
||||
static JSBool db_setProperty(JSContext * cx, JSObject * obj, jsval id, jsval *vp)
|
||||
static JSBool db_setProperty(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
|
||||
{
|
||||
char *name = JS_GetStringBytes(JS_ValueToString(cx, id));
|
||||
|
||||
@@ -332,7 +332,7 @@ const sm_module_interface_t DB_module_interface = {
|
||||
/*.next */ NULL
|
||||
};
|
||||
|
||||
SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t ** module_interface)
|
||||
SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t **module_interface)
|
||||
{
|
||||
*module_interface = &DB_module_interface;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
@@ -41,7 +41,7 @@ struct curl_obj {
|
||||
JSFunction *function;
|
||||
JSObject *user_data;
|
||||
jsrefcount saveDepth;
|
||||
jsval ret;
|
||||
jsval ret;
|
||||
};
|
||||
|
||||
|
||||
@@ -51,21 +51,21 @@ static size_t file_callback(void *ptr, size_t size, size_t nmemb, void *data)
|
||||
struct curl_obj *co = data;
|
||||
uintN argc = 0;
|
||||
jsval argv[4];
|
||||
|
||||
|
||||
|
||||
if (!co) {
|
||||
return 0;
|
||||
}
|
||||
if (co->function) {
|
||||
char *ret;
|
||||
argv[argc++] = STRING_TO_JSVAL(JS_NewStringCopyZ(co->cx, (char *)ptr));
|
||||
argv[argc++] = STRING_TO_JSVAL(JS_NewStringCopyZ(co->cx, (char *) ptr));
|
||||
if (co->user_data) {
|
||||
argv[argc++] = OBJECT_TO_JSVAL(co->user_data);
|
||||
}
|
||||
JS_ResumeRequest(co->cx, co->saveDepth);
|
||||
JS_CallFunction(co->cx, co->obj, co->function, argc, argv, &co->ret);
|
||||
co->saveDepth = JS_SuspendRequest(co->cx);
|
||||
|
||||
|
||||
if ((ret = JS_GetStringBytes(JS_ValueToString(co->cx, co->ret)))) {
|
||||
if (!strcmp(ret, "true") || !strcmp(ret, "undefined")) {
|
||||
return realsize;
|
||||
@@ -81,7 +81,7 @@ static size_t file_callback(void *ptr, size_t size, size_t nmemb, void *data)
|
||||
|
||||
/* Curl Object */
|
||||
/*********************************************************************************/
|
||||
static JSBool curl_construct(JSContext *cx, JSObject *obj, uintN argc, jsval * argv, jsval * rval)
|
||||
static JSBool curl_construct(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
struct curl_obj *co = NULL;
|
||||
|
||||
@@ -98,14 +98,14 @@ static JSBool curl_construct(JSContext *cx, JSObject *obj, uintN argc, jsval * a
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static void curl_destroy(JSContext *cx, JSObject *obj)
|
||||
static void curl_destroy(JSContext * cx, JSObject * obj)
|
||||
{
|
||||
struct curl_obj *co = JS_GetPrivate(cx, obj);
|
||||
switch_safe_free(co);
|
||||
JS_SetPrivate(cx, obj, NULL);
|
||||
}
|
||||
|
||||
static JSBool curl_run(JSContext *cx, JSObject *obj, uintN argc, jsval * argv, jsval * rval)
|
||||
static JSBool curl_run(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
struct curl_obj *co = JS_GetPrivate(cx, obj);
|
||||
char *method = NULL, *url, *cred = NULL;
|
||||
@@ -127,11 +127,11 @@ static JSBool curl_run(JSContext *cx, JSObject *obj, uintN argc, jsval * argv, j
|
||||
curl_easy_setopt(co->curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
}
|
||||
headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
|
||||
|
||||
|
||||
if (argc > 2) {
|
||||
data = JS_GetStringBytes(JS_ValueToString(cx, argv[2]));
|
||||
}
|
||||
|
||||
|
||||
if (argc > 3) {
|
||||
co->function = JS_ValueToFunction(cx, argv[3]);
|
||||
}
|
||||
@@ -148,7 +148,7 @@ static JSBool curl_run(JSContext *cx, JSObject *obj, uintN argc, jsval * argv, j
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
curl_easy_setopt(co->curl_handle, CURLOPT_HTTPHEADER, headers);
|
||||
|
||||
url_p = url;
|
||||
@@ -164,7 +164,7 @@ static JSBool curl_run(JSContext *cx, JSObject *obj, uintN argc, jsval * argv, j
|
||||
url_p = durl;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Running: method: [%s] url: [%s] data: [%s] cred=[%s] cb: [%s]\n",
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Running: method: [%s] url: [%s] data: [%s] cred=[%s] cb: [%s]\n",
|
||||
method, url_p, data, switch_str_nil(cred), co->function ? "yes" : "no");
|
||||
|
||||
curl_easy_setopt(co->curl_handle, CURLOPT_URL, url_p);
|
||||
@@ -172,7 +172,7 @@ static JSBool curl_run(JSContext *cx, JSObject *obj, uintN argc, jsval * argv, j
|
||||
curl_easy_setopt(co->curl_handle, CURLOPT_WRITEDATA, (void *) co);
|
||||
|
||||
curl_easy_setopt(co->curl_handle, CURLOPT_USERAGENT, "freeswitch-spidermonkey-curl/1.0");
|
||||
|
||||
|
||||
co->saveDepth = JS_SuspendRequest(cx);
|
||||
curl_easy_perform(co->curl_handle);
|
||||
|
||||
@@ -183,7 +183,7 @@ static JSBool curl_run(JSContext *cx, JSObject *obj, uintN argc, jsval * argv, j
|
||||
co->function = NULL;
|
||||
JS_ResumeRequest(cx, co->saveDepth);
|
||||
switch_safe_free(durl);
|
||||
|
||||
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
@@ -198,7 +198,7 @@ static JSPropertySpec curl_props[] = {
|
||||
{0}
|
||||
};
|
||||
|
||||
static JSBool curl_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval * vp)
|
||||
static JSBool curl_getProperty(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
|
||||
{
|
||||
JSBool res = JS_TRUE;
|
||||
return res;
|
||||
@@ -212,7 +212,7 @@ JSClass curl_class = {
|
||||
};
|
||||
|
||||
|
||||
switch_status_t curl_load(JSContext *cx, JSObject *obj)
|
||||
switch_status_t curl_load(JSContext * cx, JSObject * obj)
|
||||
{
|
||||
JS_InitClass(cx, obj, NULL, &curl_class, curl_construct, 3, curl_props, curl_methods, curl_props, curl_methods);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
@@ -225,7 +225,7 @@ const sm_module_interface_t curl_module_interface = {
|
||||
/*.next */ NULL
|
||||
};
|
||||
|
||||
SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t ** module_interface)
|
||||
SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t **module_interface)
|
||||
{
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
*module_interface = &curl_module_interface;
|
||||
|
||||
@@ -42,7 +42,7 @@ struct odbc_obj {
|
||||
SQLCHAR *code;
|
||||
int32 codelen;
|
||||
};
|
||||
typedef struct odbc_obj odbc_obj_t;
|
||||
typedef struct odbc_obj odbc_obj_t;
|
||||
|
||||
static odbc_obj_t *new_odbc_obj(char *dsn, char *username, char *password)
|
||||
{
|
||||
@@ -56,7 +56,7 @@ static odbc_obj_t *new_odbc_obj(char *dsn, char *username, char *password)
|
||||
if (!(new_obj->handle = switch_odbc_handle_new(dsn, username, password))) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
return new_obj;
|
||||
|
||||
err:
|
||||
@@ -72,29 +72,30 @@ static odbc_obj_t *new_odbc_obj(char *dsn, char *username, char *password)
|
||||
|
||||
switch_odbc_status_t odbc_obj_connect(odbc_obj_t *obj)
|
||||
{
|
||||
|
||||
|
||||
return switch_odbc_handle_connect(obj->handle);
|
||||
}
|
||||
|
||||
static void destroy_odbc_obj(odbc_obj_t ** objp)
|
||||
static void destroy_odbc_obj(odbc_obj_t **objp)
|
||||
{
|
||||
odbc_obj_t *obj = *objp;
|
||||
if (obj == NULL) return;
|
||||
if (obj == NULL)
|
||||
return;
|
||||
if (obj->stmt) {
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, obj->stmt);
|
||||
}
|
||||
if (obj->handle) {
|
||||
switch_odbc_handle_destroy(&obj->handle);
|
||||
}
|
||||
switch_safe_free(obj->colbuf);
|
||||
switch_safe_free(obj->code);
|
||||
if (obj->handle) {
|
||||
switch_odbc_handle_destroy(&obj->handle);
|
||||
}
|
||||
switch_safe_free(obj->colbuf);
|
||||
switch_safe_free(obj->code);
|
||||
switch_safe_free(obj);
|
||||
}
|
||||
|
||||
|
||||
/* ODBC Object */
|
||||
/*********************************************************************************/
|
||||
static JSBool odbc_construct(JSContext * cx, JSObject * obj, uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool odbc_construct(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
odbc_obj_t *odbc_obj = NULL;
|
||||
char *dsn, *username, *password;
|
||||
@@ -156,16 +157,17 @@ static JSBool odbc_construct(JSContext * cx, JSObject * obj, uintN argc, jsval *
|
||||
|
||||
static void odbc_destroy(JSContext * cx, JSObject * obj)
|
||||
{
|
||||
odbc_obj_t *odbc_obj;
|
||||
if (obj == NULL) return;
|
||||
odbc_obj_t *odbc_obj;
|
||||
if (obj == NULL)
|
||||
return;
|
||||
odbc_obj = (odbc_obj_t *) JS_GetPrivate(cx, obj);
|
||||
if (odbc_obj) {
|
||||
destroy_odbc_obj(&odbc_obj);
|
||||
JS_SetPrivate(cx, obj, NULL);
|
||||
}
|
||||
JS_SetPrivate(cx, obj, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static JSBool odbc_connect(JSContext * cx, JSObject * obj, uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool odbc_connect(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
odbc_obj_t *odbc_obj = (odbc_obj_t *) JS_GetPrivate(cx, obj);
|
||||
JSBool tf = JS_TRUE;
|
||||
@@ -183,7 +185,7 @@ static JSBool odbc_connect(JSContext * cx, JSObject * obj, uintN argc, jsval *ar
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool odbc_execute(JSContext * cx, JSObject * obj, uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool odbc_execute(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
odbc_obj_t *odbc_obj = (odbc_obj_t *) JS_GetPrivate(cx, obj);
|
||||
char *sql;
|
||||
@@ -217,7 +219,7 @@ static JSBool odbc_execute(JSContext * cx, JSObject * obj, uintN argc, jsval *ar
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool odbc_exec(JSContext * cx, JSObject * obj, uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool odbc_exec(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
odbc_obj_t *odbc_obj = (odbc_obj_t *) JS_GetPrivate(cx, obj);
|
||||
char *sql;
|
||||
@@ -253,7 +255,7 @@ static JSBool odbc_exec(JSContext * cx, JSObject * obj, uintN argc, jsval *argv,
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool odbc_num_rows(JSContext * cx, JSObject * obj, uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool odbc_num_rows(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
odbc_obj_t *odbc_obj = (odbc_obj_t *) JS_GetPrivate(cx, obj);
|
||||
|
||||
@@ -277,7 +279,7 @@ static JSBool odbc_num_rows(JSContext * cx, JSObject * obj, uintN argc, jsval *a
|
||||
}
|
||||
|
||||
|
||||
static JSBool odbc_next_row(JSContext * cx, JSObject * obj, uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool odbc_next_row(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
odbc_obj_t *odbc_obj = (odbc_obj_t *) JS_GetPrivate(cx, obj);
|
||||
int result = 0;
|
||||
@@ -285,8 +287,8 @@ static JSBool odbc_next_row(JSContext * cx, JSObject * obj, uintN argc, jsval *a
|
||||
|
||||
if (switch_odbc_handle_get_state(odbc_obj->handle) != SWITCH_ODBC_STATE_CONNECTED) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not connected!\n");
|
||||
goto done;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
if (odbc_obj->stmt) {
|
||||
@@ -345,7 +347,7 @@ static char *escape_data(char *in, char escapeChar)
|
||||
}
|
||||
|
||||
|
||||
static JSBool odbc_get_data(JSContext * cx, JSObject * obj, uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool odbc_get_data(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
|
||||
odbc_obj_t *odbc_obj = (odbc_obj_t *) JS_GetPrivate(cx, obj);
|
||||
@@ -353,8 +355,8 @@ static JSBool odbc_get_data(JSContext * cx, JSObject * obj, uintN argc, jsval *a
|
||||
|
||||
if (switch_odbc_handle_get_state(odbc_obj->handle) != SWITCH_ODBC_STATE_CONNECTED) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not connected!\n");
|
||||
goto done;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (odbc_obj->stmt) {
|
||||
SQLSMALLINT c = 0, x = 0;
|
||||
@@ -374,7 +376,7 @@ static JSBool odbc_get_data(JSContext * cx, JSObject * obj, uintN argc, jsval *a
|
||||
SQLCHAR name[1024] = "";
|
||||
SQLCHAR *data = odbc_obj->colbuf;
|
||||
SQLCHAR *esc = NULL;
|
||||
|
||||
|
||||
SQLDescribeCol(odbc_obj->stmt, x, name, sizeof(name), &NameLength, &DataType, &ColumnSize, &DecimalDigits, &Nullable);
|
||||
SQLGetData(odbc_obj->stmt, x, SQL_C_CHAR, odbc_obj->colbuf, odbc_obj->cblen, NULL);
|
||||
|
||||
@@ -407,10 +409,10 @@ static JSBool odbc_get_data(JSContext * cx, JSObject * obj, uintN argc, jsval *a
|
||||
|
||||
}
|
||||
|
||||
static JSBool odbc_close(JSContext * cx, JSObject * obj, uintN argc, jsval *argv, jsval *rval)
|
||||
static JSBool odbc_close(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
odbc_destroy(cx, obj);
|
||||
return JS_TRUE;
|
||||
odbc_destroy(cx, obj);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
enum odbc_tinyid {
|
||||
@@ -425,17 +427,17 @@ static JSFunctionSpec odbc_methods[] = {
|
||||
{"numRows", odbc_num_rows, 1},
|
||||
{"nextRow", odbc_next_row, 1},
|
||||
{"getData", odbc_get_data, 1},
|
||||
{"close", odbc_close, 1},
|
||||
{"close", odbc_close, 1},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
||||
static JSPropertySpec odbc_props[] = {
|
||||
{"name", odbc_NAME, JSPROP_READONLY|JSPROP_PERMANENT},
|
||||
{"name", odbc_NAME, JSPROP_READONLY | JSPROP_PERMANENT},
|
||||
{0}
|
||||
};
|
||||
|
||||
static JSBool odbc_setProperty(JSContext * cx, JSObject * obj, jsval id, jsval *vp)
|
||||
static JSBool odbc_setProperty(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
|
||||
{
|
||||
char *name = JS_GetStringBytes(JS_ValueToString(cx, id));
|
||||
|
||||
@@ -446,11 +448,11 @@ static JSBool odbc_setProperty(JSContext * cx, JSObject * obj, jsval id, jsval *
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool odbc_getProperty(JSContext * cx, JSObject * obj, jsval id, jsval *vp)
|
||||
static JSBool odbc_getProperty(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
|
||||
{
|
||||
int param;
|
||||
char *name = JS_GetStringBytes(JS_ValueToString(cx, id));
|
||||
|
||||
|
||||
/* numbers are our props anything else is a method */
|
||||
if (name[0] >= 48 && name[0] <= 57) {
|
||||
param = atoi(name);
|
||||
@@ -483,7 +485,7 @@ const sm_module_interface_t odbc_module_interface = {
|
||||
/*.next */ NULL
|
||||
};
|
||||
|
||||
SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t ** module_interface)
|
||||
SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t **module_interface)
|
||||
{
|
||||
*module_interface = &odbc_module_interface;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
@@ -93,7 +93,7 @@ const sm_module_interface_t skel_module_interface = {
|
||||
/*.next */ NULL
|
||||
};
|
||||
|
||||
SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t ** module_interface)
|
||||
SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t **module_interface)
|
||||
{
|
||||
*module_interface = &skel_module_interface;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
@@ -34,7 +34,7 @@ static const char modname[] = "Socket";
|
||||
struct js_socket_obj {
|
||||
switch_socket_t *socket;
|
||||
switch_memory_pool_t *pool;
|
||||
char* read_buffer;
|
||||
char *read_buffer;
|
||||
switch_size_t buffer_size;
|
||||
int state;
|
||||
};
|
||||
@@ -44,20 +44,18 @@ typedef struct js_socket_obj js_socket_obj_t;
|
||||
/*********************************************************************************/
|
||||
static JSBool socket_construct(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
js_socket_obj_t* js_socket_obj = 0;
|
||||
js_socket_obj_t *js_socket_obj = 0;
|
||||
switch_memory_pool_t *pool;
|
||||
switch_socket_t *socket;
|
||||
switch_status_t ret;
|
||||
|
||||
switch_core_new_memory_pool(&pool);
|
||||
ret = switch_socket_create(&socket, AF_INET, SOCK_STREAM, SWITCH_PROTO_TCP, pool);
|
||||
if (ret != SWITCH_STATUS_SUCCESS)
|
||||
{
|
||||
if (ret != SWITCH_STATUS_SUCCESS) {
|
||||
switch_core_destroy_memory_pool(&pool);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Failed to create socket, reason: %d.\n", ret);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// allocate information needed by JS to be able to write to the log.
|
||||
// (needed since multitple js sessions can write to the same log)
|
||||
js_socket_obj = switch_core_alloc(pool, sizeof(js_socket_obj_t));
|
||||
@@ -73,8 +71,7 @@ static void socket_destroy(JSContext * cx, JSObject * obj)
|
||||
if (socket == NULL)
|
||||
return;
|
||||
|
||||
if (socket->socket != 0)
|
||||
{
|
||||
if (socket->socket != 0) {
|
||||
switch_socket_shutdown(socket->socket, SWITCH_SHUTDOWN_READWRITE);
|
||||
switch_socket_close(socket->socket);
|
||||
switch_core_destroy_memory_pool(&socket->pool);
|
||||
@@ -84,14 +81,12 @@ static void socket_destroy(JSContext * cx, JSObject * obj)
|
||||
static JSBool socket_connect(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
js_socket_obj_t *socket = JS_GetPrivate(cx, obj);
|
||||
if (socket == NULL)
|
||||
{
|
||||
if (socket == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find js object.\n");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
if (argc == 2) {
|
||||
char *host = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
||||
int32 port;
|
||||
switch_sockaddr_t *addr;
|
||||
@@ -99,21 +94,18 @@ static JSBool socket_connect(JSContext * cx, JSObject * obj, uintN argc, jsval *
|
||||
|
||||
JS_ValueToInt32(cx, argv[1], &port);
|
||||
|
||||
ret = switch_sockaddr_info_get(&addr, host, AF_INET, (switch_port_t)port, 0, socket->pool);
|
||||
if (ret != SWITCH_STATUS_SUCCESS)
|
||||
{
|
||||
ret = switch_sockaddr_info_get(&addr, host, AF_INET, (switch_port_t) port, 0, socket->pool);
|
||||
if (ret != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "switch_sockaddr_info_get failed: %d.\n", ret);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Connecting to: %s:%d.\n", host, port);
|
||||
ret = switch_socket_connect(socket->socket, addr);
|
||||
if (ret != SWITCH_STATUS_SUCCESS)
|
||||
{
|
||||
if (ret != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "switch_socket_connect failed: %d.\n", ret);
|
||||
*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
|
||||
}
|
||||
else
|
||||
} else
|
||||
*rval = BOOLEAN_TO_JSVAL(JS_TRUE);
|
||||
|
||||
}
|
||||
@@ -124,23 +116,19 @@ static JSBool socket_connect(JSContext * cx, JSObject * obj, uintN argc, jsval *
|
||||
static JSBool socket_send(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
js_socket_obj_t *socket = JS_GetPrivate(cx, obj);
|
||||
if (socket == NULL)
|
||||
{
|
||||
if (socket == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find js object.\n");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
if (argc == 1) {
|
||||
char *buffer = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
|
||||
switch_size_t len = strlen(buffer);
|
||||
switch_status_t ret = switch_socket_send(socket->socket, buffer, &len);
|
||||
if (ret != SWITCH_STATUS_SUCCESS)
|
||||
{
|
||||
if (ret != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "switch_socket_send failed: %d.\n", ret);
|
||||
*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
|
||||
}
|
||||
else
|
||||
} else
|
||||
*rval = BOOLEAN_TO_JSVAL(JS_TRUE);
|
||||
}
|
||||
|
||||
@@ -150,35 +138,29 @@ static JSBool socket_send(JSContext * cx, JSObject * obj, uintN argc, jsval * ar
|
||||
static JSBool socket_read_bytes(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
js_socket_obj_t *socket = JS_GetPrivate(cx, obj);
|
||||
if (socket == NULL)
|
||||
{
|
||||
if (socket == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find js object.\n");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
if (argc == 1) {
|
||||
int32 bytes_to_read;
|
||||
switch_status_t ret;
|
||||
switch_size_t len;
|
||||
|
||||
JS_ValueToInt32(cx, argv[0], &bytes_to_read);
|
||||
len = (switch_size_t)bytes_to_read;
|
||||
len = (switch_size_t) bytes_to_read;
|
||||
|
||||
if (socket->buffer_size < len)
|
||||
{
|
||||
socket->read_buffer = switch_core_alloc(socket->pool, len+1);
|
||||
if (socket->buffer_size < len) {
|
||||
socket->read_buffer = switch_core_alloc(socket->pool, len + 1);
|
||||
socket->buffer_size = bytes_to_read + 1;
|
||||
}
|
||||
|
||||
ret = switch_socket_recv(socket->socket, socket->read_buffer, &len);
|
||||
if (ret != SWITCH_STATUS_SUCCESS)
|
||||
{
|
||||
if (ret != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "switch_socket_send failed: %d.\n", ret);
|
||||
*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
socket->read_buffer[len] = 0;
|
||||
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, socket->read_buffer));
|
||||
}
|
||||
@@ -190,15 +172,13 @@ static JSBool socket_read_bytes(JSContext * cx, JSObject * obj, uintN argc, jsva
|
||||
static JSBool socket_read(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
js_socket_obj_t *socket = JS_GetPrivate(cx, obj);
|
||||
if (socket == NULL)
|
||||
{
|
||||
if (socket == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find js object.\n");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (argc >= 0)
|
||||
{
|
||||
char* delimiter = "\n";
|
||||
if (argc >= 0) {
|
||||
char *delimiter = "\n";
|
||||
switch_status_t ret = SWITCH_STATUS_FALSE;
|
||||
switch_size_t len = 1;
|
||||
switch_size_t total_length = 0;
|
||||
@@ -212,8 +192,7 @@ static JSBool socket_read(JSContext * cx, JSObject * obj, uintN argc, jsval * ar
|
||||
if (socket->read_buffer == 0)
|
||||
socket->read_buffer = switch_core_alloc(socket->pool, socket->buffer_size);
|
||||
|
||||
while (can_run == TRUE)
|
||||
{
|
||||
while (can_run == TRUE) {
|
||||
ret = switch_socket_recv(socket->socket, tempbuf, &len);
|
||||
if (ret != SWITCH_STATUS_SUCCESS)
|
||||
break;
|
||||
@@ -223,13 +202,11 @@ static JSBool socket_read(JSContext * cx, JSObject * obj, uintN argc, jsval * ar
|
||||
break;
|
||||
else if (tempbuf[0] == '\r' && delimiter[0] == '\n')
|
||||
continue;
|
||||
else
|
||||
{
|
||||
else {
|
||||
// Buffer is full, let's increase it.
|
||||
if (total_length == socket->buffer_size - 1)
|
||||
{
|
||||
if (total_length == socket->buffer_size - 1) {
|
||||
switch_size_t new_size = socket->buffer_size + 4196;
|
||||
char* new_buffer = switch_core_alloc(socket->pool, socket->buffer_size);
|
||||
char *new_buffer = switch_core_alloc(socket->pool, socket->buffer_size);
|
||||
memcpy(new_buffer, socket->read_buffer, total_length);
|
||||
socket->buffer_size = new_size;
|
||||
socket->read_buffer = new_buffer;
|
||||
@@ -238,13 +215,10 @@ static JSBool socket_read(JSContext * cx, JSObject * obj, uintN argc, jsval * ar
|
||||
++total_length;
|
||||
}
|
||||
}
|
||||
if (ret != SWITCH_STATUS_SUCCESS)
|
||||
{
|
||||
if (ret != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "socket receive failed: %d.\n", ret);
|
||||
*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
socket->read_buffer[total_length] = 0;
|
||||
*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, socket->read_buffer));
|
||||
}
|
||||
@@ -256,8 +230,7 @@ static JSBool socket_read(JSContext * cx, JSObject * obj, uintN argc, jsval * ar
|
||||
static JSBool socket_close(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
|
||||
{
|
||||
js_socket_obj_t *socket = JS_GetPrivate(cx, obj);
|
||||
if (socket == NULL)
|
||||
{
|
||||
if (socket == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find js object.\n");
|
||||
return JS_FALSE;
|
||||
}
|
||||
@@ -290,7 +263,7 @@ static JSPropertySpec socket_props[] = {
|
||||
static JSBool socket_getProperty(JSContext * cx, JSObject * obj, jsval id, jsval * vp)
|
||||
{
|
||||
JSBool res = JS_TRUE;
|
||||
// js_socket_obj_t *socket = JS_GetPrivate(cx, obj);
|
||||
// js_socket_obj_t *socket = JS_GetPrivate(cx, obj);
|
||||
char *name;
|
||||
int param = 0;
|
||||
|
||||
@@ -335,7 +308,7 @@ const sm_module_interface_t socket_module_interface = {
|
||||
/*.next */ NULL
|
||||
};
|
||||
|
||||
SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t ** module_interface)
|
||||
SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t **module_interface)
|
||||
{
|
||||
*module_interface = &socket_module_interface;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
@@ -56,7 +56,7 @@ struct teletone_obj {
|
||||
};
|
||||
|
||||
|
||||
static int teletone_handler(teletone_generation_session_t * ts, teletone_tone_map_t * map)
|
||||
static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map)
|
||||
{
|
||||
struct teletone_obj *tto = ts->user_data;
|
||||
int wrote;
|
||||
@@ -249,7 +249,7 @@ static JSBool teletone_generate(JSContext * cx, JSObject * obj, uintN argc, jsva
|
||||
if (switch_test_flag(tto, TTF_DTMF)) {
|
||||
char dtmf[128];
|
||||
char *ret;
|
||||
|
||||
|
||||
if (switch_channel_has_dtmf(channel)) {
|
||||
uintN aargc = 0;
|
||||
jsval aargv[4];
|
||||
@@ -345,7 +345,7 @@ const sm_module_interface_t teletone_module_interface = {
|
||||
/*.next */ NULL
|
||||
};
|
||||
|
||||
SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t ** module_interface)
|
||||
SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t **module_interface)
|
||||
{
|
||||
*module_interface = &teletone_module_interface;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
Reference in new issue
Block a user