diff --git a/conf/freeswitch.xml b/conf/freeswitch.xml index ecbf734268..2e13d1e3e2 100644 --- a/conf/freeswitch.xml +++ b/conf/freeswitch.xml @@ -75,6 +75,13 @@ + + + + + + + diff --git a/modules.conf.in b/modules.conf.in index b8b4470e7d..8c6e335ce0 100644 --- a/modules.conf.in +++ b/modules.conf.in @@ -41,5 +41,7 @@ formats/mod_native_file formats/mod_sndfile #languages/mod_perl #languages/mod_spidermonkey +#languages/mod_spidermonkey_teletone +#languages/mod_spidermonkey_core_db timers/mod_softtimer #xml_int/mod_xml_rpc diff --git a/src/mod/languages/mod_spidermonkey/Makefile b/src/mod/languages/mod_spidermonkey/Makefile index 49f4abcb98..1f52f712a6 100644 --- a/src/mod/languages/mod_spidermonkey/Makefile +++ b/src/mod/languages/mod_spidermonkey/Makefile @@ -1,70 +1,4 @@ -# This is all used to make sure we use the right options during build and link. - -OS_ARCH := $(subst /,_,$(shell uname -s | sed /\ /s//_/)) -#VER=DBG -#BO=0 -VER=OPT -BO=1 - -# Attempt to differentiate between SunOS 5.4 and x86 5.4 -OS_CPUARCH := $(shell uname -m) -ifeq ($(OS_CPUARCH),i86pc) -OS_RELEASE := $(shell uname -r)_$(OS_CPUARCH) -else -ifeq ($(OS_ARCH),AIX) -OS_RELEASE := $(shell uname -v).$(shell uname -r) -else -OS_RELEASE := $(shell uname -r) -endif -endif -ifeq ($(OS_ARCH),IRIX64) -OS_ARCH := IRIX -endif - -# Handle output from win32 unames other than Netscape's version -ifeq (,$(filter-out Windows_95 Windows_98 CYGWIN_95-4.0 CYGWIN_98-4.10, $(OS_ARCH))) - OS_ARCH := WIN95 -endif -ifeq ($(OS_ARCH),WIN95) - OS_ARCH := WINNT - OS_RELEASE := 4.0 -endif -ifeq ($(OS_ARCH), Windows_NT) - OS_ARCH := WINNT - OS_MINOR_RELEASE := $(shell uname -v) - ifeq ($(OS_MINOR_RELEASE),00) - OS_MINOR_RELEASE = 0 - endif - OS_RELEASE := $(OS_RELEASE).$(OS_MINOR_RELEASE) -endif -ifeq (CYGWIN_NT,$(findstring CYGWIN_NT,$(OS_ARCH))) - OS_RELEASE := $(patsubst CYGWIN_NT-%,%,$(OS_ARCH)) - OS_ARCH := WINNT -endif -ifeq ($(OS_ARCH), CYGWIN32_NT) - OS_ARCH := WINNT -endif -ifeq (MINGW32_NT,$(findstring MINGW32_NT,$(OS_ARCH))) - OS_RELEASE := $(patsubst MINGW32_NT-%,%,$(OS_ARCH)) - OS_ARCH := WINNT -endif - -ifeq ($(OS_ARCH),Linux) -OS_CONFIG := Linux_All -else -ifeq ($(OS_ARCH),dgux) -OS_CONFIG := dgux -else -ifeq ($(OS_ARCH),Darwin) -OS_CONFIG := Darwin -else -OS_CONFIG := $(OS_ARCH)$(OS_OBJTYPE)$(OS_RELEASE) -endif -endif -endif - -CFLAGS += -I$(BASE)/libs/mozilla/js/src -Wall -Wno-format -g -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DHAVE_LOCALTIME_R -DX86_LINUX -DDEBUG -DDEBUG_root -DJS_THREADSAFE -I$(BASE)/libs/mozilla/js/src -I$(BASE)/libs/mozilla/js/src/$(OS_CONFIG)_$(VER).OBJ -Wall -Wno-format -g -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DHAVE_LOCALTIME_R -DX86_LINUX -DDEBUG -DDEBUG_root -DJS_THREADSAFE -I$(BASE)/libs/mozilla/nsprpub/dist/include/nspr -I$(OS_CONFIG)_$(VER).OBJ -LDFLAGS +=-DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DHAVE_LOCALTIME_R -DX86_LINUX -DDEBUG -DDEBUG_root -DJS_THREADSAFE -I$(BASE)/libs/mozilla/nsprpub/dist/include/nspr -Wall -Wno-format -g -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DHAVE_LOCALTIME_R -DX86_LINUX -DDEBUG -DDEBUG_root -DJS_THREADSAFE -I$(BASE)/libs/mozilla/nsprpub/dist/include/nspr -lteletone +include sm.mak OBJS=$(BASE)/libs/mozilla/js/src/$(OS_CONFIG)_$(VER).OBJ/libjs.a $(BASE)/libs/mozilla/nsprpub/dist/lib/libnspr4.a -lcurl -letpan LINKER=$(CC) diff --git a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c index 3c012fb73f..420ddda9ae 100644 --- a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c +++ b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c @@ -32,30 +32,8 @@ #ifndef HAVE_CURL #define HAVE_CURL #endif -#define JS_BUFFER_SIZE 1024 * 32 -#define JS_BLOCK_SIZE JS_BUFFER_SIZE -#ifdef __ICC -#pragma warning (disable:310 193 1418) -#endif -#include +#include "mod_spidermonkey.h" -#include "jstypes.h" -#include "jsarena.h" -#include "jsutil.h" -#include "jsprf.h" -#include "jsapi.h" -#include "jsatom.h" -#include "jscntxt.h" -#include "jsdbgapi.h" -#include "jsemit.h" -#include "jsfun.h" -#include "jsgc.h" -#include "jslock.h" -#include "jsobj.h" -#include "jsparse.h" -#include "jsscope.h" -#include "jsscript.h" -#include #ifdef HAVE_CURL #include #endif @@ -66,7 +44,7 @@ static const char modname[] = "mod_spidermonkey"; -static int eval_some_js(char *code, JSContext *cx, JSObject *obj, jsval *rval); + static void session_destroy(JSContext *cx, JSObject *obj); static JSBool session_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); static switch_api_interface_t js_run_interface; @@ -89,9 +67,20 @@ static JSClass global_class = { JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub }; -typedef enum { - TTF_DTMF = (1 << 0) -} teletone_flag_t; + +static struct { + switch_hash_t *mod_hash; + switch_hash_t *load_hash; + switch_memory_pool_t *pool; +} module_manager; + +struct sm_loadable_module { + char *filename; + void *lib; + const sm_module_interface_t *module_interface; + spidermonkey_init_t spidermonkey_init; +}; +typedef struct sm_loadable_module sm_loadable_module_t; typedef enum { S_HUP = (1 << 0) @@ -112,30 +101,6 @@ struct input_callback_state { void *extra; }; -struct js_session { - switch_core_session_t *session; - JSContext *cx; - JSObject *obj; - unsigned int flags; -}; - -struct teletone_obj { - teletone_generation_session_t ts; - JSContext *cx; - JSObject *obj; - switch_core_session_t *session; - switch_codec_t codec; - switch_buffer_t *audio_buffer; - switch_buffer_t *loop_buffer; - switch_memory_pool_t *pool; - switch_timer_t *timer; - switch_timer_t timer_base; - JSFunction *function; - jsval arg; - jsval ret; - unsigned int flags; -}; - struct fileio_obj { char *path; unsigned int flags; @@ -146,18 +111,6 @@ struct fileio_obj { int32 bufsize; }; -struct db_obj { - switch_memory_pool_t *pool; - switch_core_db_t *db; - switch_core_db_stmt_t *stmt; - char *dbname; - char code_buffer[2048]; - JSContext *cx; - JSObject *obj; -}; - - - struct event_obj { switch_event_t *event; int freed; @@ -457,6 +410,164 @@ static void js_error(JSContext *cx, const char *message, JSErrorReport *report) } + +static switch_status_t sm_load_file(char *filename, sm_loadable_module_t **new_module) +{ + sm_loadable_module_t *module = NULL; + apr_dso_handle_t *dso = NULL; + apr_status_t status = SWITCH_STATUS_SUCCESS; + apr_dso_handle_sym_t function_handle = NULL; + spidermonkey_init_t spidermonkey_init; + const sm_module_interface_t *module_interface, *mp; + + int loading = 1; + const char *err = NULL; + char derr[512] = ""; + + assert(filename != NULL); + + *new_module = NULL; + status = apr_dso_load(&dso, filename, module_manager.pool); + + while (loading) { + if (status != APR_SUCCESS) { + apr_dso_error(dso, derr, sizeof(derr)); + err = derr; + break; + } + + status = apr_dso_sym(&function_handle, dso, "spidermonkey_init"); + spidermonkey_init = (spidermonkey_init_t) function_handle; + + if (spidermonkey_init == NULL) { + err = "Cannot Load"; + break; + } + + if (spidermonkey_init(&module_interface) != SWITCH_STATUS_SUCCESS) { + err = "Module load routine returned an error"; + break; + } + + if ((module = switch_core_permanent_alloc(sizeof(sm_loadable_module_t))) == 0) { + err = "Could not allocate memory\n"; + break; + } + + loading = 0; + } + + if (err) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Error Loading module %s\n**%s**\n", filename, err); + return SWITCH_STATUS_GENERR; + } + + module->filename = switch_core_permanent_strdup(filename); + module->spidermonkey_init = spidermonkey_init; + module->module_interface = module_interface; + + module->lib = dso; + *new_module = module; + + switch_core_hash_insert(module_manager.mod_hash, (char *) module->filename, (void *) module); + + for (mp = module_interface; mp; mp = mp->next) { + switch_core_hash_insert(module_manager.load_hash, (char *)mp->name, (void *) mp); + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Successfully Loaded [%s]\n", module->filename); + + return SWITCH_STATUS_SUCCESS; + +} + +static switch_status_t sm_load_module(char *dir, char *fname) +{ + switch_size_t len = 0; + char *path; + char *file; + sm_loadable_module_t *new_module = NULL; + +#ifdef WIN32 + const char *ext = ".dll"; +#elif defined (MACOSX) || defined (DARWIN) + const char *ext = ".dylib"; +#else + const char *ext = ".so"; +#endif + + + if ((file = switch_core_strdup(module_manager.pool, fname)) == 0) { + return SWITCH_STATUS_FALSE; + } + + if (*file == '/') { + path = switch_core_strdup(module_manager.pool, file); + } else { + if (strchr(file, '.')) { + len = strlen(dir); + len += strlen(file); + len += 4; + path = (char *) switch_core_alloc(module_manager.pool, len); + snprintf(path, len, "%s%s%s", dir, SWITCH_PATH_SEPARATOR, file); + } else { + len = strlen(dir); + len += strlen(file); + len += 8; + path = (char *) switch_core_alloc(module_manager.pool, len); + snprintf(path, len, "%s%s%s%s", dir, SWITCH_PATH_SEPARATOR, file, ext); + } + } + + return sm_load_file(path, &new_module); +} + +static switch_status_t load_modules(void) +{ + char *cf = "spidermonkey.conf"; + switch_xml_t cfg, xml; + unsigned int count = 0; + +#ifdef WIN32 + const char *ext = ".dll"; + const char *EXT = ".DLL"; +#elif defined (MACOSX) || defined (DARWIN) + const char *ext = ".dylib"; + const char *EXT = ".DYLIB"; +#else + const char *ext = ".so"; + const char *EXT = ".SO"; +#endif + + memset(&module_manager, 0, sizeof(module_manager)); + switch_core_new_memory_pool(&module_manager.pool); + + switch_core_hash_init(&module_manager.mod_hash, module_manager.pool); + switch_core_hash_init(&module_manager.load_hash, module_manager.pool); + + if ((xml = switch_xml_open_cfg(cf, &cfg, NULL))) { + switch_xml_t mods, ld; + + if ((mods = switch_xml_child(cfg, "modules"))) { + for (ld = switch_xml_child(mods, "load"); ld; ld = ld->next) { + const char *val = switch_xml_attr_soft(ld, "module"); + if (strchr(val, '.') && !strstr(val, ext) && !strstr(val, EXT)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Invalid extension for %s\n", val); + continue; + } + sm_load_module((char *) SWITCH_GLOBAL_dirs.mod_dir, (char *) val); + count++; + } + } + switch_xml_free(xml); + + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "open of %s failed\n", cf); + } + + return SWITCH_STATUS_SUCCESS; +} + static switch_status_t init_js(void) { memset(&globals, 0, sizeof(globals)); @@ -471,6 +582,10 @@ static switch_status_t init_js(void) if (!(globals.rt = JS_NewRuntime(64L * 1024L * 1024L))) { return SWITCH_STATUS_FALSE; } + + if (load_modules() != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_FALSE; + } return SWITCH_STATUS_SUCCESS; } @@ -1101,10 +1216,13 @@ static JSBool session_execute(JSContext *cx, JSObject *obj, uintN argc, jsval *a char *app_name = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); char *app_arg = JS_GetStringBytes(JS_ValueToString(cx, argv[1])); struct js_session *jss = JS_GetPrivate(cx, obj); + jsrefcount saveDepth; if ((application_interface = switch_loadable_module_get_application_interface(app_name))) { if (application_interface->application_function) { + saveDepth = JS_SuspendRequest(cx); application_interface->application_function(jss->session, app_arg); + JS_ResumeRequest(cx, saveDepth); retval = JS_TRUE; } } @@ -1478,19 +1596,6 @@ static JSObject *new_js_session(JSContext *cx, JSObject *obj, switch_core_sessio return NULL; } -static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map) -{ - struct teletone_obj *tto = ts->user_data; - int wrote; - - if (!tto) { - return -1; - } - wrote = teletone_mux_tones(ts, map); - switch_buffer_write(tto->audio_buffer, ts->buffer, wrote * 2); - - return 0; -} /* Session Object */ /*********************************************************************************/ @@ -1821,527 +1926,6 @@ JSClass fileio_class = { }; -/* DB Object */ -/*********************************************************************************/ -static JSBool db_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - switch_memory_pool_t *pool; - switch_core_db_t *db; - struct db_obj *dbo; - - if (argc > 0) { - char *dbname = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); - switch_core_new_memory_pool(&pool); - if (! (db = switch_core_db_open_file(dbname))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Open DB!\n"); - switch_core_destroy_memory_pool(&pool); - return JS_FALSE; - } - dbo = switch_core_alloc(pool, sizeof(*dbo)); - dbo->pool = pool; - dbo->dbname = switch_core_strdup(pool, dbname); - dbo->cx = cx; - dbo->obj = obj; - dbo->db = db; - JS_SetPrivate(cx, obj, dbo); - return JS_TRUE; - } - - return JS_FALSE; -} - -static void db_destroy(JSContext *cx, JSObject *obj) -{ - struct db_obj *dbo = JS_GetPrivate(cx, obj); - - if (dbo) { - switch_memory_pool_t *pool = dbo->pool; - if (dbo->stmt) { - switch_core_db_finalize(dbo->stmt); - dbo->stmt = NULL; - } - switch_core_db_close(dbo->db); - switch_core_destroy_memory_pool(&pool); - pool = NULL; - } -} - - -static int db_callback(void *pArg, int argc, char **argv, char **columnNames) -{ - struct db_obj *dbo = pArg; - char code[1024]; - jsval rval; - int x = 0; - - snprintf(code, sizeof(code), "~var _Db_RoW_ = {}"); - eval_some_js(code, dbo->cx, dbo->obj, &rval); - - for(x=0; x < argc; x++) { - snprintf(code, sizeof(code), "~_Db_RoW_[\"%s\"] = \"%s\"", columnNames[x], argv[x]); - eval_some_js(code, dbo->cx, dbo->obj, &rval); - } - - snprintf(code, sizeof(code), "~%s(_Db_RoW_)", dbo->code_buffer); - eval_some_js(code, dbo->cx, dbo->obj, &rval); - - snprintf(code, sizeof(code), "~delete _Db_RoW_"); - eval_some_js(code, dbo->cx, dbo->obj, &rval); - - return 0; -} - -static JSBool db_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - struct db_obj *dbo = JS_GetPrivate(cx, obj); - *rval = BOOLEAN_TO_JSVAL( JS_TRUE ); - - if (argc > 0) { - char *sql = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); - char *err = NULL; - void *arg = NULL; - switch_core_db_callback_func_t cb_func = NULL; - - - if (argc > 1) { - char *js_func = JS_GetStringBytes(JS_ValueToString(cx, argv[1])); - switch_copy_string(dbo->code_buffer, js_func, sizeof(dbo->code_buffer)); - cb_func = db_callback; - arg = dbo; - } - - switch_core_db_exec(dbo->db, sql, cb_func, arg, &err); - if (err) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error %s\n", err); - switch_core_db_free(err); - *rval = BOOLEAN_TO_JSVAL( JS_FALSE ); - } - } - return JS_TRUE; -} - - -static JSBool db_next(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - struct db_obj *dbo = JS_GetPrivate(cx, obj); - *rval = BOOLEAN_TO_JSVAL( JS_FALSE ); - - if (dbo->stmt) { - int running = 1; - - while (running < 5000) { - int result = switch_core_db_step(dbo->stmt); - if (result == SQLITE_ROW) { - *rval = BOOLEAN_TO_JSVAL( JS_TRUE ); - break; - } else if (result == SQLITE_BUSY) { - running++; - continue; - } - switch_core_db_finalize(dbo->stmt); - dbo->stmt = NULL; - break; - } - } - - return JS_TRUE; -} - -static JSBool db_fetch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - struct db_obj *dbo = JS_GetPrivate(cx, obj); - int colcount = switch_core_db_column_count(dbo->stmt); - char code[1024]; - int x; - - snprintf(code, sizeof(code), "~var _dB_RoW_DaTa_ = {}"); - eval_some_js(code, dbo->cx, dbo->obj, rval); - if (*rval == JS_FALSE) { - return JS_TRUE; - } - for (x = 0; x < colcount; x++) { - 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)); - - eval_some_js(code, dbo->cx, dbo->obj, rval); - if (*rval == JS_FALSE) { - return JS_TRUE; - } - } - - JS_GetProperty(cx, obj, "_dB_RoW_DaTa_", rval); - - return JS_TRUE; -} - - -static JSBool db_prepare(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - struct db_obj *dbo = JS_GetPrivate(cx, obj); - - *rval = BOOLEAN_TO_JSVAL( JS_FALSE ); - - if (dbo->stmt) { - switch_core_db_finalize(dbo->stmt); - dbo->stmt = NULL; - } - - if (argc > 0) { - char *sql = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); - - if(switch_core_db_prepare(dbo->db, sql, 0, &dbo->stmt, 0)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error %s\n", switch_core_db_errmsg(dbo->db)); - } else { - *rval = BOOLEAN_TO_JSVAL( JS_TRUE ); - } - } - return JS_TRUE; -} - -enum db_tinyid { - DB_NAME -}; - -static JSFunctionSpec db_methods[] = { - {"exec", db_exec, 1}, - {"next", db_next, 0}, - {"fetch", db_fetch, 1}, - {"prepare", db_prepare, 0}, - {0} -}; - - -static JSPropertySpec db_props[] = { - {"path", DB_NAME, JSPROP_READONLY|JSPROP_PERMANENT}, - {0} -}; - - -static JSBool db_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSBool res = JS_TRUE; - struct db_obj *dbo = JS_GetPrivate(cx, obj); - char *name; - int param = 0; - - 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); - } else { - return JS_TRUE; - } - - switch(param) { - case DB_NAME: - *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, dbo->dbname)); - break; - } - - return res; -} - -JSClass db_class = { - "DB", JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, db_getProperty, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, db_destroy, NULL, NULL, NULL, - db_construct -}; - -/* TeleTone Object */ -/*********************************************************************************/ -static JSBool teletone_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - int32 memory = 65535; - JSObject *session_obj; - struct teletone_obj *tto = NULL; - struct js_session *jss = NULL; - switch_codec_t *read_codec; - switch_memory_pool_t *pool; - char *timer_name = NULL; - - if (argc > 0) { - if (JS_ValueToObject(cx, argv[0], &session_obj)) { - if (!(jss = JS_GetPrivate(cx, session_obj))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Find Session [1]\n"); - return JS_FALSE; - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Find Session [2]\n"); - return JS_FALSE; - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Session Arg\n"); - return JS_FALSE; - } - if (argc > 1) { - timer_name = JS_GetStringBytes(JS_ValueToString(cx, argv[1])); - } - - if (argc > 2) { - if (!JS_ValueToInt32(cx, argv[2], &memory)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Convert to INT\n"); - return JS_FALSE; - } - } - switch_core_new_memory_pool(&pool); - - if (!(tto = switch_core_alloc(pool, sizeof(*tto)))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error\n"); - return JS_FALSE; - } - - read_codec = switch_core_session_get_read_codec(jss->session); - - if (switch_core_codec_init(&tto->codec, - "L16", - NULL, - read_codec->implementation->samples_per_second, - read_codec->implementation->microseconds_per_frame / 1000, - read_codec->implementation->number_of_channels, - SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, - NULL, pool) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activated\n"); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activation Failed\n"); - return JS_FALSE; - } - - if (timer_name) { - unsigned int ms = read_codec->implementation->microseconds_per_frame / 1000; - if (switch_core_timer_init(&tto->timer_base, - timer_name, - ms, - (read_codec->implementation->samples_per_second / 50) * read_codec->implementation->number_of_channels, - pool) == SWITCH_STATUS_SUCCESS) { - tto->timer = &tto->timer_base; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timer INIT Success %u\n", ms); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timer INIT Failed\n"); - } - } - - switch_buffer_create_dynamic(&tto->audio_buffer, JS_BLOCK_SIZE, JS_BUFFER_SIZE, 0); - tto->pool = pool; - tto->obj = obj; - tto->cx = cx; - tto->session = jss->session; - teletone_init_session(&tto->ts, memory, teletone_handler, tto); - JS_SetPrivate(cx, obj, tto); - - return JS_TRUE; -} - -static void teletone_destroy(JSContext *cx, JSObject *obj) -{ - struct teletone_obj *tto = JS_GetPrivate(cx, obj); - switch_memory_pool_t *pool; - if (tto) { - if (tto->timer) { - switch_core_timer_destroy(tto->timer); - } - teletone_destroy_session(&tto->ts); - switch_buffer_destroy(&tto->audio_buffer); - switch_buffer_destroy(&tto->loop_buffer); - switch_core_codec_destroy(&tto->codec); - pool = tto->pool; - tto->pool = NULL; - if (pool) { - switch_core_destroy_memory_pool(&pool); - } - } -} - -static JSBool teletone_add_tone(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - struct teletone_obj *tto = JS_GetPrivate(cx, obj); - if (argc > 2) { - int x; - char *fval; - char *map_str; - map_str = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); - - for(x = 1; x < TELETONE_MAX_TONES; x++) { - fval = JS_GetStringBytes(JS_ValueToString(cx, argv[x])); - tto->ts.TONES[(int)*map_str].freqs[x-1] = strtod(fval, NULL); - } - return JS_TRUE; - } - - return JS_FALSE; -} - -static JSBool teletone_on_dtmf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - struct teletone_obj *tto = JS_GetPrivate(cx, obj); - if (argc > 0) { - tto->function = JS_ValueToFunction(cx, argv[0]); - if (argc > 1) { - tto->arg = argv[1]; - } - switch_set_flag(tto, TTF_DTMF); - } - return JS_TRUE; -} - -static JSBool teletone_generate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) -{ - struct teletone_obj *tto = JS_GetPrivate(cx, obj); - int32 loops = 0; - - if (argc > 0) { - char *script; - switch_core_session_t *session; - switch_frame_t write_frame = {0}; - unsigned char *fdata[1024]; - switch_frame_t *read_frame; - int stream_id; - switch_core_thread_session_t thread_session; - switch_channel_t *channel; - - if (argc > 1) { - if (!JS_ValueToInt32(cx, argv[1], &loops)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Convert to INT\n"); - return JS_FALSE; - } - loops--; - if (!tto->loop_buffer) { - switch_buffer_create_dynamic(&tto->loop_buffer, JS_BLOCK_SIZE, JS_BUFFER_SIZE, 0); - } - } - - if (tto->audio_buffer) { - switch_buffer_zero(tto->audio_buffer); - } - if (tto->loop_buffer) { - switch_buffer_zero(tto->loop_buffer); - } - tto->ts.debug = 1; - tto->ts.debug_stream = switch_core_get_console(); - - script = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); - teletone_run(&tto->ts, script); - - session = tto->session; - write_frame.codec = &tto->codec; - write_frame.data = fdata; - - channel = switch_core_session_get_channel(session); - - if (tto->timer) { - for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) { - switch_core_service_session(session, &thread_session, stream_id); - } - } - - for(;;) { - - if (switch_test_flag(tto, TTF_DTMF)) { - char dtmf[128]; - char *ret; - - if (switch_channel_has_dtmf(channel)) { - uintN aargc = 0; - jsval aargv[4]; - - switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf)); - aargv[aargc++] = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, dtmf)); - JS_CallFunction(cx, obj, tto->function, aargc, aargv, &tto->ret); - ret = JS_GetStringBytes(JS_ValueToString(cx, tto->ret)); - if (strcmp(ret, "true") && strcmp(ret, "undefined")) { - *rval = tto->ret; - return JS_TRUE; - } - } - } - - if (tto->timer) { - if (switch_core_timer_next(tto->timer)< 0) { - break; - } - - } else { - switch_status_t status; - status = switch_core_session_read_frame(session, &read_frame, -1, 0); - - if (!SWITCH_READ_ACCEPTABLE(status)) { - break; - } - } - if ((write_frame.datalen = (uint32_t)switch_buffer_read(tto->audio_buffer, fdata, write_frame.codec->implementation->bytes_per_frame)) <= 0) { - if (loops) { - switch_buffer_t *tmp; - - /* Switcharoo*/ - tmp = tto->audio_buffer; - tto->audio_buffer = tto->loop_buffer; - tto->loop_buffer = tmp; - loops--; - /* try again */ - if ((write_frame.datalen = - (uint32_t)switch_buffer_read(tto->audio_buffer, fdata, write_frame.codec->implementation->bytes_per_frame)) <= 0) { - break; - } - } else { - break; - } - } - - write_frame.samples = write_frame.datalen / 2; - for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) { - if (switch_core_session_write_frame(session, &write_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bad Write\n"); - break; - } - } - if (tto->loop_buffer && loops) { - switch_buffer_write(tto->loop_buffer, write_frame.data, write_frame.datalen); - } - } - - if (tto->timer) { - switch_core_thread_session_end(&thread_session); - } - return JS_TRUE; - } - - return JS_FALSE; -} - -enum teletone_tinyid { - TELETONE_NAME -}; - -static JSFunctionSpec teletone_methods[] = { - {"generate", teletone_generate, 1}, - {"onDTMF", teletone_on_dtmf, 1}, - {"addTone", teletone_add_tone, 10}, - {0} -}; - - -static JSPropertySpec teletone_props[] = { - {"name", TELETONE_NAME, JSPROP_READONLY|JSPROP_PERMANENT}, - {0} -}; - - -static JSBool teletone_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) -{ - JSBool res = JS_TRUE; - - return res; -} - -JSClass teletone_class = { - "TeleTone", JSCLASS_HAS_PRIVATE, - JS_PropertyStub, JS_PropertyStub, teletone_getProperty, JS_PropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, teletone_destroy, NULL, NULL, NULL, - teletone_construct -}; - - /* Built-In*/ /*********************************************************************************/ static JSBool js_exit(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) @@ -2411,6 +1995,27 @@ static int write_buf(int fd, char *buf) { return 1; } +static JSBool js_api_use(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + char *mod_name = NULL; + + if (argc > 0 && (mod_name = JS_GetStringBytes(JS_ValueToString(cx, argv[0])))) { + const sm_module_interface_t *mp; + + if ((mp = switch_core_hash_find(module_manager.load_hash, mod_name))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading %s\n", mod_name); + mp->spidermonkey_load(cx, obj); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error loading %s\n", mod_name); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Filename\n"); + } + + return JS_TRUE; + +} + static JSBool js_api_execute(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { @@ -2632,6 +2237,7 @@ static JSFunctionSpec fs_functions[] = { {"email", js_email, 2}, {"bridge", js_bridge, 2}, {"apiExecute", js_api_execute, 2}, + {"use", js_api_use, 1}, #ifdef HAVE_CURL {"fetchURLHash", js_fetchurl_hash, 1}, {"fetchURLFile", js_fetchurl_file, 1}, @@ -2640,7 +2246,7 @@ static JSFunctionSpec fs_functions[] = { }; -static int eval_some_js(char *code, JSContext *cx, JSObject *obj, jsval *rval) +SWITCH_DECLARE(int) eval_some_js(char *code, JSContext *cx, JSObject *obj, jsval *rval) { JSScript *script = NULL; char *cptr; @@ -2676,17 +2282,6 @@ static int env_init(JSContext *cx, JSObject *javascript_object) JS_InitStandardClasses(cx, javascript_object); - JS_InitClass(cx, - javascript_object, - NULL, - &teletone_class, - teletone_construct, - 3, - teletone_props, - teletone_methods, - teletone_props, - teletone_methods - ); JS_InitClass(cx, javascript_object, @@ -2712,18 +2307,6 @@ static int env_init(JSContext *cx, JSObject *javascript_object) fileio_methods ); - JS_InitClass(cx, - javascript_object, - NULL, - &db_class, - db_construct, - 3, - db_props, - db_methods, - db_props, - db_methods - ); - JS_InitClass(cx, javascript_object, NULL, @@ -2751,6 +2334,7 @@ static void js_parse_and_execute(switch_core_session_t *session, char *input_cod if ((cx = JS_NewContext(globals.rt, globals.gStackChunkSize))) { + JS_BeginRequest(cx); JS_SetErrorReporter(cx, js_error); javascript_global_object = JS_NewObject(cx, &global_class, NULL, NULL); env_init(cx, javascript_global_object); @@ -2878,7 +2462,7 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_mod if ((status = init_js()) != SWITCH_STATUS_SUCCESS) { return status; } - + /* connect my internal structure to the blank pointer passed to me */ *module_interface = &spidermonkey_module_interface; diff --git a/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h new file mode 100644 index 0000000000..45fdcd90a1 --- /dev/null +++ b/src/mod/languages/mod_spidermonkey/mod_spidermonkey.h @@ -0,0 +1,89 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005/2006, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * + * mod_spidermonkey.h -- Javascript Module + * + */ +#ifndef SWITCH_MOD_SPIDERMONKEY_H +#define SWITCH_MOD_SPIDERMONKEY_H + + +#include +#include "jstypes.h" +#include "jsarena.h" +#include "jsutil.h" +#include "jsprf.h" +#include "jsapi.h" +#include "jsatom.h" +#include "jscntxt.h" +#include "jsdbgapi.h" +#include "jsemit.h" +#include "jsfun.h" +#include "jsgc.h" +#include "jslock.h" +#include "jsobj.h" +#include "jsparse.h" +#include "jsscope.h" +#include "jsscript.h" +#include + +SWITCH_BEGIN_EXTERN_C + +#define JS_BUFFER_SIZE 1024 * 32 +#define JS_BLOCK_SIZE JS_BUFFER_SIZE +#ifdef __ICC +#pragma warning (disable:310 193 1418) +#endif + + +SWITCH_DECLARE(int) eval_some_js(char *code, JSContext *cx, JSObject *obj, jsval *rval); + +typedef switch_status_t(*spidermonkey_load_t)(JSContext *cx, JSObject *obj); + +struct sm_module_interface { + const char *name; + spidermonkey_load_t spidermonkey_load; + const struct sm_module_interface *next; +}; + +typedef struct sm_module_interface sm_module_interface_t; +typedef switch_status_t(*spidermonkey_init_t)(const sm_module_interface_t **module_interface); + +struct js_session { + switch_core_session_t *session; + JSContext *cx; + JSObject *obj; + unsigned int flags; +}; + + + +SWITCH_END_EXTERN_C + +#endif + diff --git a/src/mod/languages/mod_spidermonkey/sm.mak b/src/mod/languages/mod_spidermonkey/sm.mak new file mode 100644 index 0000000000..e279209152 --- /dev/null +++ b/src/mod/languages/mod_spidermonkey/sm.mak @@ -0,0 +1,67 @@ +# This is all used to make sure we use the right options during build and link. + +OS_ARCH := $(subst /,_,$(shell uname -s | sed /\ /s//_/)) +#VER=DBG +#BO=0 +VER=OPT +BO=1 + +# Attempt to differentiate between SunOS 5.4 and x86 5.4 +OS_CPUARCH := $(shell uname -m) +ifeq ($(OS_CPUARCH),i86pc) +OS_RELEASE := $(shell uname -r)_$(OS_CPUARCH) +else +ifeq ($(OS_ARCH),AIX) +OS_RELEASE := $(shell uname -v).$(shell uname -r) +else +OS_RELEASE := $(shell uname -r) +endif +endif +ifeq ($(OS_ARCH),IRIX64) +OS_ARCH := IRIX +endif + +# Handle output from win32 unames other than Netscape's version +ifeq (,$(filter-out Windows_95 Windows_98 CYGWIN_95-4.0 CYGWIN_98-4.10, $(OS_ARCH))) + OS_ARCH := WIN95 +endif +ifeq ($(OS_ARCH),WIN95) + OS_ARCH := WINNT + OS_RELEASE := 4.0 +endif +ifeq ($(OS_ARCH), Windows_NT) + OS_ARCH := WINNT + OS_MINOR_RELEASE := $(shell uname -v) + ifeq ($(OS_MINOR_RELEASE),00) + OS_MINOR_RELEASE = 0 + endif + OS_RELEASE := $(OS_RELEASE).$(OS_MINOR_RELEASE) +endif +ifeq (CYGWIN_NT,$(findstring CYGWIN_NT,$(OS_ARCH))) + OS_RELEASE := $(patsubst CYGWIN_NT-%,%,$(OS_ARCH)) + OS_ARCH := WINNT +endif +ifeq ($(OS_ARCH), CYGWIN32_NT) + OS_ARCH := WINNT +endif +ifeq (MINGW32_NT,$(findstring MINGW32_NT,$(OS_ARCH))) + OS_RELEASE := $(patsubst MINGW32_NT-%,%,$(OS_ARCH)) + OS_ARCH := WINNT +endif + +ifeq ($(OS_ARCH),Linux) +OS_CONFIG := Linux_All +else +ifeq ($(OS_ARCH),dgux) +OS_CONFIG := dgux +else +ifeq ($(OS_ARCH),Darwin) +OS_CONFIG := Darwin +else +OS_CONFIG := $(OS_ARCH)$(OS_OBJTYPE)$(OS_RELEASE) +endif +endif +endif + +CFLAGS += -I../mod_spidermonkey -I$(BASE)/libs/mozilla/js/src -Wall -Wno-format -g -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DHAVE_LOCALTIME_R -DX86_LINUX -DDEBUG -DDEBUG_root -DJS_THREADSAFE -I$(BASE)/libs/mozilla/js/src -I$(BASE)/libs/mozilla/js/src/$(OS_CONFIG)_$(VER).OBJ -Wall -Wno-format -g -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DHAVE_LOCALTIME_R -DX86_LINUX -DDEBUG -DDEBUG_root -DJS_THREADSAFE -I$(BASE)/libs/mozilla/nsprpub/dist/include/nspr -I$(OS_CONFIG)_$(VER).OBJ +LDFLAGS +=-DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DHAVE_LOCALTIME_R -DX86_LINUX -DDEBUG -DDEBUG_root -DJS_THREADSAFE -I$(BASE)/libs/mozilla/nsprpub/dist/include/nspr -Wall -Wno-format -g -DXP_UNIX -DSVR4 -DSYSV -D_BSD_SOURCE -DPOSIX_SOURCE -DHAVE_LOCALTIME_R -DX86_LINUX -DDEBUG -DDEBUG_root -DJS_THREADSAFE -I$(BASE)/libs/mozilla/nsprpub/dist/include/nspr -lteletone diff --git a/src/mod/languages/mod_spidermonkey_core_db/Makefile b/src/mod/languages/mod_spidermonkey_core_db/Makefile new file mode 100644 index 0000000000..2d000943d7 --- /dev/null +++ b/src/mod/languages/mod_spidermonkey_core_db/Makefile @@ -0,0 +1,19 @@ +include ../mod_spidermonkey/sm.mak + +OBJS=#$(BASE)/libs/mozilla/js/src/$(OS_CONFIG)_$(VER).OBJ/libjs.a $(BASE)/libs/mozilla/nsprpub/dist/lib/libnspr4.a +LINKER=$(CC) + + +all: depends $(MODNAME).$(DYNAMIC_LIB_EXTEN) + +depends: + +$(MODNAME).$(DYNAMIC_LIB_EXTEN): $(MODNAME).c + $(CC) $(CFLAGS) -fPIC -c $(MODNAME).c -o $(MODNAME).o + $(LINKER) $(SOLINK) -o $(MODNAME).$(DYNAMIC_LIB_EXTEN) $(MODNAME).o $(OBJS) $(LDFLAGS) + +clean: + rm -fr *.$(DYNAMIC_LIB_EXTEN) *.o *~ + +install: + cp -f $(MODNAME).$(DYNAMIC_LIB_EXTEN) $(PREFIX)/mod diff --git a/src/mod/languages/mod_spidermonkey_core_db/mod_spidermonkey_core_db.c b/src/mod/languages/mod_spidermonkey_core_db/mod_spidermonkey_core_db.c new file mode 100644 index 0000000000..f4b50075fe --- /dev/null +++ b/src/mod/languages/mod_spidermonkey_core_db/mod_spidermonkey_core_db.c @@ -0,0 +1,309 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005/2006, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * + * mod_spidermonkey_DB.c -- DB Javascript Module + * + */ +#include "mod_spidermonkey.h" + +static const char modname[] = "DB"; + +struct db_obj { + switch_memory_pool_t *pool; + switch_core_db_t *db; + switch_core_db_stmt_t *stmt; + char *dbname; + char code_buffer[2048]; + JSContext *cx; + JSObject *obj; +}; + + +/* DB Object */ +/*********************************************************************************/ +static JSBool db_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + switch_memory_pool_t *pool; + switch_core_db_t *db; + struct db_obj *dbo; + + if (argc > 0) { + char *dbname = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); + switch_core_new_memory_pool(&pool); + if (! (db = switch_core_db_open_file(dbname))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Open DB!\n"); + switch_core_destroy_memory_pool(&pool); + return JS_FALSE; + } + dbo = switch_core_alloc(pool, sizeof(*dbo)); + dbo->pool = pool; + dbo->dbname = switch_core_strdup(pool, dbname); + dbo->cx = cx; + dbo->obj = obj; + dbo->db = db; + JS_SetPrivate(cx, obj, dbo); + return JS_TRUE; + } + + return JS_FALSE; +} + +static void db_destroy(JSContext *cx, JSObject *obj) +{ + struct db_obj *dbo = JS_GetPrivate(cx, obj); + + if (dbo) { + switch_memory_pool_t *pool = dbo->pool; + if (dbo->stmt) { + switch_core_db_finalize(dbo->stmt); + dbo->stmt = NULL; + } + switch_core_db_close(dbo->db); + switch_core_destroy_memory_pool(&pool); + pool = NULL; + } +} + + +static int db_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + struct db_obj *dbo = pArg; + char code[1024]; + jsval rval; + int x = 0; + + snprintf(code, sizeof(code), "~var _Db_RoW_ = {}"); + eval_some_js(code, dbo->cx, dbo->obj, &rval); + + for(x=0; x < argc; x++) { + snprintf(code, sizeof(code), "~_Db_RoW_[\"%s\"] = \"%s\"", columnNames[x], argv[x]); + eval_some_js(code, dbo->cx, dbo->obj, &rval); + } + + snprintf(code, sizeof(code), "~%s(_Db_RoW_)", dbo->code_buffer); + eval_some_js(code, dbo->cx, dbo->obj, &rval); + + snprintf(code, sizeof(code), "~delete _Db_RoW_"); + eval_some_js(code, dbo->cx, dbo->obj, &rval); + + return 0; +} + +static JSBool db_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + struct db_obj *dbo = JS_GetPrivate(cx, obj); + *rval = BOOLEAN_TO_JSVAL( JS_TRUE ); + + if (argc > 0) { + char *sql = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); + char *err = NULL; + void *arg = NULL; + switch_core_db_callback_func_t cb_func = NULL; + + + if (argc > 1) { + char *js_func = JS_GetStringBytes(JS_ValueToString(cx, argv[1])); + switch_copy_string(dbo->code_buffer, js_func, sizeof(dbo->code_buffer)); + cb_func = db_callback; + arg = dbo; + } + + switch_core_db_exec(dbo->db, sql, cb_func, arg, &err); + if (err) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error %s\n", err); + switch_core_db_free(err); + *rval = BOOLEAN_TO_JSVAL( JS_FALSE ); + } + } + return JS_TRUE; +} + + +static JSBool db_next(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + struct db_obj *dbo = JS_GetPrivate(cx, obj); + *rval = BOOLEAN_TO_JSVAL( JS_FALSE ); + + if (dbo->stmt) { + int running = 1; + + while (running < 5000) { + int result = switch_core_db_step(dbo->stmt); + if (result == SQLITE_ROW) { + *rval = BOOLEAN_TO_JSVAL( JS_TRUE ); + break; + } else if (result == SQLITE_BUSY) { + running++; + continue; + } + switch_core_db_finalize(dbo->stmt); + dbo->stmt = NULL; + break; + } + } + + return JS_TRUE; +} + +static JSBool db_fetch(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + struct db_obj *dbo = JS_GetPrivate(cx, obj); + int colcount = switch_core_db_column_count(dbo->stmt); + char code[1024]; + int x; + + snprintf(code, sizeof(code), "~var _dB_RoW_DaTa_ = {}"); + eval_some_js(code, dbo->cx, dbo->obj, rval); + if (*rval == JS_FALSE) { + return JS_TRUE; + } + for (x = 0; x < colcount; x++) { + 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)); + + eval_some_js(code, dbo->cx, dbo->obj, rval); + if (*rval == JS_FALSE) { + return JS_TRUE; + } + } + + JS_GetProperty(cx, obj, "_dB_RoW_DaTa_", rval); + + return JS_TRUE; +} + + +static JSBool db_prepare(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + struct db_obj *dbo = JS_GetPrivate(cx, obj); + + *rval = BOOLEAN_TO_JSVAL( JS_FALSE ); + + if (dbo->stmt) { + switch_core_db_finalize(dbo->stmt); + dbo->stmt = NULL; + } + + if (argc > 0) { + char *sql = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); + + if(switch_core_db_prepare(dbo->db, sql, 0, &dbo->stmt, 0)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error %s\n", switch_core_db_errmsg(dbo->db)); + } else { + *rval = BOOLEAN_TO_JSVAL( JS_TRUE ); + } + } + return JS_TRUE; +} + +enum db_tinyid { + DB_NAME +}; + +static JSFunctionSpec db_methods[] = { + {"exec", db_exec, 1}, + {"next", db_next, 0}, + {"fetch", db_fetch, 1}, + {"prepare", db_prepare, 0}, + {0} +}; + + +static JSPropertySpec db_props[] = { + {"path", DB_NAME, JSPROP_READONLY|JSPROP_PERMANENT}, + {0} +}; + + +static JSBool db_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) +{ + JSBool res = JS_TRUE; + struct db_obj *dbo = JS_GetPrivate(cx, obj); + char *name; + int param = 0; + + 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); + } else { + return JS_TRUE; + } + + switch(param) { + case DB_NAME: + *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, dbo->dbname)); + break; + } + + return res; +} + +JSClass db_class = { + "DB", JSCLASS_HAS_PRIVATE, + JS_PropertyStub, JS_PropertyStub, db_getProperty, JS_PropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, db_destroy, NULL, NULL, NULL, + db_construct +}; + + + + + + +switch_status_t spidermonkey_load(JSContext *cx, JSObject *obj) +{ + + JS_InitClass(cx, + obj, + NULL, + &db_class, + db_construct, + 3, + db_props, + db_methods, + db_props, + db_methods + ); + + return SWITCH_STATUS_SUCCESS; +} + + +const sm_module_interface_t DB_module_interface = { + /*.name = */ modname, + /*.spidermonkey_load*/ spidermonkey_load, + /*.next*/ NULL +}; + +SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t **module_interface) +{ + *module_interface = &DB_module_interface; + return SWITCH_STATUS_SUCCESS; +} diff --git a/src/mod/languages/mod_spidermonkey_skel/Makefile b/src/mod/languages/mod_spidermonkey_skel/Makefile new file mode 100644 index 0000000000..2d000943d7 --- /dev/null +++ b/src/mod/languages/mod_spidermonkey_skel/Makefile @@ -0,0 +1,19 @@ +include ../mod_spidermonkey/sm.mak + +OBJS=#$(BASE)/libs/mozilla/js/src/$(OS_CONFIG)_$(VER).OBJ/libjs.a $(BASE)/libs/mozilla/nsprpub/dist/lib/libnspr4.a +LINKER=$(CC) + + +all: depends $(MODNAME).$(DYNAMIC_LIB_EXTEN) + +depends: + +$(MODNAME).$(DYNAMIC_LIB_EXTEN): $(MODNAME).c + $(CC) $(CFLAGS) -fPIC -c $(MODNAME).c -o $(MODNAME).o + $(LINKER) $(SOLINK) -o $(MODNAME).$(DYNAMIC_LIB_EXTEN) $(MODNAME).o $(OBJS) $(LDFLAGS) + +clean: + rm -fr *.$(DYNAMIC_LIB_EXTEN) *.o *~ + +install: + cp -f $(MODNAME).$(DYNAMIC_LIB_EXTEN) $(PREFIX)/mod diff --git a/src/mod/languages/mod_spidermonkey_skel/mod_spidermonkey_skel.c b/src/mod/languages/mod_spidermonkey_skel/mod_spidermonkey_skel.c new file mode 100644 index 0000000000..aef565cb75 --- /dev/null +++ b/src/mod/languages/mod_spidermonkey_skel/mod_spidermonkey_skel.c @@ -0,0 +1,110 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005/2006, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * + * mod_spidermonkey_skel.c -- Skel Javascript Module + * + */ +#include "mod_spidermonkey.h" + +static const char modname[] = "Skel"; + +/* Skel Object */ +/*********************************************************************************/ +static JSBool skel_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + return JS_TRUE; +} + +static void skel_destroy(JSContext *cx, JSObject *obj) +{ +} + +static JSBool skel_my_method(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + return JS_FALSE; +} + +enum skel_tinyid { + SKEL_NAME +}; + +static JSFunctionSpec skel_methods[] = { + {"myMethod", skel_my_method, 1}, + {0} +}; + + +static JSPropertySpec skel_props[] = { + {"name", SKEL_NAME, JSPROP_READONLY|JSPROP_PERMANENT}, + {0} +}; + + +static JSBool skel_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) +{ + JSBool res = JS_TRUE; + + return res; +} + +JSClass skel_class = { + modname, JSCLASS_HAS_PRIVATE, + JS_PropertyStub, JS_PropertyStub, skel_getProperty, JS_PropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, skel_destroy, NULL, NULL, NULL, + skel_construct +}; + + +switch_status_t spidermonkey_load(JSContext *cx, JSObject *obj) +{ + JS_InitClass(cx, + obj, + NULL, + &skel_class, + skel_construct, + 3, + skel_props, + skel_methods, + skel_props, + skel_methods + ); + return SWITCH_STATUS_SUCCESS; +} + + +const sm_module_interface_t skel_module_interface = { + /*.name = */ modname, + /*.spidermonkey_load*/ spidermonkey_load, + /*.next*/ NULL +}; + +SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t **module_interface) +{ + *module_interface = &skel_module_interface; + return SWITCH_STATUS_SUCCESS; +} diff --git a/src/mod/languages/mod_spidermonkey_teletone/Makefile b/src/mod/languages/mod_spidermonkey_teletone/Makefile new file mode 100644 index 0000000000..2d000943d7 --- /dev/null +++ b/src/mod/languages/mod_spidermonkey_teletone/Makefile @@ -0,0 +1,19 @@ +include ../mod_spidermonkey/sm.mak + +OBJS=#$(BASE)/libs/mozilla/js/src/$(OS_CONFIG)_$(VER).OBJ/libjs.a $(BASE)/libs/mozilla/nsprpub/dist/lib/libnspr4.a +LINKER=$(CC) + + +all: depends $(MODNAME).$(DYNAMIC_LIB_EXTEN) + +depends: + +$(MODNAME).$(DYNAMIC_LIB_EXTEN): $(MODNAME).c + $(CC) $(CFLAGS) -fPIC -c $(MODNAME).c -o $(MODNAME).o + $(LINKER) $(SOLINK) -o $(MODNAME).$(DYNAMIC_LIB_EXTEN) $(MODNAME).o $(OBJS) $(LDFLAGS) + +clean: + rm -fr *.$(DYNAMIC_LIB_EXTEN) *.o *~ + +install: + cp -f $(MODNAME).$(DYNAMIC_LIB_EXTEN) $(PREFIX)/mod diff --git a/src/mod/languages/mod_spidermonkey_teletone/mod_spidermonkey_teletone.c b/src/mod/languages/mod_spidermonkey_teletone/mod_spidermonkey_teletone.c new file mode 100644 index 0000000000..19769cd9bf --- /dev/null +++ b/src/mod/languages/mod_spidermonkey_teletone/mod_spidermonkey_teletone.c @@ -0,0 +1,394 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005/2006, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * + * mod_spidermonkey_teletone.c -- TeleTone Javascript Module + * + */ +#include "mod_spidermonkey.h" + +static const char modname[] = "TeleTone"; + +typedef enum { + TTF_DTMF = (1 << 0) +} teletone_flag_t; + + +struct teletone_obj { + teletone_generation_session_t ts; + JSContext *cx; + JSObject *obj; + switch_core_session_t *session; + switch_codec_t codec; + switch_buffer_t *audio_buffer; + switch_buffer_t *loop_buffer; + switch_memory_pool_t *pool; + switch_timer_t *timer; + switch_timer_t timer_base; + JSFunction *function; + jsval arg; + jsval ret; + unsigned int flags; +}; + + +static int teletone_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map) +{ + struct teletone_obj *tto = ts->user_data; + int wrote; + + if (!tto) { + return -1; + } + wrote = teletone_mux_tones(ts, map); + switch_buffer_write(tto->audio_buffer, ts->buffer, wrote * 2); + + return 0; +} + + +/* TeleTone Object */ +/*********************************************************************************/ +static JSBool teletone_construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + int32 memory = 65535; + JSObject *session_obj; + struct teletone_obj *tto = NULL; + struct js_session *jss = NULL; + switch_codec_t *read_codec; + switch_memory_pool_t *pool; + char *timer_name = NULL; + + if (argc > 0) { + if (JS_ValueToObject(cx, argv[0], &session_obj)) { + if (!(jss = JS_GetPrivate(cx, session_obj))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Find Session [1]\n"); + return JS_FALSE; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Find Session [2]\n"); + return JS_FALSE; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Session Arg\n"); + return JS_FALSE; + } + if (argc > 1) { + timer_name = JS_GetStringBytes(JS_ValueToString(cx, argv[1])); + } + + if (argc > 2) { + if (!JS_ValueToInt32(cx, argv[2], &memory)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Convert to INT\n"); + return JS_FALSE; + } + } + switch_core_new_memory_pool(&pool); + + if (!(tto = switch_core_alloc(pool, sizeof(*tto)))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error\n"); + return JS_FALSE; + } + + read_codec = switch_core_session_get_read_codec(jss->session); + + if (switch_core_codec_init(&tto->codec, + "L16", + NULL, + read_codec->implementation->samples_per_second, + read_codec->implementation->microseconds_per_frame / 1000, + read_codec->implementation->number_of_channels, + SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, + NULL, pool) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activated\n"); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Raw Codec Activation Failed\n"); + return JS_FALSE; + } + + if (timer_name) { + unsigned int ms = read_codec->implementation->microseconds_per_frame / 1000; + if (switch_core_timer_init(&tto->timer_base, + timer_name, + ms, + (read_codec->implementation->samples_per_second / 50) * read_codec->implementation->number_of_channels, + pool) == SWITCH_STATUS_SUCCESS) { + tto->timer = &tto->timer_base; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timer INIT Success %u\n", ms); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Timer INIT Failed\n"); + } + } + + switch_buffer_create_dynamic(&tto->audio_buffer, JS_BLOCK_SIZE, JS_BUFFER_SIZE, 0); + tto->pool = pool; + tto->obj = obj; + tto->cx = cx; + tto->session = jss->session; + teletone_init_session(&tto->ts, memory, teletone_handler, tto); + JS_SetPrivate(cx, obj, tto); + + return JS_TRUE; +} + +static void teletone_destroy(JSContext *cx, JSObject *obj) +{ + struct teletone_obj *tto = JS_GetPrivate(cx, obj); + switch_memory_pool_t *pool; + if (tto) { + if (tto->timer) { + switch_core_timer_destroy(tto->timer); + } + teletone_destroy_session(&tto->ts); + switch_buffer_destroy(&tto->audio_buffer); + switch_buffer_destroy(&tto->loop_buffer); + switch_core_codec_destroy(&tto->codec); + pool = tto->pool; + tto->pool = NULL; + if (pool) { + switch_core_destroy_memory_pool(&pool); + } + } +} + +static JSBool teletone_add_tone(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + struct teletone_obj *tto = JS_GetPrivate(cx, obj); + if (argc > 2) { + int x; + char *fval; + char *map_str; + map_str = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); + + for(x = 1; x < TELETONE_MAX_TONES; x++) { + fval = JS_GetStringBytes(JS_ValueToString(cx, argv[x])); + tto->ts.TONES[(int)*map_str].freqs[x-1] = strtod(fval, NULL); + } + return JS_TRUE; + } + + return JS_FALSE; +} + +static JSBool teletone_on_dtmf(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + struct teletone_obj *tto = JS_GetPrivate(cx, obj); + if (argc > 0) { + tto->function = JS_ValueToFunction(cx, argv[0]); + if (argc > 1) { + tto->arg = argv[1]; + } + switch_set_flag(tto, TTF_DTMF); + } + return JS_TRUE; +} + +static JSBool teletone_generate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + struct teletone_obj *tto = JS_GetPrivate(cx, obj); + int32 loops = 0; + + if (argc > 0) { + char *script; + switch_core_session_t *session; + switch_frame_t write_frame = {0}; + unsigned char *fdata[1024]; + switch_frame_t *read_frame; + int stream_id; + switch_core_thread_session_t thread_session; + switch_channel_t *channel; + + if (argc > 1) { + if (!JS_ValueToInt32(cx, argv[1], &loops)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot Convert to INT\n"); + return JS_FALSE; + } + loops--; + if (!tto->loop_buffer) { + switch_buffer_create_dynamic(&tto->loop_buffer, JS_BLOCK_SIZE, JS_BUFFER_SIZE, 0); + } + } + + if (tto->audio_buffer) { + switch_buffer_zero(tto->audio_buffer); + } + if (tto->loop_buffer) { + switch_buffer_zero(tto->loop_buffer); + } + tto->ts.debug = 1; + tto->ts.debug_stream = switch_core_get_console(); + + script = JS_GetStringBytes(JS_ValueToString(cx, argv[0])); + teletone_run(&tto->ts, script); + + session = tto->session; + write_frame.codec = &tto->codec; + write_frame.data = fdata; + + channel = switch_core_session_get_channel(session); + + if (tto->timer) { + for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) { + switch_core_service_session(session, &thread_session, stream_id); + } + } + + for(;;) { + + if (switch_test_flag(tto, TTF_DTMF)) { + char dtmf[128]; + char *ret; + + if (switch_channel_has_dtmf(channel)) { + uintN aargc = 0; + jsval aargv[4]; + + switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf)); + aargv[aargc++] = STRING_TO_JSVAL (JS_NewStringCopyZ(cx, dtmf)); + JS_CallFunction(cx, obj, tto->function, aargc, aargv, &tto->ret); + ret = JS_GetStringBytes(JS_ValueToString(cx, tto->ret)); + if (strcmp(ret, "true") && strcmp(ret, "undefined")) { + *rval = tto->ret; + return JS_TRUE; + } + } + } + + if (tto->timer) { + if (switch_core_timer_next(tto->timer)< 0) { + break; + } + + } else { + switch_status_t status; + status = switch_core_session_read_frame(session, &read_frame, -1, 0); + + if (!SWITCH_READ_ACCEPTABLE(status)) { + break; + } + } + if ((write_frame.datalen = (uint32_t)switch_buffer_read(tto->audio_buffer, fdata, write_frame.codec->implementation->bytes_per_frame)) <= 0) { + if (loops) { + switch_buffer_t *tmp; + + /* Switcharoo*/ + tmp = tto->audio_buffer; + tto->audio_buffer = tto->loop_buffer; + tto->loop_buffer = tmp; + loops--; + /* try again */ + if ((write_frame.datalen = + (uint32_t)switch_buffer_read(tto->audio_buffer, fdata, write_frame.codec->implementation->bytes_per_frame)) <= 0) { + break; + } + } else { + break; + } + } + + write_frame.samples = write_frame.datalen / 2; + for (stream_id = 0; stream_id < switch_core_session_get_stream_count(session); stream_id++) { + if (switch_core_session_write_frame(session, &write_frame, -1, stream_id) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bad Write\n"); + break; + } + } + if (tto->loop_buffer && loops) { + switch_buffer_write(tto->loop_buffer, write_frame.data, write_frame.datalen); + } + } + + if (tto->timer) { + switch_core_thread_session_end(&thread_session); + } + return JS_TRUE; + } + + return JS_FALSE; +} + +enum teletone_tinyid { + TELETONE_NAME +}; + +static JSFunctionSpec teletone_methods[] = { + {"generate", teletone_generate, 1}, + {"onDTMF", teletone_on_dtmf, 1}, + {"addTone", teletone_add_tone, 10}, + {0} +}; + + +static JSPropertySpec teletone_props[] = { + {"name", TELETONE_NAME, JSPROP_READONLY|JSPROP_PERMANENT}, + {0} +}; + + +static JSBool teletone_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) +{ + JSBool res = JS_TRUE; + + return res; +} + +JSClass teletone_class = { + modname, JSCLASS_HAS_PRIVATE, + JS_PropertyStub, JS_PropertyStub, teletone_getProperty, JS_PropertyStub, + JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, teletone_destroy, NULL, NULL, NULL, + teletone_construct +}; + + +switch_status_t spidermonkey_load(JSContext *cx, JSObject *obj) +{ + JS_InitClass(cx, + obj, + NULL, + &teletone_class, + teletone_construct, + 3, + teletone_props, + teletone_methods, + teletone_props, + teletone_methods + ); + return SWITCH_STATUS_SUCCESS; +} + + +const sm_module_interface_t teletone_module_interface = { + /*.name = */ modname, + /*.spidermonkey_load*/ spidermonkey_load, + /*.next*/ NULL +}; + +SWITCH_MOD_DECLARE(switch_status_t) spidermonkey_init(const sm_module_interface_t **module_interface) +{ + *module_interface = &teletone_module_interface; + return SWITCH_STATUS_SUCCESS; +}